Annotation of /trunk/indra/newview/llvowlsky.cpp
Parent Directory
|
Revision Log
Revision 137 - (view) (download)
| 1 : | mjm | 135 | /** |
| 2 : | * @file llvowlsky.cpp | ||
| 3 : | * @brief LLVOWLSky class implementation | ||
| 4 : | * | ||
| 5 : | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
| 6 : | * | ||
| 7 : | mjm | 137 | * Copyright (c) 2007-2010, Linden Research, Inc. |
| 8 : | mjm | 135 | * |
| 9 : | * Second Life Viewer Source Code | ||
| 10 : | * The source code in this file ("Source Code") is provided by Linden Lab | ||
| 11 : | * to you under the terms of the GNU General Public License, version 2.0 | ||
| 12 : | * ("GPL"), unless you have obtained a separate licensing agreement | ||
| 13 : | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
| 14 : | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
| 15 : | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
| 16 : | * | ||
| 17 : | * There are special exceptions to the terms and conditions of the GPL as | ||
| 18 : | * it is applied to this Source Code. View the full text of the exception | ||
| 19 : | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
| 20 : | * online at | ||
| 21 : | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
| 22 : | * | ||
| 23 : | * By copying, modifying or distributing this software, you acknowledge | ||
| 24 : | * that you have read and understood your obligations described above, | ||
| 25 : | * and agree to abide by those obligations. | ||
| 26 : | * | ||
| 27 : | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
| 28 : | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
| 29 : | * COMPLETENESS OR PERFORMANCE. | ||
| 30 : | * $/LicenseInfo$ | ||
| 31 : | */ | ||
| 32 : | |||
| 33 : | #include "llviewerprecompiledheaders.h" | ||
| 34 : | |||
| 35 : | #include "pipeline.h" | ||
| 36 : | |||
| 37 : | #include "llvowlsky.h" | ||
| 38 : | #include "llsky.h" | ||
| 39 : | #include "lldrawpoolwlsky.h" | ||
| 40 : | #include "llface.h" | ||
| 41 : | #include "llwlparammanager.h" | ||
| 42 : | #include "llviewercontrol.h" | ||
| 43 : | |||
| 44 : | #define DOME_SLICES 1 | ||
| 45 : | const F32 LLVOWLSky::DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f; | ||
| 46 : | |||
| 47 : | const U32 LLVOWLSky::MIN_SKY_DETAIL = 3; | ||
| 48 : | const U32 LLVOWLSky::MAX_SKY_DETAIL = 180; | ||
| 49 : | |||
| 50 : | inline U32 LLVOWLSky::getNumStacks(void) | ||
| 51 : | { | ||
| 52 : | return gSavedSettings.getU32("WLSkyDetail"); | ||
| 53 : | } | ||
| 54 : | |||
| 55 : | inline U32 LLVOWLSky::getNumSlices(void) | ||
| 56 : | { | ||
| 57 : | return 2 * gSavedSettings.getU32("WLSkyDetail"); | ||
| 58 : | } | ||
| 59 : | |||
| 60 : | inline U32 LLVOWLSky::getFanNumVerts(void) | ||
| 61 : | { | ||
| 62 : | return getNumSlices() + 1; | ||
| 63 : | } | ||
| 64 : | |||
| 65 : | inline U32 LLVOWLSky::getFanNumIndices(void) | ||
| 66 : | { | ||
| 67 : | return getNumSlices() * 3; | ||
| 68 : | } | ||
| 69 : | |||
| 70 : | inline U32 LLVOWLSky::getStripsNumVerts(void) | ||
| 71 : | { | ||
| 72 : | return (getNumStacks() - 1) * getNumSlices(); | ||
| 73 : | } | ||
| 74 : | |||
| 75 : | inline U32 LLVOWLSky::getStripsNumIndices(void) | ||
| 76 : | { | ||
| 77 : | return 2 * ((getNumStacks() - 2) * (getNumSlices() + 1)) + 1 ; | ||
| 78 : | } | ||
| 79 : | |||
| 80 : | inline U32 LLVOWLSky::getStarsNumVerts(void) | ||
| 81 : | { | ||
| 82 : | return 1000; | ||
| 83 : | } | ||
| 84 : | |||
| 85 : | inline U32 LLVOWLSky::getStarsNumIndices(void) | ||
| 86 : | { | ||
| 87 : | return 1000; | ||
| 88 : | } | ||
| 89 : | |||
| 90 : | LLVOWLSky::LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) | ||
| 91 : | : LLStaticViewerObject(id, pcode, regionp, TRUE) | ||
| 92 : | { | ||
| 93 : | initStars(); | ||
| 94 : | } | ||
| 95 : | |||
| 96 : | void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction, | ||
| 97 : | LLVector3 const & sun_angular_velocity) | ||
| 98 : | { | ||
| 99 : | } | ||
| 100 : | |||
| 101 : | BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | ||
| 102 : | { | ||
| 103 : | return TRUE; | ||
| 104 : | } | ||
| 105 : | |||
| 106 : | BOOL LLVOWLSky::isActive(void) const | ||
| 107 : | { | ||
| 108 : | return FALSE; | ||
| 109 : | } | ||
| 110 : | |||
| 111 : | LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline) | ||
| 112 : | { | ||
| 113 : | pipeline->allocDrawable(this); | ||
| 114 : | |||
| 115 : | //LLDrawPoolWLSky *poolp = static_cast<LLDrawPoolWLSky *>( | ||
| 116 : | gPipeline.getPool(LLDrawPool::POOL_WL_SKY); | ||
| 117 : | |||
| 118 : | mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WL_SKY); | ||
| 119 : | |||
| 120 : | return mDrawable; | ||
| 121 : | } | ||
| 122 : | |||
| 123 : | inline F32 LLVOWLSky::calcPhi(U32 i) | ||
| 124 : | { | ||
| 125 : | // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f] | ||
| 126 : | F32 t = float(i) / float(getNumStacks()); | ||
| 127 : | |||
| 128 : | // ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex) | ||
| 129 : | t = t*t*t*t; | ||
| 130 : | |||
| 131 : | // invert and square the parameter of the tesselation to bias things toward 1 (the horizon) | ||
| 132 : | t = 1.f - t; | ||
| 133 : | t = t*t; | ||
| 134 : | t = 1.f - t; | ||
| 135 : | |||
| 136 : | return (F_PI / 8.f) * t; | ||
| 137 : | } | ||
| 138 : | |||
| 139 : | #if !DOME_SLICES | ||
| 140 : | static const F32 Q = (1.f + sqrtf(5.f))/2.f; //golden ratio | ||
| 141 : | |||
| 142 : | //icosahedron verts (based on asset b0c7b76e-28c6-1f87-a1de-752d5e3cd264, contact Runitai Linden for a copy) | ||
| 143 : | static const LLVector3 icosahedron_vert[] = | ||
| 144 : | { | ||
| 145 : | LLVector3(0,1.f,Q), | ||
| 146 : | LLVector3(0,-1.f,Q), | ||
| 147 : | LLVector3(0,-1.f,-Q), | ||
| 148 : | LLVector3(0,1.f,-Q), | ||
| 149 : | |||
| 150 : | LLVector3(Q,0,1.f), | ||
| 151 : | LLVector3(-Q,0,1.f), | ||
| 152 : | LLVector3(-Q,0,-1.f), | ||
| 153 : | LLVector3(Q,0,-1.f), | ||
| 154 : | |||
| 155 : | LLVector3(1,-Q,0.f), | ||
| 156 : | LLVector3(-1,-Q,0.f), | ||
| 157 : | LLVector3(-1,Q,0.f), | ||
| 158 : | LLVector3(1,Q,0.f), | ||
| 159 : | }; | ||
| 160 : | |||
| 161 : | //indices | ||
| 162 : | static const U32 icosahedron_ind[] = | ||
| 163 : | { | ||
| 164 : | 5,0,1, | ||
| 165 : | 10,0,5, | ||
| 166 : | 5,1,9, | ||
| 167 : | 10,5,6, | ||
| 168 : | 6,5,9, | ||
| 169 : | 11,0,10, | ||
| 170 : | 3,11,10, | ||
| 171 : | 3,10,6, | ||
| 172 : | 3,6,2, | ||
| 173 : | 7,3,2, | ||
| 174 : | 8,7,2, | ||
| 175 : | 4,7,8, | ||
| 176 : | 1,4,8, | ||
| 177 : | 9,8,2, | ||
| 178 : | 9,2,6, | ||
| 179 : | 11,3,7, | ||
| 180 : | 4,0,11, | ||
| 181 : | 4,11,7, | ||
| 182 : | 1,0,4, | ||
| 183 : | 1,8,9, | ||
| 184 : | }; | ||
| 185 : | |||
| 186 : | |||
| 187 : | //split every triangle in LLVertexBuffer into even fourths (assumes index triangle lists) | ||
| 188 : | void subdivide(LLVertexBuffer& in, LLVertexBuffer* ret) | ||
| 189 : | { | ||
| 190 : | S32 tri_in = in.getNumIndices()/3; | ||
| 191 : | |||
| 192 : | ret->allocateBuffer(tri_in*4*3, tri_in*4*3, TRUE); | ||
| 193 : | |||
| 194 : | LLStrider<LLVector3> vin, vout; | ||
| 195 : | LLStrider<U16> indin, indout; | ||
| 196 : | |||
| 197 : | ret->getVertexStrider(vout); | ||
| 198 : | in.getVertexStrider(vin); | ||
| 199 : | |||
| 200 : | ret->getIndexStrider(indout); | ||
| 201 : | in.getIndexStrider(indin); | ||
| 202 : | |||
| 203 : | |||
| 204 : | for (S32 i = 0; i < tri_in; i++) | ||
| 205 : | { | ||
| 206 : | LLVector3 v0 = vin[*indin++]; | ||
| 207 : | LLVector3 v1 = vin[*indin++]; | ||
| 208 : | LLVector3 v2 = vin[*indin++]; | ||
| 209 : | |||
| 210 : | LLVector3 v3 = (v0 + v1) * 0.5f; | ||
| 211 : | LLVector3 v4 = (v1 + v2) * 0.5f; | ||
| 212 : | LLVector3 v5 = (v2 + v0) * 0.5f; | ||
| 213 : | |||
| 214 : | *vout++ = v0; | ||
| 215 : | *vout++ = v3; | ||
| 216 : | *vout++ = v5; | ||
| 217 : | |||
| 218 : | *vout++ = v3; | ||
| 219 : | *vout++ = v4; | ||
| 220 : | *vout++ = v5; | ||
| 221 : | |||
| 222 : | *vout++ = v3; | ||
| 223 : | *vout++ = v1; | ||
| 224 : | *vout++ = v4; | ||
| 225 : | |||
| 226 : | *vout++ = v5; | ||
| 227 : | *vout++ = v4; | ||
| 228 : | *vout++ = v2; | ||
| 229 : | } | ||
| 230 : | |||
| 231 : | for (S32 i = 0; i < ret->getNumIndices(); i++) | ||
| 232 : | { | ||
| 233 : | *indout++ = i; | ||
| 234 : | } | ||
| 235 : | |||
| 236 : | } | ||
| 237 : | |||
| 238 : | void chop(LLVertexBuffer& in, LLVertexBuffer* out) | ||
| 239 : | { | ||
| 240 : | //chop off all triangles below horizon | ||
| 241 : | F32 d = LLWLParamManager::sParamMgr->getDomeOffset() * LLWLParamManager::sParamMgr->getDomeRadius(); | ||
| 242 : | |||
| 243 : | std::vector<LLVector3> vert; | ||
| 244 : | |||
| 245 : | LLStrider<LLVector3> vin; | ||
| 246 : | LLStrider<U16> index; | ||
| 247 : | |||
| 248 : | in.getVertexStrider(vin); | ||
| 249 : | in.getIndexStrider(index); | ||
| 250 : | |||
| 251 : | U32 tri_count = in.getNumIndices()/3; | ||
| 252 : | for (U32 i = 0; i < tri_count; i++) | ||
| 253 : | { | ||
| 254 : | LLVector3 &v1 = vin[index[i*3+0]]; | ||
| 255 : | LLVector3 &v2 = vin[index[i*3+1]]; | ||
| 256 : | LLVector3 &v3 = vin[index[i*3+2]]; | ||
| 257 : | |||
| 258 : | if (v1.mV[1] > d || | ||
| 259 : | v2.mV[1] > d || | ||
| 260 : | v3.mV[1] > d) | ||
| 261 : | { | ||
| 262 : | v1.mV[1] = llmax(v1.mV[1], d); | ||
| 263 : | v2.mV[1] = llmax(v1.mV[1], d); | ||
| 264 : | v3.mV[1] = llmax(v1.mV[1], d); | ||
| 265 : | |||
| 266 : | vert.push_back(v1); | ||
| 267 : | vert.push_back(v2); | ||
| 268 : | vert.push_back(v3); | ||
| 269 : | } | ||
| 270 : | } | ||
| 271 : | |||
| 272 : | out->allocateBuffer(vert.size(), vert.size(), TRUE); | ||
| 273 : | |||
| 274 : | LLStrider<LLVector3> vout; | ||
| 275 : | out->getVertexStrider(vout); | ||
| 276 : | out->getIndexStrider(index); | ||
| 277 : | |||
| 278 : | for (U32 i = 0; i < vert.size(); i++) | ||
| 279 : | { | ||
| 280 : | *vout++ = vert[i]; | ||
| 281 : | *index++ = i; | ||
| 282 : | } | ||
| 283 : | } | ||
| 284 : | #endif // !DOME_SLICES | ||
| 285 : | |||
| 286 : | void LLVOWLSky::resetVertexBuffers() | ||
| 287 : | { | ||
| 288 : | mFanVerts = NULL; | ||
| 289 : | mStripsVerts.clear(); | ||
| 290 : | mStarsVerts = NULL; | ||
| 291 : | |||
| 292 : | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); | ||
| 293 : | } | ||
| 294 : | |||
| 295 : | void LLVOWLSky::cleanupGL() | ||
| 296 : | { | ||
| 297 : | mFanVerts = NULL; | ||
| 298 : | mStripsVerts.clear(); | ||
| 299 : | mStarsVerts = NULL; | ||
| 300 : | |||
| 301 : | LLDrawPoolWLSky::cleanupGL(); | ||
| 302 : | } | ||
| 303 : | |||
| 304 : | void LLVOWLSky::restoreGL() | ||
| 305 : | { | ||
| 306 : | LLDrawPoolWLSky::restoreGL(); | ||
| 307 : | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); | ||
| 308 : | } | ||
| 309 : | |||
| 310 : | BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) | ||
| 311 : | { | ||
| 312 : | LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY); | ||
| 313 : | LLStrider<LLVector3> vertices; | ||
| 314 : | LLStrider<LLVector2> texCoords; | ||
| 315 : | LLStrider<U16> indices; | ||
| 316 : | |||
| 317 : | #if DOME_SLICES | ||
| 318 : | { | ||
| 319 : | mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
| 320 : | mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); | ||
| 321 : | |||
| 322 : | BOOL success = mFanVerts->getVertexStrider(vertices) | ||
| 323 : | && mFanVerts->getTexCoord0Strider(texCoords) | ||
| 324 : | && mFanVerts->getIndexStrider(indices); | ||
| 325 : | |||
| 326 : | if(!success) | ||
| 327 : | { | ||
| 328 : | llerrs << "Failed updating WindLight sky geometry." << llendl; | ||
| 329 : | } | ||
| 330 : | |||
| 331 : | buildFanBuffer(vertices, texCoords, indices); | ||
| 332 : | |||
| 333 : | mFanVerts->setBuffer(0); | ||
| 334 : | } | ||
| 335 : | |||
| 336 : | { | ||
| 337 : | const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; | ||
| 338 : | const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; | ||
| 339 : | const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcStride(data_mask); | ||
| 340 : | |||
| 341 : | const U32 total_stacks = getNumStacks(); | ||
| 342 : | |||
| 343 : | const U32 verts_per_stack = getNumSlices(); | ||
| 344 : | |||
| 345 : | // each seg has to have one more row of verts than it has stacks | ||
| 346 : | // then round down | ||
| 347 : | const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack; | ||
| 348 : | |||
| 349 : | // round up to a whole number of segments | ||
| 350 : | const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg; | ||
| 351 : | |||
| 352 : | llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl; | ||
| 353 : | |||
| 354 : | mStripsVerts.resize(strips_segments, NULL); | ||
| 355 : | |||
| 356 : | for (U32 i = 0; i < strips_segments ;++i) | ||
| 357 : | { | ||
| 358 : | LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
| 359 : | mStripsVerts[i] = segment; | ||
| 360 : | |||
| 361 : | U32 num_stacks_this_seg = stacks_per_seg; | ||
| 362 : | if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0) | ||
| 363 : | { | ||
| 364 : | // for the last buffer only allocate what we'll use | ||
| 365 : | num_stacks_this_seg = total_stacks % stacks_per_seg; | ||
| 366 : | } | ||
| 367 : | |||
| 368 : | // figure out what range of the sky we're filling | ||
| 369 : | const U32 begin_stack = i * stacks_per_seg; | ||
| 370 : | const U32 end_stack = begin_stack + num_stacks_this_seg; | ||
| 371 : | llassert(end_stack <= total_stacks); | ||
| 372 : | |||
| 373 : | const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1); | ||
| 374 : | llassert(num_verts_this_seg <= max_verts); | ||
| 375 : | |||
| 376 : | const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack); | ||
| 377 : | llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes); | ||
| 378 : | |||
| 379 : | segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE); | ||
| 380 : | |||
| 381 : | // lock the buffer | ||
| 382 : | BOOL success = segment->getVertexStrider(vertices) | ||
| 383 : | && segment->getTexCoord0Strider(texCoords) | ||
| 384 : | && segment->getIndexStrider(indices); | ||
| 385 : | |||
| 386 : | if(!success) | ||
| 387 : | { | ||
| 388 : | llerrs << "Failed updating WindLight sky geometry." << llendl; | ||
| 389 : | } | ||
| 390 : | |||
| 391 : | // fill it | ||
| 392 : | buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices); | ||
| 393 : | |||
| 394 : | // and unlock the buffer | ||
| 395 : | segment->setBuffer(0); | ||
| 396 : | } | ||
| 397 : | } | ||
| 398 : | #else | ||
| 399 : | mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
| 400 : | |||
| 401 : | const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius(); | ||
| 402 : | |||
| 403 : | LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
| 404 : | temp->allocateBuffer(12, 60, TRUE); | ||
| 405 : | |||
| 406 : | BOOL success = temp->getVertexStrider(vertices) | ||
| 407 : | && temp->getIndexStrider(indices); | ||
| 408 : | |||
| 409 : | if (success) | ||
| 410 : | { | ||
| 411 : | for (U32 i = 0; i < 12; i++) | ||
| 412 : | { | ||
| 413 : | *vertices++ = icosahedron_vert[i]; | ||
| 414 : | } | ||
| 415 : | |||
| 416 : | for (U32 i = 0; i < 60; i++) | ||
| 417 : | { | ||
| 418 : | *indices++ = icosahedron_ind[i]; | ||
| 419 : | } | ||
| 420 : | } | ||
| 421 : | |||
| 422 : | |||
| 423 : | LLPointer<LLVertexBuffer> temp2; | ||
| 424 : | |||
| 425 : | for (U32 i = 0; i < 8; i++) | ||
| 426 : | { | ||
| 427 : | temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
| 428 : | subdivide(*temp, temp2); | ||
| 429 : | temp = temp2; | ||
| 430 : | } | ||
| 431 : | |||
| 432 : | temp->getVertexStrider(vertices); | ||
| 433 : | for (S32 i = 0; i < temp->getNumVerts(); i++) | ||
| 434 : | { | ||
| 435 : | LLVector3 v = vertices[i]; | ||
| 436 : | v.normVec(); | ||
| 437 : | vertices[i] = v*RADIUS; | ||
| 438 : | } | ||
| 439 : | |||
| 440 : | temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
| 441 : | chop(*temp, temp2); | ||
| 442 : | |||
| 443 : | mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE); | ||
| 444 : | |||
| 445 : | success = mStripsVerts->getVertexStrider(vertices) | ||
| 446 : | && mStripsVerts->getTexCoordStrider(texCoords) | ||
| 447 : | && mStripsVerts->getIndexStrider(indices); | ||
| 448 : | |||
| 449 : | LLStrider<LLVector3> v; | ||
| 450 : | temp2->getVertexStrider(v); | ||
| 451 : | LLStrider<U16> ind; | ||
| 452 : | temp2->getIndexStrider(ind); | ||
| 453 : | |||
| 454 : | if (success) | ||
| 455 : | { | ||
| 456 : | for (S32 i = 0; i < temp2->getNumVerts(); ++i) | ||
| 457 : | { | ||
| 458 : | LLVector3 vert = *v++; | ||
| 459 : | vert.normVec(); | ||
| 460 : | F32 z0 = vert.mV[2]; | ||
| 461 : | F32 x0 = vert.mV[0]; | ||
| 462 : | |||
| 463 : | vert *= RADIUS; | ||
| 464 : | |||
| 465 : | *vertices++ = vert; | ||
| 466 : | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
| 467 : | } | ||
| 468 : | |||
| 469 : | for (S32 i = 0; i < temp2->getNumIndices(); ++i) | ||
| 470 : | { | ||
| 471 : | *indices++ = *ind++; | ||
| 472 : | } | ||
| 473 : | } | ||
| 474 : | |||
| 475 : | mStripsVerts->setBuffer(0); | ||
| 476 : | #endif | ||
| 477 : | |||
| 478 : | updateStarColors(); | ||
| 479 : | updateStarGeometry(drawable); | ||
| 480 : | |||
| 481 : | LLPipeline::sCompiles++; | ||
| 482 : | |||
| 483 : | return TRUE; | ||
| 484 : | } | ||
| 485 : | |||
| 486 : | void LLVOWLSky::drawStars(void) | ||
| 487 : | { | ||
| 488 : | // render the stars as a sphere centered at viewer camera | ||
| 489 : | if (mStarsVerts.notNull()) | ||
| 490 : | { | ||
| 491 : | mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK); | ||
| 492 : | mStarsVerts->draw(LLRender::POINTS, getStarsNumIndices(), 0); | ||
| 493 : | } | ||
| 494 : | } | ||
| 495 : | |||
| 496 : | void LLVOWLSky::drawDome(void) | ||
| 497 : | { | ||
| 498 : | if (mStripsVerts.empty()) | ||
| 499 : | { | ||
| 500 : | updateGeometry(mDrawable); | ||
| 501 : | } | ||
| 502 : | |||
| 503 : | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
| 504 : | |||
| 505 : | const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; | ||
| 506 : | |||
| 507 : | #if DOME_SLICES | ||
| 508 : | std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips; | ||
| 509 : | end_strips = mStripsVerts.end(); | ||
| 510 : | for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter) | ||
| 511 : | { | ||
| 512 : | LLVertexBuffer * strips_segment = strips_vbo_iter->get(); | ||
| 513 : | |||
| 514 : | strips_segment->setBuffer(data_mask); | ||
| 515 : | |||
| 516 : | strips_segment->drawRange( | ||
| 517 : | LLRender::TRIANGLE_STRIP, | ||
| 518 : | 0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), | ||
| 519 : | 0); | ||
| 520 : | gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2); | ||
| 521 : | } | ||
| 522 : | |||
| 523 : | #else | ||
| 524 : | mStripsVerts->setBuffer(data_mask); | ||
| 525 : | glDrawRangeElements( | ||
| 526 : | GL_TRIANGLES, | ||
| 527 : | 0, mStripsVerts->getNumVerts()-1, mStripsVerts->getNumIndices(), | ||
| 528 : | GL_UNSIGNED_SHORT, | ||
| 529 : | mStripsVerts->getIndicesPointer()); | ||
| 530 : | #endif | ||
| 531 : | |||
| 532 : | LLVertexBuffer::unbind(); | ||
| 533 : | } | ||
| 534 : | |||
| 535 : | void LLVOWLSky::initStars() | ||
| 536 : | { | ||
| 537 : | // Initialize star map | ||
| 538 : | mStarVertices.resize(getStarsNumVerts()); | ||
| 539 : | mStarColors.resize(getStarsNumVerts()); | ||
| 540 : | mStarIntensities.resize(getStarsNumVerts()); | ||
| 541 : | |||
| 542 : | std::vector<LLVector3>::iterator v_p = mStarVertices.begin(); | ||
| 543 : | std::vector<LLColor4>::iterator v_c = mStarColors.begin(); | ||
| 544 : | std::vector<F32>::iterator v_i = mStarIntensities.begin(); | ||
| 545 : | |||
| 546 : | U32 i; | ||
| 547 : | for (i = 0; i < getStarsNumVerts(); ++i) | ||
| 548 : | { | ||
| 549 : | v_p->mV[VX] = ll_frand() - 0.5f; | ||
| 550 : | v_p->mV[VY] = ll_frand() - 0.5f; | ||
| 551 : | |||
| 552 : | // we only want stars on the top half of the dome! | ||
| 553 : | |||
| 554 : | v_p->mV[VZ] = ll_frand()/2.f; | ||
| 555 : | |||
| 556 : | v_p->normVec(); | ||
| 557 : | *v_p *= DISTANCE_TO_STARS; | ||
| 558 : | *v_i = llmin((F32)pow(ll_frand(),2.f) + 0.1f, 1.f); | ||
| 559 : | v_c->mV[VRED] = 0.75f + ll_frand() * 0.25f ; | ||
| 560 : | v_c->mV[VGREEN] = 1.f ; | ||
| 561 : | v_c->mV[VBLUE] = 0.75f + ll_frand() * 0.25f ; | ||
| 562 : | v_c->mV[VALPHA] = 1.f; | ||
| 563 : | v_c->clamp(); | ||
| 564 : | v_p++; | ||
| 565 : | v_c++; | ||
| 566 : | v_i++; | ||
| 567 : | } | ||
| 568 : | } | ||
| 569 : | |||
| 570 : | void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices, | ||
| 571 : | LLStrider<LLVector2> & texCoords, | ||
| 572 : | LLStrider<U16> & indices) | ||
| 573 : | { | ||
| 574 : | const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); | ||
| 575 : | |||
| 576 : | U32 i, num_slices; | ||
| 577 : | F32 phi0, theta, x0, y0, z0; | ||
| 578 : | |||
| 579 : | // paranoia checking for SL-55986/SL-55833 | ||
| 580 : | U32 count_verts = 0; | ||
| 581 : | U32 count_indices = 0; | ||
| 582 : | |||
| 583 : | // apex | ||
| 584 : | *vertices++ = LLVector3(0.f, RADIUS, 0.f); | ||
| 585 : | *texCoords++ = LLVector2(0.5f, 0.5f); | ||
| 586 : | ++count_verts; | ||
| 587 : | |||
| 588 : | num_slices = getNumSlices(); | ||
| 589 : | |||
| 590 : | // and fan in a circle around the apex | ||
| 591 : | phi0 = calcPhi(1); | ||
| 592 : | for(i = 0; i < num_slices; ++i) { | ||
| 593 : | theta = 2.f * F_PI * float(i) / float(num_slices); | ||
| 594 : | |||
| 595 : | // standard transformation from spherical to | ||
| 596 : | // rectangular coordinates | ||
| 597 : | x0 = sin(phi0) * cos(theta); | ||
| 598 : | y0 = cos(phi0); | ||
| 599 : | z0 = sin(phi0) * sin(theta); | ||
| 600 : | |||
| 601 : | *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); | ||
| 602 : | // generate planar uv coordinates | ||
| 603 : | // note: x and z are transposed in order for things to animate | ||
| 604 : | // correctly in the global coordinate system where +x is east and | ||
| 605 : | // +y is north | ||
| 606 : | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
| 607 : | ++count_verts; | ||
| 608 : | |||
| 609 : | if (i > 0) | ||
| 610 : | { | ||
| 611 : | *indices++ = 0; | ||
| 612 : | *indices++ = i; | ||
| 613 : | *indices++ = i+1; | ||
| 614 : | count_indices += 3; | ||
| 615 : | } | ||
| 616 : | } | ||
| 617 : | |||
| 618 : | // the last vertex of the last triangle should wrap around to | ||
| 619 : | // the beginning | ||
| 620 : | *indices++ = 0; | ||
| 621 : | *indices++ = num_slices; | ||
| 622 : | *indices++ = 1; | ||
| 623 : | count_indices += 3; | ||
| 624 : | |||
| 625 : | // paranoia checking for SL-55986/SL-55833 | ||
| 626 : | llassert(getFanNumVerts() == count_verts); | ||
| 627 : | llassert(getFanNumIndices() == count_indices); | ||
| 628 : | } | ||
| 629 : | |||
| 630 : | void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack, | ||
| 631 : | LLStrider<LLVector3> & vertices, | ||
| 632 : | LLStrider<LLVector2> & texCoords, | ||
| 633 : | LLStrider<U16> & indices) | ||
| 634 : | { | ||
| 635 : | const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); | ||
| 636 : | |||
| 637 : | U32 i, j, num_slices, num_stacks; | ||
| 638 : | F32 phi0, theta, x0, y0, z0; | ||
| 639 : | |||
| 640 : | // paranoia checking for SL-55986/SL-55833 | ||
| 641 : | U32 count_verts = 0; | ||
| 642 : | U32 count_indices = 0; | ||
| 643 : | |||
| 644 : | num_slices = getNumSlices(); | ||
| 645 : | num_stacks = getNumStacks(); | ||
| 646 : | |||
| 647 : | llassert(end_stack <= num_stacks); | ||
| 648 : | |||
| 649 : | // stacks are iterated one-indexed since phi(0) was handled by the fan above | ||
| 650 : | for(i = begin_stack + 1; i <= end_stack+1; ++i) | ||
| 651 : | { | ||
| 652 : | phi0 = calcPhi(i); | ||
| 653 : | |||
| 654 : | for(j = 0; j < num_slices; ++j) | ||
| 655 : | { | ||
| 656 : | theta = F_TWO_PI * (float(j) / float(num_slices)); | ||
| 657 : | |||
| 658 : | // standard transformation from spherical to | ||
| 659 : | // rectangular coordinates | ||
| 660 : | x0 = sin(phi0) * cos(theta); | ||
| 661 : | y0 = cos(phi0); | ||
| 662 : | z0 = sin(phi0) * sin(theta); | ||
| 663 : | |||
| 664 : | if (i == num_stacks-2) | ||
| 665 : | { | ||
| 666 : | *vertices++ = LLVector3(x0*RADIUS, y0*RADIUS-1024.f*2.f, z0*RADIUS); | ||
| 667 : | } | ||
| 668 : | else if (i == num_stacks-1) | ||
| 669 : | { | ||
| 670 : | *vertices++ = LLVector3(0, y0*RADIUS-1024.f*2.f, 0); | ||
| 671 : | } | ||
| 672 : | else | ||
| 673 : | { | ||
| 674 : | *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); | ||
| 675 : | } | ||
| 676 : | ++count_verts; | ||
| 677 : | |||
| 678 : | // generate planar uv coordinates | ||
| 679 : | // note: x and z are transposed in order for things to animate | ||
| 680 : | // correctly in the global coordinate system where +x is east and | ||
| 681 : | // +y is north | ||
| 682 : | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
| 683 : | } | ||
| 684 : | } | ||
| 685 : | |||
| 686 : | //build triangle strip... | ||
| 687 : | *indices++ = 0 ; | ||
| 688 : | count_indices++ ; | ||
| 689 : | S32 k = 0 ; | ||
| 690 : | for(i = 1; i <= end_stack - begin_stack; ++i) | ||
| 691 : | { | ||
| 692 : | *indices++ = i * num_slices + k ; | ||
| 693 : | count_indices++ ; | ||
| 694 : | |||
| 695 : | k = (k+1) % num_slices ; | ||
| 696 : | for(j = 0; j < num_slices ; ++j) | ||
| 697 : | { | ||
| 698 : | *indices++ = (i-1) * num_slices + k ; | ||
| 699 : | *indices++ = i * num_slices + k ; | ||
| 700 : | |||
| 701 : | count_indices += 2 ; | ||
| 702 : | |||
| 703 : | k = (k+1) % num_slices ; | ||
| 704 : | } | ||
| 705 : | |||
| 706 : | if((--k) < 0) | ||
| 707 : | { | ||
| 708 : | k = num_slices - 1 ; | ||
| 709 : | } | ||
| 710 : | |||
| 711 : | *indices++ = i * num_slices + k ; | ||
| 712 : | count_indices++ ; | ||
| 713 : | } | ||
| 714 : | } | ||
| 715 : | |||
| 716 : | void LLVOWLSky::updateStarColors() | ||
| 717 : | { | ||
| 718 : | std::vector<LLColor4>::iterator v_c = mStarColors.begin(); | ||
| 719 : | std::vector<F32>::iterator v_i = mStarIntensities.begin(); | ||
| 720 : | std::vector<LLVector3>::iterator v_p = mStarVertices.begin(); | ||
| 721 : | |||
| 722 : | const F32 var = 0.15f; | ||
| 723 : | const F32 min = 0.5f; //0.75f; | ||
| 724 : | const F32 sunclose_max = 0.6f; | ||
| 725 : | const F32 sunclose_range = 1 - sunclose_max; | ||
| 726 : | |||
| 727 : | //F32 below_horizon = - llmin(0.0f, gSky.mVOSkyp->getToSunLast().mV[2]); | ||
| 728 : | //F32 brightness_factor = llmin(1.0f, below_horizon * 20); | ||
| 729 : | |||
| 730 : | static S32 swap = 0; | ||
| 731 : | swap++; | ||
| 732 : | |||
| 733 : | if ((swap % 2) == 1) | ||
| 734 : | { | ||
| 735 : | F32 intensity; // max intensity of each star | ||
| 736 : | U32 x; | ||
| 737 : | for (x = 0; x < getStarsNumVerts(); ++x) | ||
| 738 : | { | ||
| 739 : | F32 sundir_factor = 1; | ||
| 740 : | LLVector3 tostar = *v_p; | ||
| 741 : | tostar.normVec(); | ||
| 742 : | const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast(); | ||
| 743 : | if (how_close_to_sun > sunclose_max) | ||
| 744 : | { | ||
| 745 : | sundir_factor = (1 - how_close_to_sun) / sunclose_range; | ||
| 746 : | } | ||
| 747 : | intensity = *(v_i); | ||
| 748 : | F32 alpha = v_c->mV[VALPHA] + (ll_frand() - 0.5f) * var * intensity; | ||
| 749 : | if (alpha < min * intensity) | ||
| 750 : | { | ||
| 751 : | alpha = min * intensity; | ||
| 752 : | } | ||
| 753 : | if (alpha > intensity) | ||
| 754 : | { | ||
| 755 : | alpha = intensity; | ||
| 756 : | } | ||
| 757 : | //alpha *= brightness_factor * sundir_factor; | ||
| 758 : | |||
| 759 : | alpha = llclamp(alpha, 0.f, 1.f); | ||
| 760 : | v_c->mV[VALPHA] = alpha; | ||
| 761 : | v_c++; | ||
| 762 : | v_i++; | ||
| 763 : | v_p++; | ||
| 764 : | } | ||
| 765 : | } | ||
| 766 : | } | ||
| 767 : | |||
| 768 : | BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) | ||
| 769 : | { | ||
| 770 : | LLStrider<LLVector3> verticesp; | ||
| 771 : | LLStrider<LLColor4U> colorsp; | ||
| 772 : | LLStrider<U16> indicesp; | ||
| 773 : | |||
| 774 : | if (mStarsVerts.isNull()) | ||
| 775 : | { | ||
| 776 : | mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW); | ||
| 777 : | mStarsVerts->allocateBuffer(getStarsNumVerts(), getStarsNumIndices(), TRUE); | ||
| 778 : | } | ||
| 779 : | |||
| 780 : | BOOL success = mStarsVerts->getVertexStrider(verticesp) | ||
| 781 : | && mStarsVerts->getIndexStrider(indicesp) | ||
| 782 : | && mStarsVerts->getColorStrider(colorsp); | ||
| 783 : | |||
| 784 : | if(!success) | ||
| 785 : | { | ||
| 786 : | llerrs << "Failed updating star geometry." << llendl; | ||
| 787 : | } | ||
| 788 : | |||
| 789 : | // *TODO: fix LLStrider with a real prefix increment operator so it can be | ||
| 790 : | // used as a model of OutputIterator. -Brad | ||
| 791 : | // std::copy(mStarVertices.begin(), mStarVertices.end(), verticesp); | ||
| 792 : | for (U32 vtx = 0; vtx < getStarsNumVerts(); ++vtx) | ||
| 793 : | { | ||
| 794 : | *(verticesp++) = mStarVertices[vtx]; | ||
| 795 : | *(colorsp++) = LLColor4U(mStarColors[vtx]); | ||
| 796 : | *(indicesp++) = vtx; | ||
| 797 : | } | ||
| 798 : | |||
| 799 : | mStarsVerts->setBuffer(0); | ||
| 800 : | return TRUE; | ||
| 801 : | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

