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 }