openscad/src/Camera.cc

124 lines
3.5 KiB
C++

#include "Camera.h"
#include "rendersettings.h"
#include "printutils.h"
Camera::Camera(enum CameraType camtype) :
type(camtype), projection(Camera::PERSPECTIVE), fov(22.5), viewall(false)
{
PRINTD("Camera()");
if (this->type == Camera::GIMBAL) {
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
} else if (this->type == Camera::VECTOR) {
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
}
pixel_width = RenderSettings::inst()->img_width;
pixel_height = RenderSettings::inst()->img_height;
autocenter = false;
}
void Camera::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");
}
}
void Camera::gimbalDefaultTranslate()
{ // match the GUI viewport numbers (historical reasons)
object_trans.x() *= -1;
object_trans.y() *= -1;
object_trans.z() *= -1;
object_rot.x() = fmodf(360 - object_rot.x() + 90, 360);
object_rot.y() = fmodf(360 - object_rot.y(), 360);
object_rot.z() = fmodf(360 - object_rot.z(), 360);
}
/*!
Moves camera so that the given bbox is fully visible.
*/
void Camera::viewAll(const BoundingBox &bbox)
{
if (this->type == Camera::NONE) {
this->type = Camera::VECTOR;
this->center = bbox.center();
this->eye = this->center - Vector3d(1,1,-0.5);
}
if (this->autocenter) {
// autocenter = point camera at the center of the bounding box.
if (this->type == Camera::GIMBAL) {
this->object_trans = -bbox.center(); // for Gimbal cam
}
else if (this->type == Camera::VECTOR) {
Vector3d dir = this->center - this->eye;
this->center = bbox.center(); // for Vector cam
this->eye = this->center - dir;
}
}
double bboxRadius = bbox.diagonal().norm()/2;
double radius = (bbox.center()-this->center).norm() + bboxRadius;
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;
}
default:
assert(false && "Camera type not specified");
}
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 obj trans x y z %f %f %f",object_trans.x() % object_trans.y() % object_trans.z());
PRINTDB("modified obj rot x y z %f %f %f",object_rot.x() % object_rot.y() % object_rot.z());
}
void Camera::zoom(int delta)
{
this->viewer_distance *= pow(0.9, delta / 120.0);
}
void Camera::setProjection(ProjectionType type)
{
this->projection = type;
}
void Camera::resetView()
{
type = Camera::GIMBAL;
object_rot << 35, 0, -25;
object_trans << 0, 0, 0;
viewer_distance = 140;
}
double Camera::zoomValue()
{
return viewer_distance;
}
std::string Camera::statusText()
{
boost::format fmt(_("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f"));
fmt % object_trans.x() % object_trans.y() % object_trans.z()
% object_rot.x() % object_rot.y() % object_rot.z()
% viewer_distance;
return fmt.str();
}