home *** CD-ROM | disk | FTP | other *** search
- /*
- * ViewTransform.C - general view transformation.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * University of Berne, Switzerland
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "ViewTransform.h"
- #include "Error.h"
-
- //___________________________________________________________ ViewTransform
-
-
- ViewTransform::ViewTransform(const Vector& Eye, const Vector& Lookat,
- const Vector& Up, real Fov, int ResX, int ResY)
- : eye(Eye), lookat(Lookat), up(Up), fov(Fov), resX(ResX), resY(ResY)
- {
- buildView();
- }
-
- ViewTransform::ViewTransform(const BoundingBox& b, const Vector& Up, real Fov,
- int ResX, int ResY)
- : up(Up), fov(Fov), resX(ResX), resY(ResY)
- {
- real widthX2 = 0.5*(b.xmax()-b.xmin());
- real widthY2 = 0.5*(b.ymax()-b.ymin());
- real height2 = 0.5*(b.zmax()-b.zmin());
-
- if (widthX2 > widthY2) {
- // let's look to the xz-plane
- if (widthX2 >= height2)
- eye[1] = b.ymax() + widthX2/tan(dtor(fov/2));
- else
- eye[1] = b.ymax() + height2/tan(dtor(fov/2));
- eye[0] = lookat[0] = b.xmin() + widthX2;
- lookat[1] = b.ymax();
- }
- else {
- // let's look to the yz-plane
- if (widthY2 >= height2)
- eye[0] = b.xmax() + widthY2/tan(dtor(fov/2));
- else
- eye[0] = b.xmax() + height2/tan(dtor(fov/2));
- eye[1] = lookat[1] = b.ymin() + widthY2;
- lookat[0] = b.xmax();
- }
- eye[2] = lookat[2] = b.zmin()+height2;
-
- buildView();
- }
-
- Vector ViewTransform::transformWorld2Screen(const Vector& p)
- {
- Vector vp = p*viewmat;
-
- if (equal(vp[2], 0))
- return Vector(0,0,0);
-
- real scale = widthOfViewplane/vp[2];
- vp[0] = resX*(0.5+vp[0]*scale);
- vp[1] = resY*(0.5+vp[1]*scale);
-
- return vp;
- }
-
- Vector ViewTransform::transformWorld2View(const Vector& p)
- {
- return p*viewmat;
- }
-
- Vector ViewTransform::transformView2Screen(const Vector& p)
- {
- if (equal(p[2], 0))
- return Vector(0,0,0);
-
- Vector vp = p;
- real scale = widthOfViewplane/vp[2];
- vp[0] = resX*(0.5+vp[0]*scale);
- vp[1] = resY*(0.5+vp[1]*scale);
-
- return vp;
- }
-
- // buildView assumes that eye, lookat, up, fov, resX, resY are already set!!!
- void ViewTransform::buildView()
- {
- Vector n,v,u;
-
- n = lookat - eye; n.normalize();
- v = up - (n^up)*n;
- if (v.normalize() == 0)
- Error(ERR_PANIC, "The view and up directions are identical?");
- u = n * v;
- widthOfViewplane = 0.5/(tan(dtor(fov)/2));
-
- viewmat(0,0) = u[0]; viewmat(1,0) = u[1]; viewmat(2,0) = u[2];
- viewmat(0,1) = v[0]; viewmat(1,1) = v[1]; viewmat(2,1) = v[2];
- viewmat(0,2) = n[0]; viewmat(1,2) = n[1]; viewmat(2,2) = n[2];
- viewmat(3,0) = -eye[0]*u[0] - eye[1]*u[1] - eye[2]*u[2];
- viewmat(3,1) = -eye[0]*v[0] - eye[1]*v[1] - eye[2]*v[2];
- viewmat(3,2) = -eye[0]*n[0] - eye[1]*n[1] - eye[2]*n[2];
- }
-
- ostream& operator<<(ostream& os, const ViewTransform& view)
- {
- os << "Eye: " << view.eye << '\n'
- << "Lookat: " << view.lookat << '\n'
- << "Up: " << view.up << '\n'
- << "Fov: " << view.fov << '\n';
-
- return os;
- }
-