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