From b24809f39e9a7a7fe1e64bc5fd8ee3785d710725 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 28 Oct 2010 16:49:32 +0000 Subject: [PATCH] initial dragging attempt... failed so far git-svn-id: svn://anubis/misc/sierpinski-gtk@256 bd8a9e45-a331-0410-811e-c64571078777 --- SierpinskiDA.cc | 72 +++++++++++++++--- SierpinskiDA.h | 8 +- Vector.h | 196 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 10 deletions(-) create mode 100644 Vector.h diff --git a/SierpinskiDA.cc b/SierpinskiDA.cc index 2275418..28d9729 100644 --- a/SierpinskiDA.cc +++ b/SierpinskiDA.cc @@ -9,6 +9,7 @@ #include #include "SierpinskiDA.h" +#include "Vector.h" using namespace std; @@ -22,6 +23,7 @@ SierpinskiDA::SierpinskiDA(const Glib::RefPtr & config, | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + m_dragging = false; } void SierpinskiDA::regenerate_clicked() @@ -84,17 +86,14 @@ bool SierpinskiDA::draw() glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(60, get_width()/(double)get_height(), 0.01, 1000.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(0, -3, 1.5, - 0, 0, 1, - 0, 0, 1); + + glPushMatrix(); + glMultMatrixf(m_drag_matrix); glCallList(m_dl); + glPopMatrix(); + if (get_gl_window()->is_double_buffered()) get_gl_window()->swap_buffers(); else @@ -106,17 +105,48 @@ bool SierpinskiDA::draw() bool SierpinskiDA::on_motion_notify_event(GdkEventMotion * event) { - get_pointer(m_x, m_y); + if (m_dragging) + { + Vector v = ptrToDragVector(); + Vector cross = m_dragBegin * v; + if (cross.mag2() > 0.5) + { + gl_begin(); + glPushMatrix(); + glLoadIdentity(); + glRotated(180.0 * acos(m_dragBegin % v) / M_PI, + cross[0], cross[1], cross[2]); + glGetFloatv(GL_MODELVIEW_MATRIX, &m_drag_matrix[0]); + glPopMatrix(); + gl_end(); + } + queue_draw(); + } return true; } bool SierpinskiDA::on_button_press_event(GdkEventButton * event) { + if (event->button == 1) + { + m_dragging = true; + m_dragBegin = ptrToDragVector(); + } return false; } bool SierpinskiDA::on_button_release_event(GdkEventButton * event) { + if (event->button == 1) + { + m_dragging = false; + gl_begin(); + glPushMatrix(); + glLoadIdentity(); + glGetFloatv(GL_MODELVIEW_MATRIX, &m_drag_matrix[0]); + glPopMatrix(); + gl_end(); + } return false; } @@ -143,6 +173,16 @@ void SierpinskiDA::on_realize() #endif glColor3f(1, 1, 1); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, get_width()/(double)get_height(), 0.01, 1000.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glGetFloatv(GL_MODELVIEW_MATRIX, &m_drag_matrix[0]); + gluLookAt(0, -3, 1.5, + 0, 0, 1, + 0, 0, 1); + gl_end(); regenerate(10000); @@ -167,3 +207,17 @@ bool SierpinskiDA::on_expose_event(GdkEventExpose * event) { return draw(); } + +Vector SierpinskiDA::ptrToDragVector() +{ + int x, y; + get_pointer(x, y); + int w = get_width(); + int h = get_height(); + double r = min(w, h) / 2.0; + double xd = (x - w/2.0) / r; + double yd = (h/2.0 - y) / r; + double d2 = xd*xd + yd*yd; + double z = d2 >= 1.0 ? 0.0 : sqrt(1 - d2); + return Vector(xd, yd, z).normalize(); +} diff --git a/SierpinskiDA.h b/SierpinskiDA.h index a0322cc..5ca8805 100644 --- a/SierpinskiDA.h +++ b/SierpinskiDA.h @@ -4,6 +4,8 @@ #include +#include "Vector.h" + class SierpinskiDA : public Gtk::GL::DrawingArea { public: @@ -13,7 +15,9 @@ class SierpinskiDA : public Gtk::GL::DrawingArea void regenerate_clicked(); protected: - int m_x, m_y; + bool m_dragging; + Vector m_dragBegin; + float m_drag_matrix[16]; int m_dl; Gtk::Entry & m_n_points_entry; @@ -24,6 +28,8 @@ class SierpinskiDA : public Gtk::GL::DrawingArea bool gl_begin(); void gl_end(); + Vector ptrToDragVector(); + /* signal handlers */ virtual bool on_motion_notify_event(GdkEventMotion * event); virtual bool on_button_press_event(GdkEventButton * event); diff --git a/Vector.h b/Vector.h new file mode 100644 index 0000000..7c6f55d --- /dev/null +++ b/Vector.h @@ -0,0 +1,196 @@ + +#ifndef VECTOR_H +#define VECTOR_H VECTOR_H + +#include /* sqrt() */ + +#include + +class Vector +{ + public: + Vector() + { + m_array[0] = 0.0; + m_array[1] = 0.0; + m_array[2] = 0.0; + } + + Vector(double x, double y, double z) + { + m_array[0] = x; + m_array[1] = y; + m_array[2] = z; + } + + Vector & normalize() + { + double length = mag(); + m_array[0] /= length; + m_array[1] /= length; + m_array[2] /= length; + return *this; + } + + double mag() const + { + return sqrt(m_array[0] * m_array[0] + + m_array[1] * m_array[1] + + m_array[2] * m_array[2]); + } + + double mag2() const + { + return m_array[0] * m_array[0] + + m_array[1] * m_array[1] + + m_array[2] * m_array[2]; + } + + double dist_to(const Vector & other) const + { + return (other - *this).mag(); + } + + Vector proj(const Vector & target) const + { + Vector target_normalized = target; + target_normalized.normalize(); + return target_normalized * ((*this) % target_normalized); + } + + Vector reflect(const Vector & target) const + { + return (*this) - target * (2 * dot(target)); + } + + /* + * from http://www.flipcode.com/archives/ + * Reflections_and_Refraction_in_Raytracing.shtml + * target: normal vector of surface + * n1: refraction index of object we're coming from + * n2: refraction index of object we're going into + */ + Vector refract(const Vector & target, double n1, double n2) const + { + const double n = n1 / n2; + const double cosI = -dot(target); + const double sinT2 = n * n * (1.0 - cosI * cosI); + if (sinT2 > 1.0) + return Vector(0.0, 0.0, 0.0); + return (*this) * n + target * (n * cosI - sqrt(1.0 - sinT2)); + } + + Vector getPerpendicular() const + { + Vector t = *this; + t.normalize(); + Vector p = t * Vector(0, 0, 1); + if (p.mag() <= 0.1) + { + p = t * Vector(1, 0, 0); + } + return p; + } + + Vector mult(const Vector & v2) const + { + return Vector( + m_array[0] * v2.m_array[0], + m_array[1] * v2.m_array[1], + m_array[2] * v2.m_array[2]); + } + + Vector div(const Vector & v2) const + { + return Vector( + m_array[0] / v2.m_array[0], + m_array[1] / v2.m_array[1], + m_array[2] / v2.m_array[2]); + } + + Vector operator-() const + { + return Vector( + -m_array[0], + -m_array[1], + -m_array[2]); + } + + /* Compute the dot-product of two vectors */ + double dot(const Vector & v2) const + { + return m_array[0] * v2.m_array[0] + + m_array[1] * v2.m_array[1] + + m_array[2] * v2.m_array[2]; + } + double operator%(const Vector & v2) const { return dot(v2); } + + /* Compute the cross-product of two vectors */ + Vector cross(const Vector & v2) const + { + return Vector( + m_array[1] * v2.m_array[2] - m_array[2] * v2.m_array[1], + m_array[2] * v2.m_array[0] - m_array[0] * v2.m_array[2], + m_array[0] * v2.m_array[1] - m_array[1] * v2.m_array[0]); + } + Vector operator*(const Vector & v2) const { return cross(v2); } + + Vector operator+(const Vector & v2) const + { + return Vector( + m_array[0] + v2.m_array[0], + m_array[1] + v2.m_array[1], + m_array[2] + v2.m_array[2]); + } + + Vector operator-(const Vector & v2) const + { + return Vector( + m_array[0] - v2.m_array[0], + m_array[1] - v2.m_array[1], + m_array[2] - v2.m_array[2]); + } + + Vector operator*(double scale) const + { + return Vector( + m_array[0] * scale, + m_array[1] * scale, + m_array[2] * scale); + } + + Vector operator/(double scale) const + { + return Vector( + m_array[0] / scale, + m_array[0] / scale, + m_array[0] / scale); + } + + Vector & operator+=(const Vector & v2) + { + m_array[0] += v2.m_array[0]; + m_array[1] += v2.m_array[1]; + m_array[2] += v2.m_array[2]; + return *this; + } + + Vector & operator-=(const Vector & v2) + { + m_array[0] -= v2.m_array[0]; + m_array[1] -= v2.m_array[1]; + m_array[2] -= v2.m_array[2]; + return *this; + } + + double & operator[](int idx) { return m_array[idx]; } + double operator[](int idx) const { return m_array[idx]; } + + protected: + double m_array[3]; +}; + +static inline Vector operator*(double d, const Vector & v) { return v * d; } +static inline Vector operator/(double d, const Vector & v) { return v / d; } + +#endif