00001
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llviewerpartsource.h"
00034
00035 #include "llviewercontrol.h"
00036
00037 #include "llagent.h"
00038 #include "lldrawable.h"
00039 #include "llviewerimagelist.h"
00040 #include "llviewerobject.h"
00041 #include "llviewerobjectlist.h"
00042 #include "llvoavatar.h"
00043 #include "llworld.h"
00044 #include "pipeline.h"
00045
00046 LLViewerPartSource::LLViewerPartSource(const U32 type) :
00047 mType(type),
00048 mOwnerUUID(LLUUID::null)
00049 {
00050 mLastUpdateTime = 0.f;
00051 mLastPartTime = 0.f;
00052 mIsDead = FALSE;
00053 mIsSuspended = FALSE;
00054 static U32 id_seed = 0;
00055 mID = ++id_seed;
00056 }
00057
00058 void LLViewerPartSource::setDead()
00059 {
00060 mIsDead = TRUE;
00061 }
00062
00063
00064 void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt)
00065 {
00066 }
00067
00068 void LLViewerPartSource::update(const F32 dt)
00069 {
00070 llerrs << "Creating default part source!" << llendl;
00071 }
00072
00073 LLUUID LLViewerPartSource::getImageUUID() const
00074 {
00075 LLViewerImage* imagep = mImagep;
00076 if(imagep)
00077 {
00078 return imagep->getID();
00079 }
00080 return LLUUID::null;
00081 }
00082
00083 LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
00084 LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
00085 {
00086 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00087 llassert(source_objp);
00088 mSourceObjectp = source_objp;
00089 mPosAgent = mSourceObjectp->getPositionAgent();
00090 LLUUID id;
00091 id.set( gViewerArt.getString("pixiesmall.tga") );
00092 mImagep = gImageList.getImage(id);
00093 mImagep->bind();
00094 mImagep->setClamp(TRUE, TRUE);
00095 }
00096
00097
00098 void LLViewerPartSourceScript::setDead()
00099 {
00100 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00101 mIsDead = TRUE;
00102 mSourceObjectp = NULL;
00103 mTargetObjectp = NULL;
00104 }
00105
00106 void LLViewerPartSourceScript::update(const F32 dt)
00107 {
00108 if( mIsSuspended )
00109 return;
00110
00111 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00112 F32 old_update_time = mLastUpdateTime;
00113 mLastUpdateTime += dt;
00114
00115 F32 dt_update = mLastUpdateTime - mLastPartTime;
00116
00117
00118 if (!mSourceObjectp.isNull())
00119 {
00120 if (mSourceObjectp->isDead())
00121 {
00122 mSourceObjectp = NULL;
00123 }
00124 else if (mSourceObjectp->mDrawable.notNull())
00125 {
00126 mPosAgent = mSourceObjectp->getRenderPosition();
00127 }
00128 }
00129
00130 if (mTargetObjectp.isNull()
00131 && mPartSysData.mTargetUUID.notNull())
00132 {
00133
00134
00135
00136
00137 LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID);
00138 setTargetObject(target_objp);
00139 }
00140
00141 if (!mTargetObjectp.isNull())
00142 {
00143 if (mTargetObjectp->isDead())
00144 {
00145 mTargetObjectp = NULL;
00146 }
00147 else if (mTargetObjectp->mDrawable.notNull())
00148 {
00149 mTargetPosAgent = mTargetObjectp->getRenderPosition();
00150 }
00151 }
00152
00153 if (!mTargetObjectp)
00154 {
00155 mTargetPosAgent = mPosAgent;
00156 }
00157
00158 if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge))
00159 {
00160
00161 setDead();
00162 return;
00163 }
00164
00165
00166 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
00167 {
00168 if (mSourceObjectp.notNull())
00169 {
00170 std::ostringstream ostr;
00171 ostr << mPartSysData;
00172 mSourceObjectp->setDebugText(ostr.str());
00173 }
00174 }
00175
00176 BOOL first_run = FALSE;
00177 if (old_update_time <= 0.f)
00178 {
00179 first_run = TRUE;
00180 }
00181
00182 F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate);
00183 dt_update = llmin(max_time, dt_update);
00184 while ((dt_update > mPartSysData.mBurstRate) || first_run)
00185 {
00186 first_run = FALSE;
00187
00188
00189
00190 F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
00191 if (angular_velocity_mag != 0.0f)
00192 {
00193 F32 av_angle = dt * angular_velocity_mag;
00194 LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
00195 mRotation *= dquat;
00196 }
00197 else
00198 {
00199
00200 mRotation.setQuat(0, 0, 0);
00201 }
00202
00203 if (gWorldPointer->mPartSim.aboveParticleLimit())
00204 {
00205
00206
00207 mLastPartTime = mLastUpdateTime;
00208 break;
00209 }
00210
00211 S32 i;
00212 for (i = 0; i < mPartSysData.mBurstPartCount; i++)
00213 {
00214 if (!gWorldPointer->mPartSim.shouldAddPart())
00215 {
00216
00217 continue;
00218 }
00219
00220 LLPointer<LLViewerPart> part = new LLViewerPart();
00221
00222 part->init(this, mImagep, NULL);
00223 part->mFlags = mPartSysData.mPartData.mFlags;
00224 part->mMaxAge = mPartSysData.mPartData.mMaxAge;
00225 part->mStartColor = mPartSysData.mPartData.mStartColor;
00226 part->mEndColor = mPartSysData.mPartData.mEndColor;
00227 part->mColor = part->mStartColor;
00228
00229 part->mStartScale = mPartSysData.mPartData.mStartScale;
00230 part->mEndScale = mPartSysData.mPartData.mEndScale;
00231 part->mScale = part->mStartScale;
00232
00233 part->mAccel = mPartSysData.mPartAccel;
00234
00235 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
00236 {
00237 part->mPosAgent = mPosAgent;
00238 part->mVelocity.setVec(0.f, 0.f, 0.f);
00239 }
00240 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
00241 {
00242 part->mPosAgent = mPosAgent;
00243 LLVector3 part_dir_vector;
00244
00245 F32 mvs;
00246 do
00247 {
00248 part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
00249 part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
00250 part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
00251 mvs = part_dir_vector.magVecSquared();
00252 }
00253 while ((mvs > 1.f) || (mvs < 0.01f));
00254
00255 part_dir_vector.normVec();
00256 part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
00257 part->mVelocity = part_dir_vector;
00258 F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
00259 part->mVelocity *= speed;
00260 }
00261 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
00262 || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
00263 {
00264 part->mPosAgent = mPosAgent;
00265
00266
00267 LLVector3 part_dir_vector(0.0, 0.0, 1.0);
00268
00269
00270
00271
00272 F32 innerAngle = mPartSysData.mInnerAngle;
00273 F32 outerAngle = mPartSysData.mOuterAngle;
00274
00275
00276 F32 angle = innerAngle + ll_frand(outerAngle - innerAngle);
00277
00278 if (ll_frand() < 0.5)
00279 {
00280 angle = -angle;
00281 }
00282
00283 part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
00284
00285
00286 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
00287 {
00288 part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0);
00289 }
00290
00291
00292 if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
00293 {
00294
00295 part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
00296 }
00297
00298 if (mSourceObjectp)
00299 {
00300 part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
00301 }
00302
00303 part_dir_vector = part_dir_vector * mRotation;
00304
00305 part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
00306
00307 part->mVelocity = part_dir_vector;
00308
00309 F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
00310 part->mVelocity *= speed;
00311 }
00312 else
00313 {
00314 part->mPosAgent = mPosAgent;
00315 part->mVelocity.setVec(0.f, 0.f, 0.f);
00316
00317 }
00318
00319 if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK ||
00320 part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
00321 {
00322 mPartSysData.mBurstRadius = 0;
00323 }
00324
00325 gWorldPointer->mPartSim.addPart(part);
00326 }
00327
00328 mLastPartTime = mLastUpdateTime;
00329 dt_update -= mPartSysData.mBurstRate;
00330 }
00331 }
00332
00333
00334 LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num)
00335 {
00336 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00337 if (!pssp)
00338 {
00339 if (LLPartSysData::isNullPS(block_num))
00340 {
00341 return NULL;
00342 }
00343 LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
00344 if (!new_pssp->mPartSysData.unpackBlock(block_num))
00345 {
00346 return NULL;
00347 }
00348 if (new_pssp->mPartSysData.mTargetUUID.notNull())
00349 {
00350 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
00351 new_pssp->setTargetObject(target_objp);
00352 }
00353 return new_pssp;
00354 }
00355 else
00356 {
00357 if (LLPartSysData::isNullPS(block_num))
00358 {
00359 return NULL;
00360 }
00361
00362 if (!pssp->mPartSysData.unpackBlock(block_num))
00363 {
00364 return NULL;
00365 }
00366 if (pssp->mPartSysData.mTargetUUID.notNull())
00367 {
00368 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
00369 pssp->setTargetObject(target_objp);
00370 }
00371 return pssp;
00372 }
00373 }
00374
00375
00376 LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp)
00377 {
00378 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00379 if (!pssp)
00380 {
00381 LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
00382 if (!new_pssp->mPartSysData.unpack(dp))
00383 {
00384 return NULL;
00385 }
00386 if (new_pssp->mPartSysData.mTargetUUID.notNull())
00387 {
00388 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
00389 new_pssp->setTargetObject(target_objp);
00390 }
00391 return new_pssp;
00392 }
00393 else
00394 {
00395 if (!pssp->mPartSysData.unpack(dp))
00396 {
00397 return NULL;
00398 }
00399 if (pssp->mPartSysData.mTargetUUID.notNull())
00400 {
00401 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
00402 pssp->setTargetObject(target_objp);
00403 }
00404 return pssp;
00405 }
00406 }
00407
00408 void LLViewerPartSourceScript::setImage(LLViewerImage *imagep)
00409 {
00410 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00411 mImagep = imagep;
00412 }
00413
00414 void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
00415 {
00416 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00417 mTargetObjectp = objp;
00418 }
00419
00420
00421
00422
00423
00424 LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
00425 LLViewerPartSource(LL_PART_SOURCE_CHAT)
00426 {
00427 mPosAgent = pos;
00428 }
00429
00430 void LLViewerPartSourceSpiral::setDead()
00431 {
00432 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00433 mIsDead = TRUE;
00434 mSourceObjectp = NULL;
00435 }
00436
00437
00438 void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
00439 {
00440 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00441 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00442
00443 LLVector3 center_pos;
00444 LLPointer<LLViewerPartSource>& ps = part.mPartSourcep;
00445 LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get();
00446 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
00447 {
00448 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
00449 }
00450 else
00451 {
00452 part.mPosAgent = pss->mPosAgent;
00453 }
00454 F32 x = sin(F_TWO_PI*frac + part.mParameter);
00455 F32 y = cos(F_TWO_PI*frac + part.mParameter);
00456
00457 part.mPosAgent.mV[VX] += x;
00458 part.mPosAgent.mV[VY] += y;
00459 part.mPosAgent.mV[VZ] += -0.5f + frac;
00460 }
00461
00462
00463 void LLViewerPartSourceSpiral::update(const F32 dt)
00464 {
00465 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00466 if (!mImagep)
00467 {
00468 LLUUID id;
00469 id.set( gViewerArt.getString("pixiesmall.tga") );
00470 mImagep = gImageList.getImage(id);
00471 }
00472
00473 const F32 RATE = 0.025f;
00474
00475 mLastUpdateTime += dt;
00476
00477 F32 dt_update = mLastUpdateTime - mLastPartTime;
00478 F32 max_time = llmax(1.f, 10.f*RATE);
00479 dt_update = llmin(max_time, dt_update);
00480
00481 if (dt_update > RATE)
00482 {
00483 mLastPartTime = mLastUpdateTime;
00484 if (!gWorldPointer->mPartSim.shouldAddPart())
00485 {
00486
00487 return;
00488 }
00489
00490 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00491 {
00492 mPosAgent = mSourceObjectp->getRenderPosition();
00493 }
00494 LLPointer<LLViewerPart> part = new LLViewerPart();
00495 part->init(this, mImagep, updatePart);
00496 part->mStartColor = mColor;
00497 part->mEndColor = mColor;
00498 part->mEndColor.mV[3] = 0.f;
00499 part->mPosAgent = mPosAgent;
00500 part->mMaxAge = 1.f;
00501 part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
00502 part->mLastUpdateTime = 0.f;
00503 part->mScale.mV[0] = 0.25f;
00504 part->mScale.mV[1] = 0.25f;
00505 part->mParameter = ll_frand(F_TWO_PI);
00506
00507 gWorldPointer->mPartSim.addPart(part);
00508 }
00509 }
00510
00511 void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
00512 {
00513 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00514 mSourceObjectp = objp;
00515 }
00516
00517 void LLViewerPartSourceSpiral::setColor(const LLColor4 &color)
00518 {
00519 mColor = color;
00520 }
00521
00522
00523
00524
00525
00526 LLViewerPartSourceBeam::LLViewerPartSourceBeam() :
00527 LLViewerPartSource(LL_PART_SOURCE_BEAM)
00528 {
00529 }
00530
00531 LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
00532 {
00533 }
00534
00535 void LLViewerPartSourceBeam::setDead()
00536 {
00537 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00538 mIsDead = TRUE;
00539 mSourceObjectp = NULL;
00540 mTargetObjectp = NULL;
00541 }
00542
00543 void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
00544 {
00545 mColor = color;
00546 }
00547
00548
00549 void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
00550 {
00551 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00552 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00553
00554 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
00555 LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps;
00556 if (psb->mSourceObjectp.isNull())
00557 {
00558 part.mFlags = LLPartData::LL_PART_DEAD_MASK;
00559 return;
00560 }
00561
00562 LLVector3 source_pos_agent;
00563 LLVector3 target_pos_agent;
00564 if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull())
00565 {
00566 if (psb->mSourceObjectp->isAvatar())
00567 {
00568 LLViewerObject *objp = psb->mSourceObjectp;
00569 LLVOAvatar *avp = (LLVOAvatar *)objp;
00570 source_pos_agent = avp->mWristLeftp->getWorldPosition();
00571 }
00572 else
00573 {
00574 source_pos_agent = psb->mSourceObjectp->getRenderPosition();
00575 }
00576 }
00577 if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull())
00578 {
00579 target_pos_agent = psb->mTargetObjectp->getRenderPosition();
00580 }
00581
00582 part.mPosAgent = (1.f - frac) * source_pos_agent;
00583 if (psb->mTargetObjectp.isNull())
00584 {
00585 part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal));
00586 }
00587 else
00588 {
00589 part.mPosAgent += frac * target_pos_agent;
00590 }
00591 }
00592
00593
00594 void LLViewerPartSourceBeam::update(const F32 dt)
00595 {
00596 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00597 const F32 RATE = 0.025f;
00598
00599 mLastUpdateTime += dt;
00600
00601 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00602 {
00603 if (mSourceObjectp->isAvatar())
00604 {
00605 LLViewerObject *objp = mSourceObjectp;
00606 LLVOAvatar *avp = (LLVOAvatar *)objp;
00607 mPosAgent = avp->mWristLeftp->getWorldPosition();
00608 }
00609 else
00610 {
00611 mPosAgent = mSourceObjectp->getRenderPosition();
00612 }
00613 }
00614
00615 if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull())
00616 {
00617 mTargetPosAgent = mTargetObjectp->getRenderPosition();
00618 }
00619 else if (!mLKGTargetPosGlobal.isExactlyZero())
00620 {
00621 mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
00622 }
00623
00624 F32 dt_update = mLastUpdateTime - mLastPartTime;
00625 F32 max_time = llmax(1.f, 10.f*RATE);
00626 dt_update = llmin(max_time, dt_update);
00627
00628 if (dt_update > RATE)
00629 {
00630 mLastPartTime = mLastUpdateTime;
00631 if (!gWorldPointer->mPartSim.shouldAddPart())
00632 {
00633
00634 return;
00635 }
00636
00637 if (!mImagep)
00638 {
00639 LLUUID id;
00640 id.set( gViewerArt.getString("pixiesmall.tga") );
00641 mImagep = gImageList.getImage(id);
00642 }
00643
00644 LLPointer<LLViewerPart> part = new LLViewerPart();
00645 part->init(this, mImagep, NULL);
00646
00647 part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
00648 LLPartData::LL_PART_INTERP_SCALE_MASK |
00649 LLPartData::LL_PART_TARGET_POS_MASK |
00650 LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
00651 part->mMaxAge = 0.5f;
00652 part->mStartColor = mColor;
00653 part->mEndColor = part->mStartColor;
00654 part->mEndColor.mV[3] = 0.4f;
00655 part->mColor = part->mStartColor;
00656
00657 part->mStartScale = LLVector2(0.1f, 0.1f);
00658 part->mEndScale = LLVector2(0.1f, 0.1f);
00659 part->mScale = part->mStartScale;
00660
00661 part->mPosAgent = mPosAgent;
00662 part->mVelocity = mTargetPosAgent - mPosAgent;
00663
00664 gWorldPointer->mPartSim.addPart(part);
00665 }
00666 }
00667
00668 void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
00669 {
00670 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00671 mSourceObjectp = objp;
00672 }
00673
00674 void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
00675 {
00676 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00677 mTargetObjectp = objp;
00678 }
00679
00680
00681
00682
00683 LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
00684 LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
00685 {
00686 mPosAgent = pos;
00687 }
00688
00689 void LLViewerPartSourceChat::setDead()
00690 {
00691 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00692 mIsDead = TRUE;
00693 mSourceObjectp = NULL;
00694 }
00695
00696
00697 void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
00698 {
00699 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00700 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00701
00702 LLVector3 center_pos;
00703 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
00704 LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps;
00705 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
00706 {
00707 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
00708 }
00709 else
00710 {
00711 part.mPosAgent = pss->mPosAgent;
00712 }
00713 F32 x = sin(F_TWO_PI*frac + part.mParameter);
00714 F32 y = cos(F_TWO_PI*frac + part.mParameter);
00715
00716 part.mPosAgent.mV[VX] += x;
00717 part.mPosAgent.mV[VY] += y;
00718 part.mPosAgent.mV[VZ] += -0.5f + frac;
00719 }
00720
00721
00722 void LLViewerPartSourceChat::update(const F32 dt)
00723 {
00724 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00725 if (!mImagep)
00726 {
00727 LLUUID id;
00728 id.set( gViewerArt.getString("pixiesmall.tga") );
00729 mImagep = gImageList.getImage(id);
00730 }
00731
00732
00733 const F32 RATE = 0.025f;
00734
00735 mLastUpdateTime += dt;
00736
00737 if (mLastUpdateTime > 2.f)
00738 {
00739
00740 setDead();
00741 return;
00742 }
00743
00744 F32 dt_update = mLastUpdateTime - mLastPartTime;
00745
00746
00747 F32 max_time = llmax(1.f, 10.f*RATE);
00748 dt_update = llmin(max_time, dt_update);
00749
00750 if (dt_update > RATE)
00751 {
00752 mLastPartTime = mLastUpdateTime;
00753 if (!gWorldPointer->mPartSim.shouldAddPart())
00754 {
00755
00756 return;
00757 }
00758
00759 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00760 {
00761 mPosAgent = mSourceObjectp->getRenderPosition();
00762 }
00763 LLPointer<LLViewerPart> part = new LLViewerPart();
00764 part->init(this, mImagep, updatePart);
00765 part->mStartColor = mColor;
00766 part->mEndColor = mColor;
00767 part->mEndColor.mV[3] = 0.f;
00768 part->mPosAgent = mPosAgent;
00769 part->mMaxAge = 1.f;
00770 part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
00771 part->mLastUpdateTime = 0.f;
00772 part->mScale.mV[0] = 0.25f;
00773 part->mScale.mV[1] = 0.25f;
00774 part->mParameter = ll_frand(F_TWO_PI);
00775
00776 gWorldPointer->mPartSim.addPart(part);
00777 }
00778 }
00779
00780 void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
00781 {
00782 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00783 mSourceObjectp = objp;
00784 }
00785
00786 void LLViewerPartSourceChat::setColor(const LLColor4 &color)
00787 {
00788 mColor = color;
00789 }
00790
00791