llvopartgroup.cpp

Go to the documentation of this file.
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;                    // users can't select particle systems
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         // mPixelArea is calculated during render
00097         F32 mid_scale = getMidScale();
00098         F32 range = (getRenderPosition()-LLViewerCamera::getInstance()->getOrigin()).magVec();
00099 
00100         if (range < 0.001f || isHUDAttachment())                // range == zero
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         // Texture stats for particles need to be updated in a different way...
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; // some tuned constant, limits on how much particle area to draw
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;  // Only discard particles > 5 m from the camera
00218                 const F32 MIN_PART_AREA = .005f*.005f;  // only less than 5 mm x 5 mm at 1 m from camera
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; // scale area to increase priority a bit
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                         //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
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 

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