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 
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;                    // users can't select particle systems
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         // mPixelArea is calculated during render
00099         F32 mid_scale = getMidScale();
00100         F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec();
00101 
00102         if (range < 0.001f || isHUDAttachment())                // range == zero
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         // Texture stats for particles need to be updated in a different way...
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; // some tuned constant, limits on how much particle area to draw
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;  // Only discard particles > 5 m from the camera
00220                 const F32 MIN_PART_AREA = .005f*.005f;  // only less than 5 mm x 5 mm at 1 m from camera
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; // scale area to increase priority a bit
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; //gGLManager.mHasPointParameters && mViewerPartGroupp->mUniformParticles;
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 

Generated on Thu Jul 1 06:09:42 2010 for Second Life Viewer by  doxygen 1.4.7