llvowlsky.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "pipeline.h"
00035 
00036 #include "llvowlsky.h"
00037 #include "llsky.h"
00038 #include "lldrawpoolwlsky.h"
00039 #include "llface.h"
00040 #include "llwlparammanager.h"
00041 #include "llviewercontrol.h"
00042 
00043 #define DOME_SLICES 1
00044 const F32 LLVOWLSky::DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f;
00045 
00046 const U32 LLVOWLSky::MIN_SKY_DETAIL = 3;
00047 const U32 LLVOWLSky::MAX_SKY_DETAIL = 180;
00048 
00049 inline U32 LLVOWLSky::getNumStacks(void)
00050 {
00051         return gSavedSettings.getU32("WLSkyDetail");
00052 }
00053 
00054 inline U32 LLVOWLSky::getNumSlices(void)
00055 {
00056         return 2 * gSavedSettings.getU32("WLSkyDetail");
00057 }
00058 
00059 inline U32 LLVOWLSky::getFanNumVerts(void)
00060 {
00061         return getNumSlices() + 1;
00062 }
00063 
00064 inline U32 LLVOWLSky::getFanNumIndices(void)
00065 {
00066         return getNumSlices() * 3;
00067 }
00068 
00069 inline U32 LLVOWLSky::getStripsNumVerts(void)
00070 {
00071         return (getNumStacks() - 1) * getNumSlices();
00072 }
00073 
00074 inline U32 LLVOWLSky::getStripsNumIndices(void)
00075 {
00076         return 2 * ((getNumStacks() - 2) * (getNumSlices() + 1)) + 1 ; 
00077 }
00078 
00079 inline U32 LLVOWLSky::getStarsNumVerts(void)
00080 {
00081         return 1000;
00082 }
00083 
00084 inline U32 LLVOWLSky::getStarsNumIndices(void)
00085 {
00086         return 1000;
00087 }
00088 
00089 LLVOWLSky::LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00090         : LLStaticViewerObject(id, pcode, regionp)
00091 {
00092         initStars();
00093 }
00094 
00095 void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction,
00096                 LLVector3 const & sun_angular_velocity)
00097 {
00098 }
00099 
00100 BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00101 {
00102         return TRUE;
00103 }
00104 
00105 BOOL LLVOWLSky::isActive(void) const
00106 {
00107         return FALSE;
00108 }
00109 
00110 LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline)
00111 {
00112         pipeline->allocDrawable(this);
00113 
00114         //LLDrawPoolWLSky *poolp = static_cast<LLDrawPoolWLSky *>(
00115                 gPipeline.getPool(LLDrawPool::POOL_WL_SKY);
00116 
00117         mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WL_SKY);
00118 
00119         return mDrawable;
00120 }
00121 
00122 inline F32 LLVOWLSky::calcPhi(U32 i)
00123 {
00124         // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f]
00125         F32 t = float(i) / float(getNumStacks());
00126 
00127         // ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex)
00128         t = t*t*t*t;
00129         
00130         // invert and square the parameter of the tesselation to bias things toward 1 (the horizon)
00131         t = 1.f - t;
00132         t = t*t;
00133         t = 1.f - t;
00134 
00135         return (F_PI / 8.f) * t;
00136 }
00137 
00138 #if !DOME_SLICES
00139 static const F32 Q = (1.f + sqrtf(5.f))/2.f; //golden ratio
00140 
00141 //icosahedron verts (based on asset b0c7b76e-28c6-1f87-a1de-752d5e3cd264, contact Runitai Linden for a copy)
00142 static const LLVector3 icosahedron_vert[] =
00143 {
00144         LLVector3(0,1.f,Q),
00145         LLVector3(0,-1.f,Q),
00146         LLVector3(0,-1.f,-Q),
00147         LLVector3(0,1.f,-Q),
00148 
00149         LLVector3(Q,0,1.f),
00150         LLVector3(-Q,0,1.f),
00151         LLVector3(-Q,0,-1.f),
00152         LLVector3(Q,0,-1.f),
00153 
00154         LLVector3(1,-Q,0.f),
00155         LLVector3(-1,-Q,0.f),
00156         LLVector3(-1,Q,0.f),
00157         LLVector3(1,Q,0.f),
00158 };
00159 
00160 //indices
00161 static const U32 icosahedron_ind[] = 
00162 {
00163         5,0,1,
00164         10,0,5,
00165         5,1,9,
00166         10,5,6,
00167         6,5,9,
00168         11,0,10,
00169         3,11,10,
00170         3,10,6,
00171         3,6,2,
00172         7,3,2,
00173         8,7,2,
00174         4,7,8,
00175         1,4,8,
00176         9,8,2,
00177         9,2,6,
00178         11,3,7,
00179         4,0,11,
00180         4,11,7,
00181         1,0,4,
00182         1,8,9,
00183 };
00184 
00185 
00186 //split every triangle in LLVertexBuffer into even fourths (assumes index triangle lists)
00187 void subdivide(LLVertexBuffer& in, LLVertexBuffer* ret)
00188 {
00189         S32 tri_in = in.getNumIndices()/3;
00190 
00191         ret->allocateBuffer(tri_in*4*3, tri_in*4*3, TRUE);
00192 
00193         LLStrider<LLVector3> vin, vout;
00194         LLStrider<U16> indin, indout;
00195 
00196         ret->getVertexStrider(vout);
00197         in.getVertexStrider(vin);
00198 
00199         ret->getIndexStrider(indout);
00200         in.getIndexStrider(indin);
00201         
00202         
00203         for (S32 i = 0; i < tri_in; i++)
00204         {
00205                 LLVector3 v0 = vin[*indin++];
00206                 LLVector3 v1 = vin[*indin++];
00207                 LLVector3 v2 = vin[*indin++];
00208 
00209                 LLVector3 v3 = (v0 + v1) * 0.5f;
00210                 LLVector3 v4 = (v1 + v2) * 0.5f;
00211                 LLVector3 v5 = (v2 + v0) * 0.5f;
00212 
00213                 *vout++ = v0;
00214                 *vout++ = v3;
00215                 *vout++ = v5;
00216 
00217                 *vout++ = v3;
00218                 *vout++ = v4;
00219                 *vout++ = v5;
00220 
00221                 *vout++ = v3;
00222                 *vout++ = v1;
00223                 *vout++ = v4;
00224 
00225                 *vout++ = v5;
00226                 *vout++ = v4;
00227                 *vout++ = v2;
00228         }
00229         
00230         for (S32 i = 0; i < ret->getNumIndices(); i++)
00231         {
00232                 *indout++ = i;
00233         }
00234 
00235 }
00236 
00237 void chop(LLVertexBuffer& in, LLVertexBuffer* out)
00238 {
00239         //chop off all triangles below horizon 
00240         F32 d = LLWLParamManager::sParamMgr->getDomeOffset() * LLWLParamManager::sParamMgr->getDomeRadius();
00241         
00242         std::vector<LLVector3> vert;
00243         
00244         LLStrider<LLVector3> vin;
00245         LLStrider<U16> index;
00246 
00247         in.getVertexStrider(vin);
00248         in.getIndexStrider(index);
00249 
00250         U32 tri_count = in.getNumIndices()/3;
00251         for (U32 i = 0; i < tri_count; i++)
00252         {
00253                 LLVector3 &v1 = vin[index[i*3+0]];
00254                 LLVector3 &v2 = vin[index[i*3+1]];
00255                 LLVector3 &v3 = vin[index[i*3+2]];
00256 
00257                 if (v1.mV[1] > d ||
00258                         v2.mV[1] > d ||
00259                         v3.mV[1] > d)
00260                 {
00261                         v1.mV[1] = llmax(v1.mV[1], d);
00262                         v2.mV[1] = llmax(v1.mV[1], d);
00263                         v3.mV[1] = llmax(v1.mV[1], d);
00264 
00265                         vert.push_back(v1);
00266                         vert.push_back(v2);
00267                         vert.push_back(v3);
00268                 }
00269         }
00270 
00271         out->allocateBuffer(vert.size(), vert.size(), TRUE);
00272 
00273         LLStrider<LLVector3> vout;
00274         out->getVertexStrider(vout);
00275         out->getIndexStrider(index);
00276 
00277         for (U32 i = 0; i < vert.size(); i++)
00278         {
00279                 *vout++ = vert[i];
00280                 *index++ = i;
00281         }       
00282 }
00283 #endif // !DOME_SLICES
00284 
00285 void LLVOWLSky::resetVertexBuffers()
00286 {
00287         mFanVerts = NULL;
00288         mStripsVerts.clear();
00289         mStarsVerts = NULL;
00290 
00291         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00292 }
00293         
00294 void LLVOWLSky::cleanupGL()
00295 {
00296         mFanVerts = NULL;
00297         mStripsVerts.clear();
00298         mStarsVerts = NULL;
00299 
00300         LLDrawPoolWLSky::cleanupGL();
00301 }
00302 
00303 void LLVOWLSky::restoreGL()
00304 {
00305         LLDrawPoolWLSky::restoreGL();
00306         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00307 }
00308 
00309 BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
00310 {
00311         LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY);
00312         LLStrider<LLVector3>    vertices;
00313         LLStrider<LLVector2>    texCoords;
00314         LLStrider<U16>                  indices;
00315 
00316 #if DOME_SLICES
00317         {
00318                 mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
00319                 mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE);
00320 
00321                 BOOL success = mFanVerts->getVertexStrider(vertices)
00322                         && mFanVerts->getTexCoordStrider(texCoords)
00323                         && mFanVerts->getIndexStrider(indices);
00324 
00325                 if(!success) 
00326                 {
00327                         llerrs << "Failed updating WindLight sky geometry." << llendl;
00328                 }
00329 
00330                 buildFanBuffer(vertices, texCoords, indices);
00331 
00332                 mFanVerts->setBuffer(0);
00333         }
00334 
00335         {
00336                 const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024;
00337                 const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
00338                 const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcStride(data_mask);
00339 
00340                 const U32 total_stacks = getNumStacks();
00341 
00342                 const U32 verts_per_stack = getNumSlices();
00343 
00344                 // each seg has to have one more row of verts than it has stacks
00345                 // then round down
00346                 const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack;
00347 
00348                 // round up to a whole number of segments
00349                 const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg;
00350 
00351                 llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl;
00352 
00353                 mStripsVerts.resize(strips_segments, NULL);
00354 
00355                 for (U32 i = 0; i < strips_segments ;++i)
00356                 {
00357                         LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
00358                         mStripsVerts[i] = segment;
00359 
00360                         U32 num_stacks_this_seg = stacks_per_seg;
00361                         if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0)
00362                         {
00363                                 // for the last buffer only allocate what we'll use
00364                                 num_stacks_this_seg = total_stacks % stacks_per_seg;
00365                         }
00366 
00367                         // figure out what range of the sky we're filling
00368                         const U32 begin_stack = i * stacks_per_seg;
00369                         const U32 end_stack = begin_stack + num_stacks_this_seg;
00370                         llassert(end_stack <= total_stacks);
00371 
00372                         const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1);
00373                         llassert(num_verts_this_seg <= max_verts);
00374 
00375                         const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack);
00376                         llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes);
00377 
00378                         segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE);
00379 
00380                         // lock the buffer
00381                         BOOL success = segment->getVertexStrider(vertices)
00382                                 && segment->getTexCoordStrider(texCoords)
00383                                 && segment->getIndexStrider(indices);
00384 
00385                         if(!success) 
00386                         {
00387                                 llerrs << "Failed updating WindLight sky geometry." << llendl;
00388                         }
00389 
00390                         // fill it
00391                         buildStripsBuffer(begin_stack, end_stack,  vertices, texCoords, indices);
00392 
00393                         // and unlock the buffer
00394                         segment->setBuffer(0);
00395                 }
00396         }
00397 #else
00398         mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
00399         
00400         const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius();
00401 
00402         LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
00403         temp->allocateBuffer(12, 60, TRUE);
00404 
00405         BOOL success = temp->getVertexStrider(vertices)
00406                 && temp->getIndexStrider(indices);
00407 
00408         if (success)
00409         {
00410                 for (U32 i = 0; i < 12; i++)
00411                 {
00412                         *vertices++ = icosahedron_vert[i];
00413                 }
00414 
00415                 for (U32 i = 0; i < 60; i++)
00416                 {
00417                         *indices++ = icosahedron_ind[i];
00418                 }
00419         }
00420 
00421 
00422         LLPointer<LLVertexBuffer> temp2;
00423         
00424         for (U32 i = 0; i < 8; i++)
00425         {
00426                 temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
00427                 subdivide(*temp, temp2);
00428                 temp = temp2;
00429         }
00430         
00431         temp->getVertexStrider(vertices);
00432         for (S32 i = 0; i < temp->getNumVerts(); i++)
00433         {
00434                 LLVector3 v = vertices[i];
00435                 v.normVec();
00436                 vertices[i] = v*RADIUS;
00437         }
00438 
00439         temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
00440         chop(*temp, temp2);
00441 
00442         mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE);
00443         
00444         success = mStripsVerts->getVertexStrider(vertices)
00445                 && mStripsVerts->getTexCoordStrider(texCoords)
00446                 && mStripsVerts->getIndexStrider(indices);
00447 
00448         LLStrider<LLVector3> v;
00449         temp2->getVertexStrider(v);
00450         LLStrider<U16> ind;
00451         temp2->getIndexStrider(ind);
00452 
00453         if (success)
00454         {
00455                 for (S32 i = 0; i < temp2->getNumVerts(); ++i)
00456                 {
00457                         LLVector3 vert = *v++;
00458                         vert.normVec();
00459                         F32 z0 = vert.mV[2];
00460                         F32 x0 = vert.mV[0];
00461                         
00462                         vert *= RADIUS;
00463                         
00464                         *vertices++ = vert;
00465                         *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
00466                 }
00467 
00468                 for (S32 i = 0; i < temp2->getNumIndices(); ++i)
00469                 {
00470                         *indices++ = *ind++;
00471                 }
00472         }
00473 
00474         mStripsVerts->setBuffer(0);
00475 #endif
00476 
00477         updateStarColors();
00478         updateStarGeometry(drawable);
00479 
00480         LLPipeline::sCompiles++;
00481 
00482         return TRUE;
00483 }
00484 
00485 void LLVOWLSky::drawStars(void)
00486 {
00487         //  render the stars as a sphere centered at viewer camera 
00488         if (mStarsVerts.notNull())
00489         {
00490                 mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK);
00491                 mStarsVerts->draw(LLVertexBuffer::POINTS, getStarsNumIndices(), 0);
00492         }
00493 }
00494 
00495 void LLVOWLSky::drawDome(void)
00496 {
00497         if (mStripsVerts.empty())
00498         {
00499                 updateGeometry(mDrawable);
00500         }
00501 
00502         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
00503 
00504         const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
00505         
00506 #if DOME_SLICES
00507         std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips;
00508         end_strips = mStripsVerts.end();
00509         for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter)
00510         {
00511                 LLVertexBuffer * strips_segment = strips_vbo_iter->get();
00512 
00513                 strips_segment->setBuffer(data_mask);
00514 
00515                 strips_segment->drawRange(
00516                         LLVertexBuffer::TRIANGLE_STRIP, 
00517                         0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), 
00518                         0);
00519                 gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2);
00520         }
00521 
00522 #else
00523         mStripsVerts->setBuffer(data_mask);
00524         glDrawRangeElements(
00525                 GL_TRIANGLES,
00526                 0, mStripsVerts->getNumVerts()-1, mStripsVerts->getNumIndices(),
00527                 GL_UNSIGNED_SHORT,
00528                 mStripsVerts->getIndicesPointer());
00529 #endif
00530 
00531         LLVertexBuffer::unbind();
00532 }
00533 
00534 void LLVOWLSky::initStars()
00535 {
00536         // Initialize star map
00537         mStarVertices.resize(getStarsNumVerts());
00538         mStarColors.resize(getStarsNumVerts());
00539         mStarIntensities.resize(getStarsNumVerts());
00540 
00541         std::vector<LLVector3>::iterator v_p = mStarVertices.begin();
00542         std::vector<LLColor4>::iterator v_c = mStarColors.begin();
00543         std::vector<F32>::iterator v_i = mStarIntensities.begin();
00544 
00545         U32 i;
00546         for (i = 0; i < getStarsNumVerts(); ++i)
00547         {
00548                 v_p->mV[VX] = ll_frand() - 0.5f;
00549                 v_p->mV[VY] = ll_frand() - 0.5f;
00550                 
00551                 // we only want stars on the top half of the dome!
00552 
00553                 v_p->mV[VZ] = ll_frand()/2.f;
00554 
00555                 v_p->normVec();
00556                 *v_p *= DISTANCE_TO_STARS;
00557                 *v_i = llmin((F32)pow(ll_frand(),2.f) + 0.1f, 1.f);
00558                 v_c->mV[VRED]   = 0.75f + ll_frand() * 0.25f ;
00559                 v_c->mV[VGREEN] = 1.f ;
00560                 v_c->mV[VBLUE]  = 0.75f + ll_frand() * 0.25f ;
00561                 v_c->mV[VALPHA] = 1.f;
00562                 v_c->clamp();
00563                 v_p++;
00564                 v_c++;
00565                 v_i++;
00566         }
00567 }
00568 
00569 void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices,
00570                                                            LLStrider<LLVector2> & texCoords,
00571                                                            LLStrider<U16> & indices)
00572 {
00573         const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius();
00574 
00575         U32 i, num_slices;
00576         F32 phi0, theta, x0, y0, z0;
00577 
00578         // paranoia checking for SL-55986/SL-55833
00579         U32 count_verts = 0;
00580         U32 count_indices = 0;
00581 
00582         // apex
00583         *vertices++             = LLVector3(0.f, RADIUS, 0.f);
00584         *texCoords++    = LLVector2(0.5f, 0.5f);
00585         ++count_verts;
00586 
00587         num_slices = getNumSlices();
00588 
00589         // and fan in a circle around the apex
00590         phi0 = calcPhi(1);
00591         for(i = 0; i < num_slices; ++i) {
00592                 theta = 2.f * F_PI * float(i) / float(num_slices);
00593 
00594                 // standard transformation from  spherical to
00595                 // rectangular coordinates
00596                 x0 = sin(phi0) * cos(theta);
00597                 y0 = cos(phi0);
00598                 z0 = sin(phi0) * sin(theta);
00599 
00600                 *vertices++             = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS);
00601                 // generate planar uv coordinates
00602                 // note: x and z are transposed in order for things to animate
00603                 // correctly in the global coordinate system where +x is east and
00604                 // +y is north
00605                 *texCoords++    = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
00606                 ++count_verts;
00607 
00608                 if (i > 0)
00609                 {
00610                         *indices++ = 0;
00611                         *indices++ = i;
00612                         *indices++ = i+1;
00613                         count_indices += 3;
00614                 }
00615         }
00616 
00617         // the last vertex of the last triangle should wrap around to 
00618         // the beginning
00619         *indices++ = 0;
00620         *indices++ = num_slices;
00621         *indices++ = 1;
00622         count_indices += 3;
00623 
00624         // paranoia checking for SL-55986/SL-55833
00625         llassert(getFanNumVerts() == count_verts);
00626         llassert(getFanNumIndices() == count_indices);
00627 }
00628 
00629 void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
00630                                                                   LLStrider<LLVector3> & vertices,
00631                                                                   LLStrider<LLVector2> & texCoords,
00632                                                                   LLStrider<U16> & indices)
00633 {
00634         const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius();
00635 
00636         U32 i, j, num_slices, num_stacks;
00637         F32 phi0, theta, x0, y0, z0;
00638 
00639         // paranoia checking for SL-55986/SL-55833
00640         U32 count_verts = 0;
00641         U32 count_indices = 0;
00642 
00643         num_slices = getNumSlices();
00644         num_stacks = getNumStacks();
00645 
00646         llassert(end_stack <= num_stacks);
00647 
00648         // stacks are iterated one-indexed since phi(0) was handled by the fan above
00649         for(i = begin_stack + 1; i <= end_stack+1; ++i) 
00650         {
00651                 phi0 = calcPhi(i);
00652 
00653                 for(j = 0; j < num_slices; ++j)
00654                 {
00655                         theta = F_TWO_PI * (float(j) / float(num_slices));
00656 
00657                         // standard transformation from  spherical to
00658                         // rectangular coordinates
00659                         x0 = sin(phi0) * cos(theta);
00660                         y0 = cos(phi0);
00661                         z0 = sin(phi0) * sin(theta);
00662 
00663                         if (i == num_stacks-2)
00664                         {
00665                                 *vertices++ = LLVector3(x0*RADIUS, y0*RADIUS-1024.f*2.f, z0*RADIUS);
00666                         }
00667                         else if (i == num_stacks-1)
00668                         {
00669                                 *vertices++ = LLVector3(0, y0*RADIUS-1024.f*2.f, 0);
00670                         }
00671                         else
00672                         {
00673                                 *vertices++             = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS);
00674                         }
00675                         ++count_verts;
00676 
00677                         // generate planar uv coordinates
00678                         // note: x and z are transposed in order for things to animate
00679                         // correctly in the global coordinate system where +x is east and
00680                         // +y is north
00681                         *texCoords++    = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
00682                 }
00683         }
00684 
00685         //build triangle strip...
00686         *indices++ = 0 ;
00687         count_indices++ ;
00688         S32 k = 0 ;
00689         for(i = 1; i <= end_stack - begin_stack; ++i) 
00690         {
00691                 *indices++ = i * num_slices + k ;
00692                 count_indices++ ;
00693 
00694                 k = (k+1) % num_slices ;
00695                 for(j = 0; j < num_slices ; ++j) 
00696                 {
00697                         *indices++ = (i-1) * num_slices + k ;
00698                         *indices++ = i * num_slices + k ;
00699 
00700                         count_indices += 2 ;
00701 
00702                         k = (k+1) % num_slices ;
00703                 }
00704 
00705                 if((--k) < 0)
00706                 {
00707                         k = num_slices - 1 ;
00708                 }
00709 
00710                 *indices++ = i * num_slices + k ;
00711                 count_indices++ ;
00712         }
00713 }
00714 
00715 void LLVOWLSky::updateStarColors()
00716 {
00717         std::vector<LLColor4>::iterator v_c = mStarColors.begin();
00718         std::vector<F32>::iterator v_i = mStarIntensities.begin();
00719         std::vector<LLVector3>::iterator v_p = mStarVertices.begin();
00720 
00721         const F32 var = 0.15f;
00722         const F32 min = 0.5f; //0.75f;
00723         const F32 sunclose_max = 0.6f;
00724         const F32 sunclose_range = 1 - sunclose_max;
00725 
00726         //F32 below_horizon = - llmin(0.0f, gSky.mVOSkyp->getToSunLast().mV[2]);
00727         //F32 brightness_factor = llmin(1.0f, below_horizon * 20);
00728 
00729         static S32 swap = 0;
00730         swap++;
00731 
00732         if ((swap % 2) == 1)
00733         {
00734                 F32 intensity;                                          //  max intensity of each star
00735                 U32 x;
00736                 for (x = 0; x < getStarsNumVerts(); ++x)
00737                 {
00738                         F32 sundir_factor = 1;
00739                         LLVector3 tostar = *v_p;
00740                         tostar.normVec();
00741                         const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast();
00742                         if (how_close_to_sun > sunclose_max)
00743                         {
00744                                 sundir_factor = (1 - how_close_to_sun) / sunclose_range;
00745                         }
00746                         intensity = *(v_i);
00747                         F32 alpha = v_c->mV[VALPHA] + (ll_frand() - 0.5f) * var * intensity;
00748                         if (alpha < min * intensity)
00749                         {
00750                                 alpha = min * intensity;
00751                         }
00752                         if (alpha > intensity)
00753                         {
00754                                 alpha = intensity;
00755                         }
00756                         //alpha *= brightness_factor * sundir_factor;
00757 
00758                         alpha = llclamp(alpha, 0.f, 1.f);
00759                         v_c->mV[VALPHA] = alpha;
00760                         v_c++;
00761                         v_i++;
00762                         v_p++;
00763                 }
00764         }
00765 }
00766 
00767 BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
00768 {
00769         LLStrider<LLVector3> verticesp;
00770         LLStrider<LLColor4U> colorsp;
00771         LLStrider<U16> indicesp;
00772 
00773         if (mStarsVerts.isNull())
00774         {
00775                 mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW);
00776                 mStarsVerts->allocateBuffer(getStarsNumVerts(), getStarsNumIndices(), TRUE);
00777         }
00778 
00779         BOOL success = mStarsVerts->getVertexStrider(verticesp)
00780                 && mStarsVerts->getIndexStrider(indicesp)
00781                 && mStarsVerts->getColorStrider(colorsp);
00782 
00783         if(!success)
00784         {
00785                 llerrs << "Failed updating star geometry." << llendl;
00786         }
00787 
00788         // *TODO: fix LLStrider with a real prefix increment operator so it can be
00789         // used as a model of OutputIterator. -Brad
00790         // std::copy(mStarVertices.begin(), mStarVertices.end(), verticesp);
00791         for (U32 vtx = 0; vtx < getStarsNumVerts(); ++vtx)
00792         {
00793                 *(verticesp++)  = mStarVertices[vtx];
00794                 *(colorsp++)    = LLColor4U(mStarColors[vtx]);
00795                 *(indicesp++)   = vtx;
00796         }
00797 
00798         mStarsVerts->setBuffer(0);
00799         return TRUE;
00800 }

Generated on Fri May 16 08:34:24 2008 for SecondLife by  doxygen 1.5.5