llvopartgroup.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /**
  2. * @file llvopartgroup.cpp
  3. * @brief Group of particle systems
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llvopartgroup.h"
  34. #include "llfasttimer.h"
  35. #include "llmessage.h"
  36. #include "llagent.h" // For getCameraPositionAgent()
  37. #include "llappviewer.h" // For gFrameTimeSeconds
  38. #include "lldrawable.h"
  39. #include "lldrawpoolalpha.h"
  40. #include "llface.h"
  41. #include "llpipeline.h"
  42. #include "llsky.h"
  43. #include "llspatialpartition.h"
  44. #include "llviewercamera.h"
  45. #include "llviewercontrol.h"
  46. #include "llviewerobjectlist.h"
  47. #include "llviewerpartsim.h"
  48. #include "llvoclouds.h"
  49. // Some tuned constant, limits on how much particle area to draw
  50. constexpr F32 MAX_PARTICLE_AREA_SCALE = 0.02f;
  51. extern U64 gFrameTime;
  52. ///////////////////////////////////////////////////////////////////////////////
  53. // LLVOPartGroup class
  54. ///////////////////////////////////////////////////////////////////////////////
  55. LLVOPartGroup::LLVOPartGroup(const LLUUID& id, LLViewerRegion* regionp,
  56. LLPCode pcode)
  57. : LLAlphaObject(id, pcode, regionp),
  58. mViewerPartGroupp(NULL)
  59. {
  60. setNumTEs(1);
  61. setTETexture(0, LLUUID::null);
  62. // Users cannot select particle systems
  63. mCanSelect = false;
  64. }
  65. F32 LLVOPartGroup::getBinRadius()
  66. {
  67. return mViewerPartGroupp->getBoxSide();
  68. }
  69. void LLVOPartGroup::updateSpatialExtents(LLVector4a& new_min,
  70. LLVector4a& new_max)
  71. {
  72. const LLVector3& pos_agent = getPositionAgent();
  73. LLVector4a p;
  74. p.load3(pos_agent.mV);
  75. LLVector4a scale;
  76. scale.splat(mScale.mV[0] + mViewerPartGroupp->getBoxSide() * 0.5f);
  77. new_min.setSub(p, scale);
  78. new_max.setAdd(p, scale);
  79. llassert(new_min.isFinite3() && new_max.isFinite3() && p.isFinite3());
  80. mDrawable->setPositionGroup(p);
  81. }
  82. void LLVOPartGroup::setPixelAreaAndAngle()
  83. {
  84. // mPixelArea is calculated during render
  85. F32 mid_scale = getMidScale();
  86. F32 range = (getRenderPosition() - gViewerCamera.getOrigin()).length();
  87. if (range < 0.001f || isHUDAttachment()) // range == zero
  88. {
  89. mAppAngle = 180.f;
  90. }
  91. else
  92. {
  93. mAppAngle = atan2f(mid_scale, range) * RAD_TO_DEG;
  94. }
  95. }
  96. LLDrawable* LLVOPartGroup::createDrawable()
  97. {
  98. gPipeline.allocDrawable(this);
  99. mDrawable->setLit(false);
  100. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
  101. return mDrawable;
  102. }
  103. const LLUUID& LLVOPartGroup::getPartOwner(S32 idx)
  104. {
  105. if (idx >= 0 && idx < (S32)mViewerPartGroupp->mParticles.size())
  106. {
  107. LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
  108. if (part && part->mPartSourcep.notNull())
  109. {
  110. return part->mPartSourcep->getOwnerUUID();
  111. }
  112. }
  113. return LLUUID::null;
  114. }
  115. const LLUUID& LLVOPartGroup::getPartSource(S32 idx)
  116. {
  117. if (idx >= 0 && idx < (S32)mViewerPartGroupp->mParticles.size())
  118. {
  119. LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
  120. if (part)
  121. {
  122. LLViewerPartSource* psrc = part->mPartSourcep.get();
  123. if (psrc)
  124. {
  125. LLViewerObject* objp = psrc->mSourceObjectp.get();
  126. if (objp)
  127. {
  128. return objp->getID();
  129. }
  130. }
  131. }
  132. }
  133. return LLUUID::null;
  134. }
  135. F32 LLVOPartGroup::getPartSize(S32 idx)
  136. {
  137. if (idx >= 0 && idx < (S32)mViewerPartGroupp->mParticles.size())
  138. {
  139. LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
  140. if (part)
  141. {
  142. return part->mScale.mV[0];
  143. }
  144. }
  145. return 0.f;
  146. }
  147. //virtual
  148. bool LLVOPartGroup::getBlendFunc(S32 face, U32& src, U32& dst)
  149. {
  150. if (face < 0 || face >= (S32)mViewerPartGroupp->mParticles.size())
  151. {
  152. LL_DEBUGS_SPARSE("Particles") << "Index out of range for mParticles size"
  153. << LL_ENDL;
  154. return false;
  155. }
  156. LLViewerPart* part = mViewerPartGroupp->mParticles[face];
  157. src = part->mBlendFuncSource;
  158. dst = part->mBlendFuncDest;
  159. return true;
  160. }
  161. //virtual
  162. const LLVector3& LLVOPartGroup::getCameraPosition() const
  163. {
  164. return gAgent.getCameraPositionAgent();
  165. }
  166. bool LLVOPartGroup::updateGeometry(LLDrawable* drawable)
  167. {
  168. LL_FAST_TIMER(FTM_UPDATE_PARTICLES);
  169. S32 num_parts = mViewerPartGroupp->getCount();
  170. LLSpatialGroup* group = drawable->getSpatialGroup();
  171. if (!group && num_parts)
  172. {
  173. drawable->movePartition();
  174. group = drawable->getSpatialGroup();
  175. }
  176. if (group && group->isVisible())
  177. {
  178. dirtySpatialGroup();
  179. }
  180. if (!num_parts)
  181. {
  182. if (group && drawable->getNumFaces())
  183. {
  184. group->setState(LLSpatialGroup::GEOM_DIRTY);
  185. }
  186. drawable->setNumFaces(0, NULL, getTEImage(0));
  187. return true;
  188. }
  189. if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))
  190. {
  191. return true;
  192. }
  193. if (num_parts > drawable->getNumFaces())
  194. {
  195. drawable->setNumFacesFast(num_parts + num_parts / 4, NULL,
  196. getTEImage(0));
  197. }
  198. F32 tot_area = 0;
  199. F32 max_area = LLViewerPartSim::getMaxPartCount() *
  200. MAX_PARTICLE_AREA_SCALE;
  201. F32 pixel_meter_ratio = gViewerCamera.getPixelMeterRatio();
  202. pixel_meter_ratio *= pixel_meter_ratio;
  203. F32 max_scale = 0.f;
  204. S32 count = 0;
  205. mDepth = 0.f;
  206. LLVector3 camera_agent = getCameraPosition();
  207. U32 part_count = mViewerPartGroupp->mParticles.size();
  208. #if LL_DEBUG
  209. LLViewerPartSim::checkParticleCount(part_count);
  210. #endif
  211. for (U32 i = 0; i < part_count; ++i)
  212. {
  213. const LLViewerPart* partp = mViewerPartGroupp->mParticles[i];
  214. // Remember the largest particle
  215. max_scale = llmax(max_scale, partp->mScale.mV[0], partp->mScale.mV[1]);
  216. if (partp->mFlags & LLPartData::LL_PART_RIBBON_MASK)
  217. {
  218. // Include ribbon segment length in scale
  219. const LLVector3* pos_agent = NULL;
  220. if (partp->mParent)
  221. {
  222. pos_agent = &(partp->mParent->mPosAgent);
  223. }
  224. else if (partp->mPartSourcep.notNull())
  225. {
  226. pos_agent = &(partp->mPartSourcep->mPosAgent);
  227. }
  228. if (pos_agent)
  229. {
  230. F32 dist = (*pos_agent-partp->mPosAgent).length();
  231. max_scale = llmax(max_scale, dist);
  232. }
  233. }
  234. LLVector3 part_pos_agent(partp->mPosAgent);
  235. LLVector3 at(part_pos_agent - camera_agent);
  236. F32 camera_dist_squared = at.lengthSquared();
  237. F32 inv_camera_dist_squared;
  238. if (camera_dist_squared > 1.f)
  239. {
  240. inv_camera_dist_squared = 1.f / camera_dist_squared;
  241. }
  242. else
  243. {
  244. inv_camera_dist_squared = 1.f;
  245. }
  246. F32 area = partp->mScale.mV[0] * partp->mScale.mV[1] *
  247. inv_camera_dist_squared;
  248. tot_area = llmax(tot_area, area);
  249. if (tot_area > max_area)
  250. {
  251. break;
  252. }
  253. ++count;
  254. LLFace* facep = drawable->getFace(i);
  255. if (!facep)
  256. {
  257. continue;
  258. }
  259. facep->setTEOffset(i);
  260. // Only discard particles > 5 m from the camera
  261. constexpr F32 NEAR_PART_DIST_SQ = 5.f * 5.f;
  262. // Only less than 5 mm x 5 mm at 1 m from camera
  263. constexpr F32 MIN_PART_AREA = .005f * .005f;
  264. if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
  265. {
  266. facep->setSize(0, 0);
  267. continue;
  268. }
  269. facep->setSize(4, 6);
  270. facep->setViewerObject(this);
  271. if (partp->mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
  272. {
  273. facep->setState(LLFace::FULLBRIGHT);
  274. }
  275. else
  276. {
  277. facep->clearState(LLFace::FULLBRIGHT);
  278. }
  279. facep->mCenterLocal = partp->mPosAgent;
  280. facep->setFaceColor(partp->mColor);
  281. LLViewerTexture* texp = partp->mImagep.get();
  282. facep->setDiffuseMap(texp);
  283. // Check if this particle texture is replaced by a parcel media texture
  284. if (texp && texp->hasParcelMedia())
  285. {
  286. texp->getParcelMedia()->addMediaToFace(facep);
  287. }
  288. mPixelArea = tot_area * pixel_meter_ratio;
  289. // Scale area to increase priority a bit
  290. constexpr F32 area_scale = 10.f;
  291. facep->setVirtualSize(mPixelArea * area_scale);
  292. }
  293. for (S32 i = count, faces = drawable->getNumFaces(); i < faces; ++i)
  294. {
  295. LLFace* facep = drawable->getFace(i);
  296. if (facep)
  297. {
  298. facep->setTEOffset(i);
  299. facep->setSize(0, 0);
  300. }
  301. }
  302. // Record max scale (used to stretch bounding box for visibility culling)
  303. mScale.set(max_scale, max_scale, max_scale);
  304. mDrawable->movePartition();
  305. return true;
  306. }
  307. bool LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start,
  308. const LLVector4a& end,
  309. S32 face, bool pick_transparent,
  310. bool pick_rigged, S32* face_hit,
  311. LLVector4a* intersection,
  312. LLVector2* tex_coord,
  313. LLVector4a* normal,
  314. LLVector4a* tangent)
  315. {
  316. LLVector4a dir;
  317. dir.setSub(end, start);
  318. F32 closest_t = 2.f;
  319. bool ret = false;
  320. LLVector4a v[4];
  321. LLStrider<LLVector4a> verticesp;
  322. for (U32 idx = 0, count = mViewerPartGroupp->mParticles.size();
  323. idx < count; ++idx)
  324. {
  325. const LLViewerPart& part =
  326. *((LLViewerPart*)mViewerPartGroupp->mParticles[idx]);
  327. verticesp = v;
  328. getGeometry(part, verticesp);
  329. F32 a, b, t;
  330. if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t) ||
  331. LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, a, b, t))
  332. {
  333. if (t >= 0.f && t <= 1.f && t < closest_t)
  334. {
  335. ret = true;
  336. closest_t = t;
  337. if (face_hit)
  338. {
  339. *face_hit = idx;
  340. }
  341. if (intersection)
  342. {
  343. LLVector4a intersect = dir;
  344. intersect.mul(closest_t);
  345. intersection->setAdd(intersect, start);
  346. }
  347. }
  348. }
  349. }
  350. return ret;
  351. }
  352. void LLVOPartGroup::getGeometry(const LLViewerPart& part,
  353. LLStrider<LLVector4a>& verticesp)
  354. {
  355. if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)
  356. {
  357. LLVector4a axis, pos, paxis, ppos;
  358. F32 scale, pscale;
  359. pos.load3(part.mPosAgent.mV);
  360. axis.load3(part.mAxis.mV);
  361. scale = part.mScale.mV[0];
  362. if (part.mParent)
  363. {
  364. ppos.load3(part.mParent->mPosAgent.mV);
  365. paxis.load3(part.mParent->mAxis.mV);
  366. pscale = part.mParent->mScale.mV[0];
  367. }
  368. else if (part.mPartSourcep->mSourceObjectp.notNull())
  369. {
  370. // Use source object as position
  371. LLVector3 v =
  372. LLVector3::z_axis *
  373. part.mPartSourcep->mSourceObjectp->getRenderRotation();
  374. paxis.load3(v.mV);
  375. ppos.load3(part.mPartSourcep->mPosAgent.mV);
  376. pscale = part.mStartScale.mV[0];
  377. }
  378. else
  379. {
  380. // No source object, no parent, nothing to draw
  381. ppos = pos;
  382. pscale = scale;
  383. paxis = axis;
  384. }
  385. LLVector4a p0, p1, p2, p3;
  386. scale *= 0.5f;
  387. pscale *= 0.5f;
  388. axis.mul(scale);
  389. paxis.mul(pscale);
  390. p0.setAdd(pos, axis);
  391. p1.setSub(pos,axis);
  392. p2.setAdd(ppos, paxis);
  393. p3.setSub(ppos, paxis);
  394. *verticesp++ = p2;
  395. *verticesp++ = p3;
  396. *verticesp++ = p0;
  397. *verticesp++ = p1;
  398. }
  399. else
  400. {
  401. LLVector4a part_pos_agent;
  402. part_pos_agent.load3(part.mPosAgent.mV);
  403. LLVector4a camera_agent;
  404. camera_agent.load3(getCameraPosition().mV);
  405. LLVector4a at;
  406. at.setSub(part_pos_agent, camera_agent);
  407. LLVector4a up(0, 0, 1);
  408. LLVector4a right;
  409. right.setCross3(at, up);
  410. right.normalize3fast();
  411. up.setCross3(right, at);
  412. up.normalize3fast();
  413. if ((part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) &&
  414. !part.mVelocity.isExactlyZero())
  415. {
  416. LLVector4a normvel;
  417. normvel.load3(part.mVelocity.mV);
  418. normvel.normalize3fast();
  419. LLVector2 up_fracs;
  420. up_fracs.mV[0] = normvel.dot3(right).getF32();
  421. up_fracs.mV[1] = normvel.dot3(up).getF32();
  422. up_fracs.normalize();
  423. LLVector4a new_up;
  424. LLVector4a new_right;
  425. #if 0
  426. new_up = up_fracs.mV[0] * right + up_fracs.mV[1] * up;
  427. #endif
  428. LLVector4a t = right;
  429. t.mul(up_fracs.mV[0]);
  430. new_up = up;
  431. new_up.mul(up_fracs.mV[1]);
  432. new_up.add(t);
  433. #if 0
  434. new_right = up_fracs.mV[1] * right - up_fracs.mV[0] * up;
  435. #endif
  436. t = right;
  437. t.mul(up_fracs.mV[1]);
  438. new_right = up;
  439. new_right.mul(up_fracs.mV[0]);
  440. t.sub(new_right);
  441. up = new_up;
  442. right = t;
  443. up.normalize3fast();
  444. right.normalize3fast();
  445. }
  446. right.mul(0.5f * part.mScale.mV[0]);
  447. up.mul(0.5f * part.mScale.mV[1]);
  448. // *HACK: the verticesp->mV[3] = 0.f here are to set the texture index
  449. // to 0 (particles do not use texture batching, maybe they should) this
  450. // works because there is actually a 4th float stored after the vertex
  451. // position which is used as a texture index also, somebody please
  452. // VECTORIZE THIS
  453. LLVector4a ppapu;
  454. LLVector4a ppamu;
  455. ppapu.setAdd(part_pos_agent, up);
  456. ppamu.setSub(part_pos_agent, up);
  457. verticesp->setSub(ppapu, right);
  458. verticesp++->getF32ptr()[3] = 0.f;
  459. verticesp->setSub(ppamu, right);
  460. verticesp++->getF32ptr()[3] = 0.f;
  461. verticesp->setAdd(ppapu, right);
  462. verticesp++->getF32ptr()[3] = 0.f;
  463. verticesp->setAdd(ppamu, right);
  464. verticesp++->getF32ptr()[3] = 0.f;
  465. }
  466. }
  467. void LLVOPartGroup::getGeometry(S32 idx, LLStrider<LLVector4a>& verticesp,
  468. LLStrider<LLVector3>& normalsp,
  469. LLStrider<LLVector2>& texcoordsp,
  470. LLStrider<LLColor4U>& colorsp,
  471. LLStrider<LLColor4U>& emissivep,
  472. LLStrider<U16>& indicesp)
  473. {
  474. if (idx < 0 || idx >= (S32)mViewerPartGroupp->mParticles.size())
  475. {
  476. return;
  477. }
  478. const LLViewerPart& part =
  479. *((LLViewerPart*)(mViewerPartGroupp->mParticles[idx]));
  480. getGeometry(part, verticesp);
  481. LLColor4U color = LLColor4U(part.mColor);
  482. LLColor4U pglow, pcolor;
  483. if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)
  484. {
  485. // Make sure color blends properly
  486. if (part.mParent)
  487. {
  488. pglow = part.mParent->mGlow;
  489. pcolor = LLColor4U(part.mParent->mColor);
  490. }
  491. else
  492. {
  493. pglow = LLColor4U(0, 0, 0, (U8)ll_roundp(255.f * part.mStartGlow));
  494. pcolor = LLColor4U(part.mStartColor);
  495. }
  496. }
  497. else
  498. {
  499. pglow = part.mGlow;
  500. pcolor = color;
  501. }
  502. *colorsp++ = pcolor;
  503. *colorsp++ = pcolor;
  504. *colorsp++ = color;
  505. *colorsp++ = color;
  506. #if 1
  507. if ((pglow.mV[3] > 0 || part.mGlow.mV[3] > 0) && gPipeline.shadersLoaded())
  508. #endif
  509. {
  510. *emissivep++ = pglow;
  511. *emissivep++ = pglow;
  512. *emissivep++ = part.mGlow;
  513. *emissivep++ = part.mGlow;
  514. }
  515. if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))
  516. {
  517. // Not fullbright, needs normal
  518. LLVector3 normal = -gViewerCamera.getXAxis();
  519. *normalsp++ = normal;
  520. *normalsp++ = normal;
  521. *normalsp++ = normal;
  522. *normalsp++ = normal;
  523. }
  524. }
  525. ///////////////////////////////////////////////////////////////////////////////
  526. // LLParticlePartition class (declared in llspatialpartition.h)
  527. ///////////////////////////////////////////////////////////////////////////////
  528. LLParticlePartition::LLParticlePartition(LLViewerRegion* regionp)
  529. : LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK |
  530. LLVertexBuffer::MAP_TEXTURE_INDEX,
  531. true, regionp)
  532. {
  533. mRenderPass = LLRenderPass::PASS_ALPHA;
  534. mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
  535. mPartitionType = LLViewerRegion::PARTITION_PARTICLE;
  536. mSlopRatio = 0.f;
  537. mLODPeriod = 1;
  538. }
  539. LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp)
  540. : LLParticlePartition(regionp)
  541. {
  542. mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES;
  543. mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE;
  544. }
  545. //static
  546. bool LLParticlePartition::createVB(LLPointer<LLVertexBuffer>& vb,
  547. U32 vert_count, U32 idx_count)
  548. {
  549. constexpr U32 VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
  550. LLVertexBuffer::MAP_TANGENT |
  551. LLVertexBuffer::MAP_NORMAL |
  552. LLVertexBuffer::MAP_TEXCOORD0 |
  553. LLVertexBuffer::MAP_TEXCOORD1 |
  554. LLVertexBuffer::MAP_TEXCOORD2 |
  555. LLVertexBuffer::MAP_COLOR |
  556. LLVertexBuffer::MAP_EMISSIVE |
  557. LLVertexBuffer::MAP_TEXTURE_INDEX;
  558. vb = new LLVertexBuffer(VERTEX_DATA_MASK);
  559. if (!vb->allocateBuffer(vert_count, idx_count))
  560. {
  561. llwarns << "Failure to allocate a vertex buffer with "
  562. << vert_count << " vertices and "
  563. << idx_count << " indices" << llendl;
  564. return false; // Abort
  565. }
  566. // Initialize index and texture coordinates only when buffer is reallocated
  567. U16* indicesp = (U16*)vb->mapIndexBuffer(0, idx_count);
  568. U16 geom_idx = 0;
  569. for (U32 i = 0; i < idx_count; i += 6)
  570. {
  571. *indicesp++ = geom_idx;
  572. *indicesp++ = geom_idx + 1;
  573. *indicesp++ = geom_idx + 2;
  574. *indicesp++ = geom_idx + 1;
  575. *indicesp++ = geom_idx + 3;
  576. *indicesp++ = geom_idx + 2;
  577. geom_idx += 4;
  578. }
  579. LLStrider<LLVector2> texcoordsp;
  580. if (!vb->getTexCoord0Strider(texcoordsp))
  581. {
  582. return false; // Abort
  583. }
  584. for (U32 i = 0; i < vert_count; i += 4)
  585. {
  586. *texcoordsp++ = LLVector2(0.f, 1.f);
  587. *texcoordsp++ = LLVector2(0.f, 0.f);
  588. *texcoordsp++ = LLVector2(1.f, 1.f);
  589. *texcoordsp++ = LLVector2(1.f, 0.f);
  590. }
  591. return true; // Success
  592. }
  593. //virtual
  594. void LLParticlePartition::rebuildGeom(LLSpatialGroup* group)
  595. {
  596. if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY))
  597. {
  598. return;
  599. }
  600. if (group->changeLOD())
  601. {
  602. group->mLastUpdateDistance = group->mDistance;
  603. group->mLastUpdateViewAngle = group->mViewAngle;
  604. }
  605. LL_FAST_TIMER(FTM_REBUILD_PARTICLE_VBO);
  606. group->clearDrawMap();
  607. // Get geometry count
  608. U32 idx_count = 0;
  609. U32 vert_count = 0;
  610. addGeometryCount(group, vert_count, idx_count);
  611. bool has_vb = vert_count > 0 && idx_count > 0;
  612. if (has_vb &&
  613. (group->mVertexBuffer.isNull() ||
  614. group->mVertexBuffer->getNumVerts() < vert_count ||
  615. group->mVertexBuffer->getNumIndices() < idx_count))
  616. {
  617. has_vb = createVB(group->mVertexBuffer, vert_count, idx_count);
  618. }
  619. if (has_vb)
  620. {
  621. group->mBuilt = 1.f;
  622. getGeometry(group);
  623. }
  624. else
  625. {
  626. group->mVertexBuffer = NULL;
  627. group->mBufferMap.clear();
  628. }
  629. group->mLastUpdateTime = gFrameTimeSeconds;
  630. group->clearState(LLSpatialGroup::GEOM_DIRTY);
  631. }
  632. //virtual
  633. void LLParticlePartition::addGeometryCount(LLSpatialGroup* group,
  634. U32& vertex_count,
  635. U32& index_count)
  636. {
  637. mFaceList.clear();
  638. const LLVector3 camera_at_axis = gViewerCamera.getAtAxis();
  639. const LLVector3 camera_origin = gViewerCamera.getOrigin();
  640. for (LLSpatialGroup::element_iter i = group->getDataBegin(),
  641. end = group->getDataEnd();
  642. i != end; ++i)
  643. {
  644. LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
  645. if (!drawablep || drawablep->isDead())
  646. {
  647. continue;
  648. }
  649. LLAlphaObject* obj = drawablep->getVObj().get()->asAlphaObject();
  650. if (!obj)
  651. {
  652. llwarns_once << "Not an alpha object for drawable " << std::hex
  653. << drawablep << std::dec << llendl;
  654. continue;
  655. }
  656. obj->mDepth = 0.f;
  657. U32 count = 0;
  658. for (S32 j = 0, faces = drawablep->getNumFaces(); j < faces; ++j)
  659. {
  660. drawablep->updateFaceSize(j);
  661. LLFace* facep = drawablep->getFace(j);
  662. if (!facep || !facep->hasGeometry())
  663. {
  664. continue;
  665. }
  666. vertex_count += facep->getGeomCount();
  667. index_count += facep->getIndicesCount();
  668. ++count;
  669. facep->mDistance = (facep->mCenterLocal - camera_origin) *
  670. camera_at_axis;
  671. obj->mDepth += facep->mDistance;
  672. mFaceList.push_back(facep);
  673. llassert(facep->getIndicesCount() < 65536);
  674. }
  675. obj->mDepth /= count;
  676. }
  677. }
  678. //virtual
  679. void LLParticlePartition::getGeometry(LLSpatialGroup* group)
  680. {
  681. LL_FAST_TIMER(FTM_REBUILD_PARTICLE_GEOM);
  682. std::sort(mFaceList.begin(), mFaceList.end(),
  683. LLFace::CompareDistanceGreater());
  684. group->clearDrawMap();
  685. LLVertexBuffer* buffer = group->mVertexBuffer.get();
  686. if (!buffer)
  687. {
  688. return;
  689. }
  690. LLStrider<LLVector4a> verticesp;
  691. LLStrider<LLVector3> normalsp;
  692. LLStrider<LLColor4U> colorsp;
  693. LLStrider<LLColor4U> emissivep;
  694. if (!buffer->getVertexStrider(verticesp) ||
  695. !buffer->getNormalStrider(normalsp) ||
  696. !buffer->getColorStrider(colorsp) ||
  697. !buffer->getEmissiveStrider(emissivep))
  698. {
  699. return;
  700. }
  701. S32 geom_idx = 0;
  702. S32 indices_idx = 0;
  703. LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
  704. for (U32 i = 0, count = mFaceList.size(); i < count; ++i)
  705. {
  706. LLFace* facep = mFaceList[i];
  707. LLAlphaObject* object = facep->getViewerObject()->asAlphaObject();
  708. if (!object)
  709. {
  710. llwarns_once << "Not an alpha object for face " << std::hex
  711. << facep << std::dec << llendl;
  712. continue;
  713. }
  714. facep->setGeomIndex(geom_idx);
  715. facep->setIndicesIndex(indices_idx);
  716. LLStrider<LLVector4a> cur_vert = verticesp + geom_idx;
  717. LLStrider<LLVector3> cur_norm = normalsp + geom_idx;
  718. LLStrider<LLColor4U> cur_col = colorsp + geom_idx;
  719. LLStrider<LLColor4U> cur_glow = emissivep + geom_idx;
  720. // Not actually used
  721. LLStrider<LLVector2> cur_tc;
  722. LLStrider<U16> cur_idx;
  723. geom_idx += 4;
  724. indices_idx += 6;
  725. LLColor4U* start_glow = cur_glow.get();
  726. object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc,
  727. cur_col, cur_glow, cur_idx);
  728. bool has_glow = cur_glow.get() != start_glow;
  729. llassert(facep->getGeomCount() == 4 && facep->getIndicesCount() == 6);
  730. S32 idx = draw_vec.size() - 1;
  731. bool fullbright = facep->isState(LLFace::FULLBRIGHT);
  732. F32 vsize = facep->getVirtualSize();
  733. U32 bf_src = LLRender::BF_SOURCE_ALPHA;
  734. U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
  735. if (!object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst))
  736. {
  737. continue;
  738. }
  739. bool batched = false;
  740. if (idx >= 0)
  741. {
  742. LLDrawInfo* info = draw_vec[idx];
  743. if (info->mTexture == facep->getTexture() &&
  744. info->mHasGlow == has_glow &&
  745. info->mFullbright == fullbright &&
  746. info->mBlendFuncDst == bf_dst &&
  747. info->mBlendFuncSrc == bf_src)
  748. {
  749. if (info->mEnd == facep->getGeomIndex() - 1)
  750. {
  751. batched = true;
  752. info->mCount += facep->getIndicesCount();
  753. info->mEnd += facep->getGeomCount();
  754. info->mVSize = llmax(info->mVSize, vsize);
  755. }
  756. else if (info->mStart == facep->getGeomIndex() +
  757. facep->getGeomCount() + 1)
  758. {
  759. batched = true;
  760. info->mCount += facep->getIndicesCount();
  761. info->mStart -= facep->getGeomCount();
  762. info->mOffset = facep->getIndicesStart();
  763. info->mVSize = llmax(info->mVSize, vsize);
  764. }
  765. }
  766. }
  767. if (!batched)
  768. {
  769. U32 start = facep->getGeomIndex();
  770. U32 end = start + facep->getGeomCount() - 1;
  771. U32 offset = facep->getIndicesStart();
  772. U32 count = facep->getIndicesCount();
  773. LLDrawInfo* info = new LLDrawInfo(start, end, count, offset,
  774. facep->getTexture(), buffer,
  775. fullbright);
  776. const LLVector4a* exts = group->getObjectExtents();
  777. info->mExtents[0] = exts[0];
  778. info->mExtents[1] = exts[1];
  779. info->mVSize = vsize;
  780. info->mBlendFuncDst = bf_dst;
  781. info->mBlendFuncSrc = bf_src;
  782. info->mHasGlow = has_glow;
  783. draw_vec.emplace_back(info);
  784. // For alpha sorting
  785. facep->setDrawInfo(info);
  786. }
  787. }
  788. buffer->unmapBuffer();
  789. mFaceList.clear();
  790. }
  791. LLDrawable* LLVOHUDPartGroup::createDrawable()
  792. {
  793. gPipeline.allocDrawable(this);
  794. mDrawable->setLit(false);
  795. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
  796. return mDrawable;
  797. }