diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/epix/camera.cc |
Initial commit
Diffstat (limited to 'graphics/epix/camera.cc')
-rw-r--r-- | graphics/epix/camera.cc | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/graphics/epix/camera.cc b/graphics/epix/camera.cc new file mode 100644 index 0000000000..0a70da081b --- /dev/null +++ b/graphics/epix/camera.cc @@ -0,0 +1,318 @@ +/* + * camera.cc -- ePiX::camera functions + * + * This file is part of ePiX, a C++ library for creating high-quality + * figures in LaTeX + * + * Version 1.1.21 + * Last Change: September 22, 2007 + */ + +/* + * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + * Andrew D. Hwang <rot 13 nujnat at zngupf dot ubylpebff dot rqh> + * Department of Mathematics and Computer Science + * College of the Holy Cross + * Worcester, MA, 01610-2395, USA + */ + +/* + * ePiX is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ePiX is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ePiX; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <cmath> + +#include "errors.h" +#include "constants.h" + +#include "pairs.h" +#include "triples.h" +#include "frame.h" + +#include "functions.h" + +#include "halfspace.h" + +#include "lens.h" +#include "camera.h" + +namespace ePiX { + + // Need to initialize frame argument for Apple gcc; otherwise cam() + // gets null vectors in frame()... + Camera::Camera() + : the_viewpt(P(0,0,EPIX_INFTY)), the_target(P(0,0,0)), + the_orient(frame(E_1, E_2, E_3)), + the_distance(EPIX_INFTY), the_clip_range(MIN_CLIP), + the_filter(Neutral()), the_lens(new Perspective()) { } + + // viewpt, target, orient + Camera::Camera(const P& vpt) + : the_viewpt(vpt), the_target(P(0,0,0)), the_clip_range(MIN_CLIP), + the_filter(Neutral()) + { + if (the_viewpt == P(0,0,0)) + { + epix_warning("Cannot initialize Camera at Origin, using (0, 0, oo)"); + the_viewpt = P(0, 0, EPIX_INFTY); + } + P viewer(the_viewpt - the_target); + the_distance = norm(viewer); + + viewer *= recip(norm(viewer)); + + // viewer is "eye", if possible E_3 is "sky" + P tmp_sea(E_3*viewer); + + if (norm(tmp_sea) < EPIX_EPSILON) // we're on the "z-axis through vpt" + tmp_sea = E_1; + + // eye*sea = sky + the_orient = frame(tmp_sea, viewer*tmp_sea, viewer); + adjust(); + + the_lens = new Perspective(); + } + + + Camera::Camera(const Camera& cam) + : the_viewpt(cam.the_viewpt), the_target(cam.the_target), + the_orient(cam.the_orient), the_distance(cam.the_distance), + the_clip_range(cam.the_clip_range), the_filter(cam.the_filter), + the_lens(cam.the_lens->clone()) { } + + Camera& Camera::operator= (const Camera& cam) + { + Lens* tmp_lens(cam.the_lens->clone()); + the_lens = tmp_lens; + + the_viewpt = cam.the_viewpt; + the_target = cam.the_target; + the_orient =cam.the_orient; + the_distance = cam.the_distance; + the_clip_range = cam.the_distance; + + the_filter = cam.the_filter; + + return *this; + } + + Camera::~Camera() + { + delete the_lens; + } + + // rotate up/down + Camera& Camera::tilt(double angle) + { + the_orient.rot1(-angle); + the_target = the_viewpt + (-the_distance)*the_orient.eye(); + return *this; + } + + // rotate left/right + Camera& Camera::pan(double angle) + { + the_orient.rot2(-angle); + the_target = the_viewpt + (-the_distance)*the_orient.eye(); + return *this; + } + + // rotate about viewing axis + Camera& Camera::roll(double angle) + { + the_orient.rot3(-angle); // target unchanged + return *this; + } + + // fix target, move viewpt radially along eye() + Camera& Camera::range(double d) + { + if (d == 0) + d = EPIX_INFTY; + + the_distance = d; + the_viewpt = the_target + d*the_orient.eye(); + + return *this; + } + + // fix viewpt, move target radially along eye() + Camera& Camera::focus(double d) + { + if (d == 0) + d = EPIX_INFTY; + + the_distance = d; + the_target = the_viewpt - d*the_orient.eye(); + + return *this; + } + + // clip everything behind this + Camera& Camera::clip_range(double dist) + { + the_clip_range = (dist < MIN_CLIP ? MIN_CLIP : dist); + return *this; + } + + // fix target, set viewpt + Camera& Camera::at(const P& vpt) + { + the_viewpt = vpt; + adjust(); + + return *this; + } + + // fix viewpt, set target + Camera& Camera::look_at(const P& tgt) + { + the_target = tgt; + adjust(); + + return *this; + } + + Camera& Camera::at(double x1, double x2, double x3) + { + the_viewpt = P(x1, x2, x3); + adjust(); + + return *this; + } + + // fix viewpt, set target + Camera& Camera::look_at(double x1, double x2, double x3) + { + the_target = P(x1, x2, x3); + adjust(); + + return *this; + } + + Camera& Camera::filter(const Color& filter) + { + the_filter=filter; + return *this; + } + + Camera& Camera::perspective() + { + delete the_lens; + the_lens = new Perspective; + return *this; + } + + Camera& Camera::orthog() + { + delete the_lens; + the_lens = new Orthog; + return *this; + } + + Camera& Camera::fisheye() + { + delete the_lens; + the_lens = new Fisheye; + return *this; + } + + Camera& Camera::bubble() + { + delete the_lens; + the_lens = new Bubble; + return *this; + } + + Color Camera::operator() (const Color& in_color) const + { + Color temp = the_filter; + return temp.filter(in_color); + } + + // lens interface + pair Camera::operator() (const P& arg) const + { + return (*the_lens)(arg, the_orient, the_viewpt, the_distance); + } + + bool Camera::is_linear() const + { + return (*the_lens).is_linear(); + } + + bool Camera::needs_clip() const + { + return (*the_lens).needs_clip(); + } + + + halfspace Camera::clip_plane() const + { + const P N(-the_orient.eye()); + return halfspace(the_viewpt + the_clip_range*N, N); + } + + P Camera::eye() const + { + return the_orient.eye(); + } + + P Camera::viewpt() const + { + return the_viewpt; + } + + // private function + void Camera::adjust() + { + P temp(the_target - the_viewpt); + the_distance = norm(temp); + + if (the_distance < EPIX_EPSILON) + { + epix_warning("Cannot make viewpoint and target the same, no action"); + return; + } + + // else + temp *= -1.0/the_distance; // reverse direction + + double z_ht(temp|E_3); + + // too close to "z-axis" through target? + if (sqrt((1-z_ht)*(1+z_ht)) < EPIX_EPSILON) + { + if (z_ht >= 0) + the_orient = frame(); + + else // z_ht < 0 + the_orient = frame(-E_1, E_2, -E_3); + } + + else // far enough from axis + the_orient = frame(P(-temp.x2(), temp.x1(), 0), E_3, temp); + } + + + Camera& cam() + { + static Camera* the_camera(new Camera()); + return *the_camera; + } + + Camera& camera(cam()); + +} // end of namespace |