/indra/newview/llviewerpartsource.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 865 lines · 655 code · 143 blank · 67 comment · 89 complexity · 90516a456c26a0e9ede9a0acf2e989d8 MD5 · raw file

  1. /**
  2. * @file llviewerpartsource.cpp
  3. * @brief LLViewerPartSource class implementation
  4. *
  5. * $LicenseInfo:firstyear=2003&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 "llviewerpartsource.h"
  28. #include "llviewercontrol.h"
  29. #include "llrender.h"
  30. #include "llagent.h"
  31. #include "lldrawable.h"
  32. #include "llviewercamera.h"
  33. #include "llviewertexturelist.h"
  34. #include "llviewerobject.h"
  35. #include "llviewerobjectlist.h"
  36. #include "llvoavatar.h"
  37. #include "llworld.h"
  38. #include "pipeline.h"
  39. LLViewerPartSource::LLViewerPartSource(const U32 type) :
  40. mType(type),
  41. mOwnerUUID(LLUUID::null),
  42. mPartFlags(0)
  43. {
  44. mLastUpdateTime = 0.f;
  45. mLastPartTime = 0.f;
  46. mIsDead = FALSE;
  47. mIsSuspended = FALSE;
  48. static U32 id_seed = 0;
  49. mID = ++id_seed;
  50. mDelay = 0 ;
  51. }
  52. void LLViewerPartSource::setDead()
  53. {
  54. mIsDead = TRUE;
  55. }
  56. void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt)
  57. {
  58. }
  59. void LLViewerPartSource::update(const F32 dt)
  60. {
  61. llerrs << "Creating default part source!" << llendl;
  62. }
  63. LLUUID LLViewerPartSource::getImageUUID() const
  64. {
  65. LLViewerTexture* imagep = mImagep;
  66. if(imagep)
  67. {
  68. return imagep->getID();
  69. }
  70. return LLUUID::null;
  71. }
  72. void LLViewerPartSource::setStart()
  73. {
  74. //cancel delaying to start a new added particle source, because some particle source just emits for a short time.
  75. //however, canceling this might cause overall particle emmitting fluctuate for a while because the new added source jumps to
  76. //the current particle emmitting settings instantly. -->bao
  77. mDelay = 0 ; //99
  78. }
  79. LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
  80. LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
  81. {
  82. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  83. llassert(source_objp);
  84. mSourceObjectp = source_objp;
  85. mPosAgent = mSourceObjectp->getPositionAgent();
  86. mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
  87. mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
  88. }
  89. void LLViewerPartSourceScript::setDead()
  90. {
  91. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  92. mIsDead = TRUE;
  93. mSourceObjectp = NULL;
  94. mTargetObjectp = NULL;
  95. }
  96. void LLViewerPartSourceScript::update(const F32 dt)
  97. {
  98. if( mIsSuspended )
  99. return;
  100. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  101. F32 old_update_time = mLastUpdateTime;
  102. mLastUpdateTime += dt;
  103. F32 ref_rate_travelspeed = llmin(LLViewerPartSim::getInstance()->getRefRate(), 1.f);
  104. F32 dt_update = mLastUpdateTime - mLastPartTime;
  105. // Update this for objects which have the follow flag set...
  106. if (!mSourceObjectp.isNull())
  107. {
  108. if (mSourceObjectp->isDead())
  109. {
  110. mSourceObjectp = NULL;
  111. }
  112. else if (mSourceObjectp->mDrawable.notNull())
  113. {
  114. mPosAgent = mSourceObjectp->getRenderPosition();
  115. }
  116. }
  117. if (mTargetObjectp.isNull()
  118. && mPartSysData.mTargetUUID.notNull())
  119. {
  120. //
  121. // Hmm, missing object, let's see if we can find it...
  122. //
  123. LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID);
  124. setTargetObject(target_objp);
  125. }
  126. if (!mTargetObjectp.isNull())
  127. {
  128. if (mTargetObjectp->isDead())
  129. {
  130. mTargetObjectp = NULL;
  131. }
  132. else if (mTargetObjectp->mDrawable.notNull())
  133. {
  134. mTargetPosAgent = mTargetObjectp->getRenderPosition();
  135. }
  136. }
  137. if (!mTargetObjectp)
  138. {
  139. mTargetPosAgent = mPosAgent;
  140. }
  141. if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge))
  142. {
  143. // Kill particle source because it has outlived its max age...
  144. setDead();
  145. return;
  146. }
  147. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
  148. {
  149. if (mSourceObjectp.notNull())
  150. {
  151. std::ostringstream ostr;
  152. ostr << mPartSysData;
  153. mSourceObjectp->setDebugText(ostr.str());
  154. }
  155. }
  156. BOOL first_run = FALSE;
  157. if (old_update_time <= 0.f)
  158. {
  159. first_run = TRUE;
  160. }
  161. F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate);
  162. dt_update = llmin(max_time, dt_update);
  163. while ((dt_update > mPartSysData.mBurstRate) || first_run)
  164. {
  165. first_run = FALSE;
  166. // Update the rotation of the particle source by the angular velocity
  167. // First check to see if there is still an angular velocity.
  168. F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
  169. if (angular_velocity_mag != 0.0f)
  170. {
  171. F32 av_angle = dt * angular_velocity_mag;
  172. LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
  173. mRotation *= dquat;
  174. }
  175. else
  176. {
  177. // No angular velocity. Reset our rotation.
  178. mRotation.setQuat(0, 0, 0);
  179. }
  180. if (LLViewerPartSim::getInstance()->aboveParticleLimit())
  181. {
  182. // Don't bother doing any more updates if we're above the particle limit,
  183. // just give up.
  184. mLastPartTime = mLastUpdateTime;
  185. break;
  186. }
  187. // find the greatest length that the shortest side of a system
  188. // particle is expected to have
  189. F32 max_short_side =
  190. llmax(
  191. llmax(llmin(mPartSysData.mPartData.mStartScale[0],
  192. mPartSysData.mPartData.mStartScale[1]),
  193. llmin(mPartSysData.mPartData.mEndScale[0],
  194. mPartSysData.mPartData.mEndScale[1])),
  195. llmin((mPartSysData.mPartData.mStartScale[0]
  196. + mPartSysData.mPartData.mEndScale[0])/2,
  197. (mPartSysData.mPartData.mStartScale[1]
  198. + mPartSysData.mPartData.mEndScale[1])/2));
  199. F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
  200. // Maximum distance at which spawned particles will be viewable
  201. F32 max_dist = max_short_side * pixel_meter_ratio;
  202. if (max_dist < 0.25f)
  203. {
  204. // < 1 pixel wide at a distance of >=25cm. Particles
  205. // this tiny are useless and mostly spawned by buggy
  206. // sources
  207. mLastPartTime = mLastUpdateTime;
  208. break;
  209. }
  210. // Distance from camera
  211. F32 dist = (mPosAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
  212. // Particle size vs distance vs maxage throttling
  213. F32 limited_rate=0.f;
  214. if (dist - max_dist > 0.f)
  215. {
  216. if((dist - max_dist) * ref_rate_travelspeed > mPartSysData.mPartData.mMaxAge - 0.2f )
  217. {
  218. // You need to travel faster than 1 divided by reference rate m/s directly towards these particles to see them at least 0.2s
  219. mLastPartTime = mLastUpdateTime;
  220. break;
  221. }
  222. limited_rate = ((dist - max_dist) * ref_rate_travelspeed) / mPartSysData.mPartData.mMaxAge;
  223. }
  224. if(mDelay)
  225. {
  226. limited_rate = llmax(limited_rate, 0.01f * mDelay--) ;
  227. }
  228. S32 i;
  229. for (i = 0; i < mPartSysData.mBurstPartCount; i++)
  230. {
  231. if (ll_frand() < llmax(1.0f - LLViewerPartSim::getInstance()->getBurstRate(), limited_rate))
  232. {
  233. // Limit particle generation
  234. continue;
  235. }
  236. LLViewerPart* part = new LLViewerPart();
  237. part->init(this, mImagep, NULL);
  238. part->mFlags = mPartSysData.mPartData.mFlags;
  239. if (!mSourceObjectp.isNull() && mSourceObjectp->isHUDAttachment())
  240. {
  241. part->mFlags |= LLPartData::LL_PART_HUD;
  242. }
  243. part->mMaxAge = mPartSysData.mPartData.mMaxAge;
  244. part->mStartColor = mPartSysData.mPartData.mStartColor;
  245. part->mEndColor = mPartSysData.mPartData.mEndColor;
  246. part->mColor = part->mStartColor;
  247. part->mStartScale = mPartSysData.mPartData.mStartScale;
  248. part->mEndScale = mPartSysData.mPartData.mEndScale;
  249. part->mScale = part->mStartScale;
  250. part->mAccel = mPartSysData.mPartAccel;
  251. if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
  252. {
  253. part->mPosAgent = mPosAgent;
  254. part->mVelocity.setVec(0.f, 0.f, 0.f);
  255. }
  256. else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
  257. {
  258. part->mPosAgent = mPosAgent;
  259. LLVector3 part_dir_vector;
  260. F32 mvs;
  261. do
  262. {
  263. part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
  264. part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
  265. part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
  266. mvs = part_dir_vector.magVecSquared();
  267. }
  268. while ((mvs > 1.f) || (mvs < 0.01f));
  269. part_dir_vector.normVec();
  270. part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
  271. part->mVelocity = part_dir_vector;
  272. F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
  273. part->mVelocity *= speed;
  274. }
  275. else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
  276. || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
  277. {
  278. part->mPosAgent = mPosAgent;
  279. // original implemenetation for part_dir_vector was just:
  280. LLVector3 part_dir_vector(0.0, 0.0, 1.0);
  281. // params from the script...
  282. // outer = outer cone angle
  283. // inner = inner cone angle
  284. // between outer and inner there will be particles
  285. F32 innerAngle = mPartSysData.mInnerAngle;
  286. F32 outerAngle = mPartSysData.mOuterAngle;
  287. // generate a random angle within the given space...
  288. F32 angle = innerAngle + ll_frand(outerAngle - innerAngle);
  289. // split which side it will go on randomly...
  290. if (ll_frand() < 0.5)
  291. {
  292. angle = -angle;
  293. }
  294. // Both patterns rotate around the x-axis first:
  295. part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
  296. // If this is a cone pattern, rotate again to create the cone.
  297. if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
  298. {
  299. part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0);
  300. }
  301. // Only apply this rotation if using the deprecated angles.
  302. if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
  303. {
  304. // Deprecated...
  305. part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
  306. }
  307. if (mSourceObjectp)
  308. {
  309. part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
  310. }
  311. part_dir_vector = part_dir_vector * mRotation;
  312. part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
  313. part->mVelocity = part_dir_vector;
  314. F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
  315. part->mVelocity *= speed;
  316. }
  317. else
  318. {
  319. part->mPosAgent = mPosAgent;
  320. part->mVelocity.setVec(0.f, 0.f, 0.f);
  321. //llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl;
  322. }
  323. if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK || // SVC-193, VWR-717
  324. part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
  325. {
  326. mPartSysData.mBurstRadius = 0;
  327. }
  328. LLViewerPartSim::getInstance()->addPart(part);
  329. }
  330. mLastPartTime = mLastUpdateTime;
  331. dt_update -= mPartSysData.mBurstRate;
  332. }
  333. }
  334. // static
  335. LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num)
  336. {
  337. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  338. if (!pssp)
  339. {
  340. if (LLPartSysData::isNullPS(block_num))
  341. {
  342. return NULL;
  343. }
  344. LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
  345. if (!new_pssp->mPartSysData.unpackBlock(block_num))
  346. {
  347. return NULL;
  348. }
  349. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  350. {
  351. LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  352. new_pssp->setTargetObject(target_objp);
  353. }
  354. return new_pssp;
  355. }
  356. else
  357. {
  358. if (LLPartSysData::isNullPS(block_num))
  359. {
  360. return NULL;
  361. }
  362. if (!pssp->mPartSysData.unpackBlock(block_num))
  363. {
  364. return NULL;
  365. }
  366. if (pssp->mPartSysData.mTargetUUID.notNull())
  367. {
  368. LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
  369. pssp->setTargetObject(target_objp);
  370. }
  371. return pssp;
  372. }
  373. }
  374. LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp)
  375. {
  376. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  377. if (!pssp)
  378. {
  379. LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
  380. if (!new_pssp->mPartSysData.unpack(dp))
  381. {
  382. return NULL;
  383. }
  384. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  385. {
  386. LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  387. new_pssp->setTargetObject(target_objp);
  388. }
  389. return new_pssp;
  390. }
  391. else
  392. {
  393. if (!pssp->mPartSysData.unpack(dp))
  394. {
  395. return NULL;
  396. }
  397. if (pssp->mPartSysData.mTargetUUID.notNull())
  398. {
  399. LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
  400. pssp->setTargetObject(target_objp);
  401. }
  402. return pssp;
  403. }
  404. }
  405. /* static */
  406. LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters)
  407. {
  408. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  409. LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
  410. new_pssp->mPartSysData = particle_parameters;
  411. if (new_pssp->mPartSysData.mTargetUUID.notNull())
  412. {
  413. LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
  414. new_pssp->setTargetObject(target_objp);
  415. }
  416. return new_pssp;
  417. }
  418. void LLViewerPartSourceScript::setImage(LLViewerTexture *imagep)
  419. {
  420. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  421. mImagep = imagep;
  422. }
  423. void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
  424. {
  425. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  426. mTargetObjectp = objp;
  427. }
  428. LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
  429. LLViewerPartSource(LL_PART_SOURCE_CHAT)
  430. {
  431. mPosAgent = pos;
  432. }
  433. void LLViewerPartSourceSpiral::setDead()
  434. {
  435. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  436. mIsDead = TRUE;
  437. mSourceObjectp = NULL;
  438. }
  439. void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
  440. {
  441. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  442. F32 frac = part.mLastUpdateTime/part.mMaxAge;
  443. LLVector3 center_pos;
  444. LLPointer<LLViewerPartSource>& ps = part.mPartSourcep;
  445. LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get();
  446. if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
  447. {
  448. part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
  449. }
  450. else
  451. {
  452. part.mPosAgent = pss->mPosAgent;
  453. }
  454. F32 x = sin(F_TWO_PI*frac + part.mParameter);
  455. F32 y = cos(F_TWO_PI*frac + part.mParameter);
  456. part.mPosAgent.mV[VX] += x;
  457. part.mPosAgent.mV[VY] += y;
  458. part.mPosAgent.mV[VZ] += -0.5f + frac;
  459. }
  460. void LLViewerPartSourceSpiral::update(const F32 dt)
  461. {
  462. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  463. if (!mImagep)
  464. {
  465. mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
  466. }
  467. const F32 RATE = 0.025f;
  468. mLastUpdateTime += dt;
  469. F32 dt_update = mLastUpdateTime - mLastPartTime;
  470. F32 max_time = llmax(1.f, 10.f*RATE);
  471. dt_update = llmin(max_time, dt_update);
  472. if (dt_update > RATE)
  473. {
  474. mLastPartTime = mLastUpdateTime;
  475. if (!LLViewerPartSim::getInstance()->shouldAddPart())
  476. {
  477. // Particle simulation says we have too many particles, skip all this
  478. return;
  479. }
  480. if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
  481. {
  482. mPosAgent = mSourceObjectp->getRenderPosition();
  483. }
  484. LLViewerPart* part = new LLViewerPart();
  485. part->init(this, mImagep, updatePart);
  486. part->mStartColor = mColor;
  487. part->mEndColor = mColor;
  488. part->mEndColor.mV[3] = 0.f;
  489. part->mPosAgent = mPosAgent;
  490. part->mMaxAge = 1.f;
  491. part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
  492. part->mLastUpdateTime = 0.f;
  493. part->mScale.mV[0] = 0.25f;
  494. part->mScale.mV[1] = 0.25f;
  495. part->mParameter = ll_frand(F_TWO_PI);
  496. LLViewerPartSim::getInstance()->addPart(part);
  497. }
  498. }
  499. void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
  500. {
  501. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  502. mSourceObjectp = objp;
  503. }
  504. void LLViewerPartSourceSpiral::setColor(const LLColor4 &color)
  505. {
  506. mColor = color;
  507. }
  508. LLViewerPartSourceBeam::LLViewerPartSourceBeam() :
  509. LLViewerPartSource(LL_PART_SOURCE_BEAM)
  510. {
  511. }
  512. LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
  513. {
  514. }
  515. void LLViewerPartSourceBeam::setDead()
  516. {
  517. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  518. mIsDead = TRUE;
  519. mSourceObjectp = NULL;
  520. mTargetObjectp = NULL;
  521. }
  522. void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
  523. {
  524. mColor = color;
  525. }
  526. void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
  527. {
  528. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  529. F32 frac = part.mLastUpdateTime/part.mMaxAge;
  530. LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
  531. LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps;
  532. if (psb->mSourceObjectp.isNull())
  533. {
  534. part.mFlags = LLPartData::LL_PART_DEAD_MASK;
  535. return;
  536. }
  537. LLVector3 source_pos_agent;
  538. LLVector3 target_pos_agent;
  539. if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull())
  540. {
  541. if (psb->mSourceObjectp->isAvatar())
  542. {
  543. LLViewerObject *objp = psb->mSourceObjectp;
  544. LLVOAvatar *avp = (LLVOAvatar *)objp;
  545. source_pos_agent = avp->mWristLeftp->getWorldPosition();
  546. }
  547. else
  548. {
  549. source_pos_agent = psb->mSourceObjectp->getRenderPosition();
  550. }
  551. }
  552. if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull())
  553. {
  554. target_pos_agent = psb->mTargetObjectp->getRenderPosition();
  555. }
  556. part.mPosAgent = (1.f - frac) * source_pos_agent;
  557. if (psb->mTargetObjectp.isNull())
  558. {
  559. part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal));
  560. }
  561. else
  562. {
  563. part.mPosAgent += frac * target_pos_agent;
  564. }
  565. }
  566. void LLViewerPartSourceBeam::update(const F32 dt)
  567. {
  568. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  569. const F32 RATE = 0.025f;
  570. mLastUpdateTime += dt;
  571. if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
  572. {
  573. if (mSourceObjectp->isAvatar())
  574. {
  575. LLViewerObject *objp = mSourceObjectp;
  576. LLVOAvatar *avp = (LLVOAvatar *)objp;
  577. mPosAgent = avp->mWristLeftp->getWorldPosition();
  578. }
  579. else
  580. {
  581. mPosAgent = mSourceObjectp->getRenderPosition();
  582. }
  583. }
  584. if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull())
  585. {
  586. mTargetPosAgent = mTargetObjectp->getRenderPosition();
  587. }
  588. else if (!mLKGTargetPosGlobal.isExactlyZero())
  589. {
  590. mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
  591. }
  592. F32 dt_update = mLastUpdateTime - mLastPartTime;
  593. F32 max_time = llmax(1.f, 10.f*RATE);
  594. dt_update = llmin(max_time, dt_update);
  595. if (dt_update > RATE)
  596. {
  597. mLastPartTime = mLastUpdateTime;
  598. if (!LLViewerPartSim::getInstance()->shouldAddPart())
  599. {
  600. // Particle simulation says we have too many particles, skip all this
  601. return;
  602. }
  603. if (!mImagep)
  604. {
  605. mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
  606. }
  607. LLViewerPart* part = new LLViewerPart();
  608. part->init(this, mImagep, NULL);
  609. part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
  610. LLPartData::LL_PART_INTERP_SCALE_MASK |
  611. LLPartData::LL_PART_TARGET_POS_MASK |
  612. LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
  613. part->mMaxAge = 0.5f;
  614. part->mStartColor = mColor;
  615. part->mEndColor = part->mStartColor;
  616. part->mEndColor.mV[3] = 0.4f;
  617. part->mColor = part->mStartColor;
  618. part->mStartScale = LLVector2(0.1f, 0.1f);
  619. part->mEndScale = LLVector2(0.1f, 0.1f);
  620. part->mScale = part->mStartScale;
  621. part->mPosAgent = mPosAgent;
  622. part->mVelocity = mTargetPosAgent - mPosAgent;
  623. LLViewerPartSim::getInstance()->addPart(part);
  624. }
  625. }
  626. void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
  627. {
  628. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  629. mSourceObjectp = objp;
  630. }
  631. void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
  632. {
  633. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  634. mTargetObjectp = objp;
  635. }
  636. LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
  637. LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
  638. {
  639. mPosAgent = pos;
  640. }
  641. void LLViewerPartSourceChat::setDead()
  642. {
  643. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  644. mIsDead = TRUE;
  645. mSourceObjectp = NULL;
  646. }
  647. void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
  648. {
  649. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  650. F32 frac = part.mLastUpdateTime/part.mMaxAge;
  651. LLVector3 center_pos;
  652. LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
  653. LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps;
  654. if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
  655. {
  656. part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
  657. }
  658. else
  659. {
  660. part.mPosAgent = pss->mPosAgent;
  661. }
  662. F32 x = sin(F_TWO_PI*frac + part.mParameter);
  663. F32 y = cos(F_TWO_PI*frac + part.mParameter);
  664. part.mPosAgent.mV[VX] += x;
  665. part.mPosAgent.mV[VY] += y;
  666. part.mPosAgent.mV[VZ] += -0.5f + frac;
  667. }
  668. void LLViewerPartSourceChat::update(const F32 dt)
  669. {
  670. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  671. if (!mImagep)
  672. {
  673. mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
  674. }
  675. const F32 RATE = 0.025f;
  676. mLastUpdateTime += dt;
  677. if (mLastUpdateTime > 2.f)
  678. {
  679. // Kill particle source because it has outlived its max age...
  680. setDead();
  681. return;
  682. }
  683. F32 dt_update = mLastUpdateTime - mLastPartTime;
  684. // Clamp us to generating at most one second's worth of particles on a frame.
  685. F32 max_time = llmax(1.f, 10.f*RATE);
  686. dt_update = llmin(max_time, dt_update);
  687. if (dt_update > RATE)
  688. {
  689. mLastPartTime = mLastUpdateTime;
  690. if (!LLViewerPartSim::getInstance()->shouldAddPart())
  691. {
  692. // Particle simulation says we have too many particles, skip all this
  693. return;
  694. }
  695. if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
  696. {
  697. mPosAgent = mSourceObjectp->getRenderPosition();
  698. }
  699. LLViewerPart* part = new LLViewerPart();
  700. part->init(this, mImagep, updatePart);
  701. part->mStartColor = mColor;
  702. part->mEndColor = mColor;
  703. part->mEndColor.mV[3] = 0.f;
  704. part->mPosAgent = mPosAgent;
  705. part->mMaxAge = 1.f;
  706. part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
  707. part->mLastUpdateTime = 0.f;
  708. part->mScale.mV[0] = 0.25f;
  709. part->mScale.mV[1] = 0.25f;
  710. part->mParameter = ll_frand(F_TWO_PI);
  711. LLViewerPartSim::getInstance()->addPart(part);
  712. }
  713. }
  714. void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
  715. {
  716. LLMemType mt(LLMemType::MTYPE_PARTICLES);
  717. mSourceObjectp = objp;
  718. }
  719. void LLViewerPartSourceChat::setColor(const LLColor4 &color)
  720. {
  721. mColor = color;
  722. }