llviewerpartsource.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. /**
  2. * @file llviewerpartsource.cpp
  3. * @brief LLViewerPartSource class implementation
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-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 "llviewerpartsource.h"
  34. #include "llrender.h"
  35. #include "llagent.h"
  36. #include "lldrawable.h"
  37. #include "llpipeline.h"
  38. #include "llviewercamera.h"
  39. #include "llviewercontrol.h"
  40. #include "llviewerobjectlist.h"
  41. #include "llviewertexturelist.h"
  42. #include "llworld.h"
  43. static LLVOAvatar* find_avatar(const LLUUID& id)
  44. {
  45. LLViewerObject* obj = gObjectList.findObject(id);
  46. while (obj && obj->isAttachment())
  47. {
  48. obj = (LLViewerObject*)obj->getParent();
  49. }
  50. if (obj && obj->isAvatar())
  51. {
  52. return (LLVOAvatar*)obj;
  53. }
  54. return NULL;
  55. }
  56. ///////////////////////////////////////////////////////////////////////////////
  57. // LLViewerPartSource base class
  58. ///////////////////////////////////////////////////////////////////////////////
  59. LLViewerPartSource::LLViewerPartSource(U32 type)
  60. : mType(type),
  61. mOwnerUUID(LLUUID::null),
  62. mLastPart(NULL),
  63. mPartFlags(0),
  64. mIsDead(false),
  65. mIsSuspended(false),
  66. mLastUpdateTime(0.f),
  67. mLastPartTime(0.f),
  68. mDistFromCamera(0.f),
  69. mDelay(0),
  70. mPartCount(0),
  71. mPartUpdates(1)
  72. {
  73. static U32 id_seed = 0;
  74. mID = ++id_seed;
  75. }
  76. void LLViewerPartSource::setDead()
  77. {
  78. mIsDead = true;
  79. }
  80. const LLUUID& LLViewerPartSource::getImageUUID() const
  81. {
  82. return mImagep.notNull() ? mImagep->getID() : LLUUID::null;
  83. }
  84. void LLViewerPartSource::incPartCount()
  85. {
  86. if (++mPartCount > U32_MAX)
  87. {
  88. mPartCount /= mPartUpdates;
  89. mPartUpdates = 1;
  90. }
  91. }
  92. U64 LLViewerPartSource::getAveragePartCount()
  93. {
  94. return mPartCount / mPartUpdates;
  95. }
  96. //static
  97. void LLViewerPartSource::updatePart(LLViewerPart& part, F32 dt)
  98. {
  99. }
  100. ///////////////////////////////////////////////////////////////////////////////
  101. // LLViewerPartSourceScript sub-class
  102. ///////////////////////////////////////////////////////////////////////////////
  103. LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject* source_objp)
  104. : LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
  105. {
  106. llassert(source_objp);
  107. mSourceObjectp = source_objp;
  108. mPosAgent = mSourceObjectp->getPositionAgent();
  109. mImagep = gImgPixieSmall;
  110. mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
  111. LLMuteList::addObserver(this);
  112. }
  113. LLViewerPartSourceScript::~LLViewerPartSourceScript()
  114. {
  115. LLMuteList::removeObserver(this);
  116. }
  117. void LLViewerPartSourceScript::setDead()
  118. {
  119. mIsDead = true;
  120. mSourceObjectp = NULL;
  121. mTargetObjectp = NULL;
  122. }
  123. //virtual
  124. void LLViewerPartSourceScript::onChange()
  125. {
  126. if ((mOwnerUUID.notNull() &&
  127. LLMuteList::isMuted(mOwnerUUID, LLMute::flagParticles)) ||
  128. (mSourceObjectp.notNull() &&
  129. LLMuteList::isMuted(mSourceObjectp->getID())))
  130. {
  131. // Kill particle source because it has been muted !
  132. setDead();
  133. }
  134. }
  135. void LLViewerPartSourceScript::update(F32 dt)
  136. {
  137. if (mIsSuspended)
  138. {
  139. return;
  140. }
  141. // By default (for particles that will not be updated), set a far distance
  142. mDistFromCamera = 1024.f;
  143. if (mOwnerAvatarp.isNull() && mOwnerUUID.notNull())
  144. {
  145. mOwnerAvatarp = find_avatar(mOwnerUUID);
  146. }
  147. if (mOwnerAvatarp.notNull() &&
  148. mOwnerAvatarp->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER)
  149. {
  150. return;
  151. }
  152. F32 old_update_time = mLastUpdateTime;
  153. mLastUpdateTime += dt;
  154. F32 travelspeed = llmin(gViewerPartSim.getRefRate(), 1.f);
  155. F32 dt_update = mLastUpdateTime - mLastPartTime;
  156. // Update this for objects which have the follow flag set...
  157. if (mSourceObjectp.notNull())
  158. {
  159. if (mSourceObjectp->isDead())
  160. {
  161. mSourceObjectp = NULL;
  162. }
  163. else if (mSourceObjectp->mDrawable.notNull())
  164. {
  165. mPosAgent = mSourceObjectp->getRenderPosition();
  166. }
  167. }
  168. if (mTargetObjectp.isNull() && mPartSysData.mTargetUUID.notNull())
  169. {
  170. // Hmm, missing object, let's see if we can find it...
  171. LLViewerObject* target_objp =
  172. gObjectList.findObject(mPartSysData.mTargetUUID);
  173. setTargetObject(target_objp);
  174. }
  175. if (mTargetObjectp.notNull())
  176. {
  177. if (mTargetObjectp->isDead())
  178. {
  179. mTargetObjectp = NULL;
  180. }
  181. else if (mTargetObjectp->mDrawable.notNull())
  182. {
  183. mTargetPosAgent = mTargetObjectp->getRenderPosition();
  184. }
  185. }
  186. if (mTargetObjectp.isNull())
  187. {
  188. mTargetPosAgent = mPosAgent;
  189. }
  190. if (mPartSysData.mMaxAge &&
  191. mPartSysData.mStartAge + mLastUpdateTime + dt_update > mPartSysData.mMaxAge)
  192. {
  193. // Kill particle source because it has outlived its max age...
  194. setDead();
  195. return;
  196. }
  197. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
  198. {
  199. if (mSourceObjectp.notNull())
  200. {
  201. std::ostringstream ostr;
  202. ostr << mPartSysData;
  203. mSourceObjectp->setDebugText(ostr.str());
  204. }
  205. }
  206. bool first_run = false;
  207. if (old_update_time <= 0.f)
  208. {
  209. first_run = true;
  210. // Check we are not already muted...
  211. onChange();
  212. if (mIsDead) return;
  213. }
  214. // Distance from camera
  215. static LLCachedControl<F32> far_clip(gSavedSettings, "RenderFarClip");
  216. mDistFromCamera = (mPosAgent - gViewerCamera.getOrigin()).length();
  217. if (mDistFromCamera > far_clip)
  218. {
  219. // Do not even bother !
  220. LL_DEBUGS("Particles") << "Particle source " << mID
  221. << " skipped because it is too far away."
  222. << LL_ENDL;
  223. return;
  224. }
  225. F32 pixel_meter_ratio = gViewerCamera.getPixelMeterRatio();
  226. F32 max_time = llmax(1.f, 10.f * mPartSysData.mBurstRate);
  227. dt_update = llmin(max_time, dt_update);
  228. while (dt_update > mPartSysData.mBurstRate || first_run)
  229. {
  230. first_run = false;
  231. // Update the rotation of the particle source by the angular velocity
  232. // First check to see if there is still an angular velocity.
  233. F32 angular_velocity_mag = mPartSysData.mAngularVelocity.length();
  234. if (angular_velocity_mag != 0.f)
  235. {
  236. F32 av_angle = dt * angular_velocity_mag;
  237. LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
  238. mRotation *= dquat;
  239. }
  240. else
  241. {
  242. // No angular velocity. Reset our rotation.
  243. mRotation.setEulerAngles(0.f, 0.f, 0.f);
  244. }
  245. if (LLViewerPartSim::aboveParticleLimit())
  246. {
  247. // Do not bother doing any more updates if we are above the
  248. // particle limit, just give up.
  249. mLastPartTime = mLastUpdateTime;
  250. break;
  251. }
  252. // Find the greatest length that the shortest side of a system particle
  253. // is expected to have
  254. F32 max_short_side =
  255. llmax(llmax(llmin(mPartSysData.mPartData.mStartScale[0],
  256. mPartSysData.mPartData.mStartScale[1]),
  257. llmin(mPartSysData.mPartData.mEndScale[0],
  258. mPartSysData.mPartData.mEndScale[1])),
  259. llmin((mPartSysData.mPartData.mStartScale[0] +
  260. mPartSysData.mPartData.mEndScale[0]) * 0.5f,
  261. (mPartSysData.mPartData.mStartScale[1] +
  262. mPartSysData.mPartData.mEndScale[1]) * 0.5f));
  263. // Maximum distance at which spawned particles will be viewable
  264. F32 max_dist = max_short_side * pixel_meter_ratio;
  265. if (max_dist < 0.25f)
  266. {
  267. // < 1 pixel wide at a distance of >= 25cm. Particles this tiny are
  268. // useless and mostly spawned by buggy sources
  269. mLastPartTime = mLastUpdateTime;
  270. LL_DEBUGS("Particles") << "Particle source " << mID
  271. << " skipped because it is too small."
  272. << LL_ENDL;
  273. break;
  274. }
  275. // Particle size vs distance vs maxage throttling
  276. F32 limited_rate = 0.f;
  277. if (mDistFromCamera - max_dist > 0.f)
  278. {
  279. F32 max_age = mPartSysData.mPartData.mMaxAge;
  280. if ((mDistFromCamera - max_dist) * travelspeed > max_age - 0.2f)
  281. {
  282. // You need to travel faster than 1 divided by reference rate
  283. // m/s directly towards these particles to see them at least
  284. // 0.2s.
  285. LL_DEBUGS("Particles") << "Particle source " << mID
  286. << " skipped because it won't have time to show up."
  287. << LL_ENDL;
  288. mLastPartTime = mLastUpdateTime;
  289. break;
  290. }
  291. limited_rate = (mDistFromCamera - max_dist) * travelspeed / max_age;
  292. }
  293. if (mDelay)
  294. {
  295. limited_rate = llmax(limited_rate, 0.01f * mDelay--);
  296. }
  297. bool ribbon = (mPartSysData.mPartData.mFlags &
  298. LLPartData::LL_PART_RIBBON_MASK) != 0;
  299. for (S32 i = 0; i < mPartSysData.mBurstPartCount; ++i)
  300. {
  301. F32 burst_rate = gViewerPartSim.getBurstRate();
  302. if (burst_rate == 0.f)
  303. {
  304. LL_DEBUGS("Particles") << "Particle source " << mID
  305. << " skipped because MAX_PART_COUNT was reached."
  306. << LL_ENDL;
  307. break; // Do not insist, we reached MAX_PART_COUNT...
  308. }
  309. // Always create at least one particle
  310. if (i > 0 && ll_frand() < llmax(1.f - burst_rate, limited_rate))
  311. {
  312. // Limit particle generation
  313. continue;
  314. }
  315. if (ribbon && mLastPart &&
  316. (mLastPart->mPosAgent - mPosAgent).length() <= .005f)
  317. {
  318. // Do not generate a new ribbon particle if its length is too
  319. // small to be visible
  320. continue;
  321. }
  322. LLViewerPart* part = new LLViewerPart();
  323. part->init(this, mImagep, NULL);
  324. part->mFlags = mPartSysData.mPartData.mFlags;
  325. if (mSourceObjectp.notNull() && mSourceObjectp->isHUDAttachment())
  326. {
  327. part->mFlags |= LLPartData::LL_PART_HUD;
  328. }
  329. if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart)
  330. {
  331. // Set previous particle parent to this particle to chain
  332. // ribbons together
  333. mLastPart->mParent = part;
  334. part->mChild = mLastPart;
  335. part->mAxis = LLVector3::z_axis;
  336. if (mSourceObjectp.notNull())
  337. {
  338. LLQuaternion rot = mSourceObjectp->getRenderRotation();
  339. part->mAxis *= rot;
  340. }
  341. }
  342. mLastPart = part;
  343. part->mMaxAge = mPartSysData.mPartData.mMaxAge;
  344. part->mStartColor = mPartSysData.mPartData.mStartColor;
  345. part->mEndColor = mPartSysData.mPartData.mEndColor;
  346. part->mColor = part->mStartColor;
  347. part->mStartScale = mPartSysData.mPartData.mStartScale;
  348. part->mEndScale = mPartSysData.mPartData.mEndScale;
  349. part->mScale = part->mStartScale;
  350. part->mAccel = mPartSysData.mPartAccel;
  351. part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest;
  352. part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource;
  353. part->mStartGlow = mPartSysData.mPartData.mStartGlow;
  354. part->mEndGlow = mPartSysData.mPartData.mEndGlow;
  355. part->mGlow = LLColor4U(0, 0, 0,
  356. (U8)ll_roundp(part->mStartGlow * 255.f));
  357. if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
  358. {
  359. part->mPosAgent = mPosAgent;
  360. part->mVelocity.clear();
  361. }
  362. else if (mPartSysData.mPattern &
  363. LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
  364. {
  365. part->mPosAgent = mPosAgent;
  366. LLVector3 part_dir_vector;
  367. F32 mvs;
  368. do
  369. {
  370. part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
  371. part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
  372. part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
  373. mvs = part_dir_vector.lengthSquared();
  374. }
  375. while (mvs > 1.f || mvs < 0.01f);
  376. part_dir_vector.normalize();
  377. part->mPosAgent += mPartSysData.mBurstRadius * part_dir_vector;
  378. part->mVelocity = part_dir_vector;
  379. F32 speed = mPartSysData.mBurstSpeedMin +
  380. ll_frand(mPartSysData.mBurstSpeedMax -
  381. mPartSysData.mBurstSpeedMin);
  382. part->mVelocity *= speed;
  383. }
  384. else if ((mPartSysData.mPattern &
  385. LLPartSysData::LL_PART_SRC_PATTERN_ANGLE) ||
  386. (mPartSysData.mPattern &
  387. LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE))
  388. {
  389. part->mPosAgent = mPosAgent;
  390. // Original implemenetation for part_dir_vector was just:
  391. LLVector3 part_dir_vector = LLVector3::z_axis;
  392. // params from the script...
  393. // outer = outer cone angle
  394. // inner = inner cone angle
  395. // between outer and inner there will be particles
  396. F32 inner_angle = mPartSysData.mInnerAngle;
  397. F32 outer_angle = mPartSysData.mOuterAngle;
  398. // Generate a random angle within the given space...
  399. F32 angle = inner_angle + ll_frand(outer_angle - inner_angle);
  400. // Split which side it will go on randomly...
  401. if (ll_frand() < 0.5)
  402. {
  403. angle = -angle;
  404. }
  405. // Both patterns rotate around the x-axis first:
  406. part_dir_vector.rotVec(angle, 1.f, 0.f, 0.f);
  407. // If this is a cone pattern, rotate again to create the cone.
  408. if (mPartSysData.mPattern &
  409. LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
  410. {
  411. part_dir_vector.rotVec(ll_frand(4 * F_PI), 0.f, 0.f, 1.f);
  412. }
  413. // Only apply this rotation if using the deprecated angles.
  414. if (!(mPartSysData.mFlags &
  415. LLPartSysData::LL_PART_USE_NEW_ANGLE))
  416. {
  417. // Deprecated...
  418. part_dir_vector.rotVec(outer_angle, 1.f, 0.f, 0.f);
  419. }
  420. if (mSourceObjectp)
  421. {
  422. part_dir_vector = part_dir_vector *
  423. mSourceObjectp->getRenderRotation();
  424. }
  425. part_dir_vector = part_dir_vector * mRotation;
  426. part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
  427. part->mVelocity = part_dir_vector;
  428. F32 speed = mPartSysData.mBurstSpeedMin +
  429. ll_frand(mPartSysData.mBurstSpeedMax -
  430. mPartSysData.mBurstSpeedMin);
  431. part->mVelocity *= speed;
  432. }
  433. else
  434. {
  435. part->mPosAgent = mPosAgent;
  436. part->mVelocity.set(0.f, 0.f, 0.f);
  437. LL_DEBUGS("Particles") << "Unknown source pattern: "
  438. << (S32)mPartSysData.mPattern
  439. << LL_ENDL;
  440. }
  441. if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK ||
  442. part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
  443. {
  444. mPartSysData.mBurstRadius = 0;
  445. }
  446. gViewerPartSim.addPart(part);
  447. }
  448. mLastPartTime = mLastUpdateTime;
  449. dt_update -= mPartSysData.mBurstRate;
  450. }
  451. }
  452. //static
  453. LLPointer<LLViewerPartSourceScript>
  454. LLViewerPartSourceScript::unpackPSS(LLViewerObject* source_objp,
  455. LLPointer<LLViewerPartSourceScript> pssp,
  456. S32 block_num)
  457. {
  458. if (LLPartSysData::isNullPS(block_num))
  459. {
  460. return NULL;
  461. }
  462. if (!pssp)
  463. {
  464. LLPointer<LLViewerPartSourceScript> new_pssp =
  465. new LLViewerPartSourceScript(source_objp);
  466. if (!new_pssp->mPartSysData.unpackBlock(block_num))
  467. {
  468. return NULL;
  469. }
  470. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  471. {
  472. LLViewerObject* target_objp =
  473. gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  474. new_pssp->setTargetObject(target_objp);
  475. }
  476. return new_pssp;
  477. }
  478. if (!pssp->mPartSysData.unpackBlock(block_num))
  479. {
  480. return NULL;
  481. }
  482. F32 prev_max_age = pssp->mPartSysData.mMaxAge;
  483. F32 prev_start_age = pssp->mPartSysData.mStartAge;
  484. if (pssp->mPartSysData.mMaxAge &&
  485. (prev_max_age != pssp->mPartSysData.mMaxAge ||
  486. prev_start_age != pssp->mPartSysData.mStartAge))
  487. {
  488. // Reusing existing pss, so reset time to allow particles to start
  489. // again
  490. pssp->mLastUpdateTime = pssp->mLastPartTime = 0.f;
  491. }
  492. if (pssp->mPartSysData.mTargetUUID.notNull())
  493. {
  494. LLViewerObject* target_objp =
  495. gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
  496. pssp->setTargetObject(target_objp);
  497. }
  498. return pssp;
  499. }
  500. LLPointer<LLViewerPartSourceScript>
  501. LLViewerPartSourceScript::unpackPSS(LLViewerObject* source_objp,
  502. LLPointer<LLViewerPartSourceScript> pssp,
  503. LLDataPacker& dp, bool legacy)
  504. {
  505. if (!pssp)
  506. {
  507. LLPointer<LLViewerPartSourceScript> new_pssp =
  508. new LLViewerPartSourceScript(source_objp);
  509. bool res = legacy ? new_pssp->mPartSysData.unpackLegacy(dp)
  510. : new_pssp->mPartSysData.unpack(dp);
  511. if (!res)
  512. {
  513. return NULL;
  514. }
  515. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  516. {
  517. LLViewerObject* target_objp =
  518. gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  519. new_pssp->setTargetObject(target_objp);
  520. }
  521. return new_pssp;
  522. }
  523. bool res = legacy ? pssp->mPartSysData.unpackLegacy(dp)
  524. : pssp->mPartSysData.unpack(dp);
  525. if (!res)
  526. {
  527. return NULL;
  528. }
  529. if (pssp->mPartSysData.mTargetUUID.notNull())
  530. {
  531. LLViewerObject* target_objp =
  532. gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
  533. pssp->setTargetObject(target_objp);
  534. }
  535. return pssp;
  536. }
  537. //static
  538. LLPointer<LLViewerPartSourceScript>
  539. LLViewerPartSourceScript::createPSS(LLViewerObject* source_objp,
  540. const LLPartSysData& part_params)
  541. {
  542. LLPointer<LLViewerPartSourceScript> new_pssp =
  543. new LLViewerPartSourceScript(source_objp);
  544. new_pssp->mPartSysData = part_params;
  545. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  546. {
  547. LLViewerObject* target_objp =
  548. gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  549. new_pssp->setTargetObject(target_objp);
  550. }
  551. return new_pssp;
  552. }
  553. ///////////////////////////////////////////////////////////////////////////////
  554. // LLViewerPartSourceSpiral sub-class
  555. ///////////////////////////////////////////////////////////////////////////////
  556. LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3& pos)
  557. : LLViewerPartSource(LL_PART_SOURCE_CHAT)
  558. {
  559. mPosAgent = pos;
  560. }
  561. void LLViewerPartSourceSpiral::setDead()
  562. {
  563. mIsDead = true;
  564. mSourceObjectp = NULL;
  565. }
  566. //static
  567. void LLViewerPartSourceSpiral::updatePart(LLViewerPart& part, F32 dt)
  568. {
  569. F32 frac = part.mLastUpdateTime / part.mMaxAge;
  570. LLVector3 center_pos;
  571. LLViewerPartSourceSpiral* pss =
  572. (LLViewerPartSourceSpiral*)part.mPartSourcep.get();
  573. if (pss->mSourceObjectp.notNull() &&
  574. pss->mSourceObjectp->mDrawable.notNull())
  575. {
  576. part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
  577. }
  578. else
  579. {
  580. part.mPosAgent = pss->mPosAgent;
  581. }
  582. F32 x = sinf(F_TWO_PI * frac + part.mParameter);
  583. F32 y = cosf(F_TWO_PI * frac + part.mParameter);
  584. part.mPosAgent.mV[VX] += x;
  585. part.mPosAgent.mV[VY] += y;
  586. part.mPosAgent.mV[VZ] += -0.5f + frac;
  587. }
  588. void LLViewerPartSourceSpiral::update(F32 dt)
  589. {
  590. if (!mImagep)
  591. {
  592. mImagep = gImgPixieSmall;
  593. }
  594. constexpr F32 RATE = 0.025f;
  595. mLastUpdateTime += dt;
  596. F32 dt_update = mLastUpdateTime - mLastPartTime;
  597. F32 max_time = llmax(1.f, 10.f * RATE);
  598. dt_update = llmin(max_time, dt_update);
  599. if (dt_update > RATE)
  600. {
  601. mLastPartTime = mLastUpdateTime;
  602. if (!LLViewerPartSim::shouldAddPart())
  603. {
  604. // Particle simulation says we have too many particles, skip all
  605. // this
  606. return;
  607. }
  608. if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
  609. {
  610. mPosAgent = mSourceObjectp->getRenderPosition();
  611. }
  612. LLViewerPart* part = new LLViewerPart();
  613. part->init(this, mImagep, updatePart);
  614. part->mStartColor = mColor;
  615. part->mEndColor = mColor;
  616. part->mEndColor.mV[3] = 0.f;
  617. part->mPosAgent = mPosAgent;
  618. part->mMaxAge = 1.f;
  619. part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
  620. part->mLastUpdateTime = 0.f;
  621. part->mScale.mV[0] = part->mScale.mV[1] = 0.25f;
  622. part->mParameter = ll_frand(F_TWO_PI);
  623. part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
  624. part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
  625. part->mStartGlow = part->mEndGlow = 0.f;
  626. part->mGlow = LLColor4U(0, 0, 0, 0);
  627. gViewerPartSim.addPart(part);
  628. }
  629. }
  630. ///////////////////////////////////////////////////////////////////////////////
  631. // LLViewerPartSourceBeam sub-class
  632. ///////////////////////////////////////////////////////////////////////////////
  633. LLViewerPartSourceBeam::LLViewerPartSourceBeam()
  634. : LLViewerPartSource(LL_PART_SOURCE_BEAM)
  635. {
  636. }
  637. void LLViewerPartSourceBeam::setDead()
  638. {
  639. mIsDead = true;
  640. mSourceObjectp = NULL;
  641. mTargetObjectp = NULL;
  642. }
  643. //static
  644. void LLViewerPartSourceBeam::updatePart(LLViewerPart& part, F32 dt)
  645. {
  646. F32 frac = part.mLastUpdateTime/part.mMaxAge;
  647. LLViewerPartSourceBeam* psb =
  648. (LLViewerPartSourceBeam*)part.mPartSourcep.get();
  649. if (psb->mSourceObjectp.isNull())
  650. {
  651. part.mFlags = LLPartData::LL_PART_DEAD_MASK;
  652. return;
  653. }
  654. LLVector3 source_pos_agent;
  655. LLVector3 target_pos_agent;
  656. if (psb->mSourceObjectp.notNull() &&
  657. psb->mSourceObjectp->mDrawable.notNull())
  658. {
  659. if (psb->mSourceObjectp->isAvatar())
  660. {
  661. LLViewerObject* objp = psb->mSourceObjectp;
  662. LLVOAvatar* avp = (LLVOAvatar*)objp;
  663. source_pos_agent = avp->mWristLeftp->getWorldPosition();
  664. }
  665. else
  666. {
  667. source_pos_agent = psb->mSourceObjectp->getRenderPosition();
  668. }
  669. }
  670. if (psb->mTargetObjectp.notNull() &&
  671. psb->mTargetObjectp->mDrawable.notNull())
  672. {
  673. target_pos_agent = psb->mTargetObjectp->getRenderPosition();
  674. }
  675. part.mPosAgent = (1.f - frac) * source_pos_agent;
  676. if (psb->mTargetObjectp.isNull())
  677. {
  678. part.mPosAgent += frac *
  679. gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal);
  680. }
  681. else
  682. {
  683. part.mPosAgent += frac * target_pos_agent;
  684. }
  685. }
  686. void LLViewerPartSourceBeam::update(F32 dt)
  687. {
  688. mLastUpdateTime += dt;
  689. if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
  690. {
  691. if (mSourceObjectp->isAvatar())
  692. {
  693. LLViewerObject* objp = mSourceObjectp;
  694. LLVOAvatar* avp = (LLVOAvatar*)objp;
  695. mPosAgent = avp->mWristLeftp->getWorldPosition();
  696. }
  697. else
  698. {
  699. mPosAgent = mSourceObjectp->getRenderPosition();
  700. }
  701. }
  702. if (mTargetObjectp.notNull() && mTargetObjectp->mDrawable.notNull())
  703. {
  704. mTargetPosAgent = mTargetObjectp->getRenderPosition();
  705. }
  706. else if (!mLKGTargetPosGlobal.isExactlyZero())
  707. {
  708. mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
  709. }
  710. F32 dt_update = mLastUpdateTime - mLastPartTime;
  711. constexpr F32 RATE = 0.025f;
  712. F32 max_time = llmax(1.f, 10.f * RATE);
  713. dt_update = llmin(max_time, dt_update);
  714. if (dt_update <= RATE)
  715. {
  716. return;
  717. }
  718. mLastPartTime = mLastUpdateTime;
  719. if (!LLViewerPartSim::shouldAddPart())
  720. {
  721. // Particle simulation says we have too many particles, skip all this
  722. return;
  723. }
  724. if (!mImagep)
  725. {
  726. mImagep = gImgPixieSmall;
  727. }
  728. LLViewerPart* part = new LLViewerPart();
  729. part->init(this, mImagep, updatePart);
  730. part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
  731. LLPartData::LL_PART_INTERP_SCALE_MASK |
  732. LLPartData::LL_PART_TARGET_POS_MASK |
  733. LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
  734. part->mMaxAge = 0.5f;
  735. part->mStartColor = mColor;
  736. part->mEndColor = part->mStartColor;
  737. part->mEndColor.mV[3] = 0.4f;
  738. part->mColor = part->mStartColor;
  739. part->mStartScale = LLVector2(0.1f, 0.1f);
  740. part->mEndScale = LLVector2(0.1f, 0.1f);
  741. part->mScale = part->mStartScale;
  742. part->mPosAgent = mPosAgent;
  743. part->mVelocity = mTargetPosAgent - mPosAgent;
  744. part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
  745. part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
  746. part->mStartGlow = 0.f;
  747. part->mEndGlow = 0.f;
  748. part->mGlow = LLColor4U(0, 0, 0, 0);
  749. gViewerPartSim.addPart(part);
  750. }
  751. ///////////////////////////////////////////////////////////////////////////////
  752. // LLViewerPartSourceChat sub-class
  753. ///////////////////////////////////////////////////////////////////////////////
  754. LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3& pos)
  755. : LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
  756. {
  757. mPosAgent = pos;
  758. }
  759. void LLViewerPartSourceChat::setDead()
  760. {
  761. mIsDead = true;
  762. mSourceObjectp = NULL;
  763. }
  764. //static
  765. void LLViewerPartSourceChat::updatePart(LLViewerPart& part, F32 dt)
  766. {
  767. F32 frac = part.mLastUpdateTime / part.mMaxAge;
  768. LLVector3 center_pos;
  769. LLViewerPartSourceChat* pss =
  770. (LLViewerPartSourceChat*)part.mPartSourcep.get();
  771. if (pss->mSourceObjectp.notNull() &&
  772. pss->mSourceObjectp->mDrawable.notNull())
  773. {
  774. part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
  775. }
  776. else
  777. {
  778. part.mPosAgent = pss->mPosAgent;
  779. }
  780. F32 x = sinf(F_TWO_PI * frac + part.mParameter);
  781. F32 y = cosf(F_TWO_PI * frac + part.mParameter);
  782. part.mPosAgent.mV[VX] += x;
  783. part.mPosAgent.mV[VY] += y;
  784. part.mPosAgent.mV[VZ] += -0.5f + frac;
  785. }
  786. void LLViewerPartSourceChat::update(F32 dt)
  787. {
  788. if (!mImagep)
  789. {
  790. mImagep = gImgPixieSmall;
  791. }
  792. mLastUpdateTime += dt;
  793. if (mLastUpdateTime > 2.f)
  794. {
  795. // Kill particle source because it has outlived its max age...
  796. setDead();
  797. return;
  798. }
  799. F32 dt_update = mLastUpdateTime - mLastPartTime;
  800. // Clamp us to generating at most one second's worth of particles on a
  801. // frame
  802. constexpr F32 RATE = 0.025f;
  803. F32 max_time = llmax(1.f, 10.f * RATE);
  804. dt_update = llmin(max_time, dt_update);
  805. if (dt_update > RATE)
  806. {
  807. mLastPartTime = mLastUpdateTime;
  808. if (!LLViewerPartSim::shouldAddPart())
  809. {
  810. // Particle simulation says we have too many particles, skip all this
  811. return;
  812. }
  813. if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
  814. {
  815. mPosAgent = mSourceObjectp->getRenderPosition();
  816. }
  817. LLViewerPart* part = new LLViewerPart();
  818. part->init(this, mImagep, updatePart);
  819. part->mStartColor = mColor;
  820. part->mEndColor = mColor;
  821. part->mEndColor.mV[3] = 0.f;
  822. part->mPosAgent = mPosAgent;
  823. part->mMaxAge = 1.f;
  824. part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
  825. part->mLastUpdateTime = 0.f;
  826. part->mScale.mV[0] = part->mScale.mV[1] = 0.25f;
  827. part->mParameter = ll_frand(F_TWO_PI);
  828. part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
  829. part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
  830. part->mStartGlow = part->mEndGlow = 0.f;
  831. part->mGlow = LLColor4U(0, 0, 0, 0);
  832. gViewerPartSim.addPart(part);
  833. }
  834. }