/indra/newview/llhudicon.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 400 lines · 283 code · 71 blank · 46 comment · 33 complexity · 03d137b78da6bb45059f38993ea17090 MD5 · raw file

  1. /**
  2. * @file llhudicon.cpp
  3. * @brief LLHUDIcon class implementation
  4. *
  5. * $LicenseInfo:firstyear=2006&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 "llhudicon.h"
  28. #include "llgl.h"
  29. #include "llrender.h"
  30. #include "llviewerobject.h"
  31. #include "lldrawable.h"
  32. #include "llvector4a.h"
  33. #include "llviewercamera.h"
  34. #include "llviewertexture.h"
  35. #include "llviewerwindow.h"
  36. //-----------------------------------------------------------------------------
  37. // Local consts
  38. //-----------------------------------------------------------------------------
  39. const F32 ANIM_TIME = 0.4f;
  40. const F32 DIST_START_FADE = 15.f;
  41. const F32 DIST_END_FADE = 30.f;
  42. const F32 MAX_VISIBLE_TIME = 15.f;
  43. const F32 FADE_OUT_TIME = 1.f;
  44. //-----------------------------------------------------------------------------
  45. // Utility functions
  46. //-----------------------------------------------------------------------------
  47. static F32 calc_bouncy_animation(F32 x)
  48. {
  49. return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
  50. }
  51. //-----------------------------------------------------------------------------
  52. // static declarations
  53. //-----------------------------------------------------------------------------
  54. LLHUDIcon::icon_instance_t LLHUDIcon::sIconInstances;
  55. LLHUDIcon::LLHUDIcon(const U8 type) :
  56. LLHUDObject(type),
  57. mImagep(NULL),
  58. mPickID(0),
  59. mScale(0.1f),
  60. mHidden(FALSE)
  61. {
  62. sIconInstances.push_back(this);
  63. }
  64. LLHUDIcon::~LLHUDIcon()
  65. {
  66. mImagep = NULL;
  67. }
  68. void LLHUDIcon::renderIcon(BOOL for_select)
  69. {
  70. LLGLSUIDefault texture_state;
  71. LLGLDepthTest gls_depth(GL_TRUE);
  72. if (for_select)
  73. {
  74. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  75. }
  76. if (mHidden)
  77. return;
  78. if (mSourceObject.isNull() || mImagep.isNull())
  79. {
  80. markDead();
  81. return;
  82. }
  83. LLVector3 obj_position = mSourceObject->getRenderPosition();
  84. // put icon above object, and in front
  85. // RN: don't use drawable radius, it's fricking HUGE
  86. LLViewerCamera* camera = LLViewerCamera::getInstance();
  87. LLVector3 icon_relative_pos = (camera->getUpAxis() * ~mSourceObject->getRenderRotation());
  88. icon_relative_pos.abs();
  89. F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX],
  90. mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY],
  91. mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]);
  92. F32 up_distance = 0.5f * distance_scale;
  93. LLVector3 icon_position = obj_position + (up_distance * camera->getUpAxis()) * 1.2f;
  94. LLVector3 icon_to_cam = LLViewerCamera::getInstance()->getOrigin() - icon_position;
  95. icon_to_cam.normVec();
  96. icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f;
  97. mDistance = dist_vec(icon_position, camera->getOrigin());
  98. F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
  99. LLVector3 x_pixel_vec;
  100. LLVector3 y_pixel_vec;
  101. camera->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
  102. F32 scale_factor = 1.f;
  103. if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME)
  104. {
  105. scale_factor = llmax(0.f, calc_bouncy_animation(mAnimTimer.getElapsedTimeF32() / ANIM_TIME));
  106. }
  107. F32 time_elapsed = mLifeTimer.getElapsedTimeF32();
  108. if (time_elapsed > MAX_VISIBLE_TIME)
  109. {
  110. markDead();
  111. return;
  112. }
  113. if (time_elapsed > MAX_VISIBLE_TIME - FADE_OUT_TIME)
  114. {
  115. alpha_factor *= clamp_rescale(time_elapsed, MAX_VISIBLE_TIME - FADE_OUT_TIME, MAX_VISIBLE_TIME, 1.f, 0.f);
  116. }
  117. F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ;
  118. LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec;
  119. LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec;
  120. LLVector3 lower_left = icon_position - (x_scale * 0.5f);
  121. LLVector3 lower_right = icon_position + (x_scale * 0.5f);
  122. LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale;
  123. LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale;
  124. if (for_select)
  125. {
  126. // set color to unique color id for picking
  127. LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID);
  128. gGL.color4ubv(coloru.mV);
  129. }
  130. else
  131. {
  132. LLColor4 icon_color = LLColor4::white;
  133. icon_color.mV[VALPHA] = alpha_factor;
  134. gGL.color4fv(icon_color.mV);
  135. gGL.getTexUnit(0)->bind(mImagep);
  136. }
  137. gGL.begin(LLRender::QUADS);
  138. {
  139. gGL.texCoord2f(0.f, 1.f);
  140. gGL.vertex3fv(upper_left.mV);
  141. gGL.texCoord2f(0.f, 0.f);
  142. gGL.vertex3fv(lower_left.mV);
  143. gGL.texCoord2f(1.f, 0.f);
  144. gGL.vertex3fv(lower_right.mV);
  145. gGL.texCoord2f(1.f, 1.f);
  146. gGL.vertex3fv(upper_right.mV);
  147. }
  148. gGL.end();
  149. }
  150. void LLHUDIcon::setImage(LLViewerTexture* imagep)
  151. {
  152. mImagep = imagep;
  153. mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
  154. }
  155. void LLHUDIcon::setScale(F32 fraction_of_fov)
  156. {
  157. mScale = fraction_of_fov;
  158. }
  159. void LLHUDIcon::markDead()
  160. {
  161. if (mSourceObject)
  162. {
  163. mSourceObject->clearIcon();
  164. }
  165. LLHUDObject::markDead();
  166. }
  167. void LLHUDIcon::render()
  168. {
  169. renderIcon(FALSE);
  170. }
  171. BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3* intersection)
  172. {
  173. if (mHidden)
  174. return FALSE;
  175. if (mSourceObject.isNull() || mImagep.isNull())
  176. {
  177. markDead();
  178. return FALSE;
  179. }
  180. LLVector3 obj_position = mSourceObject->getRenderPosition();
  181. // put icon above object, and in front
  182. // RN: don't use drawable radius, it's fricking HUGE
  183. LLViewerCamera* camera = LLViewerCamera::getInstance();
  184. LLVector3 icon_relative_pos = (camera->getUpAxis() * ~mSourceObject->getRenderRotation());
  185. icon_relative_pos.abs();
  186. F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX],
  187. mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY],
  188. mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]);
  189. F32 up_distance = 0.5f * distance_scale;
  190. LLVector3 icon_position = obj_position + (up_distance * camera->getUpAxis()) * 1.2f;
  191. LLVector3 icon_to_cam = LLViewerCamera::getInstance()->getOrigin() - icon_position;
  192. icon_to_cam.normVec();
  193. icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f;
  194. mDistance = dist_vec(icon_position, camera->getOrigin());
  195. LLVector3 x_pixel_vec;
  196. LLVector3 y_pixel_vec;
  197. camera->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
  198. F32 scale_factor = 1.f;
  199. if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME)
  200. {
  201. scale_factor = llmax(0.f, calc_bouncy_animation(mAnimTimer.getElapsedTimeF32() / ANIM_TIME));
  202. }
  203. F32 time_elapsed = mLifeTimer.getElapsedTimeF32();
  204. if (time_elapsed > MAX_VISIBLE_TIME)
  205. {
  206. markDead();
  207. return FALSE;
  208. }
  209. F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ;
  210. LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec;
  211. LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec;
  212. LLVector4a x_scalea;
  213. LLVector4a icon_positiona;
  214. LLVector4a y_scalea;
  215. x_scalea.load3(x_scale.mV);
  216. x_scalea.mul(0.5f);
  217. y_scalea.load3(y_scale.mV);
  218. icon_positiona.load3(icon_position.mV);
  219. LLVector4a lower_left;
  220. lower_left.setSub(icon_positiona, x_scalea);
  221. LLVector4a lower_right;
  222. lower_right.setAdd(icon_positiona, x_scalea);
  223. LLVector4a upper_left;
  224. upper_left.setAdd(lower_left, y_scalea);
  225. LLVector4a upper_right;
  226. upper_right.setAdd(lower_right, y_scalea);
  227. LLVector4a enda;
  228. enda.load3(end.mV);
  229. LLVector4a starta;
  230. starta.load3(start.mV);
  231. LLVector4a dir;
  232. dir.setSub(enda, starta);
  233. F32 a,b,t;
  234. if (LLTriangleRayIntersect(upper_right, upper_left, lower_right, starta, dir, a,b,t) ||
  235. LLTriangleRayIntersect(upper_left, lower_left, lower_right, starta, dir, a,b,t))
  236. {
  237. if (intersection)
  238. {
  239. dir.mul(t);
  240. starta.add(dir);
  241. *intersection = LLVector3(starta.getF32ptr());
  242. }
  243. return TRUE;
  244. }
  245. return FALSE;
  246. }
  247. //static
  248. S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size)
  249. {
  250. S32 cur_id = start_id;
  251. icon_instance_t::iterator icon_it;
  252. for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
  253. {
  254. (*icon_it)->mPickID = cur_id;
  255. cur_id += step_size;
  256. }
  257. return cur_id;
  258. }
  259. //static
  260. LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id)
  261. {
  262. icon_instance_t::iterator icon_it;
  263. for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
  264. {
  265. if (pick_id == (*icon_it)->mPickID)
  266. {
  267. return *icon_it;
  268. }
  269. }
  270. return NULL;
  271. }
  272. //static
  273. LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector3& start, const LLVector3& end, LLVector3* intersection)
  274. {
  275. icon_instance_t::iterator icon_it;
  276. LLVector3 local_end = end;
  277. LLVector3 position;
  278. LLHUDIcon* ret = NULL;
  279. for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
  280. {
  281. LLHUDIcon* icon = *icon_it;
  282. if (icon->lineSegmentIntersect(start, local_end, &position))
  283. {
  284. ret = icon;
  285. if (intersection)
  286. {
  287. *intersection = position;
  288. }
  289. local_end = position;
  290. }
  291. }
  292. return ret;
  293. }
  294. //static
  295. void LLHUDIcon::updateAll()
  296. {
  297. cleanupDeadIcons();
  298. }
  299. //static
  300. BOOL LLHUDIcon::iconsNearby()
  301. {
  302. return !sIconInstances.empty();
  303. }
  304. //static
  305. void LLHUDIcon::cleanupDeadIcons()
  306. {
  307. icon_instance_t::iterator icon_it;
  308. icon_instance_t icons_to_erase;
  309. for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
  310. {
  311. if ((*icon_it)->mDead)
  312. {
  313. icons_to_erase.push_back(*icon_it);
  314. }
  315. }
  316. for(icon_it = icons_to_erase.begin(); icon_it != icons_to_erase.end(); ++icon_it)
  317. {
  318. icon_instance_t::iterator found_it = std::find(sIconInstances.begin(), sIconInstances.end(), *icon_it);
  319. if (found_it != sIconInstances.end())
  320. {
  321. sIconInstances.erase(found_it);
  322. }
  323. }
  324. }
  325. //static
  326. S32 LLHUDIcon::getNumInstances()
  327. {
  328. return (S32)sIconInstances.size();
  329. }