Main restructuring. added many new modes
This commit is contained in:
parent
9ed47e4afa
commit
db4c4f0944
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.19 2006/08/30 07:01:54 cignoni
|
||||
Reverted to version 1.17. Version 1.18 was wrongly done starting from a outdated version.
|
||||
|
||||
Revision 1.17 2006/07/26 13:54:45 cignoni
|
||||
Reversed the direction of wheel scaling and added middle mouse panning
|
||||
|
||||
|
@ -79,242 +82,617 @@ Adding copyright.
|
|||
|
||||
#include <wrap/gui/trackmode.h>
|
||||
#include <wrap/gui/trackball.h>
|
||||
#include <vcg/space/intersection3.h>
|
||||
#include <vcg/math/similarity.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <wrap/gui/trackutils.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
using namespace vcg::trackutils;
|
||||
|
||||
|
||||
void TrackMode::Apply(Trackball *trackball, float WheelNotch) {
|
||||
trackball->track.sca*=pow(1.2f,-WheelNotch);
|
||||
}
|
||||
|
||||
void ScaleMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
float ScreenHeight= float(tb->camera.viewport[3]-tb->camera.viewport[1]);
|
||||
float dist=(new_point[1]-tb->last_point[1])/ScreenHeight;
|
||||
tb->track.sca= tb->last_track.sca*pow(3.0f,-dist);
|
||||
}
|
||||
|
||||
/// Compute the plane plane perpedicular to view dir and passing through manip center
|
||||
Plane3f TrackMode::GetViewPlane(const View<float> &camera, const Point3f ¢er) {
|
||||
Point3f vp = camera.ViewPoint();
|
||||
|
||||
Plane3f pl;
|
||||
Point3f plnorm= vp - center;
|
||||
plnorm.Normalize();
|
||||
pl.Set(plnorm, plnorm*center);
|
||||
return pl;
|
||||
}
|
||||
|
||||
/// 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 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 = */IntersectionLinePlane<float>(vp,ln,PonVP);
|
||||
return PonVP;
|
||||
}
|
||||
|
||||
// the most important function; given a new point in window coord, it update the transformation computed by the trackball.
|
||||
// General scheme : the transformation is a function of just the begin and current mouse positions, with greater precision is function of just two 3d points over the manipulator.
|
||||
void SphereMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
Point3f hitOld=Hit(tb, tb->last_point);
|
||||
Point3f hitNew=Hit(tb, new_point);
|
||||
tb->Hits.push_back(hitNew);
|
||||
|
||||
// Point3f center = tb->track.tra+tb->center; // original 2006 01 12
|
||||
Point3f center = tb->center;
|
||||
Point3f axis = (hitNew - center)^(hitOld- center);
|
||||
|
||||
// Figure out how much to rotate around that axis.
|
||||
//float phi=Angle((hitNew- tb->center),(hitOld- tb->center));
|
||||
float phi = Distance(hitNew,hitOld) / tb->radius;
|
||||
|
||||
tb->track.rot = tb->last_track.rot * Quaternionf(phi,axis);
|
||||
/* Codice Originale Ponchio
|
||||
|
||||
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;*/
|
||||
|
||||
}
|
||||
|
||||
// the old implementation is not used anymore, some of the old support functions,
|
||||
// like HitViewPlane, GetViewPlane, HitHyper and SphereMode::Hit were made
|
||||
// class-independent and moved to trackutils.h
|
||||
/*
|
||||
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
|
||||
|
||||
*/
|
||||
void TrackMode::Apply(Trackball *trackball, float WheelNotch) {
|
||||
}
|
||||
void ScaleMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
}
|
||||
Plane3f TrackMode::GetViewPlane(const View<float> &camera, const Point3f ¢er) {
|
||||
}
|
||||
Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) {
|
||||
}
|
||||
void SphereMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
}
|
||||
bool SphereMode::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 oould 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 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);
|
||||
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;
|
||||
}
|
||||
|
||||
void PlaneMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
Point3f hitOld = HitViewPlane(tb, tb->last_point);
|
||||
Point3f hitNew = HitViewPlane(tb, new_point);
|
||||
//Matrix44f m; tb->track.rot.ToMatrix(m);
|
||||
//tb->track.tra = tb->last_track.tra + Inverse(m)*Point3f(hitNew- hitOld);// orig 2006 01 12
|
||||
//tb->track.tra = tb->last_track.tra + Inverse(m)*Point3f(hitNew- hitOld)/tb->track.sca;;
|
||||
tb->Translate(hitNew- hitOld);
|
||||
}
|
||||
|
||||
}
|
||||
void ZMode::Apply(Trackball *tb, Point3f new_point) {
|
||||
float ScreenHeight= float(tb->camera.viewport[3]-tb->camera.viewport[1]);
|
||||
float dist=(new_point[1]-tb->last_point[1])/ScreenHeight;
|
||||
//Matrix44f m; tb->track.rot.ToMatrix(m);
|
||||
//tb->track.tra = tb->last_track.tra + Inverse(m)*Point3f(0,0,-2*dist)/tb->track.sca;;
|
||||
tb->Translate(Point3f(0,0,-2*dist));
|
||||
}
|
||||
*/
|
||||
|
||||
// Track mode implementation, dummy.
|
||||
void TrackMode::Apply (Trackball * , float ){}
|
||||
|
||||
void TrackMode::Apply (Trackball * , Point3f ){}
|
||||
|
||||
void TrackMode::Draw(Trackball * ){}
|
||||
|
||||
void TrackMode::SetAction (){}
|
||||
|
||||
void TrackMode::Reset (){}
|
||||
|
||||
// draw an inactive trackball
|
||||
void InactiveMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,false);
|
||||
}
|
||||
|
||||
// Sphere mode implementation.
|
||||
// the most important function; given a new point in window coord,
|
||||
// it update the transformation computed by the trackball.
|
||||
// General scheme : the transformation is a function of just
|
||||
// the begin and current mouse positions, with greater precision
|
||||
// is function of just two 3d points over the manipulator.
|
||||
void SphereMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
Point3f hitOld = HitSphere (tb, tb->last_point);
|
||||
Point3f hitNew = HitSphere (tb, new_point);
|
||||
tb->Hits.push_back (hitNew);
|
||||
Point3f center = tb->center;
|
||||
Point3f axis = (hitNew - center) ^ (hitOld - center);
|
||||
// Figure out how much to rotate around that axis.
|
||||
float phi = Distance (hitNew, hitOld) / tb->radius;
|
||||
tb->track.rot = tb->last_track.rot * Quaternionf (phi, axis);
|
||||
}
|
||||
|
||||
void SphereMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
}
|
||||
|
||||
// Pan mode implementation.
|
||||
void PanMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
Point3f hitOld = HitViewPlane (tb, tb->last_point);
|
||||
Point3f hitNew = HitViewPlane (tb, new_point);
|
||||
tb->Translate (hitNew - hitOld);
|
||||
}
|
||||
|
||||
void PanMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyPanMode(tb);
|
||||
}
|
||||
|
||||
// Z mode implementation.
|
||||
void ZMode::Apply (Trackball * tb, float WheelNotch)
|
||||
{
|
||||
Point3f dir= (GetViewPlane (tb->camera, tb->center)).Direction();
|
||||
dir.Normalize();
|
||||
tb->Translate (dir * (-WheelNotch));
|
||||
}
|
||||
|
||||
void ZMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
Point3f dir= (GetViewPlane (tb->camera, tb->center)).Direction();
|
||||
dir.Normalize();
|
||||
tb->Translate (dir * ( -2.0f * getDeltaY(tb,new_point)));
|
||||
}
|
||||
|
||||
void ZMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyZMode(tb);
|
||||
}
|
||||
|
||||
// Scale mode implementation.
|
||||
void ScaleMode::Apply (Trackball * tb, float WheelNotch)
|
||||
{
|
||||
tb->track.sca *= pow (1.2f, -WheelNotch);
|
||||
}
|
||||
|
||||
void ScaleMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
tb->track.sca = tb->last_track.sca * pow (3.0f, -(getDeltaY(tb,new_point)));
|
||||
}
|
||||
|
||||
void ScaleMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyScaleMode(tb);
|
||||
}
|
||||
|
||||
// Axis mode implementation.
|
||||
void AxisMode::Apply (Trackball * tb, float WheelNotch)
|
||||
{
|
||||
tb->Translate (axis.Direction () * (WheelNotch / 10.0f));
|
||||
}
|
||||
|
||||
void AxisMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
pair< Point3f,bool > hitOld = HitNearestPointOnAxis (tb, axis, tb->last_point);
|
||||
pair< Point3f,bool > hitNew = HitNearestPointOnAxis (tb, axis, new_point);
|
||||
if (hitOld.second && hitNew.second){
|
||||
tb->Translate (hitNew.first - hitOld.first);
|
||||
}
|
||||
}
|
||||
|
||||
void AxisMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyAxisMode(tb,axis);
|
||||
}
|
||||
|
||||
// Plane mode implementation.
|
||||
void PlaneMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
pair< Point3f, bool > hitOld = HitPlane(tb,tb->last_point,plane);
|
||||
pair< Point3f, bool > hitNew = HitPlane(tb,new_point,plane);
|
||||
if(hitOld.second && hitNew.second){
|
||||
tb->Translate (hitNew.first - hitOld.first);
|
||||
}
|
||||
}
|
||||
|
||||
void PlaneMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyPlaneMode(tb, plane);
|
||||
}
|
||||
|
||||
// Cylinder mode implementation.
|
||||
void CylinderMode::Apply (Trackball * tb, float WheelNotch)
|
||||
{
|
||||
const float PI2=6.283185307179586232;
|
||||
tb->track.rot = tb->last_track.rot * Quaternionf (WheelNotch/(tb->radius * PI2),axis.Direction());
|
||||
}
|
||||
|
||||
void CylinderMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
Plane3f viewplane=GetViewPlane (tb->camera, tb->center);
|
||||
Line3f axisproj;
|
||||
axisproj=ProjectLineOnPlane(axis,viewplane);
|
||||
float angle;
|
||||
const float EPSILON=0.005f; // this IS scale independent
|
||||
if(axisproj.Direction().Norm() < EPSILON){
|
||||
angle=(10.0 * getDeltaY(tb,new_point)) / tb->radius;
|
||||
} else {
|
||||
Point3f hitOld = HitViewPlane (tb, tb->last_point);
|
||||
Point3f hitNew = HitViewPlane (tb, new_point);
|
||||
axisproj.Normalize();
|
||||
Point3f plusdir= viewplane.Direction() ^ axisproj.Direction();
|
||||
float distOld = signedDistance(axisproj,hitOld,plusdir);
|
||||
float distNew = signedDistance(axisproj,hitNew,plusdir);
|
||||
angle= (distNew-distOld) / tb->radius;
|
||||
}
|
||||
tb->track.rot = tb->last_track.rot * Quaternionf (angle,axis.Direction());
|
||||
}
|
||||
|
||||
void CylinderMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyCylinderMode(tb,axis);
|
||||
}
|
||||
|
||||
// Path mode implementation.
|
||||
void PathMode::Init(const vector < Point3f > &pts)
|
||||
{
|
||||
unsigned int npts=pts.size();
|
||||
assert(npts >= 2);
|
||||
points.reserve(npts);
|
||||
for(unsigned int i=0;i<npts;i++){
|
||||
points.push_back(pts[i]);
|
||||
}
|
||||
path_length=0.0f;
|
||||
min_seg_length=Distance(points[0],points[1]);
|
||||
float seg_length;
|
||||
for(unsigned int i=1;i<npts;i++){
|
||||
seg_length=Distance(points[i-1],points[i]);
|
||||
path_length += seg_length;
|
||||
min_seg_length = min(seg_length,min_seg_length);
|
||||
}
|
||||
if(wrap){
|
||||
seg_length=Distance(points[npts-1],points[0]);
|
||||
path_length += seg_length;
|
||||
min_seg_length = min(seg_length,min_seg_length);
|
||||
}
|
||||
}
|
||||
|
||||
void PathMode::Reset()
|
||||
{
|
||||
current_state=initial_state;
|
||||
}
|
||||
|
||||
Point3f PathMode::SetStartNear(Point3f point)
|
||||
{
|
||||
float p0_state=0;
|
||||
Point3f p0,p1;
|
||||
float nearest_state=0;
|
||||
Point3f nearest_point=points[0];
|
||||
float nearest_distance=Distance(nearest_point,point);
|
||||
unsigned int npts=points.size();
|
||||
for(unsigned int i = 1;i <= npts;i++){
|
||||
if( i == npts){
|
||||
if (wrap){
|
||||
p0=points[npts-1];
|
||||
p1=points[0];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
p0=points[i-1];
|
||||
p1=points[i];
|
||||
}
|
||||
Point3f segment_point=ClosestPoint(Segment3f(p0,p1),point);
|
||||
float distance=Distance(segment_point,point);
|
||||
if(distance<nearest_distance){
|
||||
nearest_point=segment_point;
|
||||
nearest_distance=distance;
|
||||
nearest_state=p0_state+(Distance(p0,nearest_point)/path_length);
|
||||
}
|
||||
float segment_norm= Distance(p0,p1) / path_length;
|
||||
p0_state+=segment_norm;
|
||||
}
|
||||
assert( nearest_state >= 0.0 );
|
||||
if(nearest_state > 1.0){
|
||||
nearest_state=1.0;
|
||||
nearest_point=( wrap ? points[0] : points[npts-1] );
|
||||
}
|
||||
initial_state=nearest_state;
|
||||
return nearest_point;
|
||||
}
|
||||
|
||||
void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Point3f & next_point)
|
||||
{
|
||||
assert(state >= 0.0f);
|
||||
assert(state <= 1.0f);
|
||||
float remaining_norm=state;
|
||||
Point3f p0,p1;
|
||||
unsigned int npts=points.size();
|
||||
for(unsigned int i = 1;i <= npts;i++){
|
||||
if( i == npts){
|
||||
if (wrap){
|
||||
p0=points[npts-1];
|
||||
p1=points[0];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
p0=points[i-1];
|
||||
p1=points[i];
|
||||
}
|
||||
float segment_norm= Distance(p0,p1) / path_length;
|
||||
if (segment_norm < remaining_norm){
|
||||
remaining_norm -= segment_norm;
|
||||
continue;
|
||||
}
|
||||
prev_point = p0;
|
||||
next_point = p1;
|
||||
float ratio= remaining_norm / segment_norm;
|
||||
point = prev_point + (( next_point - prev_point ) * ratio);
|
||||
const float EPSILON=min_seg_length * 0.01f;
|
||||
if(Distance(point,prev_point) < EPSILON){
|
||||
point=prev_point;
|
||||
if (i > 1){
|
||||
prev_point=points[i-2];
|
||||
} else if (wrap){
|
||||
prev_point=points[npts-1];
|
||||
}
|
||||
} else if (Distance(point,next_point) < EPSILON){
|
||||
point=next_point;
|
||||
if( i < (npts-1)){
|
||||
next_point=points[i+1];
|
||||
} else {
|
||||
if (wrap){
|
||||
next_point=points[1];
|
||||
} else {
|
||||
next_point=points[npts-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// rounding errors can lead out of the for..
|
||||
prev_point = p0;
|
||||
point = p1;
|
||||
if (wrap){
|
||||
next_point=points[1];
|
||||
}else{
|
||||
next_point = points[npts-1];
|
||||
}
|
||||
}
|
||||
|
||||
void PathMode::Apply (Trackball * tb, float WheelNotch)
|
||||
{
|
||||
const float STEP_COEFF = min_seg_length * 0.5f;
|
||||
float delta=(WheelNotch*STEP_COEFF)/path_length;
|
||||
Point3f old_point,new_point,prev_point,next_point;
|
||||
GetPoints(current_state,old_point,prev_point,next_point);
|
||||
current_state=Normalize(current_state+delta);
|
||||
GetPoints(current_state,new_point,prev_point,next_point);
|
||||
tb->Translate (new_point - old_point);
|
||||
}
|
||||
|
||||
float PathMode::Normalize(float state)
|
||||
{
|
||||
if ( wrap ) {
|
||||
double intpart;
|
||||
float fractpart;
|
||||
fractpart =(float) modf(state,&intpart);
|
||||
if( fractpart < 0.0f )
|
||||
fractpart += 1.0f;
|
||||
return fractpart;
|
||||
}
|
||||
if ( state < 0.0f )
|
||||
return 0.0f;
|
||||
if ( state > 1.0f )
|
||||
return 1.0f;
|
||||
return state;
|
||||
}
|
||||
|
||||
int PathMode::Verse(Point3f reference_point,Point3f current_point,Point3f prev_point,Point3f next_point)
|
||||
{
|
||||
Point3f reference_dir = reference_point - current_point ;
|
||||
Point3f prev_dir = prev_point - current_point ;
|
||||
Point3f next_dir = next_point - current_point ;
|
||||
const float EPSILON=min_seg_length * 0.005f;
|
||||
if (reference_dir.Norm() < EPSILON)
|
||||
reference_dir = Point3f(0,0,0);
|
||||
if (prev_dir.Norm() < EPSILON)
|
||||
prev_dir = Point3f(0,0,0);
|
||||
if (next_dir.Norm() < EPSILON)
|
||||
next_dir = Point3f(0,0,0);
|
||||
reference_dir.Normalize();
|
||||
prev_dir.Normalize();
|
||||
next_dir.Normalize();
|
||||
float prev_coeff,next_coeff;
|
||||
prev_coeff = prev_dir * reference_dir;
|
||||
next_coeff = next_dir * reference_dir;
|
||||
if (prev_coeff < 0.0f)
|
||||
prev_coeff = 0.0f;
|
||||
if (next_coeff < 0.0f)
|
||||
next_coeff = 0.0f;
|
||||
if( (prev_coeff == 0.0f) && (next_coeff == 0.0f)){
|
||||
return 0;
|
||||
}
|
||||
if ( prev_coeff <= next_coeff ){
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
float PathMode::HitPoint(float state, Ray3fN ray, Point3f &hit_point)
|
||||
{
|
||||
Point3f current_point, next_point, prev_point;
|
||||
GetPoints(state,current_point,prev_point,next_point);
|
||||
|
||||
Point3f closest_point;
|
||||
closest_point=ray.ClosestPoint(current_point);
|
||||
int verse=Verse(closest_point,current_point,prev_point,next_point);
|
||||
if (verse == 0){
|
||||
hit_point=current_point;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
Segment3f active_segment;
|
||||
if (verse > 0){
|
||||
active_segment=Segment3f(current_point,next_point);
|
||||
} else {
|
||||
active_segment= Segment3f(current_point,prev_point);
|
||||
}
|
||||
|
||||
hit_point=ClosestPoint(active_segment,closest_point);
|
||||
|
||||
return verse * ((hit_point-current_point).Norm() / path_length);
|
||||
}
|
||||
|
||||
void PathMode::SetAction (){
|
||||
Point3f temp1,temp2;
|
||||
GetPoints(current_state,old_hitpoint,temp1,temp2);
|
||||
}
|
||||
|
||||
void PathMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (new_point));
|
||||
Point3f hit_point;
|
||||
float delta_state=HitPoint(current_state,ray,hit_point);
|
||||
current_state=Normalize(current_state+delta_state);
|
||||
tb->Translate (hit_point - old_hitpoint);
|
||||
}
|
||||
|
||||
void PathMode::Draw(Trackball * tb){
|
||||
DrawSphereIcon(tb,true );
|
||||
Point3f current_point,prev_point,next_point;
|
||||
GetPoints(current_state,current_point,prev_point,next_point);
|
||||
DrawUglyPathMode(tb,points,current_point,prev_point,
|
||||
next_point,old_hitpoint,wrap);
|
||||
}
|
||||
|
||||
// Area mode implementation.
|
||||
void AreaMode::Init(const vector < Point3f > &pts)
|
||||
{
|
||||
unsigned int npts=pts.size();
|
||||
|
||||
assert(npts >= 3);
|
||||
//get the plane
|
||||
Point3f p0=pts[0];
|
||||
unsigned int onethird=(unsigned int)floor(npts/3.0);
|
||||
const float EPSILON=0.005;
|
||||
bool pts_not_in_line=false;
|
||||
Point3f a,b;
|
||||
for(unsigned int i=0;i<onethird;i++){
|
||||
a=(pts[(i+ onethird )%npts] - pts[i%npts]).Normalize();
|
||||
b=(pts[(i+(2*onethird))%npts] - pts[i%npts]).Normalize();
|
||||
pts_not_in_line = (a ^ b).Norm() > EPSILON;
|
||||
if(pts_not_in_line){
|
||||
plane.Init( pts[i%npts],
|
||||
pts[(i+(onethird))%npts],
|
||||
pts[(i+(2*onethird))%npts]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(pts_not_in_line);
|
||||
float ncx,ncy,ncz;
|
||||
ncx=fabs(plane.Direction()[0]);
|
||||
ncy=fabs(plane.Direction()[1]);
|
||||
ncz=fabs(plane.Direction()[2]);
|
||||
if(( ncx > ncy ) && ( ncx > ncz )){
|
||||
first_coord_kept=1;
|
||||
second_coord_kept=2;
|
||||
} else if(( ncy > ncx ) && ( ncy > ncz)){
|
||||
first_coord_kept=0;
|
||||
second_coord_kept=2;
|
||||
} else {
|
||||
first_coord_kept=0;
|
||||
second_coord_kept=1;
|
||||
}
|
||||
points.reserve(npts);
|
||||
for(unsigned int i=0;i<npts;i++){
|
||||
points.push_back(plane.Projection(pts[i]));
|
||||
}
|
||||
min_side_length=Distance(points[0],points[1]);
|
||||
for(unsigned int i=1;i<npts;i++){
|
||||
min_side_length=min(Distance(points[i-1],points[i]),min_side_length);
|
||||
}
|
||||
rubberband_handle=old_status=status=initial_status=p0;
|
||||
}
|
||||
|
||||
void AreaMode::Reset()
|
||||
{
|
||||
rubberband_handle=old_status=status=initial_status;
|
||||
path.clear();
|
||||
}
|
||||
|
||||
void AreaMode::Apply (Trackball * tb, Point3f new_point)
|
||||
{
|
||||
if(begin_action){
|
||||
delta_mouse=tb->camera.Project(status)-new_point;
|
||||
begin_action=false;
|
||||
}
|
||||
pair< Point3f, bool > hitNew = HitPlane(tb,new_point+delta_mouse,plane);
|
||||
if(! hitNew.second){
|
||||
return;
|
||||
}
|
||||
Point3f hit_point=hitNew.first;
|
||||
Point3f delta_status=Move(status,hit_point);
|
||||
status += delta_status;
|
||||
tb->Translate (status - old_status);
|
||||
rubberband_handle=hit_point;
|
||||
}
|
||||
|
||||
|
||||
void AreaMode::SetAction ()
|
||||
{
|
||||
begin_action=true;
|
||||
old_status=status;
|
||||
|
||||
|
||||
path.clear();
|
||||
path.push_back(status);
|
||||
rubberband_handle=status;
|
||||
}
|
||||
|
||||
Point3f AreaMode::Move(Point3f start,Point3f end)
|
||||
{
|
||||
const float EPSILON=min_side_length*0.001f;
|
||||
Point3f pt=start;
|
||||
bool done=false;
|
||||
bool end_inside=Inside(end);
|
||||
while(!done){
|
||||
path.push_back(pt);
|
||||
Segment3f segment(pt,end);
|
||||
bool p_on_side = false;
|
||||
bool hit=false;
|
||||
|
||||
Point3f pside,phit;
|
||||
bool slide,mid_inside;
|
||||
|
||||
int np=points.size(), i, j;
|
||||
for (i = 0, j = np-1; i < np; j = i++) {
|
||||
Segment3f side(points[i],points[j]);
|
||||
Point3f pseg,psid;
|
||||
pair<float,bool> res=SegmentSegmentDistance(segment,side,pseg,psid);
|
||||
if(res.first < EPSILON && ! res.second){
|
||||
float dist= Distance(pt,pseg);
|
||||
if(dist < EPSILON){
|
||||
Point3f pn=ClosestPoint(side,end);
|
||||
if(!p_on_side || (Distance(pn,end)<Distance(end,pside))){
|
||||
pside=pn;
|
||||
p_on_side=true;
|
||||
}
|
||||
} else {
|
||||
if (!hit || Distance(pt,pseg) < Distance(pt,phit)){
|
||||
phit=pseg;
|
||||
hit=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_on_side)
|
||||
slide = Distance(pside,pt) > EPSILON;
|
||||
|
||||
if (hit)
|
||||
mid_inside = Inside( pt + ( ( phit - pt ) / 2) );
|
||||
|
||||
if ( !hit && end_inside ){
|
||||
pt = end;
|
||||
done = true;
|
||||
} else if ( hit && (!p_on_side || (p_on_side && mid_inside))) {
|
||||
pt = phit;
|
||||
} else if ( p_on_side && slide) {
|
||||
pt = pside;
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
path.push_back(pt);
|
||||
return pt - start;
|
||||
}
|
||||
|
||||
// adapted from the original C code by W. Randolph Franklin
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
bool AreaMode::Inside(Point3f point)
|
||||
{
|
||||
bool inside=false;
|
||||
float x=point[first_coord_kept];
|
||||
float y=point[second_coord_kept];
|
||||
float yi, yj, xi, xj;
|
||||
int i, j, np=points.size();
|
||||
for (i = 0, j = np-1; i < np; j = i++) {
|
||||
xi=points[i][first_coord_kept];
|
||||
yi=points[i][second_coord_kept];
|
||||
xj=points[j][first_coord_kept];
|
||||
yj=points[j][second_coord_kept];
|
||||
if ( ( ( (yi<=y) && (y<yj) ) || ( (yj<=y) && (y<yi) ) ) &&
|
||||
( x < ( xj - xi ) * ( y - yi ) / ( yj - yi ) + xi ) )
|
||||
{
|
||||
inside=!inside;
|
||||
}
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
Point3f AreaMode::SetStartNear(Point3f point)
|
||||
{
|
||||
Point3f candidate=plane.Projection(point);
|
||||
if (Inside(candidate)){
|
||||
initial_status=candidate;
|
||||
return initial_status;
|
||||
}
|
||||
Point3f nearest_point=initial_status;
|
||||
float nearest_distance=Distance(nearest_point,candidate);
|
||||
int i, j, np=points.size();
|
||||
for (i = 0, j = np-1; i < np; j = i++) {
|
||||
Segment3f side(points[i],points[j]);
|
||||
Point3f side_point=ClosestPoint(side,candidate);
|
||||
float distance=Distance(side_point,candidate);
|
||||
if( distance < nearest_distance ){
|
||||
nearest_point=side_point;
|
||||
nearest_distance=distance;
|
||||
}
|
||||
}
|
||||
initial_status=nearest_point;
|
||||
return initial_status;
|
||||
}
|
||||
|
||||
void AreaMode::Draw(Trackball * tb)
|
||||
{
|
||||
DrawSphereIcon(tb,true );
|
||||
DrawUglyAreaMode(tb,points,status,old_status,plane,path,rubberband_handle);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.10 2007/02/26 01:30:02 cignoni
|
||||
Added reflection Name
|
||||
|
||||
Revision 1.9 2006/02/13 13:10:27 cignoni
|
||||
Added Zmode for moving objects along the perpendicular to the viewplane
|
||||
|
||||
|
@ -56,75 +59,283 @@ Adding copyright.
|
|||
|
||||
#include <vcg/space/line3.h>
|
||||
#include <vcg/space/plane3.h>
|
||||
#include <vcg/space/segment3.h>
|
||||
#include <vcg/space/ray3.h>
|
||||
#include <wrap/gui/view.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace vcg {
|
||||
|
||||
class Trackball;
|
||||
|
||||
// Base class for all the track modes.
|
||||
// This class' functions does nothing.
|
||||
class TrackMode {
|
||||
public:
|
||||
virtual ~TrackMode() {}
|
||||
virtual void Apply(Trackball *trackball, Point3f new_point) = 0;
|
||||
virtual void Apply(Trackball *trackball, float WheelNotch);
|
||||
virtual const char *Name()=0;
|
||||
virtual void Draw() {}
|
||||
protected:
|
||||
Plane3f GetViewPlane(const View<float> &view, const Point3f ¢er);
|
||||
Point3f HitViewPlane(Trackball *trackball, const Point3f &p);
|
||||
virtual ~TrackMode () {
|
||||
}
|
||||
virtual void Apply (Trackball * trackball, Point3f new_point);
|
||||
virtual void Apply (Trackball * trackball, float WheelNotch);
|
||||
virtual void SetAction ();
|
||||
virtual void Reset ();
|
||||
virtual const char *Name (){
|
||||
return "TrackMode";
|
||||
};
|
||||
virtual void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
// Inactive mode.
|
||||
// useful only for drawing the inactive trackball
|
||||
class InactiveMode:public TrackMode {
|
||||
public:
|
||||
const char *Name () {
|
||||
return "InactiveMode";
|
||||
};
|
||||
void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
|
||||
/* View space modes */
|
||||
|
||||
// old interfaces
|
||||
/*
|
||||
class SphereMode: public TrackMode {
|
||||
public:
|
||||
void Apply(Trackball *trackball, Point3f new_point);
|
||||
const char* Name() {return "SphereMode";};
|
||||
protected:
|
||||
Point3f Hit(Trackball *trackball, const Point3f &p);
|
||||
bool HitHyper(Point3f center, float radius, Point3f viewpoint, Plane3f vp, Point3f hitplane, Point3f &hit) ;
|
||||
};
|
||||
|
||||
}
|
||||
class CylinderMode: public TrackMode {
|
||||
}
|
||||
class PlaneMode: public TrackMode {
|
||||
}
|
||||
class ZMode: public TrackMode {
|
||||
}
|
||||
class LineMode: public TrackMode {
|
||||
}
|
||||
class LineMode: public TrackMode {
|
||||
}
|
||||
class ScaleMode: public TrackMode {
|
||||
|
||||
*/
|
||||
|
||||
// Sphere mode.
|
||||
// The classic trackball.
|
||||
class SphereMode:public TrackMode {
|
||||
public:
|
||||
CylinderMode(const Line3f &/*line*/, float /*radius = 1*/) {}
|
||||
void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {}
|
||||
const char* Name() {return "CylinderMode";};
|
||||
protected:
|
||||
Line3f line;
|
||||
float radius;
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
const char *Name () {
|
||||
return "SphereMode";
|
||||
};
|
||||
void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
class PlaneMode: public TrackMode {
|
||||
// Panning mode.
|
||||
// The user can drag the model on the view plane.
|
||||
class PanMode:public TrackMode {
|
||||
public:
|
||||
PlaneMode(const Plane3f &pl): plane(pl) {}
|
||||
void Apply(Trackball *trackball, Point3f new_point);
|
||||
const char* Name() {return "PlaneMode";};
|
||||
protected:
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
const char *Name () {
|
||||
return "PanMode";
|
||||
};
|
||||
void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
// Z mode.
|
||||
// Dragging the mouse up and down or scrolling the
|
||||
// mouse wheel will move the object along the Z of the camera.
|
||||
class ZMode:public TrackMode {
|
||||
public:
|
||||
const char *Name () {
|
||||
return "ZMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Apply (Trackball * trackball, float WheelNotch);
|
||||
void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
// Scale Mode.
|
||||
// Dragging the mouse up and down or scrolling the
|
||||
// mouse wheel will scale the object.
|
||||
class ScaleMode:public TrackMode {
|
||||
public:
|
||||
const char *Name () {
|
||||
return "ScaleMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Apply (Trackball * trackball, float WheelNotch);
|
||||
void Draw (Trackball * trackball);
|
||||
};
|
||||
|
||||
// Axis mode.
|
||||
// Moves the object in a costrained direction.
|
||||
// The user can either drag the mouse or scroll the wheel.
|
||||
// The direction can be specified either with a line
|
||||
// or a origin and a direction.
|
||||
// the object posistion is not needed to be on the line.
|
||||
class AxisMode:public TrackMode {
|
||||
public:
|
||||
AxisMode (const Line3f & ln)
|
||||
: axis (ln) {
|
||||
}
|
||||
AxisMode (const Point3f & origin, const Point3f & direction) {
|
||||
axis = Line3fN (origin, direction);
|
||||
}
|
||||
const char *Name () {
|
||||
return "AxisMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Apply (Trackball * trackball, float WheelNotch);
|
||||
void Draw (Trackball * trackball);
|
||||
private:
|
||||
Line3fN axis;
|
||||
};
|
||||
|
||||
// Plane mode.
|
||||
// The user can drag the object in a costrained plane.
|
||||
// The plane can be specified either with a plane
|
||||
// or the plane's equation parameters
|
||||
// the object posistion is not needed to be on the plane.
|
||||
class PlaneMode:public TrackMode {
|
||||
public:
|
||||
PlaneMode (float a, float b, float c, float d)
|
||||
: plane(Plane3f(d,Point3f(a,b,c))){
|
||||
}
|
||||
PlaneMode (Plane3f & pl)
|
||||
: plane(pl) {
|
||||
}
|
||||
const char *Name () {
|
||||
return "PlaneMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Draw (Trackball * trackball);
|
||||
private:
|
||||
Plane3f plane;
|
||||
};
|
||||
|
||||
// Move the object along the Z of the Camera
|
||||
// complement of the Plane mode
|
||||
class ZMode: public TrackMode {
|
||||
const char* Name() {return "ZMode";};
|
||||
// Cylinder mode.
|
||||
// Rotates the object along a fixed axis
|
||||
// The user can either drag the mouse or scroll the wheel,
|
||||
// in either cases the rotation's angle is influenced by
|
||||
// the radius of the trackball.
|
||||
// The axis can be specified either with a line
|
||||
// or a origin and a direction
|
||||
// when the user drags the mouse, if the axis is too
|
||||
// perpendicular to view plane, the angle is specified
|
||||
// only by the vertical component of the mouse drag and the radius.
|
||||
class CylinderMode:public TrackMode {
|
||||
public:
|
||||
void Apply(Trackball *trackball, Point3f new_point);
|
||||
CylinderMode (Line3fN & ln)
|
||||
: axis (ln){
|
||||
}
|
||||
CylinderMode (const Point3f & origin, const Point3f & direction)
|
||||
: axis (Line3fN(origin,direction)){
|
||||
}
|
||||
const char *Name () {
|
||||
return "CylinderMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Apply (Trackball * trackball, float WheelNotch);
|
||||
void Draw (Trackball * trackball);
|
||||
private:
|
||||
Line3fN axis;
|
||||
};
|
||||
|
||||
class LineMode: public TrackMode {
|
||||
// Path mode.
|
||||
// move the object along an eventually closed path.
|
||||
// The user can either drag the mouse or scroll the wheel,
|
||||
// when the user drags the mouse, the object tries to slide toward it.
|
||||
// if the path is a simple segment, it can be specified just with the endpoints,
|
||||
// otherwise it's specified with a point vector and, eventually, a boolean value used for closing the path.
|
||||
// the object is assumed to initially be on the same position of the first point on the path.
|
||||
// you can try to set the starting point calling SetStartNear(Point3f)
|
||||
// the path is NOT assumed to have 0-length segments, so, if you want to close the path, please DO NOT add
|
||||
// a copy of the first point on the end of the vector...
|
||||
// the vector passed to build the path is copied locally.
|
||||
class PathMode:public TrackMode {
|
||||
public:
|
||||
LineMode(const Line3f &/*line*/) {}
|
||||
void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {}
|
||||
const char* Name() {return "LineMode";};
|
||||
protected:
|
||||
Line3f line;
|
||||
PathMode ( const vector < Point3f > &pts, bool w = false)
|
||||
: points(), wrap(w), current_state(0), initial_state(0), old_hitpoint()
|
||||
{
|
||||
Init(pts);
|
||||
assert(min_seg_length > 0.0f);
|
||||
}
|
||||
PathMode ( const Point3f &start, const Point3f &end )
|
||||
: points(), wrap(false), current_state(0), initial_state(0), old_hitpoint()
|
||||
{
|
||||
points.push_back(start);
|
||||
points.push_back(end);
|
||||
path_length=Distance(start,end);
|
||||
min_seg_length=path_length;
|
||||
assert(min_seg_length > 0.0f);
|
||||
}
|
||||
const char *Name () {
|
||||
return "PathMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Apply (Trackball * trackball, float WheelNotch);
|
||||
void Draw (Trackball * trackball);
|
||||
void SetAction ();
|
||||
void Reset ();
|
||||
Point3f SetStartNear(Point3f p);
|
||||
private:
|
||||
void Init(const vector < Point3f > &points);
|
||||
void GetPoints(float state, Point3f & point, Point3f & prev_point, Point3f & next_point);
|
||||
float Normalize(float state);
|
||||
float HitPoint(float state, Ray3fN ray, Point3f &hit_point);
|
||||
int Verse(Point3f reference_point,Point3f current_point,Point3f prev_point,Point3f next_point);
|
||||
|
||||
vector < Point3f > points;
|
||||
bool wrap;
|
||||
float current_state;
|
||||
float initial_state;
|
||||
float path_length;
|
||||
float min_seg_length;
|
||||
Point3f old_hitpoint;
|
||||
|
||||
};
|
||||
|
||||
class ScaleMode: public TrackMode {
|
||||
// Area mode.
|
||||
// The user can drag the object inside a planar area, defined by a polygon.
|
||||
// the polygon can be non convex, and is specified with a vector of vertexes
|
||||
// if the object's trajectory intersects some poligon side, it tries to slide
|
||||
// around it, in a "rubber band flavoured" way.
|
||||
// for the vertexes vector its calculated the plane of the polygon, and then
|
||||
// every point in the vector is projected on this plane.
|
||||
// the object is assumed to initially be on the same position of the first vertex.
|
||||
// you can try to set the starting point calling SetStartNear(Point3f)
|
||||
// the vector is assumed to be formed of NON collinear points
|
||||
// the polygon is NOT assumed to have 0-length sides, so please DO NOT add
|
||||
// a copy of the first point on the end of the vector...
|
||||
// the vector passed to build the polygon is copied locally.
|
||||
|
||||
class AreaMode:public TrackMode {
|
||||
public:
|
||||
const char* Name() {return "ScaleMode";};
|
||||
void Apply(Trackball *trackball, Point3f new_point);
|
||||
AreaMode (const vector < Point3f > &pts)
|
||||
{
|
||||
Init(pts);
|
||||
assert(min_side_length > 0.0f);
|
||||
}
|
||||
const char *Name () {
|
||||
return "AreaMode";
|
||||
};
|
||||
void Apply (Trackball * trackball, Point3f new_point);
|
||||
void Draw (Trackball * trackball);
|
||||
void SetAction ();
|
||||
void Reset ();
|
||||
Point3f SetStartNear(Point3f p);
|
||||
private:
|
||||
void Init(const vector < Point3f > &pts);
|
||||
bool Inside(Point3f point);
|
||||
Point3f Move(Point3f start,Point3f end);
|
||||
|
||||
vector < Point3f > points;
|
||||
bool begin_action;
|
||||
int first_coord_kept;
|
||||
int second_coord_kept;
|
||||
float min_side_length;
|
||||
Point3f status,delta_mouse,old_status,initial_status;
|
||||
|
||||
Plane3f plane;
|
||||
Point3f rubberband_handle ;
|
||||
vector < Point3f > path;
|
||||
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
|
Loading…
Reference in New Issue