Restructured and adapted in a better way to opengl

This commit is contained in:
Paolo Cignoni 2004-05-07 12:46:08 +00:00
parent ab4f6f00ef
commit 6df79edd1f
5 changed files with 376 additions and 187 deletions

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.4 2004/04/07 10:54:10 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.3 2004/03/31 15:08:03 ponchio Revision 1.3 2004/03/31 15:08:03 ponchio
Fixed current_action initialization. Fixed current_action initialization.
@ -33,16 +36,21 @@ Adding copyright.
****************************************************************************/ ****************************************************************************/
#include <gl/glew.h>
#include "trackball.h" #include "trackball.h"
#include <wrap/gl/math.h> #include <wrap/gl/math.h>
#include <wrap/gl/space.h>
using namespace vcg; using namespace vcg;
#include <iostream> //debug! #include <iostream> //debug!
using namespace std; using namespace std;
Transform::Transform() { Transform::Transform() {
local.SetIdentity();
track.SetIdentity(); track.SetIdentity();
radius=1.0f;
center=Point3f(0,0,0);
} }
Trackball::Trackball(): current_button(0), last_x(-1), last_y(-1), dragging(false), Trackball::Trackball(): current_button(0), last_x(-1), last_y(-1), dragging(false),
@ -57,12 +65,11 @@ Trackball::Trackball(): current_button(0), last_x(-1), last_y(-1), dragging(fals
} }
void Trackball::SetIdentity() { void Trackball::SetIdentity() {
local.SetIdentity(); track.SetIdentity();
Reset(); Reset();
} }
void Trackball::SetPosition(const Similarityf &m, int /* millisec */) { void Trackball::SetPosition(const Point3f &c, int /* millisec */) {
local = m; center = c;
//millisec ignored at the moment.
} }
//operating //operating
@ -70,13 +77,15 @@ void Trackball::GetView() {
camera.GetView(); camera.GetView();
//lets get view matrix //lets get view matrix
Similarityf m = local * last_track; Similarityf m = last_track;
Point3f c_obj = Point3f(0, 0, 0) * m; //coordinate of the center of the trackball in obj coords Point3f c_obj = m*center; //coordinate of the center of the trackball in obj coords
Point3f c_view = camera.Project(c_obj); //center of the trackball in screen coords. ScreenCenter = camera.Project(c_obj); //center of the trackball in screen coords.
ScreenRadius = 10.0f/Distance(center, camera.UnProject(Point3f(ScreenCenter[0] + 10, ScreenCenter[1], ScreenCenter[2])));
Point3f X, Y, Z, C; Point3f X, Y, Z, C;
X = camera.UnProject(Point3f(c_view[0] + 100, c_view[1], c_view[2])); X = camera.UnProject(Point3f(ScreenCenter[0] + 100, ScreenCenter[1], ScreenCenter[2]));
Y = camera.UnProject(Point3f(c_view[0], c_view[1] - 100, c_view[2])); Y = camera.UnProject(Point3f(ScreenCenter[0], ScreenCenter[1] - 100, ScreenCenter[2]));
Z = camera.UnProject(Point3f(c_view[0], c_view[1], c_view[2] + 0.1f)); Z = camera.UnProject(Point3f(ScreenCenter[0], ScreenCenter[1], ScreenCenter[2] + 0.1f));
C = c_obj; C = c_obj;
X = X - C; X.Normalize(); X = X - C; X.Normalize();
Y = Y - C; Y.Normalize(); Y = Y - C; Y.Normalize();
@ -93,30 +102,124 @@ void Trackball::GetView() {
//spinning ignored //spinning ignored
} }
void Trackball::Apply() { void Trackball::Apply() {
Matrix44f a = track.Matrix(); glMultMatrix(track.Matrix());
//Transpose(a); }
glMultMatrix(a);
//glMultMatrix(track.Matrix()); /***************************************************************/
//glMultMatrix(track);
void Trackball::DrawCircle()
{
const int nside=18;
const double pi2=3.14159265*2.0;
glBegin(GL_LINE_STRIP);
for(double i=0;i<=nside;i++){
glNormal3d(cos(i*pi2/nside), sin(i*pi2/nside), 0.0);
glVertex3d(cos(i*pi2/nside), sin(i*pi2/nside), 0.0);
}
glEnd();
DrawPlaneHandle();
}
void Trackball::DrawPlane()
{
const int nl=10;
float w=5.0f/3.0f;
float u;
glBegin(GL_LINES);
glNormal3f(0.0,0.0,1.0);
for( u=-w; u<=w+0.01f; u+=2*w/nl){
glVertex3f(-w, +u, 0);
glVertex3f(+w, +u, 0);
glVertex3f(+u, -w, 0);
glVertex3f(+u, +w, 0);
}
glEnd();
}
void Trackball::DrawPlaneHandle()
{
float r=1.0;
float dr=r/10.0f;
glBegin(GL_LINE_STRIP);
glVertex3f(+r+dr, +r, 0.0);
glVertex3f(+r , +r+dr,0.0);
glVertex3f(+r-dr, +r, 0.0);
glVertex3f(+r , +r-dr,0.0);
glVertex3f(+r+dr, +r, 0.0);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(-r+dr, -r, 0.0);
glVertex3f(-r , -r+dr,0.0);
glVertex3f(-r-dr, -r, 0.0);
glVertex3f(-r , -r-dr,0.0);
glVertex3f(-r+dr, -r, 0.0);
glEnd();
} }
void Trackball::Draw() { void Trackball::Draw() {
glPushMatrix(); glPushMatrix();
glMultMatrix(local.Matrix()); glTranslate(center);
//Disegnamo un cubo: glScalef(radius,radius,radius);
glColor3f(1, 0, 0);
glScalef(0.5, 0.5, 0.5); /// Here start the real drawing stuff
glBegin(GL_LINE_STRIP);
glVertex3f(-1, -1, -1); float amb[4] ={.3f,.3f,.3f,1.0f};
glVertex3f( 1, -1, -1); float col[4] ={.5f,.5f,.8f,1.0f};
glVertex3f( 1, 1, -1); float col2[4]={.9f,.9f,1.0f,1.0f};
glVertex3f(-1, 1, -1); glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
glVertex3f(-1, 1, 1); glLineWidth(2.0);
glVertex3f( 1, 1, 1); glEnable(GL_LIGHTING);
glVertex3f( 1, -1, 1); glEnable(GL_LINE_SMOOTH);
glVertex3f(-1, -1, 1); glEnable(GL_BLEND);
glVertex3f(-1, -1, 1);
glEnd(); glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,amb);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,col);
glPushMatrix();
DrawCircle();
glPushMatrix();
glRotatef(90,1,0,0);
DrawCircle();
glRotatef(90,0,1,0);
DrawCircle();
glPopMatrix();
glPopMatrix();
glColor4f(1.0,.8f,.8f,1.0f);
if(current_action.motion==ROTATE_X || current_action.motion==ROTATE_Y || current_action.motion==ROTATE_Z ){
//Point3d raxt(0,0,0),rax;// compute the rotation axis
//raxt[current_action.motion-ROTATE_X]=1;
//RotM.Apply(rax,raxt);
//
//glDisable(GL_LIGHTING);
//glBegin(GL_LINE_STRIP);
// glVertex(Manip.c-raxt*TrackballRadius*1.3);
// glVertex(Manip.c+raxt*TrackballRadius*1.3);
//glEnd();
}
glPopAttrib();
if(current_action.motion==DRAG_XY) {
glPushMatrix();
//glTranslate(Manip.c);
DrawPlane();
glPopMatrix();
}
if(current_action.motion==DRAG_XZ) {
glPushMatrix();
//glTranslate(Manip.c);
glRotatef(90,1,0,0);
DrawPlane();
glPopMatrix();
}
if(current_action.motion==DRAG_YZ) {
glPushMatrix();
//glTranslate(Manip.c);
glRotatef(90,0,1,0);
DrawPlane();
glPopMatrix();
}
glPopMatrix(); glPopMatrix();
} }
@ -140,32 +243,14 @@ void Trackball::MouseMove(int x, int y) {
return; return;
} }
Point3f origin = camera.ViewportToScreen(ScreenOrigin());
Point3f new_point = camera.ViewportToScreen(Point3f(float(x), float(y), 0)) - origin;
Point3f old_point = camera.ViewportToScreen(Point3f(float(last_x), float(last_y), 0)) - origin;
new_point *= 2;
old_point *= 2;
Similarityf u;
TrackMode *mode = CurrentMode(); TrackMode *mode = CurrentMode();
Similarityf new_track = mode->Apply(new_point, u); mode->tb=this;
Similarityf old_track = mode->Apply(old_point, u);
delete mode;
Invert(old_track); Point3f new_point = Point3f(float(x), float(y), 0);
new_track = old_track * new_track; Point3f old_point = Point3f(float(last_x), float(last_y), 0);
Similarityf diff=mode->ComputeFromWindow(old_point,new_point);
Similarityf diff;
switch(current_action.system) {
case VIEW:
u = last_view * Similarityf((-local.tra) * Similarityf(last_track.rot)) * Similarityf(-last_track.tra);
diff = Inverse(u) * new_track * u;
break;
default: break;
}
track = diff * last_track;
track = last_track*diff;
} }
void Trackball::MouseUp(int /* x */, int /* y */, Trackball::Button button) { void Trackball::MouseUp(int /* x */, int /* y */, Trackball::Button button) {
@ -240,24 +325,24 @@ TrackMode *Trackball::CurrentMode() {
} }
return mode; return mode;
} }
//return center of trackball in Screen coordinates. ////return center of trackball in Window coordinates.
Point3f Trackball::ScreenOrigin() { //Point3f Trackball::ScreenOrigin() {
return camera.Project(ModelOrigin()); // return camera.Project(ModelOrigin());
} //}
//return center of trackball in Model coordinates //return center of trackball in Model coordinates
Point3f Trackball::ModelOrigin() { Point3f Trackball::ModelOrigin() {
Similarityf m = local * last_track; return center;
return Point3f(0, 0, 0) * m;
} }
Matrix44f Trackball::ScreenToModel() { //Matrix44f Trackball::ScreenToModel() {
return camera.inverse; // return camera.inverse;
} //}
//
Similarityf Trackball::ModelToLocal() { //Similarityf Trackball::ModelToLocal() {
Similarityf m = local * last_track; // Similarityf m = local * last_track;
return m; // return m;
} //}

View File

@ -2,7 +2,8 @@
* VCGLib o o * * VCGLib o o *
* Visual and Computer Graphics Library o o * * Visual and Computer Graphics Library o o *
* _ O _ * * _ O _ *
* Copyright(C) 2004 \/)\/ * * Copyright(C) 2004
\/)\/ *
* Visual Computing Lab /\/| * * Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | * * ISTI - Italian National Research Council | *
* \ * * \ *
@ -24,6 +25,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.3 2004/04/07 10:54:10 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.2 2004/03/25 14:55:25 ponchio Revision 1.2 2004/03/25 14:55:25 ponchio
Adding copyright. Adding copyright.
@ -40,16 +44,27 @@ Adding copyright.
#include <map> #include <map>
namespace vcg { namespace vcg {
/* A trackball stores two transformations
the first one, local, is the one 'placing' the trackball somewhere,
the second one, track, is the one that effectively rotate the object.
The 'local' transformation is the one that contains information about
the rotation center, the size and the orientation of the trackball.
the 'track' is the one implementing the effective transformation.
*/
class Transform { class Transform {
public: public:
Transform(); Transform();
Similarityf track; Similarityf track;
Similarityf local;
Point3f center; // la posizione della trackball nello spazio di modello. il defgault e' 000
float radius; /// size of the widget in spazio di modello.
//Quaternion orientation;
}; };
Transform interpolate(const Transform &a, const Transform &b, float t); Transform interpolate(const Transform &a, const Transform &b, float t);
class TrackMode;
class Trackball: public Transform { class Trackball: public Transform {
public: public:
enum Button { BUTTON_NONE = 0x0000, enum Button { BUTTON_NONE = 0x0000,
@ -64,8 +79,10 @@ public:
Trackball(); Trackball();
void SetIdentity(); void SetIdentity();
void SetPosition(const Similarityf &local, int millisec = 0); void SetPosition(const Point3f &c, int millisec = 0);
void SetScale(const float s) {radius=s;};
void SetTransform(const Transform &transform, int miilisec = 0); void SetTransform(const Transform &transform, int miilisec = 0);
// float ScreenScale();
//operating //operating
void GetView(); void GetView();
@ -73,6 +90,12 @@ public:
void Draw(); void Draw();
void Reset(); void Reset();
// Internal Drawing stuff
void DrawCircle ();
void DrawPlane();
void DrawPlaneHandle();
//interface //interface
void MouseDown(int x, int y, Button button); void MouseDown(int x, int y, Button button);
void MouseMove(int x, int y); void MouseMove(int x, int y);
@ -120,10 +143,13 @@ public:
///Find the current action ussing the current button ///Find the current action ussing the current button
void SetCurrentAction(); void SetCurrentAction();
protected: //protected:
View<float> camera; View<float> camera;
Similarityf view; //Rotate LOCAL coordinate into VIEW coordinates Similarityf view; //Rotate LOCAL coordinate into VIEW coordinates
float ScreenRadius;
Point3f ScreenCenter;
int current_button; int current_button;
Action current_action; Action current_action;
@ -144,7 +170,7 @@ protected:
int history_size; int history_size;
Point3f ScreenOrigin(); //center of trackball in Screen coord //Point3f ScreenOrigin(); //center of trackball in Screen coord
Point3f ModelOrigin(); //center of trackball in Model coord Point3f ModelOrigin(); //center of trackball in Model coord
Matrix44f ScreenToModel(); //forse non serve..... Matrix44f ScreenToModel(); //forse non serve.....

View File

@ -24,81 +24,116 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.3 2004/04/07 10:54:11 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.2 2004/03/25 14:55:25 ponchio Revision 1.2 2004/03/25 14:55:25 ponchio
Adding copyright. Adding copyright.
****************************************************************************/ ****************************************************************************/
#include "trackmode.h" #include <vcg/space/point2.h>
#include <vcg/space/point3.h> #include <vcg/space/point3.h>
#include <vcg/space/plane3.h>
#include <vcg/space/intersection3.h>
#include "trackmode.h"
#include <vcg/math/similarity.h> #include <vcg/math/similarity.h>
using namespace vcg; using namespace vcg;
Similarityf SphereMode::Apply(const Point3f &p, const Similarityf & /* m */) {
float u = p[0];
float w = p[1];
float thr = 1/math::Sqrt(2.0f); //in the plane x-y distance from origin, above this use hyperboloid
float dist = math::Sqrt(u * u + w * w);
Point3f result;
if(dist < thr) { // First case: The ray is nearer to the sphere than r/sqrt(2) /*
float z = math::Sqrt(1 - u * u - w* w); Le varie Apply prendono una coppia di punti in screen space e restituiscono una trasformazione
result = Point3f(u, w, z); */
} else { // Second case: The ray should hit the 1/d hyperboloid
float a = thr; Plane3f SphereMode::GetViewPlane()
result = Point3f(u, w, -a*(u*u + w * w) + 3*a/2); {
result.Normalize(); Point3f mo=tb->ModelOrigin();
Point3f vp; vp.Import(tb->camera.ViewPoint());
Plane3f pl; // plane perpedicular to view direction and passing through manip center
pl.Set(vp-tb->center, (vp-tb->center)*tb->center);
return pl;
} }
if(result == Point3f(0, 0, 1))
/* dato un punto in coordinate di schermo e.g. in pixel stile opengl
restituisce un punto in coordinate di mondo sulla superficie della trackball
La superficie della trackball e' data da una sfera + una porzione di iperboloide di rotazione
assumiamo la sfera di raggio unitario e centrata sull'origine e di guardare lungo la y negativa.
X 0 sqrt(1/2) 1
eq sfera: y=sqrt(1-x*x); 1 sqrt(1/2) 0
eq iperboloide : y=1/2x; inf sqrt(1/2) 1/2
*/
Point3f SphereMode::Hit(const Point3f &p)
{
printf("Hit in screen space at %5.3f %5.3f %5.3f\n",p[0],p[1],p[2]);
Plane3f vp=GetViewPlane(); // plane perpedicular to view direction and passing through manip center
Line3fN ln= tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0));
//Point3f P0,P1;
Point3f PonVP;
bool res=Intersection<float>(vp,ln,PonVP);
const float Thr=tb->radius/math::Sqrt(2.0f);
Point3f HitPoint;
float dd=Distance(tb->center,PonVP);
if(dd<Thr)
{ // First case: We hit the sphere so, we must set the z accordingly
float hh=math::Sqrt(tb->radius*tb->radius - dd*dd);
HitPoint=PonVP+ln.Direction()*hh;
printf("Hit the sphere point on plane is %5.3f %5.3f %5.3f\n",PonVP[0],PonVP[1],PonVP[2]);
printf(" Distance from center is %5.3f \n",dd);
printf(" Heigth for view plane should be %5.3f \n",hh );
}
else
{ // Second Case we hit the hyperboloid
float hh=tb->radius/(2.0f*(dd/tb->radius));
HitPoint=PonVP+ln.Direction()*hh;
printf("Hit the hiperboloid at %5.3f %5.3f %5.3f\n",PonVP[0],PonVP[1],PonVP[2]);
printf(" Distance from center is %5.3f \n",dd);
printf(" Heigth for view plane should be %5.3f \n",hh );
}
return HitPoint;
}
/*
Nella trackball classica si considera
*/
Similarityf PlaneMode::ComputeFromWindow(const Point3f &oldP, const Point3f &newP)
{
return Similarityf().SetIdentity();
}
/*
Restituisce la trasformazione originata dal drag in window coord da oldp a newp.
*/
Similarityf SphereMode::ComputeFromWindow(const Point3f &oldP, const Point3f &newP)
{
Point3f hitOld=Hit(oldP);
Point3f hitNew=Hit(newP);
// Now compute the rotation defined on the sphere...
Point3f norm;
return Similarityf().SetIdentity(); return Similarityf().SetIdentity();
Point3f axis = Point3f(0, 0, 1)^result; /* Axis of rotation */ //Point3f axis = Point3f(0, 0, 1)^result; /* Axis of rotation */
axis.Normalize(); //axis.Normalize();
Point3f d = result - Point3f(0, 0, 1); //Point3f d = result - Point3f(0, 0, 1);
float t = d.Norm() / 2.0f; //float t = d.Norm() / 2.0f;
if(t > thr) //if(t > thr)
t += (t - thr) * 0.7f; // t += (t - thr) * 0.7f;
if (t > 1.0f) t = 1.0f; //if (t > 1.0f) t = 1.0f;
if (t < -1.0f) t = -1.0f; //if (t < -1.0f) t = -1.0f;
float phi = 2 * math::Asin(t); // float phi = 2 * math::Asin(t);
//return Similarityf().SetRotate(phi * 180/(float)M_PI, axis); ////return Similarityf().SetRotate(phi * 180/(float)M_PI, axis);
return Similarityf().SetRotate(phi, axis); // return Similarityf().SetRotate(phi, axis);
}
Similarityf PlaneMode::Apply(const Point3f &p, const Similarityf &a) {
return Similarityf(Point3f(p[0], p[1], 0));
Point3f r = x * a;
Point3f u = y * a;
int leading = 0; //leadiing x.
if(fabs(u[2]) < fabs(r[2])) //sceglie l'asse principale: quello che piu' e' parallelo al piano di vista.
leading = 1;
r[2] = 0;
u[2] = 0;
if(r == Point3f(0,0,0)) //casi degeneri: un asse e' perpendicolare al piano di vista.
r = Point3f(0, 1, 0);
if(u == Point3f(0,0,0))
u = Point3f(0, 1, 0);
r.Normalize();
u.Normalize();
float cu, cr;
if(leading == 0) { //leading x
if(u == r || u == -r) { //caso degenere: i due assi si proiettano sullo stesso
u[0] = -r[1];
u[1] = r[0];
}
u = u - r * (r * u);
u.Normalize();
} else {
if(r == u || r == -u) { //caso degenere: i due assi si proiettano sullo stesso
r[0] = -u[1];
r[1] = u[0];
}
r = r - u * (u * r);
r.Normalize();
}
cr = r * p;
cu = u * p;
return Similarityf(x * cr + y * cu);
} }

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.3 2004/04/07 10:54:11 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.2 2004/03/25 14:55:25 ponchio Revision 1.2 2004/03/25 14:55:25 ponchio
Adding copyright. Adding copyright.
@ -35,19 +38,28 @@ Adding copyright.
#include <vcg/space/point3.h> #include <vcg/space/point3.h>
#include <vcg/math/similarity.h> #include <vcg/math/similarity.h>
#include <wrap/gui/trackball.h>
namespace vcg { namespace vcg {
class Trackball;
class TrackMode { class TrackMode {
public: public:
virtual ~TrackMode() {} virtual ~TrackMode() {}
virtual void Draw() {} //virtual void Draw() {}
virtual Similarityf Apply(const Point3f &/* p */, const Similarityf &/*a*/) { return Similarityf().SetIdentity(); } virtual Similarityf ComputeFromWindow(const Point3f &/* oldp */, const Point3f &/* newp */) { return Similarityf().SetIdentity(); }
Point3f Hit(const Point3f &p);
Trackball *tb;
}; };
class SphereMode: public TrackMode { class SphereMode: public TrackMode {
public: public:
Similarityf Apply(const Point3f &p, const Similarityf &/*a*/); Similarityf ComputeFromWindow(const Point3f &oldP, const Point3f &newP);
//Plane3f SetViewPlane();
Point3f Hit(const Point3f &p);
Plane3f GetViewPlane();
// Line3f GetViewLine(const Point3f &p);
}; };
class GravityMode: public TrackMode { class GravityMode: public TrackMode {
@ -64,7 +76,7 @@ protected:
class PlaneMode: public TrackMode { class PlaneMode: public TrackMode {
public: public:
PlaneMode(const Point3f _x, const Point3f _y): x(_x), y(_y) { x.Normalize(); y.Normalize(); } PlaneMode(const Point3f _x, const Point3f _y): x(_x), y(_y) { x.Normalize(); y.Normalize(); }
Similarityf Apply(const Point3f &p, const Similarityf &a); Similarityf ComputeFromWindow(const Point3f &oldP, const Point3f &newP);
protected: protected:
Point3f x; Point3f x;
Point3f y; Point3f y;

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.4 2004/04/07 10:54:11 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.3 2004/03/31 15:07:37 ponchio Revision 1.3 2004/03/31 15:07:37 ponchio
CAMERA_H -> VCG_CAMERA_H CAMERA_H -> VCG_CAMERA_H
@ -36,13 +39,24 @@ Adding copyright.
#ifndef VCG_CAMERA_H #ifndef VCG_CAMERA_H
#define VCG_CAMERA_H #define VCG_CAMERA_H
#include <vcg/space/point3.h> /**********************
#include <vcg/math/Matrix44.h> WARNING
Everything here assumes the opengl window coord system.
the 0,0 is bottom left
y is upward!
**********************/
#include <windows.h> #include <vcg/space/point3.h>
#include <GL/GL.h> #include <vcg/space/plane3.h>
#include <vcg/space/line3.h>
#include <vcg/math/matrix44.h>
namespace vcg { namespace vcg {
/**
This class represent the viewing parameters under opengl.
Mainly it stores the projection and modelview matrix and the viewport
and it is used to simply project back and forth points, computing line of sight, planes etc.
*/
template <class T> class View { template <class T> class View {
public: public:
@ -51,10 +65,18 @@ public:
Point3<T> Project(const Point3<T> &p) const; Point3<T> Project(const Point3<T> &p) const;
Point3<T> UnProject(const Point3<T> &p) const; Point3<T> UnProject(const Point3<T> &p) const;
Point3<T> ViewPoint(); Point3<T> ViewPoint();
//convert coordinates range 0-1 to range 0 viewport[2]
Point3<T> ScreenToViewport(const Point3<T> &p) const; /// Return the plane perpendicular to the view axis and passing through point P.
//viceversa Plane3<T> ViewPlaneFromModel(const Point3<T> &p);
Point3<T> ViewportToScreen(const Point3<T> &p) const;
/// Return the line passing through the point p and the observer.
Line3<T> ViewLineFromWindow(const Point3<T> &p);
/// Convert coordinates from the range -1..1 of Normalized Device Coords to range 0 viewport[2]
Point3<T> NormDevCoordToWindowCoord(const Point3<T> &p) const;
/// Convert coordinates from 0--viewport[2] to the range -1..1 of Normalized Device Coords to
Point3<T> WindowCoordToNormDevCoord(const Point3<T> &p) const;
Matrix44<T> proj; Matrix44<T> proj;
Matrix44<T> model; Matrix44<T> model;
@ -65,14 +87,14 @@ public:
template <class T> void View<T>::GetView() { template <class T> void View<T>::GetView() {
double m[16]; double m[16];
glGetDoublev(GL_PROJECTION_MATRIX, m); glGetDoublev(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, m);
proj.Import(Matrix44d(m)); proj.Import(Matrix44d(m));
glGetDoublev(GL_MODELVIEW_MATRIX, m); glGetDoublev(GL_TRANSPOSE_MODELVIEW_MATRIX_ARB, m);
model.Import(Matrix44d(m)); model.Import(Matrix44d(m));
glGetIntegerv(GL_VIEWPORT, viewport); glGetIntegerv(GL_VIEWPORT, viewport);
matrix = model * proj; matrix = proj*model;
inverse = matrix; inverse = matrix;
Invert(inverse); Invert(inverse);
} }
@ -82,56 +104,65 @@ template <class T> void View<T>::SetView() {
} }
template <class T> Point3<T> View<T>::ViewPoint() { template <class T> Point3<T> View<T>::ViewPoint() {
return inverse * Point3<T>(0, 0, 0); Matrix44<T> mi=model;
/*Matrix44d model(model_matrix); Invert(mi);
model.Invert(); return mi* Point3<T>(0, 0, 0);
Point3d view = model * Point3d(0, 0, 0); }
return Point3<T>(view[0], view[1], view[2]); */ // Note that p it is assumed to be in model coordinate.
template <class T> Plane3<T> View<T>::ViewPlaneFromModel(const Point3<T> &p)
{
Point3<T> vp=ViewPoint();
Plane3<T> pl; // plane perpedicular to view direction and passing through manip center
pl.n=(vp-p);
pl.d=pl.n*p;
return pl;
}
// Note that p it is assumed to be in window coordinate.
template <class T> Line3<T> View<T>::ViewLineFromWindow(const Point3<T> &p)
{
Point3<T> vp=ViewPoint();
Line3<T> ln; // plane perpedicular to view direction and passing through manip center
/*Matrix44<T> mi=model;
Invert(mi);
*/Point3f pp=UnProject(p);
ln.SetOrigin(vp);
ln.SetDirection(pp-vp);
return ln;
} }
template <class T> Point3<T> View<T>::Project(const Point3<T> &p) const { template <class T> Point3<T> View<T>::Project(const Point3<T> &p) const {
Point3<T> r; Point3<T> r;
r = p * matrix; r = matrix * p;
r[0] = (r[0]+1)*(viewport[2]/(T)2.0)+viewport[0]; return NormDevCoordToWindowCoord(r);
r[1] =(r[1]+1)*(viewport[3]/(T)2.0)+viewport[1];
r[1] = viewport[3]-r[1];
return r;
/*double r[3];
gluProject(p[0], p[1], p[2], model_matrix, proj_matrix, viewport, &r[0], &r[1], &r[2]);
return Point3<T>((T)r[0], (T)r[1], (T)r[2]);*/
} }
template <class T> Point3<T> View<T>::UnProject(const Point3<T> &p) const { template <class T> Point3<T> View<T>::UnProject(const Point3<T> &p) const {
Point3<T> s = p; Point3<T> s = WindowCoordToNormDevCoord(p);
s[0] = (p[0]- viewport[0])/ (viewport[2]/(T)2.0) - 1; s = inverse * s ;
s[1] = (p[1]- viewport[1])/ (viewport[3]/(T)2.0) - 1;
s[1] = -s[1];
s[2] = p[2];
//s[1] = -s[1]; // pezza aggiunta per il tan2.... ?????????????
s = s * inverse;
return s; return s;
/*double r[3];
gluUnProject(p[0], p[1], p[2], model_matrix, proj_matrix, viewport, &r[0], &r[1], &r[2]);
return Point3<T>((T)r[0], (T)r[1], (T)r[2]);*/
} }
template <class T> Point3<T> View<T>::ScreenToViewport(const Point3<T> &p) const { // Come spiegato nelle glspec
// dopo la perspective division le coordinate sono dette normalized device coords ( NDC ).
// Per passare alle window coords si deve fare la viewport transformation.
// Le coordinate di viewport stanno tra -1 e 1
template <class T> Point3<T> View<T>::NormDevCoordToWindowCoord(const Point3<T> &p) const {
Point3<T> a; Point3<T> a;
a[0] = (p[0]+1)*(viewport[2]/(T)2.0)+viewport[0]; a[0] = (p[0]+1)*(viewport[2]/(T)2.0)+viewport[0];
a[1] = (p[1]+1)*(viewport[3]/(T)2.0)+viewport[1]; a[1] = (p[1]+1)*(viewport[3]/(T)2.0)+viewport[1];
a[1] = viewport[3] - a[1]; //a[1] = viewport[3] - a[1];
a[2] = p[2]; a[2] = p[2];
return a; return a;
} }
//viceversa
template <class T> Point3<T> View<T>::ViewportToScreen(const Point3<T> &p) const {
template <class T> Point3<T> View<T>::WindowCoordToNormDevCoord(const Point3<T> &p) const {
Point3<T> a; Point3<T> a;
a[0] = (p[0]- viewport[0])/ (viewport[2]/(T)2.0) - 1; a[0] = (p[0]- viewport[0])/ (viewport[2]/(T)2.0) - 1;
a[1] = (p[1]- viewport[1])/ (viewport[3]/(T)2.0) - 1; a[1] = (p[1]- viewport[1])/ (viewport[3]/(T)2.0) - 1;
a[1] = -a[1]; //a[1] = -a[1];
a[2] = p[2]; a[2] = p[2];
//a[1] = -a[1]; // pezza aggiunta per il tan2.... ?????????????
return a; return a;
} }