Fixed snapping of rotation in the edge-on case

Patch by https://codereview.secondlife.com/users/cron.stardust/
Jira: https://jira.secondlife.com/browse/STORM-1919
This commit is contained in:
Aleric Inglewood
2012-11-28 17:04:24 +01:00
parent 165bebda3e
commit e17405d80a
2 changed files with 123 additions and 110 deletions

View File

@@ -248,6 +248,7 @@ Celierra Darling
VWR-6975
Cron Stardust
VWR-10579
STORM-1919
Cypren Christenson
SNOW-129
SNOW-140

View File

@@ -1381,74 +1381,28 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
projected_mouse -= snap_plane_center;
S32 snap_plane = 0;
F32 dot = cam_to_snap_plane * constraint_axis;
if (llabs(dot) < 0.01f)
{
// looking at ring edge on, project onto view plane and check if mouse is past ring
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
projected_mouse -= snap_plane_center;
dot = projected_mouse * constraint_axis;
if (projected_mouse * constraint_axis > 0)
{
snap_plane = 1;
}
projected_mouse -= dot * constraint_axis;
}
else if (dot > 0.f)
{
// look for mouse position outside and in front of snap circle
if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
{
snap_plane = 1;
}
}
else
{
// look for mouse position inside or in back of snap circle
if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
{
snap_plane = 1;
}
}
if (snap_plane == 0)
{
// try other plane
snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
}
else
{
cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent();
cam_to_snap_plane.normVec();
}
hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
projected_mouse -= snap_plane_center;
dot = cam_to_snap_plane * constraint_axis;
if (gSavedSettings.getBOOL("SnapEnabled")) {
S32 snap_plane = 0;
F32 dot = cam_to_snap_plane * constraint_axis;
if (llabs(dot) < 0.01f)
{
// looking at ring edge on, project onto view plane and check if mouse is past ring
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
projected_mouse -= snap_plane_center;
dot = projected_mouse * constraint_axis;
if (projected_mouse * constraint_axis < 0)
if (projected_mouse * constraint_axis > 0)
{
snap_plane = 2;
snap_plane = 1;
}
projected_mouse -= dot * constraint_axis;
}
else if (dot < 0.f)
else if (dot > 0.f)
{
// look for mouse position outside and in front of snap circle
if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
{
snap_plane = 2;
snap_plane = 1;
}
}
else
@@ -1456,78 +1410,136 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
// look for mouse position inside or in back of snap circle
if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
{
snap_plane = 2;
snap_plane = 1;
}
}
}
if (snap_plane > 0)
{
LLVector3 cam_at_axis;
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
if (snap_plane == 0)
{
cam_at_axis.setVec(1.f, 0.f, 0.f);
// try other plane
snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
}
else
{
cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent();
cam_to_snap_plane.normVec();
}
hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis);
projected_mouse -= snap_plane_center;
dot = cam_to_snap_plane * constraint_axis;
if (llabs(dot) < 0.01f)
{
// looking at ring edge on, project onto view plane and check if mouse is past ring
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane);
projected_mouse -= snap_plane_center;
dot = projected_mouse * constraint_axis;
if (projected_mouse * constraint_axis < 0)
{
snap_plane = 2;
}
projected_mouse -= dot * constraint_axis;
}
else if (dot < 0.f)
{
// look for mouse position outside and in front of snap circle
if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f)
{
snap_plane = 2;
}
}
else
{
// look for mouse position inside or in back of snap circle
if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit)
{
snap_plane = 2;
}
}
}
else
{
cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent();
cam_at_axis.normVec();
}
// first, project mouse onto screen plane at point tangent to rotation radius.
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis);
// project that point onto rotation plane
projected_mouse -= snap_plane_center;
projected_mouse -= projected_vec(projected_mouse, constraint_axis);
F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec());
F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
if (llabs(mouse_lateral_dist) > 0.01f)
{
mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
(mouse_lateral_dist * mouse_lateral_dist));
}
LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis);
projected_mouse -= mouse_depth * projected_camera_at;
if (!mInSnapRegime)
{
mSmoothRotate = TRUE;
}
mInSnapRegime = TRUE;
// 0 to 360 deg
F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
//fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f);
LLVector3 object_axis;
getObjectAxisClosestToMouse(object_axis);
object_axis = object_axis * first_object_node->mSavedRotation;
// project onto constraint plane
object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
object_axis.normVec();
if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
if (snap_plane > 0)
{
F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
LLVector3 cam_at_axis;
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
cam_at_axis.setVec(1.f, 0.f, 0.f);
}
else
{
cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent();
cam_at_axis.normVec();
}
// first, project mouse onto screen plane at point tangent to rotation radius.
getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis);
// project that point onto rotation plane
projected_mouse -= snap_plane_center;
projected_mouse -= projected_vec(projected_mouse, constraint_axis);
F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec());
F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
if (llabs(mouse_lateral_dist) > 0.01f)
{
mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) -
(mouse_lateral_dist * mouse_lateral_dist));
}
LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis);
projected_mouse -= mouse_depth * projected_camera_at;
if (!mInSnapRegime)
{
mSmoothRotate = TRUE;
}
mInSnapRegime = TRUE;
// 0 to 360 deg
F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f);
F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT);
//fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f);
LLVector3 object_axis;
getObjectAxisClosestToMouse(object_axis);
object_axis = object_axis * first_object_node->mSavedRotation;
// project onto constraint plane
object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
object_axis.normVec();
if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
{
F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f));
angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
}
else
{
angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
}
return LLQuaternion( -angle, constraint_axis );
}
else
{
angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2);
if (mInSnapRegime)
{
mSmoothRotate = TRUE;
}
mInSnapRegime = FALSE;
}
return LLQuaternion( -angle, constraint_axis );
}
else
{
else {
if (mInSnapRegime)
{
mSmoothRotate = TRUE;
}
mInSnapRegime = FALSE;
}
if (!mInSnapRegime)
{
LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis;
up_from_axis.normVec();
LLVector3 cur_intersection;