vcglib/wrap/gui/trackmode.cpp

104 lines
4.1 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.2 2004/03/25 14:55:25 ponchio
Adding copyright.
****************************************************************************/
#include "trackmode.h"
#include <vcg/space/point3.h>
#include <vcg/math/similarity.h>
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);
result = Point3f(u, w, z);
} else { // Second case: The ray should hit the 1/d hyperboloid
float a = thr;
result = Point3f(u, w, -a*(u*u + w * w) + 3*a/2);
result.Normalize();
}
if(result == Point3f(0, 0, 1))
return Similarityf().SetIdentity();
Point3f axis = Point3f(0, 0, 1)^result; /* Axis of rotation */
axis.Normalize();
Point3f d = result - Point3f(0, 0, 1);
float t = d.Norm() / 2.0f;
if(t > thr)
t += (t - thr) * 0.7f;
if (t > 1.0f) t = 1.0f;
if (t < -1.0f) t = -1.0f;
float phi = 2 * math::Asin(t);
//return Similarityf().SetRotate(phi * 180/(float)M_PI, 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);
}