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 "llrendersphere.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 S32 i;
00280 for (i = 0; i < NUM_POINTS; i++)
00281 {
00282 mInterp[i].update(time);
00283 if (!mInterp[i].isActive())
00284 {
00285 continue;
00286 }
00287 mInterpFade[i].update(time);
00288
00289 if (mInterp[i].isDone())
00290 {
00291
00292 setupParticle(i);
00293 }
00294
00295 F32 frac = mInterp[i].getCurFrac();
00296 F32 scale = 0.025f + fabs(0.05f*sin(2.f*F_PI*(frac - time)));
00297 scale *= mInterpFade[i].getCurVal();
00298
00299 LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mInterp[i].getCurVal());
00300
00301 F32 alpha = mFadeInterp.getCurVal()*mColor.mV[3];
00302 alpha *= mInterpFade[i].getCurVal();
00303 coloru.mV[3] = (U8)alpha;
00304 glColor4ubv(coloru.mV);
00305
00306 glPushMatrix();
00307 glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
00308 glScalef(scale, scale, scale);
00309 gSphere.render(0);
00310 glPopMatrix();
00311 }
00312 }
00313
00314 void LLHUDEffectBeam::setupParticle(const S32 i)
00315 {
00316 LLVector3d start_pos_global;
00317 if (mSourceObject->getPCode() == LL_PCODE_LEGACY_AVATAR)
00318 {
00319 LLViewerObject *objp = mSourceObject;
00320 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
00321 start_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
00322 }
00323 else
00324 {
00325 start_pos_global = mSourceObject->getPositionGlobal();
00326 }
00327
00328
00329 const F32 SCALE = 0.5f;
00330 F32 x, y, z;
00331 x = ll_frand(SCALE) - 0.5f*SCALE;
00332 y = ll_frand(SCALE) - 0.5f*SCALE;
00333 z = ll_frand(SCALE) - 0.5f*SCALE;
00334
00335 LLVector3d target_pos_global(mTargetPos);
00336 target_pos_global += LLVector3d(x, y, z);
00337
00338 mInterp[i].setStartTime(mInterp[i].getEndTime());
00339 mInterp[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS);
00340 mInterp[i].setStartVal(start_pos_global);
00341 mInterp[i].setEndVal(target_pos_global);
00342 mInterp[i].start();
00343
00344
00345
00346 mInterpFade[i].setStartTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.5f*NUM_POINTS*BEAM_SPACING);
00347 mInterpFade[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.05f);
00348 mInterpFade[i].start();
00349 }