source: projectionDesigner/trunk/projdesigner/src/gui/QGLViewerWidget.cpp

Last change on this file was 433, checked in by Torben Dannhauer, 11 years ago
File size: 13.1 KB
Line 
1#include <float.h>
2#include <QMouseEvent>
3
4#include <GL/glu.h>     // Added! for gluPerspective() call. [ben 27Sep13]
5
6#include "gui/QGLViewerWidget.h"
7
8#define INERTIA_MAX 5.0f
9#define INERTIA_THRESHOLD 0.2f
10
11using namespace gmtl;
12
13static void dom2vp(const QDomElement& parent, gmtl::Vec3f& center, gmtl::Quatf& rot, float& distance)
14{
15    if (parent.isNull())
16        return;
17
18    center[0] = parent.attribute("centerx", "0").toFloat();
19    center[1] = parent.attribute("centery", "0").toFloat();
20    center[2] = parent.attribute("centerz", "0").toFloat();
21    rot[0] = parent.attribute("rotx", "0").toFloat();
22    rot[1] = parent.attribute("roty", "0").toFloat();
23    rot[2] = parent.attribute("rotz", "0").toFloat();
24    rot[3] = parent.attribute("rotw", "1").toFloat();
25    distance = parent.attribute("distance", "1").toFloat();
26}
27
28static QDomElement vp2dom(QDomDocument& doc, const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
29{
30    QDomElement cm = doc.createElement("Camera");
31    cm.setAttribute("centerx", QString::number(center[0]));
32    cm.setAttribute("centery", QString::number(center[1]));
33    cm.setAttribute("centerz", QString::number(center[2]));
34    cm.setAttribute("rotx", QString::number(rot[0]));
35    cm.setAttribute("roty", QString::number(rot[1]));
36    cm.setAttribute("rotz", QString::number(rot[2]));
37    cm.setAttribute("rotw", QString::number(rot[3]));
38    cm.setAttribute("distance", QString::number(distance));
39    return cm;
40}
41
42QGLViewerWidget::QGLViewerWidget(QWidget* pParent, const QGLWidget* pShareWidget, Qt::WindowFlags f) : QGLWidget(pParent, pShareWidget, f)
43{
44    m_bPerspective = true;
45    m_fovy = 45.0f;
46    m_znear = 0.01f;
47    m_zfar = 100.0f;
48
49    m_bInertia = true;
50    m_animX = 0.0f;
51    m_animY = 0.0f;
52    m_bAnimating = false;
53
54    m_clearColor = QColor(64, 64, 64);
55    m_sceneSize = 10.0f;
56    m_bGridVisible = false;
57    m_bAxisVisible = false;
58    m_gridSize = 10.0f;
59    m_gridSubdiv = 10;
60
61    viewAll();
62
63    m_timer.setInterval(30);
64    connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
65    m_timer.start();
66
67    setFocusPolicy(Qt::StrongFocus);
68}
69
70void QGLViewerWidget::setView(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
71{
72    m_center = center;
73    m_rot = rot;
74    m_distance = distance;
75    m_matrix = makeTrans<Matrix44f>(m_center) * makeRot<Matrix44f>(m_rot) * makeTrans<Matrix44f>(Vec3f(0.0f, 0.0f, m_distance));
76    invert(m_matrix);
77
78    emit cameraChanged(center, rot, distance);
79}
80
81void QGLViewerWidget::init()
82{
83}
84
85void QGLViewerWidget::draw()
86{
87}
88
89void QGLViewerWidget::idle()
90{
91}
92
93void QGLViewerWidget::stop()
94{
95    m_pivotCenter = m_center;
96    m_pivotRot = m_rot;
97    m_pivotDistance = m_distance;
98    m_pivotOrthoScale = m_orthoScale;
99    m_animX = 0.0f;
100    m_animY = 0.0f;
101    m_bAnimating = false;
102}
103
104void QGLViewerWidget::centerView()
105{
106    stop();
107    m_center = Vec3f(0.0f, 0.0f, 0.0f);
108    m_rot = Quatf();
109    m_distance = 0.0f;
110    m_orthoScale = 0.25f;
111    setView(m_center, m_rot, m_distance);
112    updateGL();
113}
114
115void QGLViewerWidget::viewAll()
116{
117    stop();
118    m_center = Vec3f(0.0f, 0.0f, 0.0f);
119    if (m_bPerspective)
120        m_distance = m_sceneSize * 0.5f;
121    else
122        m_distance = 0.0f;
123    m_orthoScale = 0.25f;
124    setView(m_center, m_rot, m_distance);
125    updateGL();
126}
127
128void QGLViewerWidget::drawGrid()
129{
130    if (m_gridSubdiv == 0)
131        return;
132
133    glPushAttrib(GL_ALL_ATTRIB_BITS);
134    glDisable(GL_TEXTURE_2D);
135    glDisable(GL_LIGHTING);
136    glDisable(GL_BLEND);
137    glEnable(GL_DEPTH_TEST);
138    glLineWidth(1.0f);
139    glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
140    glBegin(GL_LINES);
141    for (int x=0; x<m_gridSubdiv+1; ++x)
142    {
143        glVertex3f(-m_gridSize/2.0f+m_gridSize/m_gridSubdiv*x, 0.0f, -m_gridSize/2.0f);
144        glVertex3f(-m_gridSize/2.0f+m_gridSize/m_gridSubdiv*x, 0.0f,  m_gridSize/2.0f);
145    }
146    for (int y=0; y<m_gridSubdiv+1; ++y)
147    {
148        glVertex3f(-m_gridSize/2.0f, 0.0f, -m_gridSize/2.0f+m_gridSize/m_gridSubdiv*y);
149        glVertex3f( m_gridSize/2.0f, 0.0f, -m_gridSize/2.0f+m_gridSize/m_gridSubdiv*y);
150    }
151    glEnd();
152    glPopAttrib();
153}
154
155void QGLViewerWidget::drawAxis()
156{
157    glPushAttrib(GL_ALL_ATTRIB_BITS);
158    glDisable(GL_TEXTURE_2D);
159    glDisable(GL_LIGHTING);
160    glDisable(GL_BLEND);
161    glEnable(GL_DEPTH_TEST);
162    glLineWidth(3.0f);
163    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
164    glBegin(GL_LINES);
165    glVertex3f(0.0f, 0.0f, 0.0f);
166    glVertex3f(m_gridSize*0.6f, 0.0f, 0.0f);
167    glEnd();
168    glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
169    glBegin(GL_LINES);
170    glVertex3f(0.0f, 0.0f, 0.0f);
171    glVertex3f(0.0f, m_gridSize*0.6f, 0.0f);
172    glEnd();
173    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
174    glBegin(GL_LINES);
175    glVertex3f(0.0f, 0.0f, 0.0f);
176    glVertex3f(0.0f, 0.0f, m_gridSize*0.6f);
177    glEnd();
178    glPopAttrib();
179}
180
181void QGLViewerWidget::initializeGL()
182{
183    init();
184}
185
186void QGLViewerWidget::paintGL()
187{
188    glViewport(0, 0, width(), height());
189
190    glClearColor((float)m_clearColor.red() / 255.0f,
191                 (float)m_clearColor.green() / 255.0f,
192                 (float)m_clearColor.blue() / 255.0f,
193                 1.0f);
194                 
195    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
196
197    glMatrixMode(GL_PROJECTION);
198    glLoadIdentity();
199
200    float aspect = 1.0f;
201    if (height() > 0)
202        aspect = (float)width()/height();
203    if (m_bPerspective)
204        gluPerspective(m_fovy, aspect, m_znear, m_zfar);
205    else
206    {
207        float size = m_sceneSize * m_orthoScale;
208        glOrtho(-size*aspect, size*aspect, -size, size, -m_sceneSize*4.0f, m_sceneSize*4.0f);
209    }
210
211    glMatrixMode(GL_MODELVIEW);
212    glLoadMatrixf(m_matrix.getData());
213
214    glEnable(GL_LIGHTING);
215    glEnable(GL_LIGHT0);
216    Vec3f pos = Vec3f(1.0f, 1.0f, 1.0f);
217    if (!isnan(m_rot[0]))
218        pos = m_rot * pos;
219    GLfloat lposition[] = { pos[0], pos[1], pos[2], 0.0f };
220    GLfloat lambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
221    GLfloat ldiffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
222    glLightfv(GL_LIGHT0, GL_POSITION, lposition);
223    glLightfv(GL_LIGHT0, GL_AMBIENT, lambient);
224    glLightfv(GL_LIGHT0, GL_DIFFUSE, ldiffuse);
225
226    glEnable(GL_DEPTH_TEST);
227    glEnable(GL_COLOR_MATERIAL);
228    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
229
230    draw();
231
232    glDisable(GL_LIGHTING);
233
234    if (m_bGridVisible)
235        drawGrid();
236
237    if (m_bAxisVisible)
238        drawAxis();
239
240    glFlush();
241}
242
243void QGLViewerWidget::mousePressEvent(QMouseEvent* pEvent)
244{
245    m_timer.stop();
246
247    stop();
248
249    m_lastMousePos = pEvent->pos();
250    m_lastTime = QTime::currentTime();
251
252    setMouseTracking(true);
253}
254
255void QGLViewerWidget::mouseMoveEvent(QMouseEvent* pEvent)
256{
257    if (m_bPerspective && (pEvent->buttons() & Qt::LeftButton))
258    {
259        float delta = (float)m_lastTime.msecsTo(QTime::currentTime()) / 1000.0f;
260        float deltaX = ((float)(pEvent->x()-m_lastMousePos.x())/width()*90.0f) / 180.0f * Math::PI;
261        float deltaY = ((float)(pEvent->y()-m_lastMousePos.y())/height()*90.0f) / 180.0f * Math::PI;
262        if (delta != 0.0f && (fabs(deltaX / delta) > INERTIA_THRESHOLD || fabs(deltaY / delta) > INERTIA_THRESHOLD))
263        {
264            m_animX = deltaX / delta;
265            m_animY = deltaY / delta;
266            float length = sqrt(m_animX*m_animX+m_animY*m_animY);
267            if (length > INERTIA_MAX)
268            {
269                m_animX = m_animX / length * INERTIA_MAX;
270                m_animY = m_animY / length * INERTIA_MAX;
271            }
272        }
273        else
274        {
275            m_animX = 0.0f;
276            m_animY = 0.0f;
277        }
278        m_rot = m_pivotRot * make<Quatf>(AxisAnglef(-deltaX, Vec3f(0.0f, 1.0f, 0.0f))) *
279                             make<Quatf>(AxisAnglef(-deltaY, Vec3f(1.0f, 0.0f, 0.0f)));
280    }
281    else if (pEvent->buttons() & Qt::MidButton ||
282             (!m_bPerspective && pEvent->buttons() & Qt::LeftButton))
283    {
284        float deltaX = (float)(pEvent->x()-m_lastMousePos.x())/width();
285        float deltaY = (float)(pEvent->y()-m_lastMousePos.y())/height();
286        Vec3f panX = m_rot * Vec3f(-deltaX, 0.0f, 0.0f);
287        Vec3f panY = m_rot * Vec3f(0.0f, deltaY, 0.0f);
288        m_center = m_pivotCenter + panX + panY;
289    }
290    else if (m_bPerspective && (pEvent->buttons() & Qt::RightButton))
291    {
292        if (m_distance > 0.0f)
293        {
294            m_distance = m_pivotDistance - m_pivotDistance * (float)(pEvent->y()-m_lastMousePos.y())/height() * 1.0f;
295            if (m_distance < m_znear*2.0f)
296                m_distance = m_znear*2.0f;
297        }
298    }
299    else if (!m_bPerspective && (pEvent->buttons() & Qt::RightButton))
300    {
301        m_orthoScale = m_pivotOrthoScale - m_pivotOrthoScale * (float)(pEvent->y()-m_lastMousePos.y())/height() * 1.0f;
302        if (m_orthoScale < 0.01f)
303            m_orthoScale = 0.01f;
304    }
305
306    setView(m_center, m_rot, m_distance);
307    m_lastTime = QTime::currentTime();
308
309    updateGL();
310}
311
312void QGLViewerWidget::mouseReleaseEvent(QMouseEvent* pEvent)
313{
314    Q_UNUSED(pEvent);
315
316    if (m_lastTime.msecsTo(QTime::currentTime()) > 50 || !m_bInertia)
317    {
318        m_animX = 0.0f;
319        m_animY = 0.0f;
320        m_bAnimating = false;
321    }
322    if (m_animX != 0.0f || m_animY != 0.0f)
323        m_bAnimating = true;
324
325    setMouseTracking(false);
326
327    m_timer.start();
328}
329
330void QGLViewerWidget::wheelEvent(QWheelEvent* pEvent)
331{
332    if (m_bPerspective)
333    {
334        if (pEvent->delta() > 0.0f)
335            setView(m_center, m_rot, m_distance * 1.1f);
336        else
337            setView(m_center, m_rot, m_distance / 1.1f);
338    }
339    else
340    {
341        if (pEvent->delta() > 0.0f)
342            m_orthoScale *= 1.1f;
343        else
344            m_orthoScale /= 1.1f;
345        if (m_orthoScale < 0.01f)
346            m_orthoScale = 0.01f;
347    }
348
349    updateGL();
350}
351
352void QGLViewerWidget::keyReleaseEvent(QKeyEvent* pEvent)
353{
354    QGLWidget::keyReleaseEvent(pEvent);
355
356        switch (pEvent->key())
357        {
358        case Qt::Key_A:
359        setAxisVisible(!m_bAxisVisible);
360        updateGL();
361                break;
362        case Qt::Key_G:
363        setGridVisible(!m_bGridVisible);
364        updateGL();
365                break;
366        case Qt::Key_R:
367        viewAll();
368                break;
369        default:
370                return;
371        }
372}
373
374void QGLViewerWidget::timeout()
375{
376    if (m_bAnimating)
377    {
378        float delta = (float)m_lastTime.msecsTo(QTime::currentTime()) / 1000.0f;
379        Quatf deltaRot = 
380            make<Quatf>(AxisAnglef(-m_animX*delta, Vec3f(0.0f, 1.0f, 0.0f))) *
381            make<Quatf>(AxisAnglef(-m_animY*delta, Vec3f(1.0f, 0.0f, 0.0f)));
382        Quatf rot = m_rot * deltaRot;
383        if (!isnan(rot[0]))
384            setView(m_center, rot, m_distance);
385        m_lastTime = QTime::currentTime();
386    }
387
388    idle();
389
390    if (m_bAnimating)
391        updateGL();
392}
393
394void QGLViewerWidget::initFromDOMElement(const QDomElement& element)
395{
396        if (!element.isNull())
397        {
398                QDomElement camera = element.firstChildElement("Camera");
399        dom2vp(camera, m_center, m_rot, m_distance);
400        m_bPerspective = (element.attribute("perspective", "true")=="true");
401        m_fovy = element.attribute("fovy", QString::number(45.0f)).toFloat();
402        m_orthoScale = element.attribute("orthoScale", QString::number(0.25f)).toFloat();
403        m_znear = element.attribute("near", QString::number(0.01f)).toFloat();
404        m_zfar = element.attribute("far", QString::number(100.0f)).toFloat();
405        m_bInertia = (element.attribute("inertia", "true")=="true");
406        m_clearColor = QColor(element.attribute("clearColor", QColor(64, 64, 64).name()));
407        m_bGridVisible = (element.attribute("grid", "true")=="true");
408        m_bAxisVisible = (element.attribute("axis", "true")=="true");
409        m_sceneSize = element.attribute("sceneSize", QString::number(10.0f)).toFloat();
410        if (!parentWidget())
411        {
412            move(element.attribute("x", QString::number(x())).toInt(), element.attribute("y", QString::number(y())).toInt());
413            resize(element.attribute("width", QString::number(width())).toInt(), element.attribute("height", QString::number(height())).toInt());
414        }
415        setView(m_center, m_rot, m_distance);
416        stop();
417        }
418}
419
420QDomElement QGLViewerWidget::domElement(const QString& name, QDomDocument& doc) const
421{
422        QDomElement de = doc.createElement(name);
423    de.appendChild(vp2dom(doc, m_center, m_rot, m_distance));
424    de.setAttribute("perspective", m_bPerspective?"true":"false");
425    de.setAttribute("fovy", m_fovy);
426    de.setAttribute("orthoScale", m_orthoScale);
427    de.setAttribute("near", m_znear);
428    de.setAttribute("far", m_zfar);
429    de.setAttribute("inertia", m_bInertia?"true":"false");
430    de.setAttribute("clearColor", m_clearColor.name());
431    de.setAttribute("grid", m_bGridVisible?"true":"false");
432    de.setAttribute("axis", m_bAxisVisible?"true":"false");
433    de.setAttribute("sceneSize", m_sceneSize);
434    if (!parentWidget())
435    {
436        de.setAttribute("x", x());
437        de.setAttribute("y", y());
438        de.setAttribute("width", width());
439        de.setAttribute("height", height());
440    }
441    return de;
442}
Note: See TracBrowser for help on using the repository browser.