/indra/newview/llvopartgroup.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 570 lines · 424 code · 106 blank · 40 comment · 40 complexity · 130de7d31d7cad966d4c97a056f0c45a MD5 · raw file

  1. /**
  2. * @file llvopartgroup.cpp
  3. * @brief Group of particle systems
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llvopartgroup.h"
  28. #include "lldrawpoolalpha.h"
  29. #include "llfasttimer.h"
  30. #include "message.h"
  31. #include "v2math.h"
  32. #include "llagentcamera.h"
  33. #include "lldrawable.h"
  34. #include "llface.h"
  35. #include "llsky.h"
  36. #include "llviewercamera.h"
  37. #include "llviewerpartsim.h"
  38. #include "llviewerregion.h"
  39. #include "pipeline.h"
  40. #include "llspatialpartition.h"
  41. const F32 MAX_PART_LIFETIME = 120.f;
  42. extern U64 gFrameTime;
  43. LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
  44. : LLAlphaObject(id, pcode, regionp),
  45. mViewerPartGroupp(NULL)
  46. {
  47. setNumTEs(1);
  48. setTETexture(0, LLUUID::null);
  49. mbCanSelect = FALSE; // users can't select particle systems
  50. }
  51. LLVOPartGroup::~LLVOPartGroup()
  52. {
  53. }
  54. BOOL LLVOPartGroup::isActive() const
  55. {
  56. return FALSE;
  57. }
  58. F32 LLVOPartGroup::getBinRadius()
  59. {
  60. return mScale.mV[0]*2.f;
  61. }
  62. void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
  63. {
  64. const LLVector3& pos_agent = getPositionAgent();
  65. newMin.load3( (pos_agent - mScale).mV);
  66. newMax.load3( (pos_agent + mScale).mV);
  67. LLVector4a pos;
  68. pos.load3(pos_agent.mV);
  69. mDrawable->setPositionGroup(pos);
  70. }
  71. BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
  72. {
  73. return TRUE;
  74. }
  75. void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
  76. {
  77. // mPixelArea is calculated during render
  78. F32 mid_scale = getMidScale();
  79. F32 range = (getRenderPosition()-LLViewerCamera::getInstance()->getOrigin()).length();
  80. if (range < 0.001f || isHUDAttachment()) // range == zero
  81. {
  82. mAppAngle = 180.f;
  83. }
  84. else
  85. {
  86. mAppAngle = (F32) atan2( mid_scale, range) * RAD_TO_DEG;
  87. }
  88. }
  89. void LLVOPartGroup::updateTextures()
  90. {
  91. // Texture stats for particles need to be updated in a different way...
  92. }
  93. LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline)
  94. {
  95. pipeline->allocDrawable(this);
  96. mDrawable->setLit(FALSE);
  97. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
  98. return mDrawable;
  99. }
  100. const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw
  101. F32 LLVOPartGroup::getPartSize(S32 idx)
  102. {
  103. if (idx < (S32) mViewerPartGroupp->mParticles.size())
  104. {
  105. return mViewerPartGroupp->mParticles[idx]->mScale.mV[0];
  106. }
  107. return 0.f;
  108. }
  109. LLVector3 LLVOPartGroup::getCameraPosition() const
  110. {
  111. return gAgentCamera.getCameraPositionAgent();
  112. }
  113. static LLFastTimer::DeclareTimer FTM_UPDATE_PARTICLES("Update Particles");
  114. BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
  115. {
  116. LLFastTimer ftm(FTM_UPDATE_PARTICLES);
  117. dirtySpatialGroup();
  118. S32 num_parts = mViewerPartGroupp->getCount();
  119. LLFace *facep;
  120. LLSpatialGroup* group = drawable->getSpatialGroup();
  121. if (!group && num_parts)
  122. {
  123. drawable->movePartition();
  124. group = drawable->getSpatialGroup();
  125. }
  126. if (group && group->isVisible())
  127. {
  128. dirtySpatialGroup(TRUE);
  129. }
  130. if (!num_parts)
  131. {
  132. if (group && drawable->getNumFaces())
  133. {
  134. group->setState(LLSpatialGroup::GEOM_DIRTY);
  135. }
  136. drawable->setNumFaces(0, NULL, getTEImage(0));
  137. LLPipeline::sCompiles++;
  138. return TRUE;
  139. }
  140. if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
  141. {
  142. return TRUE;
  143. }
  144. if (num_parts > drawable->getNumFaces())
  145. {
  146. drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0));
  147. }
  148. F32 tot_area = 0;
  149. F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE;
  150. F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
  151. pixel_meter_ratio *= pixel_meter_ratio;
  152. LLViewerPartSim::checkParticleCount(mViewerPartGroupp->mParticles.size()) ;
  153. S32 count=0;
  154. mDepth = 0.f;
  155. S32 i = 0 ;
  156. LLVector3 camera_agent = getCameraPosition();
  157. for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)
  158. {
  159. const LLViewerPart *part = mViewerPartGroupp->mParticles[i];
  160. LLVector3 part_pos_agent(part->mPosAgent);
  161. LLVector3 at(part_pos_agent - camera_agent);
  162. F32 camera_dist_squared = at.lengthSquared();
  163. F32 inv_camera_dist_squared;
  164. if (camera_dist_squared > 1.f)
  165. inv_camera_dist_squared = 1.f / camera_dist_squared;
  166. else
  167. inv_camera_dist_squared = 1.f;
  168. F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared;
  169. tot_area = llmax(tot_area, area);
  170. if (tot_area > max_area)
  171. {
  172. break;
  173. }
  174. count++;
  175. facep = drawable->getFace(i);
  176. if (!facep)
  177. {
  178. llwarns << "No face found for index " << i << "!" << llendl;
  179. continue;
  180. }
  181. facep->setTEOffset(i);
  182. const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera
  183. const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera
  184. if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
  185. {
  186. facep->setSize(0, 0);
  187. continue;
  188. }
  189. facep->setSize(4, 6);
  190. facep->setViewerObject(this);
  191. if (part->mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
  192. {
  193. facep->setState(LLFace::FULLBRIGHT);
  194. }
  195. else
  196. {
  197. facep->clearState(LLFace::FULLBRIGHT);
  198. }
  199. facep->mCenterLocal = part->mPosAgent;
  200. facep->setFaceColor(part->mColor);
  201. facep->setTexture(part->mImagep);
  202. //check if this particle texture is replaced by a parcel media texture.
  203. if(part->mImagep.notNull() && part->mImagep->hasParcelMedia())
  204. {
  205. part->mImagep->getParcelMedia()->addMediaToFace(facep) ;
  206. }
  207. mPixelArea = tot_area * pixel_meter_ratio;
  208. const F32 area_scale = 10.f; // scale area to increase priority a bit
  209. facep->setVirtualSize(mPixelArea*area_scale);
  210. }
  211. for (i = count; i < drawable->getNumFaces(); i++)
  212. {
  213. LLFace* facep = drawable->getFace(i);
  214. if (!facep)
  215. {
  216. llwarns << "No face found for index " << i << "!" << llendl;
  217. continue;
  218. }
  219. facep->setTEOffset(i);
  220. facep->setSize(0, 0);
  221. }
  222. mDrawable->movePartition();
  223. LLPipeline::sCompiles++;
  224. return TRUE;
  225. }
  226. void LLVOPartGroup::getGeometry(S32 idx,
  227. LLStrider<LLVector4a>& verticesp,
  228. LLStrider<LLVector3>& normalsp,
  229. LLStrider<LLVector2>& texcoordsp,
  230. LLStrider<LLColor4U>& colorsp,
  231. LLStrider<U16>& indicesp)
  232. {
  233. if (idx >= (S32) mViewerPartGroupp->mParticles.size())
  234. {
  235. return;
  236. }
  237. const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
  238. U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex();
  239. LLVector4a part_pos_agent;
  240. part_pos_agent.load3(part.mPosAgent.mV);
  241. LLVector4a camera_agent;
  242. camera_agent.load3(getCameraPosition().mV);
  243. LLVector4a at;
  244. at.setSub(part_pos_agent, camera_agent);
  245. LLVector4a up(0, 0, 1);
  246. LLVector4a right;
  247. right.setCross3(at, up);
  248. right.normalize3fast();
  249. up.setCross3(right, at);
  250. up.normalize3fast();
  251. if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)
  252. {
  253. LLVector4a normvel;
  254. normvel.load3(part.mVelocity.mV);
  255. normvel.normalize3fast();
  256. LLVector2 up_fracs;
  257. up_fracs.mV[0] = normvel.dot3(right).getF32();
  258. up_fracs.mV[1] = normvel.dot3(up).getF32();
  259. up_fracs.normalize();
  260. LLVector4a new_up;
  261. LLVector4a new_right;
  262. //new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up;
  263. LLVector4a t = right;
  264. t.mul(up_fracs.mV[0]);
  265. new_up = up;
  266. new_up.mul(up_fracs.mV[1]);
  267. new_up.add(t);
  268. //new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up;
  269. t = right;
  270. t.mul(up_fracs.mV[1]);
  271. new_right = up;
  272. new_right.mul(up_fracs.mV[0]);
  273. t.sub(new_right);
  274. up = new_up;
  275. right = t;
  276. up.normalize3fast();
  277. right.normalize3fast();
  278. }
  279. right.mul(0.5f*part.mScale.mV[0]);
  280. up.mul(0.5f*part.mScale.mV[1]);
  281. LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
  282. //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
  283. // this works because there is actually a 4th float stored after the vertex position which is used as a texture index
  284. // also, somebody please VECTORIZE THIS
  285. LLVector4a ppapu;
  286. LLVector4a ppamu;
  287. ppapu.setAdd(part_pos_agent, up);
  288. ppamu.setSub(part_pos_agent, up);
  289. verticesp->setSub(ppapu, right);
  290. (*verticesp++).getF32ptr()[3] = 0.f;
  291. verticesp->setSub(ppamu, right);
  292. (*verticesp++).getF32ptr()[3] = 0.f;
  293. verticesp->setAdd(ppapu, right);
  294. (*verticesp++).getF32ptr()[3] = 0.f;
  295. verticesp->setAdd(ppamu, right);
  296. (*verticesp++).getF32ptr()[3] = 0.f;
  297. //*verticesp++ = part_pos_agent + up - right;
  298. //*verticesp++ = part_pos_agent - up - right;
  299. //*verticesp++ = part_pos_agent + up + right;
  300. //*verticesp++ = part_pos_agent - up + right;
  301. *colorsp++ = part.mColor;
  302. *colorsp++ = part.mColor;
  303. *colorsp++ = part.mColor;
  304. *colorsp++ = part.mColor;
  305. *texcoordsp++ = LLVector2(0.f, 1.f);
  306. *texcoordsp++ = LLVector2(0.f, 0.f);
  307. *texcoordsp++ = LLVector2(1.f, 1.f);
  308. *texcoordsp++ = LLVector2(1.f, 0.f);
  309. *normalsp++ = normal;
  310. *normalsp++ = normal;
  311. *normalsp++ = normal;
  312. *normalsp++ = normal;
  313. *indicesp++ = vert_offset + 0;
  314. *indicesp++ = vert_offset + 1;
  315. *indicesp++ = vert_offset + 2;
  316. *indicesp++ = vert_offset + 1;
  317. *indicesp++ = vert_offset + 3;
  318. *indicesp++ = vert_offset + 2;
  319. }
  320. U32 LLVOPartGroup::getPartitionType() const
  321. {
  322. return LLViewerRegion::PARTITION_PARTICLE;
  323. }
  324. LLParticlePartition::LLParticlePartition()
  325. : LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
  326. {
  327. mRenderPass = LLRenderPass::PASS_ALPHA;
  328. mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
  329. mPartitionType = LLViewerRegion::PARTITION_PARTICLE;
  330. mSlopRatio = 0.f;
  331. mLODPeriod = 1;
  332. }
  333. LLHUDParticlePartition::LLHUDParticlePartition() :
  334. LLParticlePartition()
  335. {
  336. mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES;
  337. mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE;
  338. }
  339. void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
  340. {
  341. group->mBufferUsage = mBufferUsage;
  342. mFaceList.clear();
  343. LLViewerCamera* camera = LLViewerCamera::getInstance();
  344. for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
  345. {
  346. LLDrawable* drawablep = *i;
  347. if (drawablep->isDead())
  348. {
  349. continue;
  350. }
  351. LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get();
  352. obj->mDepth = 0.f;
  353. if (drawablep->isAnimating())
  354. {
  355. group->mBufferUsage = GL_STREAM_DRAW_ARB;
  356. }
  357. U32 count = 0;
  358. for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
  359. {
  360. drawablep->updateFaceSize(j);
  361. LLFace* facep = drawablep->getFace(j);
  362. if ( !facep || !facep->hasGeometry())
  363. {
  364. continue;
  365. }
  366. count++;
  367. facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis();
  368. obj->mDepth += facep->mDistance;
  369. mFaceList.push_back(facep);
  370. vertex_count += facep->getGeomCount();
  371. index_count += facep->getIndicesCount();
  372. llassert(facep->getIndicesCount() < 65536);
  373. }
  374. obj->mDepth /= count;
  375. }
  376. }
  377. static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB");
  378. static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB");
  379. void LLParticlePartition::getGeometry(LLSpatialGroup* group)
  380. {
  381. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  382. LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ?
  383. FTM_REBUILD_GRASS_VB :
  384. FTM_REBUILD_PARTICLE_VB);
  385. std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater());
  386. U32 index_count = 0;
  387. U32 vertex_count = 0;
  388. group->clearDrawMap();
  389. LLVertexBuffer* buffer = group->mVertexBuffer;
  390. LLStrider<U16> indicesp;
  391. LLStrider<LLVector4a> verticesp;
  392. LLStrider<LLVector3> normalsp;
  393. LLStrider<LLVector2> texcoordsp;
  394. LLStrider<LLColor4U> colorsp;
  395. buffer->getVertexStrider(verticesp);
  396. buffer->getNormalStrider(normalsp);
  397. buffer->getColorStrider(colorsp);
  398. buffer->getTexCoord0Strider(texcoordsp);
  399. buffer->getIndexStrider(indicesp);
  400. LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
  401. for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
  402. {
  403. LLFace* facep = *i;
  404. LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
  405. facep->setGeomIndex(vertex_count);
  406. facep->setIndicesIndex(index_count);
  407. facep->setVertexBuffer(buffer);
  408. facep->setPoolType(LLDrawPool::POOL_ALPHA);
  409. object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
  410. vertex_count += facep->getGeomCount();
  411. index_count += facep->getIndicesCount();
  412. S32 idx = draw_vec.size()-1;
  413. BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
  414. F32 vsize = facep->getVirtualSize();
  415. if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
  416. draw_vec[idx]->mTexture == facep->getTexture() &&
  417. (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange &&
  418. //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
  419. draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 &&
  420. draw_vec[idx]->mFullbright == fullbright)
  421. {
  422. draw_vec[idx]->mCount += facep->getIndicesCount();
  423. draw_vec[idx]->mEnd += facep->getGeomCount();
  424. draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
  425. }
  426. else
  427. {
  428. U32 start = facep->getGeomIndex();
  429. U32 end = start + facep->getGeomCount()-1;
  430. U32 offset = facep->getIndicesStart();
  431. U32 count = facep->getIndicesCount();
  432. LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
  433. //facep->getTexture(),
  434. buffer, fullbright);
  435. info->mExtents[0] = group->mObjectExtents[0];
  436. info->mExtents[1] = group->mObjectExtents[1];
  437. info->mVSize = vsize;
  438. draw_vec.push_back(info);
  439. //for alpha sorting
  440. facep->setDrawInfo(info);
  441. }
  442. }
  443. buffer->flush();
  444. mFaceList.clear();
  445. }
  446. F32 LLParticlePartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
  447. {
  448. return 1024.f;
  449. }
  450. U32 LLVOHUDPartGroup::getPartitionType() const
  451. {
  452. return LLViewerRegion::PARTITION_HUD_PARTICLE;
  453. }
  454. LLDrawable* LLVOHUDPartGroup::createDrawable(LLPipeline *pipeline)
  455. {
  456. pipeline->allocDrawable(this);
  457. mDrawable->setLit(FALSE);
  458. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
  459. return mDrawable;
  460. }
  461. LLVector3 LLVOHUDPartGroup::getCameraPosition() const
  462. {
  463. return LLVector3(-1,0,0);
  464. }