+89
-35
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
class Camera
|
||||
{
|
||||
@@ -115,13 +116,55 @@ class Camera
|
||||
void push_away(const double s)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace igl;
|
||||
#ifndef NDEBUG
|
||||
Vector3d old_at = camera.at();
|
||||
Vector3d old_at = at();
|
||||
#endif
|
||||
const double old_at_dist = m_at_dist;
|
||||
m_at_dist = old_at_dist * s;
|
||||
dolly(Vector3d(0,0,1)*(m_at_dist - old_at_dist));
|
||||
assert((old_at-camera.at()).squaredNorm() < DOUBLE_EPS);
|
||||
assert((old_at-at()).squaredNorm() < DOUBLE_EPS);
|
||||
}
|
||||
|
||||
// Turn around eye so that rotation is now q
|
||||
//
|
||||
// Inputs:
|
||||
// q new rotation as quaternion
|
||||
void turn_eye(const Eigen::Quaterniond & q)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace igl;
|
||||
Vector3d old_eye = eye();
|
||||
// eye should be fixed
|
||||
//
|
||||
// eye_1 = R_1 * t_1 = eye_0
|
||||
// t_1 = R_1' * eye_0
|
||||
m_rotation = q;
|
||||
m_translation = m_rotation.conjugate() * old_eye;
|
||||
assert((old_eye - eye()).squaredNorm() < DOUBLE_EPS);
|
||||
}
|
||||
|
||||
// Orbit around at so that rotation is now q
|
||||
//
|
||||
// Inputs:
|
||||
// q new rotation as quaternion
|
||||
void orbit(const Eigen::Quaterniond & q)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace igl;
|
||||
#ifndef NDEBUG
|
||||
Vector3d old_at = at();
|
||||
#endif
|
||||
// at should be fixed
|
||||
//
|
||||
// at_1 = R_1 * t_1 - R_1 * z = at_0
|
||||
// t_1 = R_1' * (at_0 + R_1 * z)
|
||||
m_rotation = q;
|
||||
m_translation =
|
||||
m_rotation.conjugate() *
|
||||
(old_at +
|
||||
m_rotation * Vector3d(0,0,1) * m_at_dist);
|
||||
assert((old_at - at()).squaredNorm() < DOUBLE_EPS);
|
||||
}
|
||||
|
||||
// Aka "Hitchcock", "Vertigo", "Spielberg" or "Trombone" zoom:
|
||||
@@ -133,9 +176,10 @@ class Camera
|
||||
void dolly_zoom(const double da)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace igl;
|
||||
using namespace Eigen;
|
||||
#ifndef NDEBUG
|
||||
Vector3d old_at = camera.at();
|
||||
Vector3d old_at = at();
|
||||
#endif
|
||||
const double old_angle = m_angle;
|
||||
m_angle += da;
|
||||
@@ -146,7 +190,7 @@ class Camera
|
||||
const double old_at_dist = m_at_dist;
|
||||
m_at_dist = old_at_dist * s;
|
||||
dolly(Vector3d(0,0,1)*(m_at_dist - old_at_dist));
|
||||
assert((old_at-camera.at()).squaredNorm() < DOUBLE_EPS);
|
||||
assert((old_at-at()).squaredNorm() < DOUBLE_EPS);
|
||||
}
|
||||
|
||||
// Return top right corner of unit plane in relative coordinates, that is
|
||||
@@ -558,7 +602,9 @@ void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
|
||||
const double delta_y = 0.125*direction;
|
||||
mouse_scroll_y += delta_y;
|
||||
TwMouseWheel(mouse_scroll_y);
|
||||
return;
|
||||
}
|
||||
|
||||
auto & camera = s.cameras[s.viewing_camera];
|
||||
switch(center_type)
|
||||
{
|
||||
@@ -571,7 +617,6 @@ void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
|
||||
//camera.m_angle *= s;
|
||||
//camera.m_angle = min(max(camera.m_angle,1),89);
|
||||
camera.push_away(s);
|
||||
// Rotation should stay around at
|
||||
}else
|
||||
{
|
||||
// Dolly zoom:
|
||||
@@ -581,8 +626,7 @@ void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
|
||||
default:
|
||||
case CENTER_TYPE_FPS:
|
||||
// Move `eye` and `at`
|
||||
Vector3d diff = (wheel==0?Vector3d(0,0,1):Vector3d(-1,0,0))*0.1;
|
||||
camera.dolly(diff*direction);
|
||||
camera.dolly((wheel==0?Vector3d(0,0,1):Vector3d(-1,0,0))*0.1*direction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -665,56 +709,35 @@ void mouse_drag(int mouse_x, int mouse_y)
|
||||
{
|
||||
// Rotate according to trackball
|
||||
igl::trackball(
|
||||
width,
|
||||
height,
|
||||
width, height,
|
||||
2.0,
|
||||
down_camera.m_rotation.conjugate(),
|
||||
down_x,
|
||||
down_y,
|
||||
mouse_x,
|
||||
mouse_y,
|
||||
down_x, down_y, mouse_x, mouse_y,
|
||||
q);
|
||||
break;
|
||||
}
|
||||
case ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP:
|
||||
{
|
||||
// Rotate according to two axis valuator with fixed up vector
|
||||
two_axis_valuator_fixed_up(
|
||||
width,
|
||||
height,
|
||||
width, height,
|
||||
2.0,
|
||||
down_camera.m_rotation.conjugate(),
|
||||
down_x,
|
||||
down_y,
|
||||
mouse_x,
|
||||
mouse_y,
|
||||
down_x, down_y, mouse_x, mouse_y,
|
||||
q);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
camera.m_rotation = q.conjugate();
|
||||
switch(center_type)
|
||||
{
|
||||
default:
|
||||
case CENTER_TYPE_ORBIT:
|
||||
// at should be fixed
|
||||
//
|
||||
// at_1 = R_1 * t_1 - R_1 * z = at_0
|
||||
// t_1 = R_1' * (at_0 + R_1 * z)
|
||||
camera.m_translation =
|
||||
camera.m_rotation.conjugate() *
|
||||
(down_camera.at() +
|
||||
camera.m_rotation * Vector3d(0,0,1) * camera.m_at_dist);
|
||||
assert((down_camera.at() - camera.at()).squaredNorm() < DOUBLE_EPS);
|
||||
camera.orbit(q.conjugate());
|
||||
break;
|
||||
case CENTER_TYPE_FPS:
|
||||
// eye should be fixed
|
||||
//
|
||||
// eye_1 = R_1 * t_1 = eye_0
|
||||
// t_1 = R_1' * eye_0
|
||||
camera.m_translation = camera.m_rotation.conjugate() * down_camera.eye();
|
||||
assert((down_camera.eye() - camera.eye()).squaredNorm() < DOUBLE_EPS);
|
||||
camera.turn_eye(q.conjugate());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -754,6 +777,36 @@ void key(unsigned char key, int mouse_x, int mouse_y)
|
||||
}
|
||||
|
||||
|
||||
void TW_CALL set_rotation(const void * value, void * clientData)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
const double * rt = (const double*)(value);
|
||||
Quaterniond conj;
|
||||
copy(rt,rt+4,conj.coeffs().data());
|
||||
auto & camera = s.cameras[s.viewing_camera];
|
||||
switch(center_type)
|
||||
{
|
||||
default:
|
||||
case CENTER_TYPE_ORBIT:
|
||||
camera.orbit(conj.conjugate());
|
||||
break;
|
||||
case CENTER_TYPE_FPS:
|
||||
camera.turn_eye(conj.conjugate());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TW_CALL get_rotation(void * value, void *clientData)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
const auto & camera = s.cameras[s.viewing_camera];
|
||||
double * rt = (double*)(value);
|
||||
Quaterniond conj = camera.m_rotation.conjugate();
|
||||
copy(conj.coeffs().data(),conj.coeffs().data()+4,rt);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
using namespace std;
|
||||
@@ -780,6 +833,7 @@ int main(int argc, char * argv[])
|
||||
rebar.TwAddVarRW("rotation_type", RotationTypeTW,&rotation_type,
|
||||
"keyIncr=] keyDecr=[");
|
||||
TwType CenterTypeTW = ReTwDefineEnumFromString("CenterType","orbit,fps");
|
||||
rebar.TwAddVarCB("rotation", TW_TYPE_QUAT4D,set_rotation,get_rotation,NULL,"");
|
||||
rebar.TwAddVarRW("center_type", CenterTypeTW,¢er_type,
|
||||
"keyIncr={ keyDecr=}");
|
||||
rebar.load(REBAR_NAME);
|
||||
|
||||
Reference in New Issue
Block a user