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:
333 bool hit0 = mapToSphere(_state, newPoint2D, newPoint3D);
334 bool hit1 = mapToSphere(_state, oldPoint2D_, oldPoint3D);
336 if ( (newPoint2D != oldPoint2D_) && hit0 && hit1)
339 if(_event->modifiers() & Qt::ShiftModifier)
344 newPoint3D.normalize();
347 direction_ += newPoint3D - oldPoint3D;
354 Vec3d axis = oldPoint3D % newPoint3D;
356 double cos_angle = ( oldPoint3D | newPoint3D );
358 if (fabs(cos_angle) < 1.0)
359 rotate(acos(cos_angle)*180.0/M_PI, axis);
362 else sphere_clicked_ =
false;
367 if(cylinder_clicked_)
371 mapToCylinder(_state, oldPoint2D_, old_axis_hit);
372 mapToCylinder(_state, newPoint2D, new_axis_hit);
375 if(_event->modifiers() & Qt::ShiftModifier)
377 scale(1.0 + (new_axis_hit - old_axis_hit) /
378 (cylinder_height_ * SCALE_CONST));
382 else if(_event->modifiers() & (Qt::ControlModifier |
385 rotate( 45.0 * (new_axis_hit-old_axis_hit) / cylinder_height_,
406 oldPoint2D_ = newPoint2D;
413 bool ManipulatorNode::hitSphere(
GLState& _state,
417 unsigned int x = _v2[0];
427 setup_sphere_system(_state);
428 _state.
scale(2*cylinder_radius_);
439 double a = direction.
sqrnorm(),
452 ManipulatorNode::mapToSphere(
GLState& _state,
457 unsigned int x = _v2[0];
471 _state.
scale(cylinder_height_ + 4*cylinder_radius_);
482 double a = direction.
sqrnorm(),
488 if (d < 0.0)
return false;
489 else if (d == 0.0) t = -b / (2.0*a);
494 double t1 = (-b - d) * a;
495 double t2 = (-b + d) * a;
496 t = (t1 < t2) ? t1 : t2;
502 _v3 = origin + direction*t;
512 ManipulatorNode::mapToCylinder(
GLState& _state,
517 unsigned int x = _v1[0];
527 setup_cylinder_system(_state);
537 const Vec3d origin2(0,0,0), direction2(0,0,1);
541 Vec3d normal = (direction % direction2).normalize();
542 Vec3d vd = ((origin2 - origin) % direction);
543 _axis_hit = (normal | vd);
545 double orthodistance = std::abs( ( origin2 - origin ) | normal);
549 return((orthodistance < cylinder_radius_) &&
551 (_axis_hit <= cylinder_height_));
560 if (draw_cylinder_) {
566 setup_cylinder_system(_state);
568 cylinder_->setBottomRadius(cylinder_radius_);
569 cylinder_->setTopRadius(cylinder_radius_);
570 cylinder_->draw(_state, cylinder_height_);
575 setup_sphere_system(_state);
577 if(_state.compatibilityProfile()) {
578 _state.
scale(2*cylinder_radius_,2*cylinder_radius_,2*cylinder_radius_);
580 sphere.draw_primitive();
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
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
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
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
int context_height() const
get gl context height
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
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