More camera fixes: Better viewall calculation, better switching between perspective and ortho

master
Marius Kintel 2015-03-07 19:02:51 -05:00
parent 788293f68f
commit 30d2440598
2 changed files with 28 additions and 37 deletions

View File

@ -3,7 +3,7 @@
#include "printutils.h" #include "printutils.h"
Camera::Camera(enum CameraType camtype) : Camera::Camera(enum CameraType camtype) :
type(camtype), projection(Camera::PERSPECTIVE), fov(22.5), viewall(false), height(60) type(camtype), projection(Camera::PERSPECTIVE), fov(22.5), viewall(false)
{ {
PRINTD("Camera()"); PRINTD("Camera()");
if (this->type == Camera::GIMBAL) { if (this->type == Camera::GIMBAL) {
@ -26,7 +26,7 @@ void Camera::setup(std::vector<double> params)
type = Camera::GIMBAL; type = Camera::GIMBAL;
object_trans << params[0], params[1], params[2]; object_trans << params[0], params[1], params[2];
object_rot << params[3], params[4], params[5]; object_rot << params[3], params[4], params[5];
height = viewer_distance = params[6]; viewer_distance = params[6];
} else if (params.size() == 6) { } else if (params.size() == 6) {
type = Camera::VECTOR; type = Camera::VECTOR;
eye << params[0], params[1], params[2]; eye << params[0], params[1], params[2];
@ -69,28 +69,20 @@ void Camera::viewAll(const BoundingBox &bbox)
} }
} }
switch (this->projection) { double bboxRadius = bbox.diagonal().norm()/2;
case Camera::ORTHOGONAL: double radius = (bbox.center()-this->center).norm() + bboxRadius;
this->height = this->viewer_distance = bbox.diagonal().norm(); double distance = radius / sin(this->fov/2*M_PI/180);
switch (this->type) {
case Camera::GIMBAL:
this->viewer_distance = distance;
break;
case Camera::VECTOR: {
Vector3d cameradir = (this->center - this->eye).normalized();
this->eye = this->center - distance*cameradir;
break; break;
case Camera::PERSPECTIVE: {
double bboxRadius = bbox.diagonal().norm()/2;
double radius = (bbox.center()-this->center).norm() + bboxRadius;
double distance = radius / sin(this->fov*M_PI/360);
switch (this->type) {
case Camera::GIMBAL:
this->height = this->viewer_distance = distance;
break;
case Camera::VECTOR: {
Vector3d cameradir = (this->center - this->eye).normalized();
this->eye = this->center - distance*cameradir;
break;
}
default:
assert(false && "Camera type not specified");
}
} }
break; default:
assert(false && "Camera type not specified");
} }
PRINTDB("modified center x y z %f %f %f",center.x() % center.y() % center.z()); PRINTDB("modified center x y z %f %f %f",center.x() % center.y() % center.z());
PRINTDB("modified eye x y z %f %f %f",eye.x() % eye.y() % eye.z()); PRINTDB("modified eye x y z %f %f %f",eye.x() % eye.y() % eye.z());
@ -100,7 +92,7 @@ void Camera::viewAll(const BoundingBox &bbox)
void Camera::zoom(int delta) void Camera::zoom(int delta)
{ {
this->height = this->viewer_distance *= pow(0.9, delta / 120.0); this->viewer_distance *= pow(0.9, delta / 120.0);
} }
void Camera::setProjection(ProjectionType type) void Camera::setProjection(ProjectionType type)
@ -113,12 +105,12 @@ void Camera::resetView()
type = Camera::GIMBAL; type = Camera::GIMBAL;
object_rot << 35, 0, -25; object_rot << 35, 0, -25;
object_trans << 0, 0, 0; object_trans << 0, 0, 0;
height = viewer_distance = 140; viewer_distance = 140;
} }
double Camera::zoomValue() double Camera::zoomValue()
{ {
return this->projection == PERSPECTIVE ? viewer_distance : height; return viewer_distance;
} }
std::string Camera::statusText() std::string Camera::statusText()
@ -126,6 +118,6 @@ std::string Camera::statusText()
boost::format fmt(_("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f")); boost::format fmt(_("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f"));
fmt % object_trans.x() % object_trans.y() % object_trans.z() fmt % object_trans.x() % object_trans.y() % object_trans.z()
% object_rot.x() % object_rot.y() % object_rot.z() % object_rot.x() % object_rot.y() % object_rot.z()
% (this->projection == PERSPECTIVE ? viewer_distance : height); % viewer_distance;
return fmt.str(); return fmt.str();
} }

View File

@ -95,22 +95,21 @@ void GLView::setupCamera()
switch (this->cam.type) { switch (this->cam.type) {
case Camera::GIMBAL: { case Camera::GIMBAL: {
double eyeY = 0.0; double dist = cam.zoomValue();
switch (this->cam.projection) { switch (this->cam.projection) {
case Camera::PERSPECTIVE: { case Camera::PERSPECTIVE: {
eyeY = cam.zoomValue(); gluPerspective(cam.fov, aspectratio, 0.1*dist, 100*dist);
gluPerspective(cam.fov, aspectratio, 0.1 * eyeY, 100 * eyeY);
break; break;
} }
case Camera::ORTHOGONAL: { case Camera::ORTHOGONAL: {
eyeY = cam.zoomValue(); double height = dist * tan(cam.fov/2*M_PI/180);
glOrtho(-eyeY/2*aspectratio, eyeY*aspectratio/2, glOrtho(-height*aspectratio, height*aspectratio,
-eyeY/2, eyeY/2, -height, height,
-far_far_away, +far_far_away); -far_far_away, +far_far_away);
break; break;
} }
} }
gluLookAt(0.0, -eyeY, 0.0, gluLookAt(0.0, -dist, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0); 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -121,16 +120,16 @@ void GLView::setupCamera()
break; break;
} }
case Camera::VECTOR: { case Camera::VECTOR: {
double dist = (cam.center - cam.eye).norm();
switch (this->cam.projection) { switch (this->cam.projection) {
case Camera::PERSPECTIVE: { case Camera::PERSPECTIVE: {
double dist = (cam.center - cam.eye).norm();
gluPerspective(cam.fov, aspectratio, 0.1*dist, 100*dist); gluPerspective(cam.fov, aspectratio, 0.1*dist, 100*dist);
break; break;
} }
case Camera::ORTHOGONAL: { case Camera::ORTHOGONAL: {
double height = cam.zoomValue(); double height = dist * tan(cam.fov/2*M_PI/180);
glOrtho(-height/2*aspectratio, height*aspectratio/2, glOrtho(-height*aspectratio, height*aspectratio,
-height/2, height/2, -height, height,
-far_far_away, +far_far_away); -far_far_away, +far_far_away);
break; break;
} }