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

/indra/newview/llagentcamera.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1985 lines | 1411 code | 298 blank | 276 comment | 291 complexity | 2f86ba108ab5e2059d20104bd762e219 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llagentcamera.cpp
  3. * @brief LLAgent class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&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 "llagentcamera.h"
  28. #include "pipeline.h"
  29. #include "llagent.h"
  30. #include "llanimationstates.h"
  31. #include "llfloatercamera.h"
  32. #include "llfloaterreg.h"
  33. #include "llhudmanager.h"
  34. #include "lljoystickbutton.h"
  35. #include "llselectmgr.h"
  36. #include "llsmoothstep.h"
  37. #include "lltoolmgr.h"
  38. #include "llviewercamera.h"
  39. #include "llviewercontrol.h"
  40. #include "llviewerjoystick.h"
  41. #include "llviewermenu.h"
  42. #include "llviewerobjectlist.h"
  43. #include "llviewerregion.h"
  44. #include "llviewerwindow.h"
  45. #include "llvoavatarself.h"
  46. #include "llwindow.h"
  47. #include "llworld.h"
  48. using namespace LLVOAvatarDefines;
  49. extern LLMenuBarGL* gMenuBarView;
  50. // Mousewheel camera zoom
  51. const F32 MIN_ZOOM_FRACTION = 0.25f;
  52. const F32 INITIAL_ZOOM_FRACTION = 1.f;
  53. const F32 MAX_ZOOM_FRACTION = 8.f;
  54. const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds
  55. const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds
  56. const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f;
  57. const F32 CAMERA_LAG_HALF_LIFE = 0.25f;
  58. const F32 MIN_CAMERA_LAG = 0.5f;
  59. const F32 MAX_CAMERA_LAG = 5.f;
  60. const F32 CAMERA_COLLIDE_EPSILON = 0.1f;
  61. const F32 MIN_CAMERA_DISTANCE = 0.1f;
  62. const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.55f;
  63. const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.7f;
  64. const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 1.15f;
  65. const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f;
  66. const F32 MAX_CAMERA_SMOOTH_DISTANCE = 50.0f;
  67. const F32 HEAD_BUFFER_SIZE = 0.3f;
  68. const F32 CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP = 0.1f;
  69. const F32 LAND_MIN_ZOOM = 0.15f;
  70. const F32 AVATAR_MIN_ZOOM = 0.5f;
  71. const F32 OBJECT_MIN_ZOOM = 0.02f;
  72. const F32 APPEARANCE_MIN_ZOOM = 0.39f;
  73. const F32 APPEARANCE_MAX_ZOOM = 8.f;
  74. const F32 CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST = 3.5f;
  75. const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f;
  76. const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f;
  77. const F32 OBJECT_EXTENTS_PADDING = 0.5f;
  78. // The agent instance.
  79. LLAgentCamera gAgentCamera;
  80. //-----------------------------------------------------------------------------
  81. // LLAgentCamera()
  82. //-----------------------------------------------------------------------------
  83. LLAgentCamera::LLAgentCamera() :
  84. mInitialized(false),
  85. mDrawDistance( DEFAULT_FAR_PLANE ),
  86. mLookAt(NULL),
  87. mPointAt(NULL),
  88. mHUDTargetZoom(1.f),
  89. mHUDCurZoom(1.f),
  90. mForceMouselook(FALSE),
  91. mCameraMode( CAMERA_MODE_THIRD_PERSON ),
  92. mLastCameraMode( CAMERA_MODE_THIRD_PERSON ),
  93. mCameraPreset(CAMERA_PRESET_REAR_VIEW),
  94. mCameraAnimating( FALSE ),
  95. mAnimationCameraStartGlobal(),
  96. mAnimationFocusStartGlobal(),
  97. mAnimationTimer(),
  98. mAnimationDuration(0.33f),
  99. mCameraFOVZoomFactor(0.f),
  100. mCameraCurrentFOVZoomFactor(0.f),
  101. mCameraFocusOffset(),
  102. mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW),
  103. mCameraCollidePlane(),
  104. mCurrentCameraDistance(2.f), // meters, set in init()
  105. mTargetCameraDistance(2.f),
  106. mCameraZoomFraction(1.f), // deprecated
  107. mThirdPersonHeadOffset(0.f, 0.f, 1.f),
  108. mSitCameraEnabled(FALSE),
  109. mCameraSmoothingLastPositionGlobal(),
  110. mCameraSmoothingLastPositionAgent(),
  111. mCameraSmoothingStop(false),
  112. mCameraUpVector(LLVector3::z_axis), // default is straight up
  113. mFocusOnAvatar(TRUE),
  114. mFocusGlobal(),
  115. mFocusTargetGlobal(),
  116. mFocusObject(NULL),
  117. mFocusObjectDist(0.f),
  118. mFocusObjectOffset(),
  119. mFocusDotRadius( 0.1f ), // meters
  120. mTrackFocusObject(TRUE),
  121. mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed
  122. mWalkKey(0), // like AtKey, but causes less forward thrust
  123. mLeftKey(0),
  124. mUpKey(0),
  125. mYawKey(0.f),
  126. mPitchKey(0.f),
  127. mOrbitLeftKey(0.f),
  128. mOrbitRightKey(0.f),
  129. mOrbitUpKey(0.f),
  130. mOrbitDownKey(0.f),
  131. mOrbitInKey(0.f),
  132. mOrbitOutKey(0.f),
  133. mPanUpKey(0.f),
  134. mPanDownKey(0.f),
  135. mPanLeftKey(0.f),
  136. mPanRightKey(0.f),
  137. mPanInKey(0.f),
  138. mPanOutKey(0.f)
  139. {
  140. mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
  141. clearGeneralKeys();
  142. clearOrbitKeys();
  143. clearPanKeys();
  144. }
  145. // Requires gSavedSettings to be initialized.
  146. //-----------------------------------------------------------------------------
  147. // init()
  148. //-----------------------------------------------------------------------------
  149. void LLAgentCamera::init()
  150. {
  151. // *Note: this is where LLViewerCamera::getInstance() used to be constructed.
  152. mDrawDistance = gSavedSettings.getF32("RenderFarClip");
  153. LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW);
  154. // Leave at 0.1 meters until we have real near clip management
  155. LLViewerCamera::getInstance()->setNear(0.1f);
  156. LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h
  157. LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() ); // default, overridden in LLViewerWindow::reshape
  158. LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape
  159. mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild"));
  160. mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPreset");
  161. mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("CameraOffsetRearView");
  162. mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("CameraOffsetFrontView");
  163. mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("CameraOffsetGroupView");
  164. mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("FocusOffsetRearView");
  165. mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("FocusOffsetFrontView");
  166. mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("FocusOffsetGroupView");
  167. mCameraCollidePlane.clearVec();
  168. mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale");
  169. mTargetCameraDistance = mCurrentCameraDistance;
  170. mCameraZoomFraction = 1.f;
  171. mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject");
  172. mInitialized = true;
  173. }
  174. //-----------------------------------------------------------------------------
  175. // cleanup()
  176. //-----------------------------------------------------------------------------
  177. void LLAgentCamera::cleanup()
  178. {
  179. setSitCamera(LLUUID::null);
  180. if(mLookAt)
  181. {
  182. mLookAt->markDead() ;
  183. mLookAt = NULL;
  184. }
  185. if(mPointAt)
  186. {
  187. mPointAt->markDead() ;
  188. mPointAt = NULL;
  189. }
  190. setFocusObject(NULL);
  191. }
  192. void LLAgentCamera::setAvatarObject(LLVOAvatarSelf* avatar)
  193. {
  194. if (!mLookAt)
  195. {
  196. mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT);
  197. }
  198. if (!mPointAt)
  199. {
  200. mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT);
  201. }
  202. if (!mLookAt.isNull())
  203. {
  204. mLookAt->setSourceObject(avatar);
  205. }
  206. if (!mPointAt.isNull())
  207. {
  208. mPointAt->setSourceObject(avatar);
  209. }
  210. }
  211. //-----------------------------------------------------------------------------
  212. // LLAgent()
  213. //-----------------------------------------------------------------------------
  214. LLAgentCamera::~LLAgentCamera()
  215. {
  216. cleanup();
  217. // *Note: this is where LLViewerCamera::getInstance() used to be deleted.
  218. }
  219. // Change camera back to third person, stop the autopilot,
  220. // deselect stuff, etc.
  221. //-----------------------------------------------------------------------------
  222. // resetView()
  223. //-----------------------------------------------------------------------------
  224. void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
  225. {
  226. if (gAgent.getAutoPilot())
  227. {
  228. gAgent.stopAutoPilot(TRUE);
  229. }
  230. LLSelectMgr::getInstance()->unhighlightAll();
  231. // By popular request, keep land selection while walking around. JC
  232. // LLViewerParcelMgr::getInstance()->deselectLand();
  233. // force deselect when walking and attachment is selected
  234. // this is so people don't wig out when their avatar moves without animating
  235. if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
  236. {
  237. LLSelectMgr::getInstance()->deselectAll();
  238. }
  239. if (gMenuHolder != NULL)
  240. {
  241. // Hide all popup menus
  242. gMenuHolder->hideMenus();
  243. }
  244. if (change_camera && !gSavedSettings.getBOOL("FreezeTime"))
  245. {
  246. changeCameraToDefault();
  247. if (LLViewerJoystick::getInstance()->getOverrideCamera())
  248. {
  249. handle_toggle_flycam();
  250. }
  251. // reset avatar mode from eventual residual motion
  252. if (LLToolMgr::getInstance()->inBuildMode())
  253. {
  254. LLViewerJoystick::getInstance()->moveAvatar(true);
  255. }
  256. //Camera Tool is needed for Free Camera Control Mode
  257. if (!LLFloaterCamera::inFreeCameraMode())
  258. {
  259. LLFloaterReg::hideInstance("build");
  260. // Switch back to basic toolset
  261. LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
  262. }
  263. gViewerWindow->showCursor();
  264. }
  265. if (reset_camera && !gSavedSettings.getBOOL("FreezeTime"))
  266. {
  267. if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson())
  268. {
  269. // leaving mouse-steer mode
  270. LLVector3 agent_at_axis = gAgent.getAtAxis();
  271. agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector());
  272. agent_at_axis.normalize();
  273. gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f)));
  274. }
  275. setFocusOnAvatar(TRUE, ANIMATE);
  276. mCameraFOVZoomFactor = 0.f;
  277. }
  278. mHUDTargetZoom = 1.f;
  279. }
  280. // Allow camera to be moved somewhere other than behind avatar.
  281. //-----------------------------------------------------------------------------
  282. // unlockView()
  283. //-----------------------------------------------------------------------------
  284. void LLAgentCamera::unlockView()
  285. {
  286. if (getFocusOnAvatar())
  287. {
  288. if (isAgentAvatarValid())
  289. {
  290. setFocusGlobal(LLVector3d::zero, gAgentAvatarp->mID);
  291. }
  292. setFocusOnAvatar(FALSE, FALSE); // no animation
  293. }
  294. }
  295. //-----------------------------------------------------------------------------
  296. // slamLookAt()
  297. //-----------------------------------------------------------------------------
  298. void LLAgentCamera::slamLookAt(const LLVector3 &look_at)
  299. {
  300. LLVector3 look_at_norm = look_at;
  301. look_at_norm.mV[VZ] = 0.f;
  302. look_at_norm.normalize();
  303. gAgent.resetAxes(look_at_norm);
  304. }
  305. //-----------------------------------------------------------------------------
  306. // calcFocusOffset()
  307. //-----------------------------------------------------------------------------
  308. LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y)
  309. {
  310. LLMatrix4 obj_matrix = object->getRenderMatrix();
  311. LLQuaternion obj_rot = object->getRenderRotation();
  312. LLVector3 obj_pos = object->getRenderPosition();
  313. BOOL is_avatar = object->isAvatar();
  314. // if is avatar - don't do any funk heuristics to position the focal point
  315. // see DEV-30589
  316. if (is_avatar)
  317. {
  318. return original_focus_point - obj_pos;
  319. }
  320. LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
  321. LLVector3 object_extents = object->getScale();
  322. // make sure they object extents are non-zero
  323. object_extents.clamp(0.001f, F32_MAX);
  324. // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object
  325. LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin();
  326. obj_to_cam_ray.rotVec(inv_obj_rot);
  327. obj_to_cam_ray.normalize();
  328. // obj_to_cam_ray_proportions are the (positive) ratios of
  329. // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions.
  330. LLVector3 obj_to_cam_ray_proportions;
  331. obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]);
  332. obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]);
  333. obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]);
  334. // find the largest ratio stored in obj_to_cam_ray_proportions
  335. // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera
  336. LLVector3 longest_object_axis;
  337. // is x-axis longest?
  338. if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY]
  339. && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ])
  340. {
  341. // then grab it
  342. longest_object_axis.setVec(obj_matrix.getFwdRow4());
  343. }
  344. // is y-axis longest?
  345. else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ])
  346. {
  347. // then grab it
  348. longest_object_axis.setVec(obj_matrix.getLeftRow4());
  349. }
  350. // otherwise, use z axis
  351. else
  352. {
  353. longest_object_axis.setVec(obj_matrix.getUpRow4());
  354. }
  355. // Use this axis as the normal to project mouse click on to plane with that normal, at the object center.
  356. // This generates a point behind the mouse cursor that is approximately in the middle of the object in
  357. // terms of depth.
  358. // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera.
  359. // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable
  360. // eccentricity to the object orientation
  361. LLVector3 focus_plane_normal(longest_object_axis);
  362. focus_plane_normal.normalize();
  363. LLVector3d focus_pt_global;
  364. gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal);
  365. LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global);
  366. // find vector from camera to focus point in object space
  367. LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin();
  368. camera_to_focus_vec.rotVec(inv_obj_rot);
  369. // find vector from object origin to focus point in object coordinates
  370. LLVector3 focus_offset_from_object_center = focus_pt - obj_pos;
  371. // convert to object-local space
  372. focus_offset_from_object_center.rotVec(inv_obj_rot);
  373. // We need to project the focus point back into the bounding box of the focused object.
  374. // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis
  375. LLVector3 clip_fraction;
  376. // for each axis...
  377. for (U32 axis = VX; axis <= VZ; axis++)
  378. {
  379. //...calculate distance that focus offset sits outside of bounding box along that axis...
  380. //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center
  381. F32 dist_out_of_bounds;
  382. if (focus_offset_from_object_center.mV[axis] > 0.f)
  383. {
  384. dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f));
  385. }
  386. else
  387. {
  388. dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f));
  389. }
  390. //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis
  391. if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f)
  392. {
  393. // don't divide by very small number
  394. clip_fraction.mV[axis] = 0.f;
  395. }
  396. else
  397. {
  398. clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis];
  399. }
  400. }
  401. LLVector3 abs_clip_fraction = clip_fraction;
  402. abs_clip_fraction.abs();
  403. // find axis of focus offset that is *most* outside the bounding box and use that to
  404. // rescale focus offset to inside object extents
  405. if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY]
  406. && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ])
  407. {
  408. focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec;
  409. }
  410. else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ])
  411. {
  412. focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec;
  413. }
  414. else
  415. {
  416. focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec;
  417. }
  418. // convert back to world space
  419. focus_offset_from_object_center.rotVec(obj_rot);
  420. // now, based on distance of camera from object relative to object size
  421. // push the focus point towards the near surface of the object when (relatively) close to the objcet
  422. // or keep the focus point in the object middle when (relatively) far
  423. // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars
  424. // is almost always "tumble about middle" and not "spin around surface point"
  425. if (!is_avatar)
  426. {
  427. LLVector3 obj_rel = original_focus_point - object->getRenderPosition();
  428. //now that we have the object relative position, we should bias toward the center of the object
  429. //based on the distance of the camera to the focus point vs. the distance of the camera to the focus
  430. F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis());
  431. F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin());
  432. LLBBox obj_bbox = object->getBoundingBoxAgent();
  433. F32 bias = 0.f;
  434. // virtual_camera_pos is the camera position we are simulating by backing the camera off
  435. // and adjusting the FOV
  436. LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor));
  437. // if the camera is inside the object (large, hollow objects, for example)
  438. // leave focus point all the way to destination depth, away from object center
  439. if(!obj_bbox.containsPointAgent(virtual_camera_pos))
  440. {
  441. // perform magic number biasing of focus point towards surface vs. planar center
  442. bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f);
  443. obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias);
  444. }
  445. focus_offset_from_object_center = obj_rel;
  446. }
  447. return focus_offset_from_object_center;
  448. }
  449. //-----------------------------------------------------------------------------
  450. // calcCameraMinDistance()
  451. //-----------------------------------------------------------------------------
  452. BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance)
  453. {
  454. BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
  455. if (!mFocusObject || mFocusObject->isDead() ||
  456. mFocusObject->isMesh() ||
  457. gSavedSettings.getBOOL("DisableCameraConstraints"))
  458. {
  459. obj_min_distance = 0.f;
  460. return TRUE;
  461. }
  462. if (mFocusObject->mDrawable.isNull())
  463. {
  464. #ifdef LL_RELEASE_FOR_DOWNLOAD
  465. llwarns << "Focus object with no drawable!" << llendl;
  466. #else
  467. mFocusObject->dump();
  468. llerrs << "Focus object with no drawable!" << llendl;
  469. #endif
  470. obj_min_distance = 0.f;
  471. return TRUE;
  472. }
  473. LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation();
  474. LLVector3 target_offset_origin = mFocusObjectOffset;
  475. LLVector3 camera_offset_target(getCameraPositionAgent() - gAgent.getPosAgentFromGlobal(mFocusTargetGlobal));
  476. // convert offsets into object local space
  477. camera_offset_target.rotVec(inv_object_rot);
  478. target_offset_origin.rotVec(inv_object_rot);
  479. // push around object extents based on target offset
  480. LLVector3 object_extents = mFocusObject->getScale();
  481. if (mFocusObject->isAvatar())
  482. {
  483. // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom)
  484. object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR;
  485. object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR;
  486. object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR;
  487. soft_limit = TRUE;
  488. }
  489. LLVector3 abs_target_offset = target_offset_origin;
  490. abs_target_offset.abs();
  491. LLVector3 target_offset_dir = target_offset_origin;
  492. F32 object_radius = mFocusObject->getVObjRadius();
  493. BOOL target_outside_object_extents = FALSE;
  494. for (U32 i = VX; i <= VZ; i++)
  495. {
  496. if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING)
  497. {
  498. target_outside_object_extents = TRUE;
  499. }
  500. if (camera_offset_target.mV[i] > 0.f)
  501. {
  502. object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f;
  503. }
  504. else
  505. {
  506. object_extents.mV[i] += target_offset_origin.mV[i] * 2.f;
  507. }
  508. }
  509. // don't shrink the object extents so far that the object inverts
  510. object_extents.clamp(0.001f, F32_MAX);
  511. // move into first octant
  512. LLVector3 camera_offset_target_abs_norm = camera_offset_target;
  513. camera_offset_target_abs_norm.abs();
  514. // make sure offset is non-zero
  515. camera_offset_target_abs_norm.clamp(0.001f, F32_MAX);
  516. camera_offset_target_abs_norm.normalize();
  517. // find camera position relative to normalized object extents
  518. LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm;
  519. camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX];
  520. camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY];
  521. camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ];
  522. if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] &&
  523. camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ])
  524. {
  525. if (camera_offset_target_abs_norm.mV[VX] < 0.001f)
  526. {
  527. obj_min_distance = object_extents.mV[VX] * 0.5f;
  528. }
  529. else
  530. {
  531. obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX];
  532. }
  533. }
  534. else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ])
  535. {
  536. if (camera_offset_target_abs_norm.mV[VY] < 0.001f)
  537. {
  538. obj_min_distance = object_extents.mV[VY] * 0.5f;
  539. }
  540. else
  541. {
  542. obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY];
  543. }
  544. }
  545. else
  546. {
  547. if (camera_offset_target_abs_norm.mV[VZ] < 0.001f)
  548. {
  549. obj_min_distance = object_extents.mV[VZ] * 0.5f;
  550. }
  551. else
  552. {
  553. obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ];
  554. }
  555. }
  556. LLVector3 object_split_axis;
  557. LLVector3 target_offset_scaled = target_offset_origin;
  558. target_offset_scaled.abs();
  559. target_offset_scaled.normalize();
  560. target_offset_scaled.mV[VX] /= object_extents.mV[VX];
  561. target_offset_scaled.mV[VY] /= object_extents.mV[VY];
  562. target_offset_scaled.mV[VZ] /= object_extents.mV[VZ];
  563. if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] &&
  564. target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ])
  565. {
  566. object_split_axis = LLVector3::x_axis;
  567. }
  568. else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ])
  569. {
  570. object_split_axis = LLVector3::y_axis;
  571. }
  572. else
  573. {
  574. object_split_axis = LLVector3::z_axis;
  575. }
  576. LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent());
  577. // length projected orthogonal to target offset
  578. F32 camera_offset_dist = (camera_offset_object - target_offset_dir * (camera_offset_object * target_offset_dir)).magVec();
  579. // calculate whether the target point would be "visible" if it were outside the bounding box
  580. // on the opposite of the splitting plane defined by object_split_axis;
  581. BOOL exterior_target_visible = FALSE;
  582. if (camera_offset_dist > object_radius)
  583. {
  584. // target is visible from camera, so turn off fov zoom
  585. exterior_target_visible = TRUE;
  586. }
  587. F32 camera_offset_clip = camera_offset_object * object_split_axis;
  588. F32 target_offset_clip = target_offset_dir * object_split_axis;
  589. // target has moved outside of object extents
  590. // check to see if camera and target are on same side
  591. if (target_outside_object_extents)
  592. {
  593. if (camera_offset_clip > 0.f && target_offset_clip > 0.f)
  594. {
  595. return FALSE;
  596. }
  597. else if (camera_offset_clip < 0.f && target_offset_clip < 0.f)
  598. {
  599. return FALSE;
  600. }
  601. }
  602. // clamp obj distance to diagonal of 10 by 10 cube
  603. obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3);
  604. obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f);
  605. return TRUE;
  606. }
  607. F32 LLAgentCamera::getCameraZoomFraction()
  608. {
  609. // 0.f -> camera zoomed all the way out
  610. // 1.f -> camera zoomed all the way in
  611. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  612. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  613. {
  614. // already [0,1]
  615. return mHUDTargetZoom;
  616. }
  617. else if (mFocusOnAvatar && cameraThirdPerson())
  618. {
  619. return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f);
  620. }
  621. else if (cameraCustomizeAvatar())
  622. {
  623. F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
  624. return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f );
  625. }
  626. else
  627. {
  628. F32 min_zoom;
  629. const F32 DIST_FUDGE = 16.f; // meters
  630. F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE,
  631. LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
  632. MAX_CAMERA_DISTANCE_FROM_AGENT);
  633. F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
  634. if (mFocusObject.notNull())
  635. {
  636. if (mFocusObject->isAvatar())
  637. {
  638. min_zoom = AVATAR_MIN_ZOOM;
  639. }
  640. else
  641. {
  642. min_zoom = OBJECT_MIN_ZOOM;
  643. }
  644. }
  645. else
  646. {
  647. min_zoom = LAND_MIN_ZOOM;
  648. }
  649. return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);
  650. }
  651. }
  652. void LLAgentCamera::setCameraZoomFraction(F32 fraction)
  653. {
  654. // 0.f -> camera zoomed all the way out
  655. // 1.f -> camera zoomed all the way in
  656. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  657. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  658. {
  659. mHUDTargetZoom = fraction;
  660. }
  661. else if (mFocusOnAvatar && cameraThirdPerson())
  662. {
  663. mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION);
  664. }
  665. else if (cameraCustomizeAvatar())
  666. {
  667. LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
  668. camera_offset_dir.normalize();
  669. mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM);
  670. }
  671. else
  672. {
  673. F32 min_zoom = LAND_MIN_ZOOM;
  674. const F32 DIST_FUDGE = 16.f; // meters
  675. F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE,
  676. LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
  677. MAX_CAMERA_DISTANCE_FROM_AGENT);
  678. if (mFocusObject.notNull())
  679. {
  680. if (mFocusObject.notNull())
  681. {
  682. if (mFocusObject->isAvatar())
  683. {
  684. min_zoom = AVATAR_MIN_ZOOM;
  685. }
  686. else
  687. {
  688. min_zoom = OBJECT_MIN_ZOOM;
  689. }
  690. }
  691. }
  692. LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
  693. camera_offset_dir.normalize();
  694. mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom);
  695. }
  696. startCameraAnimation();
  697. }
  698. //-----------------------------------------------------------------------------
  699. // cameraOrbitAround()
  700. //-----------------------------------------------------------------------------
  701. void LLAgentCamera::cameraOrbitAround(const F32 radians)
  702. {
  703. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  704. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  705. {
  706. // do nothing for hud selection
  707. }
  708. else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW))
  709. {
  710. gAgent.yaw(radians);
  711. }
  712. else
  713. {
  714. mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f);
  715. cameraZoomIn(1.f);
  716. }
  717. }
  718. //-----------------------------------------------------------------------------
  719. // cameraOrbitOver()
  720. //-----------------------------------------------------------------------------
  721. void LLAgentCamera::cameraOrbitOver(const F32 angle)
  722. {
  723. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  724. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  725. {
  726. // do nothing for hud selection
  727. }
  728. else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
  729. {
  730. gAgent.pitch(angle);
  731. }
  732. else
  733. {
  734. LLVector3 camera_offset_unit(mCameraFocusOffsetTarget);
  735. camera_offset_unit.normalize();
  736. F32 angle_from_up = acos( camera_offset_unit * gAgent.getReferenceUpVector() );
  737. LLVector3d left_axis;
  738. left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
  739. F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD);
  740. mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis);
  741. cameraZoomIn(1.f);
  742. }
  743. }
  744. //-----------------------------------------------------------------------------
  745. // cameraZoomIn()
  746. //-----------------------------------------------------------------------------
  747. void LLAgentCamera::cameraZoomIn(const F32 fraction)
  748. {
  749. if (gDisconnected)
  750. {
  751. return;
  752. }
  753. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  754. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  755. {
  756. // just update hud zoom level
  757. mHUDTargetZoom /= fraction;
  758. return;
  759. }
  760. LLVector3d camera_offset(mCameraFocusOffsetTarget);
  761. LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
  762. F32 min_zoom = LAND_MIN_ZOOM;
  763. F32 current_distance = (F32)camera_offset_unit.normalize();
  764. F32 new_distance = current_distance * fraction;
  765. // Don't move through focus point
  766. if (mFocusObject)
  767. {
  768. LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]);
  769. if (mFocusObject->isAvatar())
  770. {
  771. calcCameraMinDistance(min_zoom);
  772. }
  773. else
  774. {
  775. min_zoom = OBJECT_MIN_ZOOM;
  776. }
  777. }
  778. new_distance = llmax(new_distance, min_zoom);
  779. // Don't zoom too far back
  780. const F32 DIST_FUDGE = 16.f; // meters
  781. F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,
  782. LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
  783. if (new_distance > max_distance)
  784. {
  785. new_distance = max_distance;
  786. /*
  787. // Unless camera is unlocked
  788. if (!LLViewerCamera::sDisableCameraConstraints)
  789. {
  790. return;
  791. }
  792. */
  793. }
  794. if(cameraCustomizeAvatar())
  795. {
  796. new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
  797. }
  798. mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
  799. }
  800. //-----------------------------------------------------------------------------
  801. // cameraOrbitIn()
  802. //-----------------------------------------------------------------------------
  803. void LLAgentCamera::cameraOrbitIn(const F32 meters)
  804. {
  805. if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
  806. {
  807. F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"));
  808. mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist;
  809. if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f)
  810. {
  811. // No need to animate, camera is already there.
  812. changeCameraToMouselook(FALSE);
  813. }
  814. mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
  815. }
  816. else
  817. {
  818. LLVector3d camera_offset(mCameraFocusOffsetTarget);
  819. LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
  820. F32 current_distance = (F32)camera_offset_unit.normalize();
  821. F32 new_distance = current_distance - meters;
  822. F32 min_zoom = LAND_MIN_ZOOM;
  823. // Don't move through focus point
  824. if (mFocusObject.notNull())
  825. {
  826. if (mFocusObject->isAvatar())
  827. {
  828. min_zoom = AVATAR_MIN_ZOOM;
  829. }
  830. else
  831. {
  832. min_zoom = OBJECT_MIN_ZOOM;
  833. }
  834. }
  835. new_distance = llmax(new_distance, min_zoom);
  836. // Don't zoom too far back
  837. const F32 DIST_FUDGE = 16.f; // meters
  838. F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,
  839. LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
  840. if (new_distance > max_distance)
  841. {
  842. // Unless camera is unlocked
  843. if (!gSavedSettings.getBOOL("DisableCameraConstraints"))
  844. {
  845. return;
  846. }
  847. }
  848. if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() )
  849. {
  850. new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
  851. }
  852. // Compute new camera offset
  853. mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
  854. cameraZoomIn(1.f);
  855. }
  856. }
  857. //-----------------------------------------------------------------------------
  858. // cameraPanIn()
  859. //-----------------------------------------------------------------------------
  860. void LLAgentCamera::cameraPanIn(F32 meters)
  861. {
  862. LLVector3d at_axis;
  863. at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis());
  864. mFocusTargetGlobal += meters * at_axis;
  865. mFocusGlobal = mFocusTargetGlobal;
  866. // don't enforce zoom constraints as this is the only way for users to get past them easily
  867. updateFocusOffset();
  868. // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx
  869. mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
  870. }
  871. //-----------------------------------------------------------------------------
  872. // cameraPanLeft()
  873. //-----------------------------------------------------------------------------
  874. void LLAgentCamera::cameraPanLeft(F32 meters)
  875. {
  876. LLVector3d left_axis;
  877. left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
  878. mFocusTargetGlobal += meters * left_axis;
  879. mFocusGlobal = mFocusTargetGlobal;
  880. // disable smoothing for camera pan, which causes some residents unhappiness
  881. mCameraSmoothingStop = true;
  882. cameraZoomIn(1.f);
  883. updateFocusOffset();
  884. // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx
  885. mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
  886. }
  887. //-----------------------------------------------------------------------------
  888. // cameraPanUp()
  889. //-----------------------------------------------------------------------------
  890. void LLAgentCamera::cameraPanUp(F32 meters)
  891. {
  892. LLVector3d up_axis;
  893. up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis());
  894. mFocusTargetGlobal += meters * up_axis;
  895. mFocusGlobal = mFocusTargetGlobal;
  896. // disable smoothing for camera pan, which causes some residents unhappiness
  897. mCameraSmoothingStop = true;
  898. cameraZoomIn(1.f);
  899. updateFocusOffset();
  900. // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx
  901. mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
  902. }
  903. //-----------------------------------------------------------------------------
  904. // updateLookAt()
  905. //-----------------------------------------------------------------------------
  906. void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
  907. {
  908. static LLVector3 last_at_axis;
  909. if (!isAgentAvatarValid()) return;
  910. LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot.getWorldRotation();
  911. LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot.getWorldRotation();
  912. if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) &&
  913. (root_at * last_at_axis > 0.95f))
  914. {
  915. LLVector3 vel = gAgentAvatarp->getVelocity();
  916. if (vel.magVecSquared() > 4.f)
  917. {
  918. setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, vel * av_inv_rot);
  919. }
  920. else
  921. {
  922. // *FIX: rotate mframeagent by sit object's rotation?
  923. LLQuaternion look_rotation = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); // use camera's current rotation
  924. LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot;
  925. setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, look_offset);
  926. }
  927. last_at_axis = root_at;
  928. return;
  929. }
  930. last_at_axis = root_at;
  931. if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode())
  932. {
  933. setLookAt(LOOKAT_TARGET_NONE, gAgentAvatarp, LLVector3(-2.f, 0.f, 0.f));
  934. }
  935. else
  936. {
  937. // Move head based on cursor position
  938. ELookAtType lookAtType = LOOKAT_TARGET_NONE;
  939. LLVector3 headLookAxis;
  940. LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance());
  941. if (cameraMouselook())
  942. {
  943. lookAtType = LOOKAT_TARGET_MOUSELOOK;
  944. }
  945. else if (cameraThirdPerson())
  946. {
  947. // range from -.5 to .5
  948. F32 x_from_center =
  949. ((F32) mouse_x / (F32) gViewerWindow->getWorldViewWidthScaled() ) - 0.5f;
  950. F32 y_from_center =
  951. ((F32) mouse_y / (F32) gViewerWindow->getWorldViewHeightScaled() ) - 0.5f;
  952. frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD);
  953. frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD);
  954. lookAtType = LOOKAT_TARGET_FREELOOK;
  955. }
  956. headLookAxis = frameCamera.getAtAxis();
  957. // RN: we use world-space offset for mouselook and freelook
  958. //headLookAxis = headLookAxis * av_inv_rot;
  959. setLookAt(lookAtType, gAgentAvatarp, headLookAxis);
  960. }
  961. }
  962. //-----------------------------------------------------------------------------
  963. // updateCamera()
  964. //-----------------------------------------------------------------------------
  965. void LLAgentCamera::updateCamera()
  966. {
  967. static LLFastTimer::DeclareTimer ftm("Camera");
  968. LLFastTimer t(ftm);
  969. // - changed camera_skyward to the new global "mCameraUpVector"
  970. mCameraUpVector = LLVector3::z_axis;
  971. //LLVector3 camera_skyward(0.f, 0.f, 1.f);
  972. U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode;
  973. validateFocusObject();
  974. if (isAgentAvatarValid() &&
  975. gAgentAvatarp->isSitting() &&
  976. camera_mode == CAMERA_MODE_MOUSELOOK)
  977. {
  978. //changed camera_skyward to the new global "mCameraUpVector"
  979. mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation();
  980. }
  981. if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams())
  982. {
  983. changeCameraToFollow();
  984. }
  985. //NOTE - this needs to be integrated into a general upVector system here within llAgent.
  986. if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )
  987. {
  988. mCameraUpVector = mFollowCam.getUpVector();
  989. }
  990. if (mSitCameraEnabled)
  991. {
  992. if (mSitCameraReferenceObject->isDead())
  993. {
  994. setSitCamera(LLUUID::null);
  995. }
  996. }
  997. // Update UI with our camera inputs
  998. LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera");
  999. if (camera_floater)
  1000. {
  1001. camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left
  1002. gAgentCamera.getOrbitUpKey() > 0.f, // top
  1003. gAgentCamera.getOrbitLeftKey() > 0.f, // right
  1004. gAgentCamera.getOrbitDownKey() > 0.f); // bottom
  1005. camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left
  1006. gAgentCamera.getPanUpKey() > 0.f, // top
  1007. gAgentCamera.getPanRightKey() > 0.f, // right
  1008. gAgentCamera.getPanDownKey() > 0.f); // bottom
  1009. }
  1010. // Handle camera movement based on keyboard.
  1011. const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second
  1012. const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second
  1013. const F32 PAN_RATE = 5.f; // meters per second
  1014. if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey())
  1015. {
  1016. F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey();
  1017. cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped );
  1018. }
  1019. if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey())
  1020. {
  1021. F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey();
  1022. cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped);
  1023. }
  1024. if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey())
  1025. {
  1026. F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey();
  1027. LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal();
  1028. F32 distance_to_focus = (F32)to_focus.magVec();
  1029. // Move at distance (in meters) meters per second
  1030. cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped );
  1031. }
  1032. if (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey())
  1033. {
  1034. F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey();
  1035. cameraPanIn(input_rate * PAN_RATE / gFPSClamped);
  1036. }
  1037. if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey())
  1038. {
  1039. F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey();
  1040. cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped );
  1041. }
  1042. if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey())
  1043. {
  1044. F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey();
  1045. cameraPanUp(input_rate * PAN_RATE / gFPSClamped );
  1046. }
  1047. // Clear camera keyboard keys.
  1048. gAgentCamera.clearOrbitKeys();
  1049. gAgentCamera.clearPanKeys();
  1050. // lerp camera focus offset
  1051. mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE));
  1052. if ( mCameraMode == CAMERA_MODE_FOLLOW )
  1053. {
  1054. if (isAgentAvatarValid())
  1055. {
  1056. //--------------------------------------------------------------------------------
  1057. // this is where the avatar's position and rotation are given to followCam, and
  1058. // where it is updated. All three of its attributes are updated: (1) position,
  1059. // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent.
  1060. //--------------------------------------------------------------------------------
  1061. // *TODO: use combined rotation of frameagent and sit object
  1062. LLQuaternion avatarRotationForFollowCam = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion();
  1063. LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams();
  1064. if (current_cam)
  1065. {
  1066. mFollowCam.copyParams(*current_cam);
  1067. mFollowCam.setSubjectPositionAndRotation( gAgentAvatarp->getRenderPosition(), avatarRotationForFollowCam );
  1068. mFollowCam.update();
  1069. LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
  1070. }
  1071. else
  1072. {
  1073. changeCameraToThirdPerson(TRUE);
  1074. }
  1075. }
  1076. }
  1077. BOOL hit_limit;
  1078. LLVector3d camera_pos_global;
  1079. LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit);
  1080. mCameraVirtualPositionAgent = gAgent.getPosAgentFromGlobal(camera_target_global);
  1081. LLVector3d focus_target_global = calcFocusPositionTargetGlobal();
  1082. // perform field of view correction
  1083. mCameraFOVZoomFactor = calcCameraFOVZoomFactor();
  1084. camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor);
  1085. gAgent.setShowAvatar(TRUE); // can see avatar by default
  1086. // Adjust position for animation
  1087. if (mCameraAnimating)
  1088. {
  1089. F32 time = mAnimationTimer.getElapsedTimeF32();
  1090. // yet another instance of critically damped motion, hooray!
  1091. // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE);
  1092. // linear interpolation
  1093. F32 fraction_of_animation = time / mAnimationDuration;
  1094. BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK;
  1095. BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK;
  1096. F32 fraction_animation_to_skip;
  1097. if (mAnimationCameraStartGlobal == camera_target_global)
  1098. {
  1099. fraction_animation_to_skip = 0.f;
  1100. }
  1101. else
  1102. {
  1103. LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global;
  1104. fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec();
  1105. }
  1106. F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f;
  1107. F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f;
  1108. if (fraction_of_animation < animation_finish_fraction)
  1109. {
  1110. if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction )
  1111. {
  1112. gAgent.setShowAvatar(FALSE);
  1113. }
  1114. // ...adjust position for animation
  1115. F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation);
  1116. camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation);
  1117. mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation);
  1118. }
  1119. else
  1120. {
  1121. // ...animation complete
  1122. mCameraAnimating = FALSE;
  1123. camera_pos_global = camera_target_global;
  1124. mFocusGlobal = focus_target_global;
  1125. gAgent.endAnimationUpdateUI();
  1126. gAgent.setShowAvatar(TRUE);
  1127. }
  1128. if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK))
  1129. {
  1130. gAgentAvatarp->updateAttachmentVisibility(mCameraMode);
  1131. }
  1132. }
  1133. else
  1134. {
  1135. camera_pos_global = camera_target_global;
  1136. mFocusGlobal = focus_target_global;
  1137. gAgent.setShowAvatar(TRUE);
  1138. }
  1139. // smoothing
  1140. if (TRUE)
  1141. {
  1142. LLVector3d agent_pos = gAgent.getPositionGlobal();
  1143. LLVector3d camera_pos_agent = camera_pos_global - agent_pos;
  1144. // Sitting on what you're manipulating can cause camera jitter with smoothing.
  1145. // This turns off smoothing while editing. -MG
  1146. bool in_build_mode = LLToolMgr::getInstance()->inBuildMode();
  1147. mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode;
  1148. if (cameraThirdPerson() && !mCameraSmoothingStop)
  1149. {
  1150. const F32 SMOOTHING_HALF_LIFE = 0.02f;
  1151. F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE);
  1152. if (!mFocusObject) // we differentiate on avatar mode
  1153. {
  1154. // for avatar-relative focus, we smooth in avatar space -
  1155. // the avatar moves too jerkily w/r/t global space to smooth there.
  1156. LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent;
  1157. if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please
  1158. {
  1159. camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing);
  1160. camera_pos_global = camera_pos_agent + agent_pos;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal;
  1166. if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please
  1167. {
  1168. camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing);
  1169. }
  1170. }
  1171. }
  1172. mCameraSmoothingLastPositionGlobal = camera_pos_global;
  1173. mCameraSmoothingLastPositionAgent = camera_pos_agent;
  1174. mCameraSmoothingStop = false;
  1175. }
  1176. mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE));
  1177. // llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl;
  1178. LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal);
  1179. mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global);
  1180. // Move the camera
  1181. LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);
  1182. //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent);
  1183. // Change FOV
  1184. LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor));
  1185. // follow camera when in customize mode
  1186. if (cameraCustomizeAvatar())
  1187. {
  1188. setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent);
  1189. }
  1190. // update the travel distance stat
  1191. // this isn't directly related to the camera
  1192. // but this seemed like the best place to do this
  1193. LLVector3d global_pos = gAgent.getPositionGlobal();
  1194. if (!gAgent.getLastPositionGlobal().isExactlyZero())
  1195. {
  1196. LLVector3d delta = global_pos - gAgent.getLastPositionGlobal();
  1197. gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec());
  1198. }
  1199. gAgent.setLastPositionGlobal(global_pos);
  1200. if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook())
  1201. {
  1202. LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() +
  1203. LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +
  1204. LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation();
  1205. LLVector3 diff = mCameraPositionAgent - head_pos;
  1206. diff = diff * ~gAgentAvatarp->mRoot.getWorldRotation();
  1207. LLJoint* torso_joint = gAgentAvatarp->mTorsop;
  1208. LLJoint* chest_joint = gAgentAvatarp->mChestp;
  1209. LLVector3 torso_scale = torso_joint->getScale();
  1210. LLVector3 chest_scale = chest_joint->getScale();
  1211. // shorten avatar skeleton to avoid foot interpenetration
  1212. if (!gAgentAvatarp->mInAir)
  1213. {
  1214. LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation();
  1215. F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f);
  1216. F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f);
  1217. torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor));
  1218. LLJoint* neck_joint = gAgentAvatarp->mNeckp;
  1219. LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation();
  1220. scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f);
  1221. chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor));
  1222. diff.mV[VZ] = 0.f;
  1223. }
  1224. gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff);
  1225. gAgentAvatarp->mRoot.updateWorldMatrixChildren();
  1226. for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
  1227. iter != gAgentAvatarp->mAttachmentPoints.end(); )
  1228. {
  1229. LLVOAvatar::attachment_map_t::iterator curiter = iter++;
  1230. LLViewerJointAttachment* attachment = curiter->second;
  1231. for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
  1232. attachment_iter != attachment->mAttachedObjects.end();
  1233. ++attachment_iter)
  1234. {
  1235. LLViewerObject *attached_object = (*attachment_iter);
  1236. if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
  1237. {
  1238. // clear any existing "early" movements of attachment
  1239. attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
  1240. gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
  1241. attached_object->updateText();
  1242. }
  1243. }
  1244. }
  1245. torso_joint->setScale(torso_scale);
  1246. chest_joint->setScale(chest_scale);
  1247. }
  1248. }
  1249. void LLAgentCamera::updateLastCamera()
  1250. {
  1251. mLastCameraMode = mCameraMode;
  1252. }
  1253. void LLAgentCamera::updateFocusOffset()
  1254. {
  1255. validateFocusObject();
  1256. if (mFocusObject.notNull())
  1257. {
  1258. LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition());
  1259. mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos);
  1260. }
  1261. }
  1262. void LLAgentCamera::validateFocusObject()
  1263. {
  1264. if (mFocusObject.notNull() &&
  1265. mFocusObject->isDead())
  1266. {
  1267. mFocusObjectOffset.clearVec();
  1268. clearFocusObject();
  1269. mCameraFOVZoomFactor = 0.f;
  1270. }
  1271. }
  1272. //-----------------------------------------------------------------------------
  1273. // calcFocusPositionTargetGlobal()
  1274. //-----------------------------------------------------------------------------
  1275. LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()
  1276. {
  1277. if (mFocusObject.notNull() && mFocusObject->isDead())
  1278. {
  1279. clearFocusObject();
  1280. }
  1281. if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar)
  1282. {
  1283. mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus());
  1284. return mFocusTargetGlobal;
  1285. }
  1286. else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
  1287. {
  1288. LLVector3d at_axis(1.0, 0.0, 0.0);
  1289. LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion();
  1290. if (isAgentAvatarValid() && gAgentAvatarp->getParent())
  1291. {
  1292. LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot();
  1293. if (!root_object->flagCameraDecoupled())
  1294. {
  1295. agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation();
  1296. }
  1297. }
  1298. at_axis = at_axis * agent_rot;
  1299. mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis;
  1300. return mFocusTargetGlobal;
  1301. }
  1302. else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR)
  1303. {
  1304. return mFocusTargetGlobal;
  1305. }
  1306. else if (!mFocusOnAvatar)
  1307. {
  1308. if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull())
  1309. {
  1310. LLDrawable* drawablep = mFocusObject->mDrawable;
  1311. if (mTrackFocusObject &&
  1312. drawablep &&
  1313. drawablep->isActive())
  1314. {
  1315. if (!mFocusObject->isAvatar())
  1316. {
  1317. if (mFocusObject->isSelected())
  1318. {
  1319. gPipeline.updateMoveNormalAsync(drawablep);
  1320. }
  1321. else
  1322. {
  1323. if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
  1324. {
  1325. gPipeline.updateMoveNormalAsync(drawablep);
  1326. }
  1327. else
  1328. {
  1329. gPipeline.updateMoveDampedAsync(drawablep);
  1330. }
  1331. }
  1332. }
  1333. }
  1334. // if not tracking object, update offset based on new object position
  1335. else
  1336. {
  1337. updateFocusOffset();
  1338. }
  1339. LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset;
  1340. mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent));
  1341. }
  1342. return mFocusTargetGlobal;
  1343. }
  1344. else if (mSitCameraEnabled && isAgentAvatarValid() && gAgentAvatarp->isSitting() && mSitCameraReferenceObject.notNull())
  1345. {
  1346. // sit camera
  1347. LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition();
  1348. LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation();
  1349. LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot);
  1350. return gAgent.getPosGlobalFromAgent(target_pos);
  1351. }
  1352. else
  1353. {
  1354. return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset();
  1355. }
  1356. }
  1357. LLVector3d LLAgentCamera::calcThirdPersonFocusOffset()
  1358. {
  1359. // ...offset from avatar
  1360. LLVector3d focus_offset;
  1361. LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion();
  1362. if (isAgentAvatarValid() && gAgentAvatarp->getParent())
  1363. {
  1364. agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation();
  1365. }
  1366. focus_offset = convert_from_llsd<LLVector3d>(mFocusOffsetInitial[mCameraPreset]->get(), TYPE_VEC3D, "");
  1367. return focus_offset * agent_rot;
  1368. }
  1369. void LLAgentCamera::setupSitCamera()
  1370. {
  1371. // agent frame entering this function is in world coordinates
  1372. if (isAgentAvatarValid() && gAgentAvatarp->getParent())
  1373. {
  1374. LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation();
  1375. // slam agent coordinate frame to proper parent local version
  1376. LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis();
  1377. at_axis.mV[VZ] = 0.f;
  1378. at_axis.normalize();
  1379. gAgent.resetAxes(at_axis * ~parent_rot);
  1380. }
  1381. }
  1382. //-----------------------------------------------------------------------------
  1383. // getCameraPositionAgent()
  1384. //-----------------------------------------------------------------------------
  1385. const LLVector3 &LLAgentCamera::getCameraPositionAgent() const
  1386. {
  1387. return LLViewerCamera::getInstance()->getOrigin();
  1388. }
  1389. //-----------------------------------------------------------------------------
  1390. // getCameraPositionGlobal()
  1391. //-----------------------------------------------------------------------------
  1392. LLVector3d LLAgentCamera::getCameraPositionGlobal() const
  1393. {
  1394. return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin());
  1395. }
  1396. //-----------------------------------------------------------------------------
  1397. // calcCameraFOVZoomFactor()
  1398. //-----------------------------------------------------------------------------
  1399. F32 LLAgentCamera::calcCameraFOVZoomFactor()
  1400. {
  1401. LLVector3 camera_offset_dir;
  1402. camera_offset_dir.setVec(mCameraFocusOffset);
  1403. if (mCameraMode == CAMERA_MODE_MOUSELOOK)
  1404. {
  1405. return 0.f;
  1406. }
  1407. else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar)
  1408. {
  1409. // don't FOV zoom on mostly transparent objects
  1410. LLVector3 focus_offset = mFocusObjectOffset;
  1411. F32 obj_min_dist = 0.f;
  1412. calcCameraMinDistance(obj_min_dist);
  1413. F32 current_distance = llmax(0.001f, camera_offset_dir.magVec());
  1414. mFocusObjectDist = obj_min_dist - current_distance;
  1415. F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f);
  1416. return new_fov_zoom;
  1417. }
  1418. else // focusing on land or avatar
  1419. {
  1420. // keep old field of view until user changes focus explicitly
  1421. return mCameraFOVZoomFactor;
  1422. //return 0.f;
  1423. }
  1424. }
  1425. //-----------------------------------------------------------------------------
  1426. // calcCameraPositionTargetGlobal()
  1427. //-----------------------------------------------------------------------------
  1428. LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
  1429. {
  1430. // Compute base camera position and look-at points.
  1431. F32 camera_land_height;
  1432. LLVector3d frame_center_global = !isAgentAvatarValid() ?
  1433. gAgent.getPositionGlobal() :
  1434. gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
  1435. BOOL isConstrained = FALSE;
  1436. LLVector3d head_offset;
  1437. head_offset.setVec(mThirdPersonHeadOffset);
  1438. LLVector3d camera_position_global;
  1439. if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar)
  1440. {
  1441. camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition());
  1442. }
  1443. else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
  1444. {
  1445. if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull())
  1446. {
  1447. llwarns << "Null avatar drawable!" << llendl;
  1448. return LLVector3d::zero;
  1449. }
  1450. head_offset.clearVec();
  1451. if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent())
  1452. {
  1453. gAgentAvatarp->updateHeadOffset();
  1454. head_offset.mdV[VX] = gAgentAvatarp->mHeadOffset.mV[VX];
  1455. head_offset.mdV[VY] = gAgentAvatarp->mHeadOffset.mV[VY];
  1456. head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ] + 0.1f;
  1457. const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix();
  1458. camera_position_global = gAgent.getPosGlobalFromAgent
  1459. ((gAgentAvatarp->getPosition()+
  1460. LLVector3(head_offset)*gAgentAvatarp->getRotation()) * mat);
  1461. }
  1462. else
  1463. {
  1464. head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ];
  1465. if (gAgentAvatarp->isSitting())
  1466. {
  1467. head_offset.mdV[VZ] += 0.1;
  1468. }
  1469. camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global;
  1470. head_offset = head_offset * gAgentAvatarp->getRenderRotation();
  1471. camera_position_global = camera_position_global + head_offset;
  1472. }
  1473. }
  1474. else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar)
  1475. {
  1476. LLVector3 local_camera_offset;
  1477. F32 camera_distance = 0.f;
  1478. if (mSitCameraEnabled
  1479. && isAgentAvatarValid()
  1480. && gAgentAvatarp->isSitting()
  1481. && mSitCameraReferenceObject.notNull())
  1482. {
  1483. // sit camera
  1484. LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition();
  1485. LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation();
  1486. LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot);
  1487. camera_position_global = gAgent.getPosGlobalFromAgent(target_pos);
  1488. }
  1489. else
  1490. {
  1491. local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale");
  1492. // are we sitting down?
  1493. if (isAgentAvatarValid() && gAgentAvatarp->getParent())
  1494. {
  1495. LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation();
  1496. // slam agent coordinate frame to proper parent local version
  1497. LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot;
  1498. at_axis.mV[VZ] = 0.f;
  1499. at_axis.normalize();
  1500. gAgent.resetAxes(at_axis * ~parent_rot);
  1501. local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot;
  1502. }
  1503. else
  1504. {
  1505. local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset );
  1506. }
  1507. if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !gAgentAvatarp->isSitting()))
  1508. {
  1509. LLVector3 plane_normal;
  1510. plane_normal.setVec(mCameraCollidePlane.mV);
  1511. F32 offset_dot_norm = local_camera_offset * plane_normal;
  1512. if (llabs(offset_dot_norm) < 0.001f)
  1513. {
  1514. offset_dot_norm = 0.001f;
  1515. }
  1516. camera_distance = local_camera_offset.normalize();
  1517. F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal;
  1518. // if agent is outside the colliding half-plane
  1519. if (pos_dot_norm > mCameraCollidePlane.mV[VW])
  1520. {
  1521. // check to see if camera is on the opposite side (inside) the half-plane
  1522. if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW])
  1523. {
  1524. // diminish offset by factor to push it back outside the half-plane
  1525. camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm;
  1526. }
  1527. }
  1528. else
  1529. {
  1530. if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW])
  1531. {
  1532. camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm;
  1533. }
  1534. }
  1535. }
  1536. else
  1537. {
  1538. camera_distance = local_camera_offset.normalize();
  1539. }
  1540. mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE);
  1541. if (mTargetCameraDistance != mCurrentCameraDistance)
  1542. {
  1543. F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE);
  1544. mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt);
  1545. }
  1546. // Make the camera distance current
  1547. local_camera_offset *= mCurrentCameraDistance;
  1548. // set the global camera position
  1549. LLVector3d camera_offset;
  1550. LLVector3 av_pos = !isAgentAvatarValid() ? LLVector3::zero : gAgentAvatarp->getRenderPosition();
  1551. camera_offset.setVec( local_camera_offset );
  1552. camera_position_global = frame_center_global + head_offset + camera_offset;
  1553. if (isAgentAvatarValid())
  1554. {
  1555. LLVector3d camera_lag_d;
  1556. F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE);
  1557. LLVector3 target_lag;
  1558. LLVector3 vel = gAgent.getVelocity();
  1559. // lag by appropriate amount for flying
  1560. F32 time_in_air = gAgentAvatarp->mTimeInAir.getElapsedTimeF32();
  1561. if(!mCameraAnimating && gAgentAvatarp->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME)
  1562. {
  1563. LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis();
  1564. frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector());
  1565. frame_at_axis.normalize();
  1566. //transition smoothly in air mode, to avoid camera pop
  1567. F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME;
  1568. u = llclamp(u, 0.f, 1.f);
  1569. lag_interp *= u;
  1570. if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == gAgentAvatarp->getID())
  1571. {
  1572. // disable camera lag when using mouse-directed steering
  1573. target_lag.clearVec();
  1574. }
  1575. else
  1576. {
  1577. target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f;
  1578. }
  1579. mCameraLag = lerp(mCameraLag, target_lag, lag_interp);
  1580. F32 lag_dist = mCameraLag.magVec();
  1581. if (lag_dist > MAX_CAMERA_LAG)
  1582. {
  1583. mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist;
  1584. }
  1585. // clamp camera lag so that avatar is always in front
  1586. F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis;
  1587. if (dot < -(MIN_CAMERA_LAG * u))
  1588. {
  1589. mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis;
  1590. }
  1591. }
  1592. else
  1593. {
  1594. mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f));
  1595. }
  1596. camera_lag_d.setVec(mCameraLag);
  1597. camera_position_global = camera_position_global - camera_lag_d;
  1598. }
  1599. }
  1600. }
  1601. else
  1602. {
  1603. LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal();
  1604. // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value
  1605. camera_position_global = focusPosGlobal + mCameraFocusOffset;
  1606. }
  1607. if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike())
  1608. {
  1609. LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
  1610. bool constrain = true;
  1611. if(regionp && regionp->canManageEstate())
  1612. {
  1613. constrain = false;
  1614. }
  1615. if(constrain)
  1616. {
  1617. F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance;
  1618. LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal();
  1619. F32 camera_distance = (F32)camera_offset.magVec();
  1620. if(camera_distance > max_dist)
  1621. {
  1622. camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset;
  1623. isConstrained = TRUE;
  1624. }
  1625. }
  1626. // JC - Could constrain camera based on parcel stuff here.
  1627. // LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
  1628. //
  1629. // if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global)))
  1630. // {
  1631. // camera_position_global = last_position_global;
  1632. //
  1633. // isConstrained = TRUE;
  1634. // }
  1635. }
  1636. // Don't let camera go underground
  1637. F32 camera_min_off_ground = getCameraMinOffGround();
  1638. camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global);
  1639. if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground)
  1640. {
  1641. camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground;
  1642. isConstrained = TRUE;
  1643. }
  1644. if (hit_limit)
  1645. {
  1646. *hit_limit = isConstrained;
  1647. }
  1648. return camera_position_global;
  1649. }
  1650. LLVector3 LLAgentCamera::getCameraOffsetInitial()
  1651. {
  1652. return convert_from_llsd<LLVector3>(mCameraOffsetInitial[mCameraPreset]->get(), TYPE_VEC3, "");
  1653. }
  1654. //-----------------------------------------------------------------------------
  1655. // handleScrollWheel()
  1656. //-----------------------------------------------------------------------------
  1657. void LLAgentCamera::handleScrollWheel(S32 clicks)
  1658. {
  1659. if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar())
  1660. {
  1661. if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place
  1662. {
  1663. mFollowCam.zoom(clicks);
  1664. if (mFollowCam.isZoomedToMinimumDistance())
  1665. {
  1666. changeCameraToMouselook(FALSE);
  1667. }
  1668. }
  1669. }
  1670. else
  1671. {
  1672. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  1673. const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2);
  1674. // Block if camera is animating
  1675. if (mCameraAnimating)
  1676. {
  1677. return;
  1678. }
  1679. if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
  1680. {
  1681. F32 zoom_factor = (F32)pow(0.8, -clicks);
  1682. cameraZoomIn(zoom_factor);
  1683. }
  1684. else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON))
  1685. {
  1686. F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec();
  1687. F32 current_zoom_fraction = mTargetCameraDistance / (camera_off