57 #include "ManipulatorNode.hh" 69 const Vec4f cylinder_color (0.8f, 0.4f, 0.4f, 1.0f);
70 const Vec4f sphere_color (0.8f, 0.4f, 0.4f, 1.0f);
71 const Vec4f select_color (1.0f, 0.1f, 0.1f, 1.0f);
72 const float SCALE_CONST = 5.0f;
81 draw_cylinder_(false),
82 direction_(1.0,0.0,0.0),
88 cylinder_clicked_(false),
89 sphere_clicked_(false),
123 setup_cylinder_system(
GLState& _state)
129 Vec3d z(0.0, 0.0, 1.0);
130 double scal_prod = (direction_ | z);
131 Vec3d axis = z % direction_;
132 double norm = axis.
norm();
138 if (scal_prod > 1.0) scal_prod = 1.0;
139 if (scal_prod < -1.0) scal_prod = -1.0;
140 angle = 180.0 / M_PI * acos(scal_prod);
144 axis =
Vec3d(1.0, 0.0, 0.0);
145 angle = (scal_prod > 0.0) ? 0.0 : 180.0;
148 _state.
rotate(angle, axis[0], axis[1], axis[2]);
154 setup_sphere_system(
GLState& _state)
156 setup_cylinder_system(_state);
158 _state.
translate(0, 0, cylinder_height_+ 2*cylinder_radius_);
170 if(_state.compatibilityProfile())
186 cylinder_ =
new GLCylinder(cylinder_slices_, cylinder_stacks_, cylinder_radius_,
false,
false);
190 setup_cylinder_system(_state);
192 if( cylinder_clicked_)
208 if(_state.compatibilityProfile())
210 cylinder_->setBottomRadius(cylinder_radius_);
211 cylinder_->setTopRadius(cylinder_radius_);
212 cylinder_->draw(_state, cylinder_height_);
218 if( sphere_clicked_ )
222 if(_state.compatibilityProfile())
226 glGetIntegerv(GL_POLYGON_MODE,previous);
227 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
228 _state.
scale(cylinder_height_+4*cylinder_radius_,cylinder_height_+4*cylinder_radius_,cylinder_height_+4*cylinder_radius_);
230 sphere.draw_primitive();
231 glPolygonMode(GL_FRONT,previous[0]);
232 glPolygonMode(GL_BACK,previous[1]);
244 setup_sphere_system(_state);
257 if(_state.compatibilityProfile())
260 _state.
scale(2*cylinder_radius_,2*cylinder_radius_,2*cylinder_radius_);
262 sphere.draw_primitive();
284 Vec2i newPoint2D(_event->pos().x(), _event->pos().y());
289 switch (_event->type())
291 case QEvent::MouseButtonPress:
294 sphere_clicked_ = hitSphere(_state, newPoint2D);
297 cylinder_clicked_ = mapToCylinder(_state, newPoint2D, new_axis_hit);
300 if ( sphere_clicked_ || cylinder_clicked_)
304 if(sphere_clicked_ && cylinder_clicked_)
305 cylinder_clicked_ =
false;
307 oldPoint2D_ = newPoint2D;
312 case QEvent::MouseButtonRelease:
314 sphere_clicked_ =
false;
315 cylinder_clicked_ =
false;
320 case QEvent::MouseButtonDblClick:
322 draw_cylinder_ = !draw_cylinder_;
327 case QEvent::MouseMove:
332 bool hit0 = mapToSphere(_state, newPoint2D, newPoint3D);
333 bool hit1 = mapToSphere(_state, oldPoint2D_, oldPoint3D);
339 if(_event->modifiers() & Qt::ShiftModifier)
344 newPoint3D.normalize();
347 direction_ += newPoint3D - oldPoint3D;
353 Vec3d axis = oldPoint3D % newPoint3D;
354 double cos_angle = ( oldPoint3D | newPoint3D );
356 if (fabs(cos_angle) < 1.0)
357 rotate(acos(cos_angle)*180.0/M_PI, axis);
360 else sphere_clicked_ =
false;
365 if(cylinder_clicked_)
369 mapToCylinder(_state, oldPoint2D_, old_axis_hit);
370 mapToCylinder(_state, newPoint2D, new_axis_hit);
373 if(_event->modifiers() & Qt::ShiftModifier)
375 scale(1.0 + (new_axis_hit - old_axis_hit) /
376 (cylinder_height_ * SCALE_CONST));
380 else if(_event->modifiers() & (Qt::ControlModifier |
383 rotate( 45.0 * (new_axis_hit-old_axis_hit) / cylinder_height_,
404 oldPoint2D_ = newPoint2D;
411 bool ManipulatorNode::hitSphere(
GLState& _state,
415 unsigned int x = _v2[0];
425 setup_sphere_system(_state);
426 _state.
scale(2*cylinder_radius_);
437 double a = direction.
sqrnorm(),
450 ManipulatorNode::mapToSphere(
GLState& _state,
455 unsigned int x = _v2[0];
469 _state.
scale(cylinder_height_ + 4*cylinder_radius_);
480 double a = direction.
sqrnorm(),
486 if (d < 0.0)
return false;
487 else if (d == 0.0) t = -b / (2.0*a);
492 double t1 = (-b - d) * a;
493 double t2 = (-b + d) * a;
494 t = (t1 < t2) ? t1 : t2;
500 _v3 = origin + direction*t;
510 ManipulatorNode::mapToCylinder(
GLState& _state,
515 unsigned int x = _v1[0];
525 setup_cylinder_system(_state);
535 const Vec3d origin2(0,0,0), direction2(0,0,1);
539 Vec3d normal = (direction % direction2).normalize();
540 Vec3d vd = ((origin2 - origin) % direction);
541 _axis_hit = (normal | vd);
543 double orthodistance = std::abs( ( origin2 - origin ) | normal);
547 return((orthodistance < cylinder_radius_) &&
549 (_axis_hit <= cylinder_height_));
558 if (draw_cylinder_) {
564 setup_cylinder_system(_state);
566 cylinder_->setBottomRadius(cylinder_radius_);
567 cylinder_->setTopRadius(cylinder_radius_);
568 cylinder_->draw(_state, cylinder_height_);
573 setup_sphere_system(_state);
575 if(_state.compatibilityProfile()) {
576 _state.
scale(2*cylinder_radius_,2*cylinder_radius_,2*cylinder_radius_);
578 sphere.draw_primitive();
virtual void mouseEvent(GLState &_state, QMouseEvent *_event) override
get mouse events
ManipulatorNode(BaseNode *_parent=0, const std::string &_name="<ManipulatorNode>")
Default constructor.
void pop_modelview_matrix()
pop modelview matrix
const Vec4f & specular_color() const
get specular color
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
picks faces (should be implemented for all nodes)
Namespace providing different geometric functions concerning angles.
void scale(double _s)
scale by (_s, _s, _s)
const Vec4f & diffuse_color() const
get diffuse color
void mult_matrix(const GLMatrixd &_m, const GLMatrixd &_inv_m, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply by a given transformation matrix
void set_updateGL(bool _b)
should GL matrices be updated after each matrix operation
~ManipulatorNode()
Destructor.
PickTarget
What target to use for picking.
void push_modelview_matrix()
push modelview matrix
pick any of the prior targets (should be implemented for all nodes)
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
draw the cylinder (if enabled)
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
void translate(double _s)
translate in cylinder direction
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
void set_specular_color(const Vec4f &_col)
set specular color
void set_direction(Vec3d &_v)
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
void pick(GLState &_state, PickTarget _target) override
picking
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
int context_height() const
get gl context height
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
virtual void setIdentity() override
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
VectorT< double, 3 > Vec3d