make Camera into single class, simplify code

felipesanches-svg
don bright 2013-03-03 10:52:25 -06:00
parent bfae32fe99
commit 2b2dc7a078
7 changed files with 127 additions and 140 deletions

View File

@ -1,65 +1,69 @@
#ifndef OPENSCAD_CAMERA_H_
#define OPENSCAD_CAMERA_H_
// Cameras
// For usage, see GLView.cc / export_png.cc / openscad.cc
/*
Camera
For usage, see *View.cc / export_png.cc / openscad.cc
There are two different types of cameras represented in this class:
*Gimbal camera - uses Euler Angles, object translation, and viewer distance
*Vector camera - uses 'eye', 'center', and 'up' vectors ('lookat' style)
*/
#include <vector>
#include <Eigen/Geometry>
#include <boost/variant.hpp>
class GimbalCamera
class Camera
{
public:
GimbalCamera()
{
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
enum CameraType { NONE, GIMBAL, VECTOR } type;
Camera() {
type = Camera::NONE;
}
GimbalCamera( std::vector<double> d )
Camera( enum CameraType e )
{
assert( d.size() == 7 );
object_trans << d[0], d[1], d[2];
object_rot << d[3], d[4], d[5];
viewer_distance = d[6];
type = e;
if ( e == Camera::GIMBAL ) {
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
} else if ( e == Camera::VECTOR ) {
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
}
}
void setup( std::vector<double> params ) {
if ( params.size() == 7 ) {
type = Camera::GIMBAL;
object_trans << params[0], params[1], params[2];
object_rot << params[3], params[4], params[5];
viewer_distance = params[6];
} else if ( params.size() == 6 ) {
type = Camera::VECTOR;
eye << params[0], params[1], params[2];
center << params[3], params[4], params[5];
} else {
assert( "Gimbal cam needs 7 numbers, Vector camera needs 6" );
}
}
// Vectorcam
Eigen::Vector3d eye;
Eigen::Vector3d center; // (aka 'target')
Eigen::Vector3d up;
// Gimbalcam
Eigen::Vector3d object_trans;
Eigen::Vector3d object_rot;
double viewer_distance;
};
class VectorCamera
{
public:
VectorCamera()
{
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
// "up" not currently used
}
VectorCamera( std::vector<double> d )
{
assert( d.size() == 6 );
eye << d[0], d[1], d[2];
center << d[3], d[4], d[5];
}
Eigen::Vector3d eye;
Eigen::Vector3d center; // (aka 'target')
Eigen::Vector3d up;
};
class Camera
{
public:
enum CameraType { NONE, GIMBAL, VECTOR } type;
Camera() { type = Camera::NONE; }
void set( VectorCamera &c ) { vcam = c; type = Camera::VECTOR; }
void set( GimbalCamera &c ) { gcam = c; type = Camera::GIMBAL; }
GimbalCamera gcam;
VectorCamera vcam;
};
#endif

View File

@ -17,7 +17,7 @@ GLView::GLView()
showaxes = false;
showcrosshairs = false;
renderer = NULL;
camtype = Camera::NONE;
cam.type = Camera::NONE;
#ifdef ENABLE_OPENCSG
is_opencsg_capable = false;
has_shaders = false;
@ -50,7 +50,7 @@ void GLView::setupGimbalCamPerspective()
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY);
gluLookAt(0.0, -gcam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
gluLookAt(0.0, -cam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}
void GLView::setupGimbalCamOrtho(double distance, bool offset)
@ -63,14 +63,14 @@ void GLView::setupGimbalCamOrtho(double distance, bool offset)
glOrtho(-w_h_ratio*l, +w_h_ratio*l,
-(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
gluLookAt(0.0, -gcam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
gluLookAt(0.0, -cam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}
void GLView::setupVectorCamPerspective()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double dist = (vcam.center - vcam.eye).norm();
double dist = (cam.center - cam.eye).norm();
gluPerspective(45, w_h_ratio, 0.1*dist, 100*dist);
}
@ -79,7 +79,7 @@ void GLView::setupVectorCamOrtho(bool offset)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (offset) glTranslated(-0.8, -0.8, 0);
double l = (vcam.center - vcam.eye).norm() / 10;
double l = (cam.center - cam.eye).norm() / 10;
glOrtho(-w_h_ratio*l, +w_h_ratio*l,
-(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
@ -87,20 +87,16 @@ void GLView::setupVectorCamOrtho(bool offset)
void GLView::setCamera( Camera &cam )
{
camtype = cam.type;
if ( camtype == Camera::GIMBAL ) {
gcam = cam.gcam;
} else if ( camtype == Camera::VECTOR ) {
vcam = cam.vcam;
gcam.viewer_distance = 10*3*(vcam.center - vcam.eye).norm();
}
this->cam = cam;
// kludge to make showAxes() work on vector camera
cam.viewer_distance = 10*3*(cam.center - cam.eye).norm();
}
void GLView::paintGL()
{
if (camtype == Camera::NONE) return;
else if (camtype == Camera::GIMBAL) gimbalCamPaintGL();
else if (camtype == Camera::VECTOR) vectorCamPaintGL();
if (cam.type == Camera::NONE) return;
else if (cam.type == Camera::GIMBAL) gimbalCamPaintGL();
else if (cam.type == Camera::VECTOR) vectorCamPaintGL();
}
#ifdef ENABLE_OPENCSG
@ -293,8 +289,8 @@ void GLView::vectorCamPaintGL()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
gluLookAt(vcam.eye[0], vcam.eye[1], vcam.eye[2],
vcam.center[0], vcam.center[1], vcam.center[2],
gluLookAt(cam.eye[0], cam.eye[1], cam.eye[2],
cam.center[0], cam.center[1], cam.center[2],
0.0, 0.0, 1.0);
// fixme - showcrosshairs doesnt work with vector camera
@ -320,7 +316,7 @@ void GLView::gimbalCamPaintGL()
{
glEnable(GL_LIGHTING);
if (orthomode) GLView::setupGimbalCamOrtho(gcam.viewer_distance);
if (orthomode) GLView::setupGimbalCamOrtho(cam.viewer_distance);
else GLView::setupGimbalCamPerspective();
glMatrixMode(GL_MODELVIEW);
@ -331,13 +327,13 @@ void GLView::gimbalCamPaintGL()
glClearColor(bgcol[0], bgcol[1], bgcol[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glRotated(gcam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(gcam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(gcam.object_rot.z(), 0.0, 0.0, 1.0);
glRotated(cam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(cam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(cam.object_rot.z(), 0.0, 0.0, 1.0);
if (showcrosshairs) GLView::showCrosshairs();
glTranslated(gcam.object_trans.x(), gcam.object_trans.y(), gcam.object_trans.z() );
glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z() );
if (showaxes) GLView::showAxes();
@ -360,7 +356,7 @@ void GLView::gimbalCamPaintGL()
void GLView::showSmallaxes()
{
// Fixme - this modifies the camera and doesnt work in 'non-gimbal' camera mode
// Fixme - this doesnt work in Vector Camera mode
// Small axis cross in the lower left corner
glDepthFunc(GL_ALWAYS);
@ -369,9 +365,9 @@ void GLView::showSmallaxes()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated(gcam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(gcam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(gcam.object_rot.z(), 0.0, 0.0, 1.0);
glRotated(cam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(cam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(cam.object_rot.z(), 0.0, 0.0, 1.0);
glLineWidth(1);
glBegin(GL_LINES);
@ -446,7 +442,7 @@ void GLView::showAxes()
glLineWidth(1);
glColor3d(0.5, 0.5, 0.5);
glBegin(GL_LINES);
double l = gcam.viewer_distance/10;
double l = cam.viewer_distance/10;
glVertex3d(-l, 0, 0);
glVertex3d(+l, 0, 0);
glVertex3d(0, -l, 0);
@ -467,7 +463,7 @@ void GLView::showCrosshairs()
glBegin(GL_LINES);
for (double xf = -1; xf <= +1; xf += 2)
for (double yf = -1; yf <= +1; yf += 2) {
double vd = gcam.viewer_distance/20;
double vd = cam.viewer_distance/20;
glVertex3d(-xf*vd, -yf*vd, -vd);
glVertex3d(+xf*vd, +yf*vd, +vd);
}

View File

@ -8,18 +8,12 @@ This class is inherited by:
*QGLview - for Qt GUI
*OffscreenView - for offscreen rendering, in tests and from command-line
There are two different types of cameras:
The view assumes either a Gimbal Camera (rotation,translation,distance)
or Vector Camera (eye,center/target) is being used. See Camera.h. The
cameras are not kept in sync.
*Gimbal camera - uses Euler Angles, object translation, and viewer distance
*Vector camera - uses 'eye', 'center', and 'up' vectors ('lookat' style)
They are selectable by creating a GimbalCamera or VectorCamera (Camera.h)
and then calling GLView.setCamera().
Currently, the camera is set in two separate variables that are not kept
in sync. Some actions (showCrossHairs) only work properly on Gimbal
Camera. QGLView uses GimbalCamera while OffscreenView can use either one
(defaulting to Vector).
QGLView only uses GimbalCamera while OffscreenView can use either one.
Some actions (showCrossHairs) only work properly on Gimbal Camera.
*/
@ -73,9 +67,7 @@ public:
bool showedges;
bool showcrosshairs;
Camera::CameraType camtype;
VectorCamera vcam;
GimbalCamera gcam;
Camera cam;
#ifdef ENABLE_OPENCSG
GLint shaderinfo[11];

View File

@ -63,10 +63,10 @@ static bool running_under_wine = false;
void QGLView::init()
{
camtype = Camera::GIMBAL;
gcam.object_rot << 35, 0, -25;
gcam.object_trans << 0, 0, 0;
gcam.viewer_distance = 500;
cam.type = Camera::GIMBAL;
cam.object_rot << 35, 0, -25;
cam.object_trans << 0, 0, 0;
cam.viewer_distance = 500;
this->mouse_drag_active = false;
this->statusLabel = NULL;
@ -152,8 +152,8 @@ void QGLView::paintGL()
if (statusLabel) {
QString msg;
msg.sprintf("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f",
-gcam.object_trans.x(), -gcam.object_trans.y(), -gcam.object_trans.z(),
fmodf(360 - gcam.object_rot.x() + 90, 360), fmodf(360 - gcam.object_rot.y(), 360), fmodf(360 - gcam.object_rot.z(), 360), gcam.viewer_distance);
-cam.object_trans.x(), -cam.object_trans.y(), -cam.object_trans.z(),
fmodf(360 - cam.object_rot.x() + 90, 360), fmodf(360 - cam.object_rot.y(), 360), fmodf(360 - cam.object_rot.z(), 360), cam.viewer_distance);
statusLabel->setText(msg);
}
@ -163,12 +163,12 @@ void QGLView::paintGL()
void QGLView::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Plus) {
gcam.viewer_distance *= 0.9;
cam.viewer_distance *= 0.9;
updateGL();
return;
}
if (event->key() == Qt::Key_Minus) {
gcam.viewer_distance /= 0.9;
cam.viewer_distance /= 0.9;
updateGL();
return;
}
@ -176,7 +176,7 @@ void QGLView::keyPressEvent(QKeyEvent *event)
void QGLView::wheelEvent(QWheelEvent *event)
{
gcam.viewer_distance *= pow(0.9, event->delta() / 120.0);
cam.viewer_distance *= pow(0.9, event->delta() / 120.0);
updateGL();
}
@ -207,25 +207,25 @@ void QGLView::mouseMoveEvent(QMouseEvent *event)
) {
// Left button rotates in xz, Shift-left rotates in xy
// On Mac, Ctrl-Left is handled as right button on other platforms
gcam.object_rot.x() += dy;
cam.object_rot.x() += dy;
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0)
gcam.object_rot.y() += dx;
cam.object_rot.y() += dx;
else
gcam.object_rot.z() += dx;
cam.object_rot.z() += dx;
normalizeAngle(gcam.object_rot.x());
normalizeAngle(gcam.object_rot.y());
normalizeAngle(gcam.object_rot.z());
normalizeAngle(cam.object_rot.x());
normalizeAngle(cam.object_rot.y());
normalizeAngle(cam.object_rot.z());
} else {
// Right button pans in the xz plane
// Middle button pans in the xy plane
// Shift-right and Shift-middle zooms
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) {
gcam.viewer_distance += (GLdouble)dy;
cam.viewer_distance += (GLdouble)dy;
} else {
double mx = +(dx) * gcam.viewer_distance/1000;
double mz = -(dy) * gcam.viewer_distance/1000;
double mx = +(dx) * cam.viewer_distance/1000;
double mz = -(dy) * cam.viewer_distance/1000;
double my = 0;
#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
@ -241,9 +241,9 @@ void QGLView::mouseMoveEvent(QMouseEvent *event)
}
Matrix3d aax, aay, aaz, tm3;
aax = Eigen::AngleAxisd(-(gcam.object_rot.x()/180) * M_PI, Vector3d::UnitX());
aay = Eigen::AngleAxisd(-(gcam.object_rot.y()/180) * M_PI, Vector3d::UnitY());
aaz = Eigen::AngleAxisd(-(gcam.object_rot.z()/180) * M_PI, Vector3d::UnitZ());
aax = Eigen::AngleAxisd(-(cam.object_rot.x()/180) * M_PI, Vector3d::UnitX());
aay = Eigen::AngleAxisd(-(cam.object_rot.y()/180) * M_PI, Vector3d::UnitY());
aaz = Eigen::AngleAxisd(-(cam.object_rot.z()/180) * M_PI, Vector3d::UnitZ());
tm3 = Matrix3d::Identity();
tm3 = aaz * (aay * (aax * tm3));
@ -259,9 +259,9 @@ void QGLView::mouseMoveEvent(QMouseEvent *event)
0, 0, 0, 1
;
tm = tm * vec;
gcam.object_trans.x() += tm(0,3);
gcam.object_trans.y() += tm(1,3);
gcam.object_trans.z() += tm(2,3);
cam.object_trans.x() += tm(0,3);
cam.object_trans.y() += tm(1,3);
cam.object_trans.z() += tm(2,3);
}
}
updateGL();

View File

@ -36,12 +36,11 @@ void export_png_with_cgal(CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream
}
if (cam.type == Camera::NONE) {
VectorCamera vcam;
vcam.center = getBoundingCenter(bbox);
cam.type = Camera::VECTOR;
cam.center = getBoundingCenter(bbox);
double radius = getBoundingRadius(bbox);
Vector3d cameradir(1, 1, -0.5);
vcam.eye = vcam.center - radius*2*cameradir;
cam.set(vcam);
cam.eye = cam.center - radius*2*cameradir;
}
//std::cerr << center << "\n";
@ -79,17 +78,15 @@ void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output)
OpenCSGRenderer opencsgRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo);
if (cam.type == Camera::NONE) {
VectorCamera vcam;
vcam.center << 0,0,0;
cam.center << 0,0,0;
double radius = 1.0;
if (csgInfo.root_chain) {
BoundingBox bbox = csgInfo.root_chain->getBoundingBox();
vcam.center = (bbox.min() + bbox.max()) / 2;
cam.center = (bbox.min() + bbox.max()) / 2;
radius = (bbox.max() - bbox.min()).norm() / 2;
}
Vector3d cameradir(1, 1, -0.5);
vcam.eye = vcam.center - radius*1.8*cameradir;
cam.set(vcam);
cam.eye = cam.center - radius*1.8*cameradir;
}
csgInfo.glview->setCamera( cam );

View File

@ -964,7 +964,7 @@ void MainWindow::pasteViewportTranslation()
{
QTextCursor cursor = editor->textCursor();
QString txt;
txt.sprintf("[ %.2f, %.2f, %.2f ]", -qglview->gcam.object_trans.x(), -qglview->gcam.object_trans.y(), -qglview->gcam.object_trans.z());
txt.sprintf("[ %.2f, %.2f, %.2f ]", -qglview->cam.object_trans.x(), -qglview->cam.object_trans.y(), -qglview->cam.object_trans.z());
cursor.insertText(txt);
}
@ -973,7 +973,7 @@ void MainWindow::pasteViewportRotation()
QTextCursor cursor = editor->textCursor();
QString txt;
txt.sprintf("[ %.2f, %.2f, %.2f ]",
fmodf(360 - qglview->gcam.object_rot.x() + 90, 360), fmodf(360 - qglview->gcam.object_rot.y(), 360), fmodf(360 - qglview->gcam.object_rot.z(), 360));
fmodf(360 - qglview->cam.object_rot.x() + 90, 360), fmodf(360 - qglview->cam.object_rot.y(), 360), fmodf(360 - qglview->cam.object_rot.z(), 360));
cursor.insertText(txt);
}
@ -982,15 +982,15 @@ void MainWindow::updateTemporalVariables()
this->root_ctx.set_variable("$t", Value(this->e_tval->text().toDouble()));
Value::VectorType vpt;
vpt.push_back(Value(-qglview->gcam.object_trans.x()));
vpt.push_back(Value(-qglview->gcam.object_trans.y()));
vpt.push_back(Value(-qglview->gcam.object_trans.z()));
vpt.push_back(Value(-qglview->cam.object_trans.x()));
vpt.push_back(Value(-qglview->cam.object_trans.y()));
vpt.push_back(Value(-qglview->cam.object_trans.z()));
this->root_ctx.set_variable("$vpt", Value(vpt));
Value::VectorType vpr;
vpr.push_back(Value(fmodf(360 - qglview->gcam.object_rot.x() + 90, 360)));
vpr.push_back(Value(fmodf(360 - qglview->gcam.object_rot.y(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->gcam.object_rot.z(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360)));
root_ctx.set_variable("$vpr", Value(vpr));
}
@ -1617,49 +1617,49 @@ void MainWindow::animateUpdate()
void MainWindow::viewAngleTop()
{
qglview->gcam.object_rot << 90,0,0;
qglview->cam.object_rot << 90,0,0;
this->qglview->updateGL();
}
void MainWindow::viewAngleBottom()
{
qglview->gcam.object_rot << 270,0,0;
qglview->cam.object_rot << 270,0,0;
this->qglview->updateGL();
}
void MainWindow::viewAngleLeft()
{
qglview->gcam.object_rot << 0,0,90;
qglview->cam.object_rot << 0,0,90;
this->qglview->updateGL();
}
void MainWindow::viewAngleRight()
{
qglview->gcam.object_rot << 0,0,270;
qglview->cam.object_rot << 0,0,270;
this->qglview->updateGL();
}
void MainWindow::viewAngleFront()
{
qglview->gcam.object_rot << 0,0,0;
qglview->cam.object_rot << 0,0,0;
this->qglview->updateGL();
}
void MainWindow::viewAngleBack()
{
qglview->gcam.object_rot << 0,0,180;
qglview->cam.object_rot << 0,0,180;
this->qglview->updateGL();
}
void MainWindow::viewAngleDiagonal()
{
qglview->gcam.object_rot << 35,0,-25;
qglview->cam.object_rot << 35,0,-25;
this->qglview->updateGL();
}
void MainWindow::viewCenter()
{
qglview->gcam.object_trans << 0,0,0;
qglview->cam.object_trans << 0,0,0;
this->qglview->updateGL();
}

View File

@ -112,8 +112,7 @@ Camera determine_camera( po::variables_map vm )
} else {
BOOST_FOREACH(string &s, strs)
cam_parameters.push_back(lexical_cast<double>(s));
GimbalCamera gcam( cam_parameters );
camera.set( gcam );
camera.setup( cam_parameters );
}
}
@ -127,8 +126,7 @@ Camera determine_camera( po::variables_map vm )
} else {
BOOST_FOREACH(string &s, strs)
cam_parameters.push_back(lexical_cast<double>(s));
VectorCamera vcam( cam_parameters );
camera.set( vcam );
camera.setup( cam_parameters );
}
}