00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llvopartgroup.h"
00035
00036 #include "lldrawpoolalpha.h"
00037
00038 #include "llfasttimer.h"
00039 #include "message.h"
00040 #include "v2math.h"
00041
00042 #include "llagent.h"
00043 #include "lldrawable.h"
00044 #include "llface.h"
00045 #include "llsky.h"
00046 #include "llviewercamera.h"
00047 #include "llviewerpartsim.h"
00048 #include "llviewerregion.h"
00049 #include "pipeline.h"
00050
00051 const F32 MAX_PART_LIFETIME = 120.f;
00052
00053 extern U64 gFrameTime;
00054
00055 LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00056 : LLAlphaObject(id, pcode, regionp),
00057 mViewerPartGroupp(NULL)
00058 {
00059 setNumTEs(1);
00060 setTETexture(0, LLUUID::null);
00061 mbCanSelect = FALSE;
00062 mDebugColor = LLColor4(ll_frand(), ll_frand(), ll_frand(), 1.f);
00063 }
00064
00065
00066 LLVOPartGroup::~LLVOPartGroup()
00067 {
00068 }
00069
00070
00071 BOOL LLVOPartGroup::isActive() const
00072 {
00073 return TRUE;
00074 }
00075
00076 F32 LLVOPartGroup::getBinRadius()
00077 {
00078 return mScale.mV[0]*2.f;
00079 }
00080
00081 void LLVOPartGroup::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
00082 {
00083 LLVector3 pos_agent = getPositionAgent();
00084 mExtents[0] = pos_agent - mScale;
00085 mExtents[1] = pos_agent + mScale;
00086 newMin = mExtents[0];
00087 newMax = mExtents[1];
00088 mDrawable->setPositionGroup(pos_agent);
00089 }
00090
00091 BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00092 {
00093 return TRUE;
00094 }
00095
00096 void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
00097 {
00098
00099 F32 mid_scale = getMidScale();
00100 F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec();
00101
00102 if (range < 0.001f || isHUDAttachment())
00103 {
00104 mAppAngle = 180.f;
00105 }
00106 else
00107 {
00108 mAppAngle = (F32) atan2( mid_scale, range) * RAD_TO_DEG;
00109 }
00110 }
00111
00112 void LLVOPartGroup::updateTextures(LLAgent &agent)
00113 {
00114
00115 }
00116
00117
00118 LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline)
00119 {
00120 pipeline->allocDrawable(this);
00121 mDrawable->setLit(FALSE);
00122 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
00123 return mDrawable;
00124 }
00125
00126 const F32 MAX_PARTICLE_AREA_SCALE = 0.02f;
00127
00128 F32 LLVOPartGroup::getPartSize(S32 idx)
00129 {
00130 if (idx < (S32) mViewerPartGroupp->mParticles.size())
00131 {
00132 return mViewerPartGroupp->mParticles[idx]->mScale.mV[0];
00133 }
00134
00135 return 0.f;
00136 }
00137
00138 BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
00139 {
00140 LLFastTimer ftm(LLFastTimer::FTM_UPDATE_PARTICLES);
00141
00142 LLVector3 at;
00143 LLVector3 position_agent;
00144 LLVector3 camera_agent = gCamera->getOrigin();
00145
00146 S32 num_parts = mViewerPartGroupp->getCount();
00147 LLFace *facep;
00148 LLSpatialGroup* group = drawable->getSpatialGroup();
00149 if (!group && num_parts)
00150 {
00151 drawable->movePartition();
00152 group = drawable->getSpatialGroup();
00153 }
00154
00155 if (!num_parts)
00156 {
00157 if (group && drawable->getNumFaces())
00158 {
00159 group->dirtyGeom();
00160 }
00161 drawable->setNumFaces(0, NULL, getTEImage(0));
00162 LLPipeline::sCompiles++;
00163 return TRUE;
00164 }
00165
00166 if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
00167 {
00168 return TRUE;
00169 }
00170
00171 if (num_parts > drawable->getNumFaces())
00172 {
00173 drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0));
00174 }
00175
00176 F32 tot_area = 0;
00177 BOOL is_particle = isParticle();
00178
00179 F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE;
00180 F32 pixel_meter_ratio = gCamera->getPixelMeterRatio();
00181 pixel_meter_ratio *= pixel_meter_ratio;
00182
00183 S32 count=0;
00184 S32 i;
00185 F32 max_width = 0.f;
00186 mDepth = 0.f;
00187
00188 for (i = 0; i < num_parts; i++)
00189 {
00190 const LLViewerPart &part = *((LLViewerPart*) mViewerPartGroupp->mParticles[i]);
00191
00192 LLVector3 part_pos_agent(part.mPosAgent);
00193 at = part_pos_agent - camera_agent;
00194
00195 F32 camera_dist_squared = at.magVecSquared();
00196 F32 inv_camera_dist_squared;
00197 if (camera_dist_squared > 1.f)
00198 inv_camera_dist_squared = 1.f / camera_dist_squared;
00199 else
00200 inv_camera_dist_squared = 1.f;
00201 F32 area = part.mScale.mV[0] * part.mScale.mV[1] * inv_camera_dist_squared;
00202 tot_area += area;
00203
00204 if (!is_particle && tot_area > max_area)
00205 {
00206 break;
00207 }
00208
00209 count++;
00210
00211 facep = drawable->getFace(i);
00212 if (!facep)
00213 {
00214 llwarns << "No face found for index " << i << "!" << llendl;
00215 continue;
00216 }
00217
00218 facep->setTEOffset(i);
00219 const F32 NEAR_PART_DIST_SQ = 5.f*5.f;
00220 const F32 MIN_PART_AREA = .005f*.005f;
00221
00222 if (!is_particle)
00223 {
00224 if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
00225 {
00226 facep->setSize(0, 0);
00227 continue;
00228 }
00229
00230 facep->setSize(4, 6);
00231 }
00232 else
00233 {
00234 facep->setSize(1,1);
00235 }
00236
00237 facep->setViewerObject(this);
00238
00239 if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
00240 {
00241 facep->setState(LLFace::FULLBRIGHT);
00242 }
00243 else
00244 {
00245 facep->clearState(LLFace::FULLBRIGHT);
00246 }
00247
00248 facep->mCenterLocal = part.mPosAgent;
00249 facep->setFaceColor(part.mColor);
00250 facep->setTexture(part.mImagep);
00251
00252 if (i == 0)
00253 {
00254 mExtents[0] = mExtents[1] = part.mPosAgent;
00255 }
00256 else
00257 {
00258 update_min_max(mExtents[0], mExtents[1], part.mPosAgent);
00259 }
00260
00261 max_width = llmax(max_width, part.mScale.mV[0]);
00262 max_width = llmax(max_width, part.mScale.mV[1]);
00263
00264 mPixelArea = tot_area * pixel_meter_ratio;
00265 const F32 area_scale = 10.f;
00266 facep->setVirtualSize(mPixelArea*area_scale);
00267 }
00268 for (i = count; i < drawable->getNumFaces(); i++)
00269 {
00270 LLFace* facep = drawable->getFace(i);
00271 if (!facep)
00272 {
00273 llwarns << "No face found for index " << i << "!" << llendl;
00274 continue;
00275 }
00276 facep->setTEOffset(i);
00277 facep->setSize(0,0);
00278 }
00279
00280 LLVector3 y = gCamera->mYAxis;
00281 LLVector3 z = gCamera->mZAxis;
00282
00283 LLVector3 pad;
00284 for (i = 0; i < 3; i++)
00285 {
00286 pad.mV[i] = llmax(max_width, max_width * (fabsf(y.mV[i]) + fabsf(z.mV[i])));
00287 }
00288
00289 mExtents[0] -= pad;
00290 mExtents[1] += pad;
00291
00292 mDrawable->movePartition();
00293 LLPipeline::sCompiles++;
00294 return TRUE;
00295 }
00296
00297 void LLVOPartGroup::getGeometry(S32 idx,
00298 LLStrider<LLVector3>& verticesp,
00299 LLStrider<LLVector3>& normalsp,
00300 LLStrider<LLVector2>& texcoordsp,
00301 LLStrider<LLColor4U>& colorsp,
00302 LLStrider<U32>& indicesp)
00303 {
00304 if (idx >= (S32) mViewerPartGroupp->mParticles.size())
00305 {
00306 return;
00307 }
00308
00309 const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
00310
00311 U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex();
00312
00313 if (isParticle())
00314 {
00315 LLVector3 part_pos_agent(part.mPosAgent);
00316
00317 const LLVector3& normal = -gCamera->getXAxis();
00318
00319 *verticesp++ = part_pos_agent;
00320 *normalsp++ = normal;
00321 *colorsp++ = part.mColor;
00322 *texcoordsp++ = LLVector2(0.5f, 0.5f);
00323 *indicesp++ = vert_offset;
00324 }
00325 else
00326 {
00327 LLVector3 part_pos_agent(part.mPosAgent);
00328 LLVector3 camera_agent = gAgent.getCameraPositionAgent();
00329 LLVector3 at = part_pos_agent - camera_agent;
00330 LLVector3 up, right;
00331
00332 right = at % LLVector3(0.f, 0.f, 1.f);
00333 right.normVec();
00334 up = right % at;
00335 up.normVec();
00336
00337 if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)
00338 {
00339 LLVector3 normvel = part.mVelocity;
00340 normvel.normVec();
00341 LLVector2 up_fracs;
00342 up_fracs.mV[0] = normvel*right;
00343 up_fracs.mV[1] = normvel*up;
00344 up_fracs.normVec();
00345
00346 LLVector3 new_up;
00347 LLVector3 new_right;
00348 new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up;
00349 new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up;
00350 up = new_up;
00351 right = new_right;
00352 up.normVec();
00353 right.normVec();
00354 }
00355
00356 right *= 0.5f*part.mScale.mV[0];
00357 up *= 0.5f*part.mScale.mV[1];
00358
00359 const LLVector3& normal = -gCamera->getXAxis();
00360
00361 *verticesp++ = part_pos_agent + up - right;
00362 *verticesp++ = part_pos_agent - up - right;
00363 *verticesp++ = part_pos_agent + up + right;
00364 *verticesp++ = part_pos_agent - up + right;
00365
00366 *colorsp++ = part.mColor;
00367 *colorsp++ = part.mColor;
00368 *colorsp++ = part.mColor;
00369 *colorsp++ = part.mColor;
00370
00371 *texcoordsp++ = LLVector2(0.f, 1.f);
00372 *texcoordsp++ = LLVector2(0.f, 0.f);
00373 *texcoordsp++ = LLVector2(1.f, 1.f);
00374 *texcoordsp++ = LLVector2(1.f, 0.f);
00375
00376 *normalsp++ = normal;
00377 *normalsp++ = normal;
00378 *normalsp++ = normal;
00379 *normalsp++ = normal;
00380
00381 *indicesp++ = vert_offset + 0;
00382 *indicesp++ = vert_offset + 1;
00383 *indicesp++ = vert_offset + 2;
00384
00385 *indicesp++ = vert_offset + 1;
00386 *indicesp++ = vert_offset + 3;
00387 *indicesp++ = vert_offset + 2;
00388 }
00389 }
00390
00391 BOOL LLVOPartGroup::isParticle()
00392 {
00393 return FALSE;
00394 }
00395
00396 U32 LLVOPartGroup::getPartitionType() const
00397 {
00398 return LLPipeline::PARTITION_PARTICLE;
00399 }
00400
00401 LLParticlePartition::LLParticlePartition()
00402 : LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK)
00403 {
00404 mRenderPass = LLRenderPass::PASS_ALPHA;
00405 mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
00406 mPartitionType = LLPipeline::PARTITION_PARTICLE;
00407 mBufferUsage = GL_DYNAMIC_DRAW_ARB;
00408 mSlopRatio = 0.f;
00409 mLODPeriod = 1;
00410 }
00411
00412 void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
00413 {
00414 group->mBufferUsage = mBufferUsage;
00415
00416 mFaceList.clear();
00417
00418 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
00419 {
00420 LLDrawable* drawablep = *i;
00421
00422 if (drawablep->isDead())
00423 {
00424 continue;
00425 }
00426
00427 LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get();
00428 obj->mDepth = 0.f;
00429
00430 if (drawablep->isAnimating())
00431 {
00432 group->mBufferUsage = GL_STREAM_DRAW_ARB;
00433 }
00434
00435 U32 count = 0;
00436 for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
00437 {
00438 drawablep->updateFaceSize(j);
00439
00440 LLFace* facep = drawablep->getFace(j);
00441 if ( !facep || !facep->hasGeometry())
00442 {
00443 continue;
00444 }
00445
00446 count++;
00447 facep->mDistance = (facep->mCenterLocal - gCamera->getOrigin()) * gCamera->getAtAxis();
00448 obj->mDepth += facep->mDistance;
00449
00450 mFaceList.push_back(facep);
00451 vertex_count += facep->getGeomCount();
00452 index_count += facep->getIndicesCount();
00453 }
00454
00455 obj->mDepth /= count;
00456 }
00457 }
00458
00459 void LLParticlePartition::getGeometry(LLSpatialGroup* group)
00460 {
00461 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00462
00463 std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater());
00464
00465 U32 index_count = 0;
00466 U32 vertex_count = 0;
00467
00468 group->clearDrawMap();
00469
00470 LLVertexBuffer* buffer = group->mVertexBuffer;
00471
00472 LLStrider<U32> indicesp;
00473 LLStrider<LLVector3> verticesp;
00474 LLStrider<LLVector3> normalsp;
00475 LLStrider<LLVector2> texcoordsp;
00476 LLStrider<LLColor4U> colorsp;
00477
00478 buffer->getVertexStrider(verticesp);
00479 buffer->getNormalStrider(normalsp);
00480 buffer->getColorStrider(colorsp);
00481 buffer->getTexCoordStrider(texcoordsp);
00482 buffer->getIndexStrider(indicesp);
00483
00484 LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
00485
00486 for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
00487 {
00488 LLFace* facep = *i;
00489 LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
00490 facep->setGeomIndex(vertex_count);
00491 facep->setIndicesIndex(index_count);
00492 facep->mVertexBuffer = buffer;
00493 facep->setPoolType(LLDrawPool::POOL_ALPHA);
00494 object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
00495
00496 vertex_count += facep->getGeomCount();
00497 index_count += facep->getIndicesCount();
00498
00499 S32 idx = draw_vec.size()-1;
00500
00501 BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
00502 F32 vsize = facep->getVirtualSize();
00503
00504 if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
00505 draw_vec[idx]->mTexture == facep->getTexture() &&
00506 draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
00507 draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
00508 draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 &&
00509 draw_vec[idx]->mFullbright == fullbright)
00510 {
00511 draw_vec[idx]->mCount += facep->getIndicesCount();
00512 draw_vec[idx]->mEnd += facep->getGeomCount();
00513 draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
00514 }
00515 else
00516 {
00517 U32 start = facep->getGeomIndex();
00518 U32 end = start + facep->getGeomCount()-1;
00519 U32 offset = facep->getIndicesStart();
00520 U32 count = facep->getIndicesCount();
00521 LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright);
00522 info->mVSize = vsize;
00523 draw_vec.push_back(info);
00524 }
00525 }
00526
00527 mFaceList.clear();
00528 }
00529
00530 F32 LLParticlePartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
00531 {
00532 return 1024.f;
00533 }
00534