vcglib/wrap/gui/trackmode.cpp

150 lines
5.5 KiB
C++

/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program 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. *
* *
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.4 2004/05/07 12:46:08 cignoni
Restructured and adapted in a better way to opengl
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
Adding copyright.
****************************************************************************/
#include <wrap/gui/trackmode.h>
#include <wrap/gui/trackball.h>
#include <vcg/space/intersection3.h>
#include <vcg/math/similarity.h>
#include <iostream>
using namespace std;
using namespace vcg;
Plane3f TrackMode::GetViewPlane(const View<float> &camera, Point3f center) {
Point3f vp = camera.ViewPoint();
Plane3f pl; //plane perpedicular to view dir and passing through manip center
pl.Set(vp - center, (vp - center)*center);
return pl;
}
Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) {
// plane perpedicular to view direction and passing through manip center
Plane3f vp = GetViewPlane(tb->camera, tb->center);
Line3fN ln= tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0));
Point3f PonVP;
bool res = Intersection<float>(vp,ln,PonVP);
return PonVP;
}
void SphereMode::Apply(Trackball *tb, Point3f new_point) {
Point3f hitOld=Hit(tb, tb->last_point);
Point3f hitNew=Hit(tb, new_point);
Point3f ref = (tb->camera.ViewPoint() - tb->center).Normalize();
Point3f axis = hitNew^ref;
axis.Normalize();
float dist = (hitNew - ref).Norm()/2;
float phi = 2 * math::Asin(dist);
Point3f oaxis = hitOld^ref;
oaxis.Normalize();
float odist = (hitOld - ref).Norm()/2;
float ophi = 2 * math::Asin(odist);
Quaternionf r = tb->last_track.rot;
Quaternionf diff = r * Quaternionf(phi, axis) *
Quaternionf(-ophi, oaxis) * Inverse(r);
tb->track = Similarityf().SetRotate(diff) * tb->last_track;
}
/* 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
eq cono y=x+sqrt(2);
*/
Point3f SphereMode::Hit(Trackball *tb, const Point3f &p) {
const float Thr = tb->radius/math::Sqrt(2.0f);
Line3fN vn = tb->camera.ViewLineFromModel(tb->center);
Line3fN ln = tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0));
Point3f viewpoint = tb->camera.ViewPoint();
Plane3f vp = GetViewPlane(tb->camera, tb->center);
vp.SetOffset(vp.Offset() + Thr);
Point3f hit;
bool res = Intersection<float>(vp, ln, hit);
float d = Distance(tb->center - vn.Direction()*Thr, hit);
if(d < Thr) {
Point3f hit2;
Sphere3f sphere(tb->center, tb->radius);
bool res = Intersection<float>(sphere, ln, hit, hit2);
//find closest intersection to sphere
float d = (hit - viewpoint).Norm();
float d2 = (hit2 - viewpoint).Norm();
if(d > d2) hit = hit2;
hit -= tb->center;
} else {
if(d > 2.99 * Thr)
d = 2.99 * Thr;
Point3f norm = (hit - tb->center)^(viewpoint - tb->center);
norm.Normalize();
float phi = -M_PI/4 - 3*M_PI/8 *(d - Thr)/Thr;
Quaternionf q(phi, norm);
hit = q.Rotate((viewpoint - tb->center).Normalize() * tb->radius);
}
hit.Normalize();
return hit;
}
void PlaneMode::Apply(Trackball *tb, Point3f new_point) {
Point3f hitOld=HitViewPlane(tb, tb->last_point);
Point3f hitNew=HitViewPlane(tb, new_point);
}