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

Generated on Fri May 16 08:33:38 2008 for SecondLife by  doxygen 1.5.5