llhudeffectpointat.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llhudeffectpointat.h"
00035 
00036 #include "llgl.h"
00037 
00038 #include "llagent.h"
00039 #include "lldrawable.h"
00040 #include "llviewerobjectlist.h"
00041 #include "llvoavatar.h"
00042 #include "message.h"
00043 
00044 // packet layout
00045 const S32 SOURCE_AVATAR = 0;
00046 const S32 TARGET_OBJECT = 16;
00047 const S32 TARGET_POS = 32;
00048 const S32 POINTAT_TYPE = 56;
00049 const S32 PKT_SIZE = 57;
00050 
00051 // throttle
00052 const F32 MAX_SENDS_PER_SEC = 4.f;
00053 
00054 const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f;
00055 
00056 // timeouts
00057 // can't use actual F32_MAX, because we add this to the current frametime
00058 const F32 MAX_TIMEOUT = F32_MAX / 4.f;
00059 
00060 const F32 POINTAT_TIMEOUTS[POINTAT_NUM_TARGETS] = 
00061 {
00062         MAX_TIMEOUT, //POINTAT_TARGET_NONE
00063         MAX_TIMEOUT, //POINTAT_TARGET_SELECT
00064         MAX_TIMEOUT, //POINTAT_TARGET_GRAB
00065         0.f, //POINTAT_TARGET_CLEAR
00066 };
00067 
00068 const S32 POINTAT_PRIORITIES[POINTAT_NUM_TARGETS] = 
00069 {
00070         0, //POINTAT_TARGET_NONE
00071         1, //POINTAT_TARGET_SELECT
00072         2, //POINTAT_TARGET_GRAB
00073         3, //POINTAT_TARGET_CLEAR
00074 };
00075 
00076 // statics
00077 
00078 BOOL LLHUDEffectPointAt::sDebugPointAt;
00079 
00080 
00081 //-----------------------------------------------------------------------------
00082 // LLHUDEffectPointAt()
00083 //-----------------------------------------------------------------------------
00084 LLHUDEffectPointAt::LLHUDEffectPointAt(const U8 type) : 
00085         LLHUDEffect(type), 
00086         mKillTime(0.f),
00087         mLastSendTime(0.f)
00088 {
00089         clearPointAtTarget();
00090 }
00091 
00092 //-----------------------------------------------------------------------------
00093 // ~LLHUDEffectPointAt()
00094 //-----------------------------------------------------------------------------
00095 LLHUDEffectPointAt::~LLHUDEffectPointAt()
00096 {
00097 }
00098 
00099 //-----------------------------------------------------------------------------
00100 // packData()
00101 //-----------------------------------------------------------------------------
00102 void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
00103 {
00104         // Pack the default data
00105         LLHUDEffect::packData(mesgsys);
00106 
00107         // Pack the type-specific data.  Uses a fun packed binary format.  Whee!
00108         U8 packed_data[PKT_SIZE];
00109         memset(packed_data, 0, PKT_SIZE);
00110 
00111         if (mSourceObject)
00112         {
00113                 htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
00114         }
00115         else
00116         {
00117                 htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
00118         }
00119 
00120         // pack both target object and position
00121         // position interpreted as offset if target object is non-null
00122         if (mTargetObject)
00123         {
00124                 htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
00125         }
00126         else
00127         {
00128                 htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
00129         }
00130 
00131         htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
00132 
00133         U8 pointAtTypePacked = (U8)mTargetType;
00134         htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
00135 
00136         mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
00137 
00138         mLastSendTime = mTimer.getElapsedTimeF32();
00139 }
00140 
00141 //-----------------------------------------------------------------------------
00142 // unpackData()
00143 //-----------------------------------------------------------------------------
00144 void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
00145 {
00146         LLVector3d new_target;
00147         U8 packed_data[PKT_SIZE];
00148 
00149         LLUUID dataId;
00150         mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum);
00151 
00152         // ignore messages from ourselves
00153         if (!gAgent.mPointAt.isNull() && dataId == gAgent.mPointAt->getID())
00154         {
00155                 return;
00156         }
00157 
00158         LLHUDEffect::unpackData(mesgsys, blocknum);
00159         LLUUID source_id;
00160         LLUUID target_id;
00161         S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
00162         if (size != PKT_SIZE)
00163         {
00164                 llwarns << "PointAt effect with bad size " << size << llendl;
00165                 return;
00166         }
00167         mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
00168         
00169         htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
00170 
00171         LLViewerObject *objp = gObjectList.findObject(source_id);
00172         if (objp && objp->isAvatar())
00173         {
00174                 setSourceObject(objp);
00175         }
00176         else
00177         {
00178                 //llwarns << "Could not find source avatar for pointat effect" << llendl;
00179                 return;
00180         }
00181 
00182         htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
00183 
00184         objp = gObjectList.findObject(target_id);
00185 
00186         htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
00187 
00188         if (objp)
00189         {
00190                 setTargetObjectAndOffset(objp, new_target);
00191         }
00192         else if (target_id.isNull())
00193         {
00194                 setTargetPosGlobal(new_target);
00195         }
00196 
00197         U8 pointAtTypeUnpacked = 0;
00198         htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
00199         mTargetType = (EPointAtType)pointAtTypeUnpacked;
00200 
00201 //      mKillTime = mTimer.getElapsedTimeF32() + mDuration;
00202         update();
00203 }
00204 
00205 //-----------------------------------------------------------------------------
00206 // setTargetObjectAndOffset()
00207 //-----------------------------------------------------------------------------
00208 void LLHUDEffectPointAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset)
00209 {
00210         mTargetObject = objp;
00211         mTargetOffsetGlobal = offset;
00212 }
00213 
00214 //-----------------------------------------------------------------------------
00215 // setTargetPosGlobal()
00216 //-----------------------------------------------------------------------------
00217 void LLHUDEffectPointAt::setTargetPosGlobal(const LLVector3d &target_pos_global)
00218 {
00219         mTargetObject = NULL;
00220         mTargetOffsetGlobal = target_pos_global;
00221 }
00222 
00223 //-----------------------------------------------------------------------------
00224 // setPointAt()
00225 // called by agent logic to set look at behavior locally, and propagate to sim
00226 //-----------------------------------------------------------------------------
00227 BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)
00228 {
00229         if (!mSourceObject)
00230         {
00231                 return FALSE;
00232         }
00233         
00234         llassert(target_type < POINTAT_NUM_TARGETS);
00235 
00236         // must be same or higher priority than existing effect
00237         if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType])
00238         {
00239                 return FALSE;
00240         }
00241 
00242         F32 current_time  = mTimer.getElapsedTimeF32();
00243         
00244         // type of pointat behavior or target object has changed
00245         BOOL targetTypeChanged = (target_type != mTargetType) ||
00246                 (object != mTargetObject);
00247 
00248         BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && 
00249                 ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));
00250 
00251         if (targetTypeChanged || targetPosChanged)
00252         {
00253                 mLastSentOffsetGlobal = position;
00254                 setDuration(POINTAT_TIMEOUTS[target_type]);
00255                 setNeedsSendToSim(TRUE);
00256 //              llinfos << "Sending pointat data" << llendl;
00257         }
00258 
00259         if (target_type == POINTAT_TARGET_CLEAR)
00260         {
00261                 clearPointAtTarget();
00262         }
00263         else
00264         {
00265                 mTargetType = target_type;
00266                 mTargetObject = object;
00267                 if (object)
00268                 {
00269                         mTargetOffsetGlobal.setVec(position);
00270                 }
00271                 else
00272                 {
00273                         mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position);
00274                 }
00275 
00276                 mKillTime = mTimer.getElapsedTimeF32() + mDuration;
00277 
00278                 //set up requisite animation data
00279                 update();
00280         }
00281 
00282         return TRUE;
00283 }
00284 
00285 //-----------------------------------------------------------------------------
00286 // clearPointAtTarget()
00287 //-----------------------------------------------------------------------------
00288 void LLHUDEffectPointAt::clearPointAtTarget()
00289 {
00290         mTargetObject = NULL;
00291         mTargetOffsetGlobal.clearVec();
00292         mTargetType = POINTAT_TARGET_NONE;
00293 }
00294 
00295 //-----------------------------------------------------------------------------
00296 // markDead()
00297 //-----------------------------------------------------------------------------
00298 void LLHUDEffectPointAt::markDead()
00299 {
00300         if (!mSourceObject.isNull() && mSourceObject->isAvatar())
00301         {
00302                 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
00303         }
00304 
00305         clearPointAtTarget();
00306         LLHUDEffect::markDead();
00307 }
00308 
00309 void LLHUDEffectPointAt::setSourceObject(LLViewerObject* objectp)
00310 {
00311         // restrict source objects to avatars
00312         if (objectp && objectp->isAvatar())
00313         {
00314                 LLHUDEffect::setSourceObject(objectp);
00315         }
00316 }
00317 
00318 //-----------------------------------------------------------------------------
00319 // render()
00320 //-----------------------------------------------------------------------------
00321 void LLHUDEffectPointAt::render()
00322 {
00323         update();
00324         if (sDebugPointAt && mTargetType != POINTAT_TARGET_NONE)
00325         {
00326                 LLGLSNoTexture gls_no_texture;
00327 
00328                 LLVector3 target = mTargetPos + mSourceObject->getRenderPosition();
00329                 glPushMatrix();
00330                 glTranslatef(target.mV[VX], target.mV[VY], target.mV[VZ]);
00331                 glScalef(0.3f, 0.3f, 0.3f);
00332                 glBegin(GL_LINES);
00333                 {
00334                         glColor3f(1.f, 0.f, 0.f);
00335                         glVertex3f(-1.f, 0.f, 0.f);
00336                         glVertex3f(1.f, 0.f, 0.f);
00337 
00338                         glVertex3f(0.f, -1.f, 0.f);
00339                         glVertex3f(0.f, 1.f, 0.f);
00340 
00341                         glVertex3f(0.f, 0.f, -1.f);
00342                         glVertex3f(0.f, 0.f, 1.f);
00343                 } glEnd();
00344                 glPopMatrix();
00345         }
00346 }
00347 
00348 //-----------------------------------------------------------------------------
00349 // update()
00350 //-----------------------------------------------------------------------------
00351 void LLHUDEffectPointAt::update()
00352 {
00353         // If the target object is dead, set the target object to NULL
00354         if (!mTargetObject.isNull() && mTargetObject->isDead())
00355         {
00356                 clearPointAtTarget();
00357         }
00358 
00359         if (mSourceObject.isNull() || mSourceObject->isDead())
00360         {
00361                 markDead();
00362                 return;
00363         }
00364         
00365         F32 time = mTimer.getElapsedTimeF32();
00366 
00367         // clear out the effect if time is up
00368         if (mKillTime != 0.f && time > mKillTime)
00369         {
00370                 mTargetType = POINTAT_TARGET_NONE;
00371         }
00372 
00373         if (mSourceObject->isAvatar())
00374         {
00375                 if (mTargetType == POINTAT_TARGET_NONE)
00376                 {
00377                         ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
00378                 }
00379                 else
00380                 {
00381                         calcTargetPosition();
00382                 
00383                         ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_EDITING);
00384                 }
00385         }
00386 }
00387 
00388 //-----------------------------------------------------------------------------
00389 // calcTargetPosition()
00390 //-----------------------------------------------------------------------------
00391 void LLHUDEffectPointAt::calcTargetPosition()
00392 {
00393         LLViewerObject *targetObject = (LLViewerObject *)mTargetObject;
00394         LLVector3 local_offset;
00395         
00396         if (targetObject)
00397         {
00398                 local_offset.setVec(mTargetOffsetGlobal);
00399         }
00400         else
00401         {
00402                 local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal);
00403         }
00404 
00405         if (targetObject && targetObject->mDrawable.notNull())
00406         {
00407                 LLQuaternion objRot;
00408                 if (targetObject->isAvatar())
00409                 {
00410                         LLVOAvatar *avatarp = (LLVOAvatar *)targetObject;
00411                         mTargetPos = avatarp->mHeadp->getWorldPosition();
00412                         objRot = avatarp->mPelvisp->getWorldRotation();
00413                 }
00414                 else
00415                 {
00416                         if (targetObject->mDrawable->getGeneration() == -1)
00417                         {
00418                                 mTargetPos = targetObject->getPositionAgent();
00419                                 objRot = targetObject->getWorldRotation();
00420                         }
00421                         else
00422                         {
00423                                 mTargetPos = targetObject->getRenderPosition();
00424                                 objRot = targetObject->getRenderRotation();
00425                         }
00426                 }
00427 
00428                 mTargetPos += (local_offset * objRot);
00429         }
00430         else
00431         {
00432                 mTargetPos = local_offset;
00433         }
00434 
00435         mTargetPos -= mSourceObject->getRenderPosition();
00436 
00437         if (mSourceObject->isAvatar())
00438         {
00439                 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("PointAtPoint", (void *)&mTargetPos);
00440         }
00441 }
00442 
00443 const LLVector3d LLHUDEffectPointAt::getPointAtPosGlobal()
00444 {
00445         LLVector3d global_pos;
00446         global_pos.setVec(mTargetPos);
00447         if (mSourceObject.notNull())
00448         {
00449                 global_pos += mSourceObject->getPositionGlobal();
00450         }
00451         
00452         return global_pos;
00453 }

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