00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llhudeffectbeam.h"
00035 #include "message.h"
00036
00037 #include "llviewerobjectlist.h"
00038
00039 #include "llagent.h"
00040 #include "lldrawable.h"
00041 #include "llfontgl.h"
00042 #include "llgl.h"
00043 #include "llglheaders.h"
00044 #include "llhudrender.h"
00045 #include "llimagegl.h"
00046 #include "llsphere.h"
00047 #include "llviewercamera.h"
00048 #include "llvoavatar.h"
00049 #include "llviewercontrol.h"
00050
00051 const F32 BEAM_SPACING = 0.075f;
00052
00053 LLHUDEffectBeam::LLHUDEffectBeam(const U8 type) : LLHUDEffect(type)
00054 {
00055 mKillTime = mDuration;
00056
00057
00058 S32 i;
00059 for (i = 0; i < NUM_POINTS; i++)
00060 {
00061 mInterp[i].setStartTime(BEAM_SPACING*i);
00062 mInterp[i].setEndTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i);
00063 mInterp[i].start();
00064 mInterpFade[i].setStartTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i - 0.5f*NUM_POINTS*BEAM_SPACING);
00065 mInterpFade[i].setEndTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i);
00066 mInterpFade[i].setStartVal(1.f);
00067 mInterpFade[i].setEndVal(0.f);
00068 }
00069
00070
00071 F32 fade_length;
00072 fade_length = llmin(0.5f, mDuration);
00073 mFadeInterp.setStartTime(mKillTime - fade_length);
00074 mFadeInterp.setEndTime(mKillTime);
00075 mFadeInterp.setStartVal(1.f);
00076 mFadeInterp.setEndVal(0.f);
00077 }
00078
00079 LLHUDEffectBeam::~LLHUDEffectBeam()
00080 {
00081 }
00082
00083 void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
00084 {
00085 if (!mSourceObject)
00086 {
00087 llwarns << "Missing source object!" << llendl;
00088 }
00089
00090
00091 LLHUDEffect::packData(mesgsys);
00092
00093
00094
00095 U8 packed_data[41];
00096 memset(packed_data, 0, 41);
00097 if (mSourceObject)
00098 {
00099 htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
00100 }
00101
00102 if (mTargetObject)
00103 {
00104 packed_data[16] = 1;
00105 }
00106 else
00107 {
00108 packed_data[16] = 0;
00109 }
00110
00111 if (mTargetObject)
00112 {
00113 htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
00114 }
00115 else
00116 {
00117 htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
00118 }
00119 mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
00120 }
00121
00122 void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
00123 {
00124 llerrs << "Got beam!" << llendl;
00125 BOOL use_target_object;
00126 LLVector3d new_target;
00127 U8 packed_data[41];
00128
00129 LLHUDEffect::unpackData(mesgsys, blocknum);
00130 LLUUID source_id;
00131 LLUUID target_id;
00132 S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
00133 if (size != 41)
00134 {
00135 llwarns << "Beam effect with bad size " << size << llendl;
00136 return;
00137 }
00138 mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 41, blocknum);
00139
00140 htonmemcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
00141
00142 LLViewerObject *objp = gObjectList.findObject(source_id);
00143 if (objp)
00144 {
00145 setSourceObject(objp);
00146 }
00147
00148 use_target_object = packed_data[16];
00149
00150 if (use_target_object)
00151 {
00152 htonmemcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
00153
00154 LLViewerObject *objp = gObjectList.findObject(target_id);
00155 if (objp)
00156 {
00157 setTargetObject(objp);
00158 }
00159 }
00160 else
00161 {
00162 htonmemcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
00163 setTargetPos(new_target);
00164 }
00165
00166
00167
00168 mKillTime = mTimer.getElapsedTimeF32() + mDuration;
00169 F32 fade_length;
00170 fade_length = llmin(0.5f, mDuration);
00171 mFadeInterp.setStartTime(mKillTime - fade_length);
00172 mFadeInterp.setEndTime(mKillTime);
00173 mFadeInterp.setStartVal(1.f);
00174 mFadeInterp.setEndVal(0.f);
00175 }
00176
00177 void LLHUDEffectBeam::setSourceObject(LLViewerObject *objp)
00178 {
00179 if (objp->isDead())
00180 {
00181 llwarns << "HUDEffectBeam: Source object is dead!" << llendl;
00182 mSourceObject = NULL;
00183 return;
00184 }
00185
00186 if (mSourceObject == objp)
00187 {
00188 return;
00189 }
00190
00191 mSourceObject = objp;
00192 if (mSourceObject)
00193 {
00194 S32 i;
00195 for (i = 0; i < NUM_POINTS; i++)
00196 {
00197 if (mSourceObject->isAvatar())
00198 {
00199 LLViewerObject *objp = mSourceObject;
00200 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
00201 LLVector3d hand_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
00202 mInterp[i].setStartVal(hand_pos_global);
00203 mInterp[i].start();
00204 }
00205 else
00206 {
00207 mInterp[i].setStartVal(mSourceObject->getPositionGlobal());
00208 mInterp[i].start();
00209 }
00210 }
00211 }
00212 }
00213
00214
00215 void LLHUDEffectBeam::setTargetObject(LLViewerObject *objp)
00216 {
00217 if (mTargetObject->isDead())
00218 {
00219 llwarns << "HUDEffectBeam: Target object is dead!" << llendl;
00220 }
00221
00222 mTargetObject = objp;
00223 }
00224
00225 void LLHUDEffectBeam::setTargetPos(const LLVector3d &pos_global)
00226 {
00227 mTargetPos = pos_global;
00228 mTargetObject = NULL;
00229 }
00230
00231 void LLHUDEffectBeam::render()
00232 {
00233 if (!mSourceObject)
00234 {
00235 markDead();
00236 return;
00237 }
00238 if (mSourceObject->isDead())
00239 {
00240 markDead();
00241 return;
00242 }
00243
00244 F32 time = mTimer.getElapsedTimeF32();
00245
00246
00247 if (mKillTime < time)
00248 {
00249 markDead();
00250 return;
00251 }
00252
00253 LLGLSPipelineAlpha gls_pipeline_alpha;
00254 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00255
00256
00257
00258 mFadeInterp.update(time);
00259
00260 if (mTargetObject.notNull() && mTargetObject->mDrawable.notNull())
00261 {
00262
00263 if (mTargetObject->mDrawable->getGeneration() == -1)
00264 {
00265 mTargetPos = mTargetObject->getPositionGlobal();
00266 }
00267
00268 else
00269 {
00270 mTargetPos = gAgent.getPosGlobalFromAgent(mTargetObject->mDrawable->getPositionAgent());
00271 }
00272 }
00273
00274
00275
00276 LLColor4U coloru = mColor;
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 S32 i;
00325 for (i = 0; i < NUM_POINTS; i++)
00326 {
00327 mInterp[i].update(time);
00328 if (!mInterp[i].isActive())
00329 {
00330 continue;
00331 }
00332 mInterpFade[i].update(time);
00333
00334 if (mInterp[i].isDone())
00335 {
00336
00337 setupParticle(i);
00338 }
00339
00340 F32 frac = mInterp[i].getCurFrac();
00341 F32 scale = 0.025f + fabs(0.05f*sin(2.f*F_PI*(frac - time)));
00342 scale *= mInterpFade[i].getCurVal();
00343
00344 LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mInterp[i].getCurVal());
00345
00346 F32 alpha = mFadeInterp.getCurVal()*mColor.mV[3];
00347 alpha *= mInterpFade[i].getCurVal();
00348 coloru.mV[3] = (U8)alpha;
00349 glColor4ubv(coloru.mV);
00350
00351 glPushMatrix();
00352 glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
00353 glScalef(scale, scale, scale);
00354 gSphere.render(0);
00355 glPopMatrix();
00356 }
00357 }
00358
00359 void LLHUDEffectBeam::setupParticle(const S32 i)
00360 {
00361 LLVector3d start_pos_global;
00362 if (mSourceObject->getPCode() == LL_PCODE_LEGACY_AVATAR)
00363 {
00364 LLViewerObject *objp = mSourceObject;
00365 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
00366 start_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
00367 }
00368 else
00369 {
00370 start_pos_global = mSourceObject->getPositionGlobal();
00371 }
00372
00373
00374 const F32 SCALE = 0.5f;
00375 F32 x, y, z;
00376 x = ll_frand(SCALE) - 0.5f*SCALE;
00377 y = ll_frand(SCALE) - 0.5f*SCALE;
00378 z = ll_frand(SCALE) - 0.5f*SCALE;
00379
00380 LLVector3d target_pos_global(mTargetPos);
00381 target_pos_global += LLVector3d(x, y, z);
00382
00383 mInterp[i].setStartTime(mInterp[i].getEndTime());
00384 mInterp[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS);
00385 mInterp[i].setStartVal(start_pos_global);
00386 mInterp[i].setEndVal(target_pos_global);
00387 mInterp[i].start();
00388
00389
00390
00391 mInterpFade[i].setStartTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.5f*NUM_POINTS*BEAM_SPACING);
00392 mInterpFade[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.05f);
00393 mInterpFade[i].start();
00394 }