63 #include "ManipulatorNode.hh"
70 namespace SceneGraph {
76 const Vec4f cylinder_color (0.8f, 0.4f, 0.4f, 1.0f);
77 const Vec4f sphere_color (0.8f, 0.4f, 0.4f, 1.0f);
78 const Vec4f select_color (1.0f, 0.1f, 0.1f, 1.0f);
79 const float SCALE_CONST = 5.0f;
88 draw_cylinder_(false),
89 direction_(1.0,0.0,0.0),
95 cylinder_clicked_(false),
96 sphere_clicked_(false),
130 setup_cylinder_system(
GLState& _state)
136 Vec3d z(0.0, 0.0, 1.0);
137 double scal_prod = (direction_ | z);
138 Vec3d axis = z % direction_;
139 double norm = axis.norm();
145 if (scal_prod > 1.0) scal_prod = 1.0;
146 if (scal_prod < -1.0) scal_prod = -1.0;
147 angle = 180.0 / M_PI * acos(scal_prod);
151 axis =
Vec3d(1.0, 0.0, 0.0);
152 angle = (scal_prod > 0.0) ? 0.0 : 180.0;
155 _state.
rotate(angle, axis[0], axis[1], axis[2]);
161 setup_sphere_system(GLState& _state)
163 setup_cylinder_system(_state);
165 _state.translate(0, 0, cylinder_height_+ 2*cylinder_radius_);
190 cylinder_ =
new GLCylinder(cylinder_slices_, cylinder_stacks_, cylinder_radius_,
false,
false);
194 setup_cylinder_system(_state);
196 if( cylinder_clicked_)
213 cylinder_->setBottomRadius(cylinder_radius_);
214 cylinder_->setTopRadius(cylinder_radius_);
215 cylinder_->draw(_state, cylinder_height_);
226 glutWireSphere(cylinder_height_+4*cylinder_radius_, 20, 20);
237 setup_sphere_system(_state);
251 glutSolidSphere(2*cylinder_radius_, 20, 20);
272 Vec2i newPoint2D(_event->pos().x(), _event->pos().y());
277 switch (_event->type())
279 case QEvent::MouseButtonPress:
282 sphere_clicked_ = hitSphere(_state, newPoint2D);
285 cylinder_clicked_ = mapToCylinder(_state, newPoint2D, new_axis_hit);
288 if ( sphere_clicked_ || cylinder_clicked_)
292 if(sphere_clicked_ && cylinder_clicked_)
293 cylinder_clicked_ =
false;
295 oldPoint2D_ = newPoint2D;
300 case QEvent::MouseButtonRelease:
302 sphere_clicked_ =
false;
303 cylinder_clicked_ =
false;
308 case QEvent::MouseButtonDblClick:
310 draw_cylinder_ = !draw_cylinder_;
315 case QEvent::MouseMove:
320 bool hit0 = mapToSphere(_state, newPoint2D, newPoint3D);
321 bool hit1 = mapToSphere(_state, oldPoint2D_, oldPoint3D);
327 if(_event->modifiers() & Qt::ShiftModifier)
331 direction_.normalize();
332 newPoint3D.normalize();
333 oldPoint3D.normalize();
335 direction_ += newPoint3D - oldPoint3D;
341 Vec3d axis = oldPoint3D % newPoint3D;
342 double cos_angle = ( oldPoint3D | newPoint3D );
344 if (fabs(cos_angle) < 1.0)
345 rotate(acos(cos_angle)*180.0/M_PI, axis);
348 else sphere_clicked_ =
false;
353 if(cylinder_clicked_)
357 mapToCylinder(_state, oldPoint2D_, old_axis_hit);
358 mapToCylinder(_state, newPoint2D, new_axis_hit);
361 if(_event->modifiers() & Qt::ShiftModifier)
363 scale(1.0 + (new_axis_hit - old_axis_hit) /
364 (cylinder_height_ * SCALE_CONST));
368 else if(_event->modifiers() & (Qt::ControlModifier |
371 rotate( 45.0 * (new_axis_hit-old_axis_hit) / cylinder_height_,
392 oldPoint2D_ = newPoint2D;
399 bool ManipulatorNode::hitSphere(
GLState& _state,
403 unsigned int x = _v2[0];
413 setup_sphere_system(_state);
414 _state.
scale(2*cylinder_radius_);
425 double a = direction.sqrnorm(),
427 c = origin.sqrnorm() - 1.0,
438 ManipulatorNode::mapToSphere(
GLState& _state,
443 unsigned int x = _v2[0];
457 _state.
scale(cylinder_height_ + 4*cylinder_radius_);
468 double a = direction.sqrnorm(),
470 c = origin.sqrnorm() - 1.0,
474 if (d < 0.0)
return false;
475 else if (d == 0.0) t = -b / (2.0*a);
480 double t1 = (-b - d) * a;
481 double t2 = (-b + d) * a;
482 t = (t1 < t2) ? t1 : t2;
488 _v3 = origin + direction*t;
498 ManipulatorNode::mapToCylinder(GLState& _state,
503 unsigned int x = _v1[0];
504 unsigned int y = _state.context_height() - _v1[1];
510 _state.set_updateGL(
false);
511 _state.push_modelview_matrix();
513 setup_cylinder_system(_state);
515 _state.viewing_ray(x, y, origin, direction);
517 _state.pop_modelview_matrix();
518 _state.set_updateGL(
true);
523 const Vec3d origin2(0,0,0), direction2(0,0,1);
527 Vec3d normal = (direction % direction2).normalize();
528 Vec3d vd = ((origin2 - origin) % direction);
529 _axis_hit = (normal | vd);
531 double orthodistance = std::abs( ( origin2 - origin ) | normal);
535 return((orthodistance < cylinder_radius_) &&
537 (_axis_hit <= cylinder_height_));
546 if (draw_cylinder_) {
552 setup_cylinder_system(_state);
554 cylinder_->setBottomRadius(cylinder_radius_);
555 cylinder_->setTopRadius(cylinder_radius_);
556 cylinder_->draw(_state, cylinder_height_);
561 setup_sphere_system(_state);
563 glutSolidSphere(2* cylinder_radius_ , 20, 20);
void scale(double _s)
scale by (_s, _s, _s)
void translate(double _s)
translate in cylinder direction
Namespace providing different geometric functions concerning angles.
VectorT< signed int, 2 > Vec2i
static void enable(GLenum _cap)
replaces glEnable, but supports locking
int context_height() const
get gl context height
void pick_set_name(unsigned int _idx)
sets the current name/color (like glLoadName(_idx))
~ManipulatorNode()
Destructor.
PickTarget
What target to use for picking.
bool pick_set_maximum(unsigned int _idx)
Set the maximal number of primitives/components of your object.
picks faces (should be implemented for all nodes)
pick any of the prior targets (should be implemented for all nodes)
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
const GLMatrixd & inverse_scale() const
return inverse scale matrix
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
VectorT< double, 3 > Vec3d
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
void set_diffuse_color(const Vec4f &_col)
set diffuse color
bool touched_
if the manipulator is cklicked with a mouse, this flag will be set to true
void rotate(double _angle, const Vec3d &_axis)
void pick(GLState &_state, PickTarget _target)
picking
ManipulatorNode(BaseNode *_parent=0, const std::string &_name="<ManipulatorNode>")
Default constructor.
void push_modelview_matrix()
push modelview matrix
virtual void setIdentity()
const Vec3d & center() const
get center
void mult_matrix(const GLMatrixd &_m, const GLMatrixd &_inv_m, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply by a given transformation matrix
const Vec4f & specular_color() const
get specular color
const GLMatrixd & scale() const
return scale matrix
const GLMatrixd & inverse_rotation() const
return inverse rotation matrix
void pop_modelview_matrix()
pop modelview matrix
void set_updateGL(bool _b)
should GL matrices be updated after each matrix operation
virtual void mouseEvent(GLState &_state, QMouseEvent *_event)
get mouse events
const GLMatrixd & rotation() const
return rotation matrix
void set_specular_color(const Vec4f &_col)
set specular color
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
draw the cylinder (if enabled)
void set_direction(Vec3d &_v)
virtual void setIdentity()
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
const Vec4f & diffuse_color() const
get diffuse color