llhudeffectbeam.cpp

Go to the documentation of this file.
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         // Initialize all of these to defaults
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         // Setup default timeouts and fade animations.
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         // Pack the default data
00091         LLHUDEffect::packData(mesgsys);
00092 
00093         // Pack the type-specific data.  Uses a fun packed binary format.  Whee!
00094         // 16 + 24 + 1 = 41
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         // We've received an update for the effect, update the various timeouts
00167         // and fade animations.
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         // Kill us if our time is over...
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         // Interpolate the global fade alpha
00258         mFadeInterp.update(time);
00259 
00260         if (mTargetObject.notNull() && mTargetObject->mDrawable.notNull())
00261         {
00262                 // use viewer object position on freshly created objects
00263                 if (mTargetObject->mDrawable->getGeneration() == -1)
00264                 {
00265                         mTargetPos = mTargetObject->getPositionGlobal();
00266                 }
00267                 // otherwise use drawable
00268                 else
00269                 {
00270                         mTargetPos = gAgent.getPosGlobalFromAgent(mTargetObject->mDrawable->getPositionAgent());
00271                 }
00272         }
00273 
00274 
00275         // Init the color of the particles
00276         LLColor4U coloru = mColor;
00277 
00278         /*
00279         // This is disabled for now - DJS
00280 
00281         // Fade the alpha
00282         coloru.mV[3] = mFadeInterp.getCurVal()*mColor.mV[3];
00283 
00284         // Draw a regular "beam" that connects the source and target
00285 
00286         // First, figure out start and end positions relative to the camera
00287         LLVector3 start_pos_agent;
00288         if (mSourceObject->getPCode() == LL_PCODE_LEGACY_AVATAR)
00289         {
00290                 LLViewerObject *objp = mSourceObject;
00291                 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
00292                 LLVector3d hand_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
00293                 start_pos_agent = gAgent.getPosAgentFromGlobal(hand_pos_global);
00294         }
00295         else
00296         {
00297                 start_pos_agent = mSourceObject->getPositionAgent();
00298         }
00299         LLVector3 start_pos_camera = (start_pos_agent - gAgent.getCameraPositionAgent());
00300         LLVector3 target_pos_agent = gAgent.getPosAgentFromGlobal(mTargetPos);
00301         LLVector3 target_pos_camera = target_pos_agent - gAgent.getCameraPositionAgent();
00302 
00303         // Generate the right "up" vector which is perpendicular to the beam, make it 1/10 meter wide, going to a point.
00304         LLVector3 camera_up = gCamera->getUpAxis();
00305         LLVector3 camera_at = gCamera->getAtAxis();
00306         LLVector3 up = target_pos_camera % start_pos_camera;
00307         up.normVec();
00308         up *= 0.1f;
00309 
00310         // Draw the triangle for the beam.
00311         LLVector3 vertex;
00312         glColor4ubv(coloru.mV);
00313         glBegin(GL_TRIANGLE_STRIP);
00314         vertex = start_pos_agent + up;
00315         glVertex3fv(vertex.mV);
00316         vertex = start_pos_agent - up;
00317         glVertex3fv(vertex.mV);
00318         vertex = target_pos_agent;
00319         glVertex3fv(vertex.mV);
00320         glEnd();
00321         */
00322         
00323         // Draw the particles
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                         // Reinitialize the particle when the particle has finished its animation.
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         // Generate a random offset for the target point.
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         // Setup the interpolator that fades out the alpha.
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 }

Generated on Thu Jul 1 06:08:42 2010 for Second Life Viewer by  doxygen 1.4.7