PageRenderTime 32ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llhudeffectpointat.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 461 lines | 310 code | 69 blank | 82 comment | 50 complexity | 3d1531c51843410b8c5bdaa2505dc39c MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llhudeffectpointat.cpp
  3. * @brief LLHUDEffectPointAt class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llhudeffectpointat.h"
  28. #include "llgl.h"
  29. #include "llrender.h"
  30. #include "llagent.h"
  31. #include "llagentcamera.h"
  32. #include "lldrawable.h"
  33. #include "llviewerobjectlist.h"
  34. #include "llvoavatar.h"
  35. #include "message.h"
  36. // packet layout
  37. const S32 SOURCE_AVATAR = 0;
  38. const S32 TARGET_OBJECT = 16;
  39. const S32 TARGET_POS = 32;
  40. const S32 POINTAT_TYPE = 56;
  41. const S32 PKT_SIZE = 57;
  42. // throttle
  43. const F32 MAX_SENDS_PER_SEC = 4.f;
  44. const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f;
  45. // timeouts
  46. // can't use actual F32_MAX, because we add this to the current frametime
  47. const F32 MAX_TIMEOUT = F32_MAX / 4.f;
  48. const F32 POINTAT_TIMEOUTS[POINTAT_NUM_TARGETS] =
  49. {
  50. MAX_TIMEOUT, //POINTAT_TARGET_NONE
  51. MAX_TIMEOUT, //POINTAT_TARGET_SELECT
  52. MAX_TIMEOUT, //POINTAT_TARGET_GRAB
  53. 0.f, //POINTAT_TARGET_CLEAR
  54. };
  55. const S32 POINTAT_PRIORITIES[POINTAT_NUM_TARGETS] =
  56. {
  57. 0, //POINTAT_TARGET_NONE
  58. 1, //POINTAT_TARGET_SELECT
  59. 2, //POINTAT_TARGET_GRAB
  60. 3, //POINTAT_TARGET_CLEAR
  61. };
  62. // statics
  63. BOOL LLHUDEffectPointAt::sDebugPointAt;
  64. //-----------------------------------------------------------------------------
  65. // LLHUDEffectPointAt()
  66. //-----------------------------------------------------------------------------
  67. LLHUDEffectPointAt::LLHUDEffectPointAt(const U8 type) :
  68. LLHUDEffect(type),
  69. mKillTime(0.f),
  70. mLastSendTime(0.f)
  71. {
  72. clearPointAtTarget();
  73. }
  74. //-----------------------------------------------------------------------------
  75. // ~LLHUDEffectPointAt()
  76. //-----------------------------------------------------------------------------
  77. LLHUDEffectPointAt::~LLHUDEffectPointAt()
  78. {
  79. }
  80. //-----------------------------------------------------------------------------
  81. // packData()
  82. //-----------------------------------------------------------------------------
  83. void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
  84. {
  85. // Pack the default data
  86. LLHUDEffect::packData(mesgsys);
  87. // Pack the type-specific data. Uses a fun packed binary format. Whee!
  88. U8 packed_data[PKT_SIZE];
  89. memset(packed_data, 0, PKT_SIZE);
  90. if (mSourceObject)
  91. {
  92. htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
  93. }
  94. else
  95. {
  96. htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
  97. }
  98. // pack both target object and position
  99. // position interpreted as offset if target object is non-null
  100. if (mTargetObject)
  101. {
  102. htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
  103. }
  104. else
  105. {
  106. htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
  107. }
  108. htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
  109. U8 pointAtTypePacked = (U8)mTargetType;
  110. htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
  111. mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
  112. mLastSendTime = mTimer.getElapsedTimeF32();
  113. }
  114. //-----------------------------------------------------------------------------
  115. // unpackData()
  116. //-----------------------------------------------------------------------------
  117. void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
  118. {
  119. LLVector3d new_target;
  120. U8 packed_data[PKT_SIZE];
  121. LLUUID dataId;
  122. mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum);
  123. // ignore messages from ourselves
  124. if (!gAgentCamera.mPointAt.isNull() && dataId == gAgentCamera.mPointAt->getID())
  125. {
  126. return;
  127. }
  128. LLHUDEffect::unpackData(mesgsys, blocknum);
  129. LLUUID source_id;
  130. LLUUID target_id;
  131. U8 pointAtTypeUnpacked = 0;
  132. S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
  133. if (size != PKT_SIZE)
  134. {
  135. llwarns << "PointAt effect with bad size " << size << llendl;
  136. return;
  137. }
  138. mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
  139. htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
  140. htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
  141. htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
  142. htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
  143. LLViewerObject *objp = gObjectList.findObject(source_id);
  144. if (objp && objp->isAvatar())
  145. {
  146. setSourceObject(objp);
  147. }
  148. else
  149. {
  150. //llwarns << "Could not find source avatar for pointat effect" << llendl;
  151. return;
  152. }
  153. objp = gObjectList.findObject(target_id);
  154. if (objp)
  155. {
  156. setTargetObjectAndOffset(objp, new_target);
  157. }
  158. else if (target_id.isNull())
  159. {
  160. setTargetPosGlobal(new_target);
  161. }
  162. mTargetType = (EPointAtType)pointAtTypeUnpacked;
  163. // mKillTime = mTimer.getElapsedTimeF32() + mDuration;
  164. update();
  165. }
  166. //-----------------------------------------------------------------------------
  167. // setTargetObjectAndOffset()
  168. //-----------------------------------------------------------------------------
  169. void LLHUDEffectPointAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset)
  170. {
  171. mTargetObject = objp;
  172. mTargetOffsetGlobal = offset;
  173. }
  174. //-----------------------------------------------------------------------------
  175. // setTargetPosGlobal()
  176. //-----------------------------------------------------------------------------
  177. void LLHUDEffectPointAt::setTargetPosGlobal(const LLVector3d &target_pos_global)
  178. {
  179. mTargetObject = NULL;
  180. mTargetOffsetGlobal = target_pos_global;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // setPointAt()
  184. // called by agent logic to set look at behavior locally, and propagate to sim
  185. //-----------------------------------------------------------------------------
  186. BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)
  187. {
  188. if (!mSourceObject)
  189. {
  190. return FALSE;
  191. }
  192. if (target_type >= POINTAT_NUM_TARGETS)
  193. {
  194. llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl;
  195. return FALSE;
  196. }
  197. // must be same or higher priority than existing effect
  198. if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType])
  199. {
  200. return FALSE;
  201. }
  202. F32 current_time = mTimer.getElapsedTimeF32();
  203. // type of pointat behavior or target object has changed
  204. BOOL targetTypeChanged = (target_type != mTargetType) ||
  205. (object != mTargetObject);
  206. BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) &&
  207. ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));
  208. if (targetTypeChanged || targetPosChanged)
  209. {
  210. mLastSentOffsetGlobal = position;
  211. setDuration(POINTAT_TIMEOUTS[target_type]);
  212. setNeedsSendToSim(TRUE);
  213. // llinfos << "Sending pointat data" << llendl;
  214. }
  215. if (target_type == POINTAT_TARGET_CLEAR)
  216. {
  217. clearPointAtTarget();
  218. }
  219. else
  220. {
  221. mTargetType = target_type;
  222. mTargetObject = object;
  223. if (object)
  224. {
  225. mTargetOffsetGlobal.setVec(position);
  226. }
  227. else
  228. {
  229. mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position);
  230. }
  231. mKillTime = mTimer.getElapsedTimeF32() + mDuration;
  232. //set up requisite animation data
  233. update();
  234. }
  235. return TRUE;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // clearPointAtTarget()
  239. //-----------------------------------------------------------------------------
  240. void LLHUDEffectPointAt::clearPointAtTarget()
  241. {
  242. mTargetObject = NULL;
  243. mTargetOffsetGlobal.clearVec();
  244. mTargetType = POINTAT_TARGET_NONE;
  245. }
  246. //-----------------------------------------------------------------------------
  247. // markDead()
  248. //-----------------------------------------------------------------------------
  249. void LLHUDEffectPointAt::markDead()
  250. {
  251. if (!mSourceObject.isNull() && mSourceObject->isAvatar())
  252. {
  253. ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
  254. }
  255. clearPointAtTarget();
  256. LLHUDEffect::markDead();
  257. }
  258. void LLHUDEffectPointAt::setSourceObject(LLViewerObject* objectp)
  259. {
  260. // restrict source objects to avatars
  261. if (objectp && objectp->isAvatar())
  262. {
  263. LLHUDEffect::setSourceObject(objectp);
  264. }
  265. }
  266. //-----------------------------------------------------------------------------
  267. // render()
  268. //-----------------------------------------------------------------------------
  269. void LLHUDEffectPointAt::render()
  270. {
  271. update();
  272. if (sDebugPointAt && mTargetType != POINTAT_TARGET_NONE)
  273. {
  274. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  275. LLVector3 target = mTargetPos + mSourceObject->getRenderPosition();
  276. gGL.pushMatrix();
  277. gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]);
  278. gGL.scalef(0.3f, 0.3f, 0.3f);
  279. gGL.begin(LLRender::LINES);
  280. {
  281. gGL.color3f(1.f, 0.f, 0.f);
  282. gGL.vertex3f(-1.f, 0.f, 0.f);
  283. gGL.vertex3f(1.f, 0.f, 0.f);
  284. gGL.vertex3f(0.f, -1.f, 0.f);
  285. gGL.vertex3f(0.f, 1.f, 0.f);
  286. gGL.vertex3f(0.f, 0.f, -1.f);
  287. gGL.vertex3f(0.f, 0.f, 1.f);
  288. } gGL.end();
  289. gGL.popMatrix();
  290. }
  291. }
  292. //-----------------------------------------------------------------------------
  293. // update()
  294. //-----------------------------------------------------------------------------
  295. void LLHUDEffectPointAt::update()
  296. {
  297. // If the target object is dead, set the target object to NULL
  298. if (!mTargetObject.isNull() && mTargetObject->isDead())
  299. {
  300. clearPointAtTarget();
  301. }
  302. if (mSourceObject.isNull() || mSourceObject->isDead())
  303. {
  304. markDead();
  305. return;
  306. }
  307. F32 time = mTimer.getElapsedTimeF32();
  308. // clear out the effect if time is up
  309. if (mKillTime != 0.f && time > mKillTime)
  310. {
  311. mTargetType = POINTAT_TARGET_NONE;
  312. }
  313. if (mSourceObject->isAvatar())
  314. {
  315. if (mTargetType == POINTAT_TARGET_NONE)
  316. {
  317. ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
  318. }
  319. else
  320. {
  321. if (calcTargetPosition())
  322. {
  323. ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_EDITING);
  324. }
  325. }
  326. }
  327. }
  328. //-----------------------------------------------------------------------------
  329. // calcTargetPosition()
  330. // returns whether we successfully calculated a finite target position.
  331. //-----------------------------------------------------------------------------
  332. bool LLHUDEffectPointAt::calcTargetPosition()
  333. {
  334. LLViewerObject *targetObject = (LLViewerObject *)mTargetObject;
  335. LLVector3 local_offset;
  336. if (targetObject)
  337. {
  338. local_offset.setVec(mTargetOffsetGlobal);
  339. }
  340. else
  341. {
  342. local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal);
  343. }
  344. if (targetObject && targetObject->mDrawable.notNull())
  345. {
  346. LLQuaternion objRot;
  347. if (targetObject->isAvatar())
  348. {
  349. LLVOAvatar *avatarp = (LLVOAvatar *)targetObject;
  350. mTargetPos = avatarp->mHeadp->getWorldPosition();
  351. objRot = avatarp->mPelvisp->getWorldRotation();
  352. }
  353. else
  354. {
  355. if (targetObject->mDrawable->getGeneration() == -1)
  356. {
  357. mTargetPos = targetObject->getPositionAgent();
  358. objRot = targetObject->getWorldRotation();
  359. }
  360. else
  361. {
  362. mTargetPos = targetObject->getRenderPosition();
  363. objRot = targetObject->getRenderRotation();
  364. }
  365. }
  366. mTargetPos += (local_offset * objRot);
  367. }
  368. else
  369. {
  370. mTargetPos = local_offset;
  371. }
  372. mTargetPos -= mSourceObject->getRenderPosition();
  373. if (!llfinite(mTargetPos.lengthSquared()))
  374. {
  375. return false;
  376. }
  377. if (mSourceObject->isAvatar())
  378. {
  379. ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("PointAtPoint", (void *)&mTargetPos);
  380. }
  381. return true;
  382. }
  383. const LLVector3d LLHUDEffectPointAt::getPointAtPosGlobal()
  384. {
  385. LLVector3d global_pos;
  386. global_pos.setVec(mTargetPos);
  387. if (mSourceObject.notNull())
  388. {
  389. global_pos += mSourceObject->getPositionGlobal();
  390. }
  391. return global_pos;
  392. }