vcglib/wrap/gui/trackutils.h

848 lines
25 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 2007/05/28 08:10:47 fiorin
Removed type cast warnings
Revision 1.1 2007/05/15 14:57:34 benedetti
Utility functions for the trackmodes, first version
****************************************************************************/
#ifndef TRACKUTILS_H
#define TRACKUTILS_H
#include <assert.h>
#include <vcg/math/base.h>
#include <vcg/math/similarity.h>
#include <vcg/space/intersection3.h>
#include <vcg/space/line3.h>
#include <vcg/space/plane3.h>
#include <wrap/gl/math.h>
#include <wrap/gl/space.h>
#include <vector>
using namespace std;
namespace vcg {
namespace trackutils {
/// Compute the plane perpedicular to view dir and passing through manip center
Plane3f GetViewPlane (const View < float >&camera, const Point3f & center)
{
Point3f vp = camera.ViewPoint ();
Plane3f pl;
Point3f plnorm = vp - center;
plnorm.Normalize ();
pl.Set (plnorm, plnorm * center);
return pl;
}
Ray3f line2ray(const Line3f &l){
Ray3f r(l.Origin(),l.Direction());
r.Normalize();
return r;
}
// Given a point p in window coordinate it compute the point where the lie p
// over the plane paralell the viewplane and passing through the center of the trackball
Point3f 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 = */ IntersectionLinePlane < float >(vp, ln, PonVP);
return PonVP;
}
/*
dato un punto in coordinate di schermo e.g. in pixel stile opengl
calcola il punto di intersezione tra la viewline che passa per viewpoint e per hitplane e l'iperboloide.
l'iperboloide si assume essere quello di rotazione attorno alla retta viewpoint-center e di raggio rad
si assume come sistema di riferimento quello con l'origine su center ecome x la retta center-viewpoint
eq linea
hitplane.y
y = - ----------- * x + hitplane.y
viewpoint.x
eq hiperboloide di raggio r (e.g. che passa per (r/sqrt2,r/sqrt2)
1
y = --- * (r^2 /2.0)
x
hitplane.y
----------- * x^2 - hitplane.y *x + (r^2/2.0) == 0
viewpoint.x
*/
bool HitHyper (Point3f center, float radius, Point3f viewpoint, Plane3f vp,
Point3f hitplane, Point3f & hit)
{
float hitplaney = Distance (center, hitplane);
float viewpointx = Distance (center, viewpoint);
float a = hitplaney / viewpointx;
float b = -hitplaney;
float c = radius * radius / 2.0f;
float delta = b * b - 4 * a * c;
float x1, x2, xval, yval;
if (delta > 0) {
x1 = (-b - sqrt (delta)) / (2.0f * a);
x2 = (-b + sqrt (delta)) / (2.0f * a);
xval = x1; // always take the minimum value solution
yval = c / xval; // alternatively it also could be the other part of the equation yval=-(hitplaney/viewpointx)*xval+hitplaney;
}
else {
return false;
}
// Computing the result in 3d space;
Point3f dirRadial = hitplane - center;
dirRadial.Normalize ();
Point3f dirView = vp.Direction ();
dirView.Normalize ();
hit = center + dirRadial * yval + dirView * xval;
return true;
}
/* 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/2*x; inf sqrt(1/2) 1/2
eq cono y=x+sqrt(2);
*/
Point3f HitSphere (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);
Point3f hit, hitPlane, hitSphere, hitSphere1, hitSphere2, hitHyper;
IntersectionLinePlane < float >(vp, ln, hitPlane);
Sphere3f sphere (tb->center, tb->radius);
bool resSp = IntersectionLineSphere < float >(sphere, ln, hitSphere1, hitSphere2);
if (resSp == true) {
if (Distance (viewpoint, hitSphere1) < Distance (viewpoint, hitSphere2))
hitSphere = hitSphere1;
else
hitSphere = hitSphere2;
}
/*float dl= */ Distance (ln, tb->center);
bool resHp = HitHyper (tb->center, tb->radius, viewpoint, vp, hitPlane, hitHyper);
// four cases
// 1) Degenerate line tangent to both sphere and hyperboloid!
if ((!resSp && !resHp)) {
hit = ClosestPoint (ln, tb->center);
//printf("closest point to line %f\n",Distance(hit,tb->center));
return hit;
}
if ((resSp && !resHp))
return hitSphere; // 2) line cross only the sphere
if ((!resSp && resHp))
return hitHyper; // 3) line cross only the hyperboloid
// 4) line cross both sphere and hyperboloid: choose according angle.
float angleDeg = math::ToDeg (Angle ((viewpoint - tb->center), (hitSphere - tb->center)));
//printf("Angle %f (%5.2f %5.2f %5.2f) (%5.2f %5.2f %5.2f)\n",angleDeg,hitSphere[0],hitSphere[1],hitSphere[2],hitHyper[0],hitHyper[1],hitHyper[2]);
if (angleDeg < 45)
return hitSphere;
else
return hitHyper;
// Codice ORIGINALE PONCHIO
//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;
}
/*
calculates the minimal distance between 2 lines.
P and Q are the lines, P_s and Q_t are set to be the closest points on these lines.
it's returned the distance from P_s and Q_t, and a boolean value which is true
if the lines are parallel enough.
if P and Q are parallel P_s and Q_t aren't set.
the formula is taken from pages 81-83 of
"Eric Lengyel - Mathematics for 3D Game Programming & Computer Graphics"
*/
pair< float, bool > LineLineDistance(const Line3f & P,const Line3f & Q,Point3f & P_s, Point3f & Q_t){
Point3f p0 = P.Origin (), Vp = P.Direction ();
Point3f q0 = Q.Origin (), Vq = Q.Direction ();
float VPVP = Vp * Vp;
float VQVQ = Vq * Vq;
float VPVQ = Vp * Vq;
const float det = ( VPVP * VQVQ ) - ( VPVQ * VPVQ );
const float EPSILON = 0.00001f;
if ( fabs(det) < EPSILON ) {
return make_pair(Distance(P,q0), true);
}
float b1= (q0 - p0) * Vp;
float b2= (p0 - q0) * Vq;
float s = ( (VQVQ * b1) + (VPVQ * b2) ) / det;
float t = ( (VPVQ * b1) + (VPVP * b2) ) / det;
P_s = p0 + (Vp * s);
Q_t = q0 + (Vq * t);
return make_pair(Distance(P_s,Q_t),false);
}
/*
calculates the minimal distance between a ray and a line
R is the ray and Q is the line, R_s and Q_t are set to be the closest points on
the ray and the line.
it's returned the distance from R_s and Q_t, and a boolean value which is true
if the ray and the line are parallel enough.
if R and Q are parallel R_s and Q_t aren't set.
*/
pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3f & R_s, Point3f & Q_t){
Point3f r0 = R.Origin (), Vr = R.Direction ();
Point3f q0 = Q.Origin (), Vq = Q.Direction ();
float VRVR = Vr * Vr;
float VQVQ = Vq * Vq;
float VRVQ = Vr * Vq;
const float det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ );
const float EPSILON = 0.00001f;
if ( ( det >= 0.0f ? det : -det) < EPSILON ) {
return make_pair(Distance(Q,r0), true);
}
float b1= (q0 - r0) * Vr;
float b2= (r0 - q0) * Vq;
float s = ( (VQVQ * b1) + (VRVQ * b2) ) / det;
float t = ( (VRVQ * b1) + (VRVR * b2) ) / det;
if(s<0){
R_s = r0;
Q_t = ClosestPoint(Q,R_s);
}else {
R_s = r0 + (Vr * s);
Q_t = q0 + (Vq * t);
}
return make_pair(Distance(R_s,Q_t),false);
}
/*
calculates the minimal distance between 2 segments
R e Q are the segments, R_s and Q_t are set to be the closest points on
the segments
it's returned the distance from R_s and Q_t, and a boolean value which is true
if the segments are parallel enough.
*/
pair< float, bool > SegmentSegmentDistance(const Segment3f & R, const Segment3f & Q, Point3f & R_s, Point3f & Q_t)
{
float R_len=Distance(R.P0(),R.P1());
float Q_len=Distance(Q.P0(),Q.P1());
const float EPSILON_LENGTH = max(R_len,Q_len)*0.0001f;
if(R_len < EPSILON_LENGTH){
R_s=R.P0();
Q_t=ClosestPoint(Q,R_s);
return make_pair(Distance(R_s,Q_t),true);
}
if( Q_len < EPSILON_LENGTH){
Q_t=Q.P0();
R_s=ClosestPoint(R,Q_t);
return make_pair(Distance(R_s,Q_t),true);
}
Point3f r0 = R.P0(), Vr = (R.P1()-R.P0()).Normalize();
Point3f q0 = Q.P0(), Vq = (Q.P1()-Q.P0()).Normalize();
float VRVR = Vr * Vr;
float VQVQ = Vq * Vq;
float VRVQ = Vr * Vq;
const float det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ );
const float EPSILON = 0.00001f;
if ( ( det >= 0.0f ? det : -det) < EPSILON ) {
Line3f lR(R.P0(),R.P1());
float qa=lR.Projection(Q.P0());
float qb=lR.Projection(Q.P1());
if( (qa<=0.0f) && qb<=(0.0f)){
R_s=R.P0();
Q_t=ClosestPoint(Q,R_s);
} else if ( (qa >= 1.0f) && (qb >= 1.0f) ){
R_s=R.P1();
Q_t=ClosestPoint(Q,R_s);
} else {
if( (qa >= 0.0f) && (qa <= 1.0f) ){
Q_t=Q.P0();
R_s=ClosestPoint(R,Q_t);
} else if((qb >= 0.0f) && (qb <= 1.0f) ){
Q_t=Q.P1();
R_s=ClosestPoint(R,Q_t);
} else {
if( ((qa<=0.0f)&&(qb>=1.0f) ||((qb<=0.0f)&&(qa>=1.0f)))){
R_s=R.P0();
Q_t=ClosestPoint(Q,R_s);
}else{
assert(0);
}
}
}
return make_pair(Distance(R_s,Q_t),true);
}
float b1= (q0 - r0) * Vr;
float b2= (r0 - q0) * Vq;
float s = ( (VQVQ * b1) + (VRVQ * b2) ) / det;
float t = ( (VRVQ * b1) + (VRVR * b2) ) / det;
if( s < 0 ){
R_s = R.P0();
}else if ( s > R_len ){
R_s = R.P1();
} else {
R_s = r0 + (Vr * s);
}
if( t < 0){
Q_t = Q.P0();
}else if ( t > Q_len ){
Q_t = Q.P1();
}else{
Q_t = q0 + (Vq * t);
}
return make_pair(Distance(R_s,Q_t),false);
}
pair< Point3f,bool > HitNearestPointOnAxis (Trackball * tb,Line3f axis, Point3f point)
{
Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (point));
Point3f axis_p(0,0,0), ray_p(0,0,0);
pair< float, bool > resp=RayLineDistance(ray,axis,ray_p,axis_p);
if(resp.second || (ray_p == ray.Origin())){
return make_pair(Point3f(0,0,0),false);
}
return make_pair(axis_p,true);
}
Line3f ProjectLineOnPlane(const Line3f & ln, const Plane3f & pl)
{
Point3f l0=ln.Origin();
Point3f l1=l0+ln.Direction();
Point3f p1,p2;
p1=pl.Projection(l0);
p2=pl.Projection(l1);
Line3f res(p1,p2-p1);
return res;
}
float signedDistance(Line3f line,Point3f pt,Point3f positive_dir)
{
return Distance(line,pt) * ((((pt-ClosestPoint(line,pt)) * positive_dir) >= 0.0f )? 1.0f: -1.0f);
}
float getDeltaY(Trackball * tb, Point3f new_point)
{
float ScreenHeight = float (tb->camera.viewport[3] - tb->camera.viewport[1]);
return (new_point[1] - tb->last_point[1]) / ScreenHeight;
}
/// intersection between RAY and plane
template<class T>
inline bool IntersectionRayPlane( const Plane3<T> & pl, const Ray3<T> & ray, Point3<T> &po){
const T epsilon = T(1e-8);
T k = pl.Direction() * ray.Direction(); // Compute 'k' factor
if( (k > -epsilon) && (k < epsilon))
return false;
T r = (pl.Offset() - pl.Direction()*ray.Origin())/k; // Compute ray distance
if (r < 0)
return false;
po = ray.Origin() + ray.Direction()*r;
return true;
}
pair< Point3f, bool > HitPlane (Trackball * tb, Point3f point, Plane3f plane)
{
Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (point));
Point3f p(0,0,0);
bool res = IntersectionRayPlane < float >(plane, ray, p);
return make_pair(p,res);
}
// drawing section
class DrawingHint {
public:
DrawingHint () {
CircleStep = 64;
HideStill = false;
DrawTrack = false;
LineWidthStill = 0.5f;
LineWidthMoving = 1.5f;
color = Color4b::LightBlue;
}
int CircleStep;
bool HideStill, DrawTrack;
Color4b color;
float LineWidthStill;
float LineWidthMoving;
};
DrawingHint DH;
void 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 DrawCircle ()
{
int nside = DH.CircleStep;
const double pi2 = 3.14159265 * 2.0;
glBegin (GL_LINE_LOOP);
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 DrawSphereIcon (Trackball * tb,bool active)
{
glPushMatrix ();
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glScale (tb->radius);
Matrix44f r;
tb->track.rot.ToMatrix (r);
glMultMatrix (r);
glPushMatrix ();
float amb[4] = { .3f, .3f, .3f, 1.0f };
float col[4] = { .5f, .5f, .8f, 1.0f };
glPushAttrib (GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
if (active)
glLineWidth (DH.LineWidthMoving);
else
glLineWidth (DH.LineWidthStill);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_LINE_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor (DH.color);
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 ();
glPopAttrib ();
glPopMatrix ();
glPopMatrix ();
}
// TEMPORARY drawing section
// Disclaimer: the following code is of VERY POOR quality
// feel free to delete and rewrite everything
void prepara_attrib()
{
float amb[4] = { .3f, .3f, .3f, 1.0f };
float col[4] = { .5f, .5f, .8f, 1.0f };
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_LINE_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, amb);
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col);
}
void DrawUglyLetter(Trackball * tb,vector<Point3f> ugly_letter)
{
Point3f center=tb->camera.Project(tb->center);
float offset=0;
offset=max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(1,0,0) * tb->radius))));
offset=max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,1,0) * tb->radius))));
offset=max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,0,1) * tb->radius))));
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
glColor3f(1,1,1);
glLineWidth(4.0);
glBegin(GL_LINE_STRIP);
for(unsigned int i=0;i<ugly_letter.size();i++){
glVertex(tb->camera.UnProject(center+(ugly_letter[i] * offset * 0.25)
+Point3f(-offset,-offset,0)));
}
glEnd();
glPopAttrib ();
glPopMatrix();
}
void DrawUglyPanMode(Trackball * tb)
{
vector<Point3f> ugly_p;
ugly_p.push_back(Point3f(-1,-1,0));
ugly_p.push_back(Point3f(-1,1,0));
ugly_p.push_back(Point3f(1,1,0));
ugly_p.push_back(Point3f(1,0,0));
ugly_p.push_back(Point3f(-1,0,0));
DrawUglyLetter(tb,ugly_p);
}
void DrawUglyZMode(Trackball * tb)
{
vector<Point3f> ugly_z;
ugly_z.push_back(Point3f(-1,1,0));
ugly_z.push_back(Point3f(1,1,0));
ugly_z.push_back(Point3f(-1,-1,0));
ugly_z.push_back(Point3f(1,-1,0));
DrawUglyLetter(tb,ugly_z);
}
void DrawUglyScaleMode(Trackball * tb)
{
vector<Point3f> ugly_s;
ugly_s.push_back(Point3f(1,1,0));
ugly_s.push_back(Point3f(-1,1,0));
ugly_s.push_back(Point3f(-1,0,0));
ugly_s.push_back(Point3f(1,0,0));
ugly_s.push_back(Point3f(1,-1,0));
ugly_s.push_back(Point3f(-1,-1,0));
DrawUglyLetter(tb,ugly_s);
}
void DrawUglyAxisMode(Trackball * tb,Line3f axis)
{
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
glColor3f(0.9f, 0.9f, 0.2f);
glLineWidth(2.0);
glBegin(GL_LINES);
glVertex(axis.Origin()+(axis.Direction()*100));
glVertex(axis.Origin()-(axis.Direction()*100));
glEnd();
glPointSize(8.0);
glColor3f(0.2f, 0.2f, 0.9f);
glBegin(GL_POINTS);
glVertex(axis.Origin());
glEnd();
glPopAttrib ();
glPopMatrix();
}
void DrawUglyPlaneMode(Trackball * tb,Plane3f plane)
{
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
Point3f p0,d1,d2,norm;
norm=plane.Direction();
p0=plane.Projection(Point3f(0,0,0));
d1=Point3f(0,1,0);
if(norm == d1 || norm == -d1)
d1 = Point3f(1,0,0);
d2=plane.Projection(d1);
d1=(d2 - p0).Normalize();
d2=(d1 ^ norm).Normalize();
glLineWidth(3.0);
glColor3f(0.2f, 0.2f, 0.9f);
glBegin(GL_LINES);
glVertex(p0);
glVertex(p0+norm);
glEnd();
glLineWidth(1.0);
for(float i=0.5f; i<100.0f; i+=0.7f){
glBegin(GL_LINE_LOOP);
for(int a=0;a<360;a+=10){
float f0=i*cosf((float(M_PI)*float(a))/180.0f);
float f1=i*sinf((float(M_PI)*float(a))/180.0f);
glVertex(p0+(d1*f0)+(d2*f1));
}
glEnd();
}
glColor3f(0.9f, 0.9f, 0.2f);
glPointSize(8.0f);
glBegin(GL_POINTS);
glVertex(p0);
glEnd();
glColor3f(0.7f, 0.7f, 0.0f);
glPointSize(6.0);
glBegin(GL_POINTS);
glVertex(p0+norm);
glEnd();
glPopAttrib ();
glPopMatrix();
}
void DrawUglyCylinderMode(Trackball * tb,Line3f axis)
{
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
Plane3f plane;
plane.Init(axis.Origin(),axis.Direction());
Point3f p0,d1,d2,norm;
norm=plane.Direction();
p0=plane.Projection(Point3f(0,0,0));
d1=Point3f(0,1,0);
if(norm == d1 || norm == -d1)
d1 = Point3f(1,0,0);
d2=plane.Projection(d1);
d1=(d2 - p0).Normalize();
d2=(d1 ^ norm).Normalize();
glLineWidth(1.0);
glColor3f(0.2f, 0.2f, 0.9f);
for(int i=-100;i<100;i++){
glBegin(GL_LINE_LOOP);
for(int a=0;a<360;a+=10){
float f0=(tb->radius)*cosf((float(M_PI)*float(a))/180.0f);
float f1=(tb->radius)*sinf((float(M_PI)*float(a))/180.0f);
glVertex(axis.Origin()+p0+(norm*float(i))+(d1*f0)+(d2*f1));
}
glEnd();
}
glLineWidth(3.0);
glColor3f(0.2f, 0.2f, 0.9f);
glBegin(GL_LINES);
glVertex(axis.Origin());
glVertex(axis.Origin()+(axis.Direction()*100));
glEnd();
glLineWidth(1.5);
glColor3f(0.9f, 0.2f, 0.9f);
glBegin(GL_LINES);
glVertex(axis.Origin());
glVertex(axis.Origin()-(axis.Direction()*100));
glEnd();
glColor3f(0.9f, 0.9f, 0.2f);
glPointSize(8.0);
glBegin(GL_POINTS);
glVertex(axis.Origin());
glEnd();
glPopAttrib ();
glPopMatrix();
}
void DrawUglyPathMode(Trackball * tb,const vector < Point3f > &points,
Point3f current_point,Point3f prev_point,
Point3f next_point,Point3f old_hitpoint,bool wrap)
{
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
glColor3f(0.9f, 0.9f, 0.2f);
glLineWidth(2.0);
if(wrap)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_LINE_STRIP);
for (vector < Point3f >::const_iterator i = points.begin (); i != points.end (); ++i){
glVertex(*i);
}
glEnd();
glColor3f(1,0,1);
glPointSize(8.0);
glBegin(GL_POINTS);
glVertex(current_point);
glEnd();
glColor3f(0.6f, 0.0f, 0.6f);
glPointSize(7.0);
glBegin(GL_POINTS);
glVertex(old_hitpoint);
glEnd();
glColor3f(0.7f, 0.7f, 0.7f);
glPointSize(6.5);
glBegin(GL_POINTS);
glVertex(prev_point);
glVertex(next_point);
glEnd();
glPopAttrib ();
glPopMatrix();
}
void DrawUglyAreaMode(Trackball * tb,const vector < Point3f > &points,
Point3f status,Point3f old_status,Plane3f plane,
const vector < Point3f > &path,Point3f rubberband_handle)
{
glPushMatrix();
glPushAttrib (GL_ALL_ATTRIB_BITS);
// go to world coords
glTranslate (tb->center);
glMultMatrix (tb->track.InverseMatrix ());
glTranslate (-tb->center);
prepara_attrib();
glColor3f(0.9f, 0.9f, 0.2f);
glLineWidth(2.0);
glBegin(GL_LINE_LOOP);
for (vector < Point3f >::const_iterator i = points.begin (); i != points.end (); ++i){
glVertex(*i);
}
glEnd();
glColor3f(0.0f, 0.9f, 0.2f);
glLineWidth(1.2f);
glBegin(GL_LINE_STRIP);
for (vector < Point3f >::const_iterator i = path.begin (); i != path.end (); ++i){
glVertex(*i);
}
glEnd();
glColor3f(1,0,1);
glPointSize(8.0);
glBegin(GL_POINTS);
glVertex(status);
glEnd();
glColor3f(0.6f, 0.0f, 0.6f);
glPointSize(7.0);
glBegin(GL_POINTS);
glVertex(old_status);
glEnd();
glColor3f(0.6f, 0.0f, 0.0f);
glPointSize(6.0);
glBegin(GL_POINTS);
glVertex(rubberband_handle);
glEnd();
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex(rubberband_handle);
glVertex(status);
glEnd();
Point3f p0,d1,d2,norm;
norm=plane.Direction();
p0=plane.Projection(Point3f(0,0,0));
d1=Point3f(0,1,0);
if(norm == d1 || norm == -d1)
d1 = Point3f(1,0,0);
d2=plane.Projection(d1);
d1=(d2 - p0).Normalize();
d2=(d1 ^ norm).Normalize();
glLineWidth(3.0);
glColor3f(0.2f, 0.2f, 0.9f);
glBegin(GL_LINES);
glVertex(p0);
glVertex(p0+norm);
glEnd();
glLineWidth(0.1f);
for(float i=0.5f;i<100.0f; i+=0.7f){
glBegin(GL_LINE_LOOP);
for(int a=0;a<360;a+=10){
float f0=i*cosf((float(M_PI)*float(a))/180.0f);
float f1=i*sinf((float(M_PI)*float(a))/180.0f);
glVertex(p0+(d1*f0)+(d2*f1));
}
glEnd();
}
glPopAttrib ();
glPopMatrix();
}
} //end namespace trackutils
} //end namespace vcg
#endif //TRACKUTILS_H