1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library 2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra. 3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla 7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed 8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "quaternion_demo.h" 11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "icosphere.h" 12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/Geometry> 14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/QR> 15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/LU> 16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <iostream> 18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QEvent> 19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QMouseEvent> 20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QInputDialog> 21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QGridLayout> 22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QButtonGroup> 23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QRadioButton> 24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QDockWidget> 25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QPushButton> 26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <QGroupBox> 27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathusing namespace Eigen; 29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass FancySpheres 31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath public: 33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath EIGEN_MAKE_ALIGNED_OPERATOR_NEW 34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath FancySpheres() 36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const int levels = 4; 38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const float scale = 0.33; 39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float radius = 100; 40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::vector<int> parents; 41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // leval 0 43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCenters.push_back(Vector3f::Zero()); 44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath parents.push_back(-1); 45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRadii.push_back(radius); 46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // generate level 1 using icosphere vertices 48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath radius *= 0.45; 49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float dist = mRadii[0]*0.9; 51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for (int i=0; i<12; ++i) 52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCenters.push_back(mIcoSphere.vertices()[i] * dist); 54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRadii.push_back(radius); 55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath parents.push_back(0); 56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static const float angles [10] = { 60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 0, 0, 61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath M_PI, 0.*M_PI, 62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath M_PI, 0.5*M_PI, 63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath M_PI, 1.*M_PI, 64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath M_PI, 1.5*M_PI 65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath }; 66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // generate other levels 68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int start = 1; 69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for (int l=1; l<levels; l++) 70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath radius *= scale; 72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int end = mCenters.size(); 73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for (int i=start; i<end; ++i) 74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f c = mCenters[i]; 76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f ax0 = (c - mCenters[parents[i]]).normalized(); 77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f ax1 = ax0.unitOrthogonal(); 78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Quaternionf q; 79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath q.setFromTwoVectors(Vector3f::UnitZ(), ax0); 80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Affine3f t = Translation3f(c) * q * Scaling(mRadii[i]+radius); 81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for (int j=0; j<5; ++j) 82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f newC = c + ( (AngleAxisf(angles[j*2+1], ax0) 84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * AngleAxisf(angles[j*2+0] * (l==1 ? 0.35 : 0.5), ax1)) * ax0) 85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * (mRadii[i] + radius*0.8); 86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCenters.push_back(newC); 87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRadii.push_back(radius); 88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath parents.push_back(i); 89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath start = end; 92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath void draw() 96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int end = mCenters.size(); 98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnable(GL_NORMALIZE); 99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for (int i=0; i<end; ++i) 100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Affine3f t = Translation3f(mCenters[i]) * Scaling(mRadii[i]); 102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.pushMatrix(GL_MODELVIEW); 103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.multMatrix(t.matrix(),GL_MODELVIEW); 104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mIcoSphere.draw(2); 105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.popMatrix(GL_MODELVIEW); 106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_NORMALIZE); 108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath protected: 110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::vector<Vector3f> mCenters; 111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::vector<float> mRadii; 112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath IcoSphere mIcoSphere; 113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// generic linear interpolation method 117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T> T lerp(float t, const T& a, const T& b) 118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return a*(1-t) + b*t; 120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// quaternion slerp 123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<> Quaternionf lerp(float t, const Quaternionf& a, const Quaternionf& b) 124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ return a.slerp(t,b); } 125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// linear interpolation of a frame using the type OrientationType 127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// to perform the interpolation of the orientations 128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename OrientationType> 129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathinline static Frame lerpFrame(float alpha, const Frame& a, const Frame& b) 130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return Frame(lerp(alpha,a.position,b.position), 132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Quaternionf(lerp(alpha,OrientationType(a.orientation),OrientationType(b.orientation)))); 133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar> class EulerAngles 136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath enum { Dim = 3 }; 139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef _Scalar Scalar; 140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar,3,3> Matrix3; 141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Matrix<Scalar,3,1> Vector3; 142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef Quaternion<Scalar> QuaternionType; 143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathprotected: 145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3 m_angles; 147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic: 149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath EulerAngles() {} 151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath inline EulerAngles(Scalar a0, Scalar a1, Scalar a2) : m_angles(a0, a1, a2) {} 152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath inline EulerAngles(const QuaternionType& q) { *this = q; } 153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath const Vector3& coeffs() const { return m_angles; } 155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3& coeffs() { return m_angles; } 156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath EulerAngles& operator=(const QuaternionType& q) 158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix3 m = q.toRotationMatrix(); 160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return *this = m; 161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath EulerAngles& operator=(const Matrix3& m) 164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // mat = cy*cz -cy*sz sy 166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx 167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy 168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_angles.coeffRef(1) = std::asin(m.coeff(0,2)); 169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_angles.coeffRef(0) = std::atan2(-m.coeff(1,2),m.coeff(2,2)); 170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_angles.coeffRef(2) = std::atan2(-m.coeff(0,1),m.coeff(0,0)); 171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return *this; 172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix3 toRotationMatrix(void) const 175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3 c = m_angles.array().cos(); 177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3 s = m_angles.array().sin(); 178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Matrix3 res; 179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res << c.y()*c.z(), -c.y()*s.z(), s.y(), 180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath c.z()*s.x()*s.y()+c.x()*s.z(), c.x()*c.z()-s.x()*s.y()*s.z(), -c.y()*s.x(), 181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath -c.x()*c.z()*s.y()+s.x()*s.z(), c.z()*s.x()+c.x()*s.y()*s.z(), c.x()*c.y(); 182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath operator QuaternionType() { return QuaternionType(toRotationMatrix()); } 186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}; 187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Euler angles slerp 189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<> EulerAngles<float> lerp(float t, const EulerAngles<float>& a, const EulerAngles<float>& b) 190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath EulerAngles<float> res; 192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath res.coeffs() = lerp(t, a.coeffs(), b.coeffs()); 193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return res; 194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathRenderingWidget::RenderingWidget() 198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mAnimate = false; 200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_NO_TRACK; 201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mNavMode = NavTurnAround; 202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mLerpMode = LerpQuaternion; 203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRotationMode = RotationStable; 204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mTrackball.setCamera(&mCamera); 205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // required to capture key press events 207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath setFocusPolicy(Qt::ClickFocus); 208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::grabFrame(void) 211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // ask user for a time 213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath bool ok = false; 214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath double t = 0; 215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (!m_timeline.empty()) 216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath t = (--m_timeline.end())->first + 1.; 217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath t = QInputDialog::getDouble(this, "Eigen's RenderingWidget", "time value: ", 218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath t, 0, 1e3, 1, &ok); 219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (ok) 220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Frame aux; 222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux.orientation = mCamera.viewMatrix().linear(); 223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux.position = mCamera.viewMatrix().translation(); 224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline[t] = aux; 225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::drawScene() 229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath static FancySpheres sFancySpheres; 231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float length = 50; 232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitX(), Color(1,0,0,1)); 233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitY(), Color(0,1,0,1)); 234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitZ(), Color(0,0,1,1)); 235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // draw the fractal object 237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float sqrt3 = internal::sqrt(3.); 238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT0, GL_AMBIENT, Vector4f(0.5,0.5,0.5,1).data()); 239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT0, GL_DIFFUSE, Vector4f(0.5,1,0.5,1).data()); 240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT0, GL_SPECULAR, Vector4f(1,1,1,1).data()); 241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT0, GL_POSITION, Vector4f(-sqrt3,-sqrt3,sqrt3,0).data()); 242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT1, GL_AMBIENT, Vector4f(0,0,0,1).data()); 244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT1, GL_DIFFUSE, Vector4f(1,0.5,0.5,1).data()); 245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT1, GL_SPECULAR, Vector4f(1,1,1,1).data()); 246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightfv(GL_LIGHT1, GL_POSITION, Vector4f(-sqrt3,sqrt3,-sqrt3,0).data()); 247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Vector4f(0.7, 0.7, 0.7, 1).data()); 249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Vector4f(0.8, 0.75, 0.6, 1).data()); 250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Vector4f(1, 1, 1, 1).data()); 251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64); 252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnable(GL_LIGHTING); 254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnable(GL_LIGHT0); 255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnable(GL_LIGHT1); 256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath sFancySpheres.draw(); 258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data()); 259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glNormalPointer(GL_FLOAT, 0, mNormals[0].data()); 260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnableClientState(GL_VERTEX_ARRAY); 261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnableClientState(GL_NORMAL_ARRAY); 262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDrawArrays(GL_TRIANGLES, 0, mVertices.size()); 263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisableClientState(GL_VERTEX_ARRAY); 264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisableClientState(GL_NORMAL_ARRAY); 265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_LIGHTING); 267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::animate() 270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_alpha += double(m_timer.interval()) * 1e-3; 272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath TimeLine::const_iterator hi = m_timeline.upper_bound(m_alpha); 274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath TimeLine::const_iterator lo = hi; 275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath --lo; 276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Frame currentFrame; 278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(hi==m_timeline.end()) 280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // end 282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame = lo->second; 283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath stopAnimation(); 284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else if(hi==m_timeline.begin()) 286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // start 288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame = hi->second; 289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float s = (m_alpha - lo->first)/(hi->first - lo->first); 293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (mLerpMode==LerpEulerAngles) 294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame = ::lerpFrame<EulerAngles<float> >(s, lo->second, hi->second); 295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else if (mLerpMode==LerpQuaternion) 296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame = ::lerpFrame<Eigen::Quaternionf>(s, lo->second, hi->second); 297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cerr << "Invalid rotation interpolation mode (abort)\n"; 300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath exit(2); 301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame.orientation.coeffs().normalize(); 303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame.orientation = currentFrame.orientation.inverse(); 306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath currentFrame.position = - (currentFrame.orientation * currentFrame.position); 307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setFrame(currentFrame); 308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath updateGL(); 310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::keyPressEvent(QKeyEvent * e) 313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath switch(e->key()) 315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_Up: 317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.zoom(2); 318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_Down: 320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.zoom(-2); 321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // add a frame 323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_G: 324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath grabFrame(); 325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // clear the time line 327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_C: 328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline.clear(); 329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // move the camera to initial pos 331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_R: 332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath resetCamera(); 333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // start/stop the animation 335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::Key_A: 336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (mAnimate) 337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath stopAnimation(); 339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_alpha = 0; 343c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate())); 344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timer.start(1000/30); 345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mAnimate = true; 346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 347c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath default: 349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath updateGL(); 353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::stopAnimation() 356c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(animate())); 358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timer.stop(); 359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mAnimate = false; 360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_alpha = 0; 361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::mousePressEvent(QMouseEvent* e) 364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mMouseCoords = Vector2i(e->pos().x(), e->pos().y()); 366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath bool fly = (mNavMode==NavFly) || (e->modifiers()&Qt::ControlModifier); 367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath switch(e->button()) 368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::LeftButton: 370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(fly) 371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 372c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_LOCAL_ROTATE; 373c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mTrackball.start(Trackball::Local); 374c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 375c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 376c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 377c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_ROTATE_AROUND; 378c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mTrackball.start(Trackball::Around); 379c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 380c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mTrackball.track(mMouseCoords); 381c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 382c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::MidButton: 383c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(fly) 384c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_FLY_Z; 385c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 386c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_ZOOM; 387c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 388c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case Qt::RightButton: 389c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_FLY_PAN; 390c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 391c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath default: 392c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 393c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 394c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 395c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::mouseReleaseEvent(QMouseEvent*) 396c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 397c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCurrentTrackingMode = TM_NO_TRACK; 398c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath updateGL(); 399c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 400c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 401c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::mouseMoveEvent(QMouseEvent* e) 402c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 403c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // tracking 404c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(mCurrentTrackingMode != TM_NO_TRACK) 405c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 406c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float dx = float(e->x() - mMouseCoords.x()) / float(mCamera.vpWidth()); 407c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float dy = - float(e->y() - mMouseCoords.y()) / float(mCamera.vpHeight()); 408c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 409c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // speedup the transformations 410c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(e->modifiers() & Qt::ShiftModifier) 411c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 412c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dx *= 10.; 413c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dy *= 10.; 414c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 415c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 416c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath switch(mCurrentTrackingMode) 417c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 418c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case TM_ROTATE_AROUND: 419c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case TM_LOCAL_ROTATE: 420c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (mRotationMode==RotationStable) 421c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 422c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // use the stable trackball implementation mapping 423c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // the 2D coordinates to 3D points on a sphere. 424c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mTrackball.track(Vector2i(e->pos().x(), e->pos().y())); 425c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 426c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 427c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 428c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // standard approach mapping the x and y displacements as rotations 429c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // around the camera's X and Y axes. 430c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Quaternionf q = AngleAxisf( dx*M_PI, Vector3f::UnitY()) 431c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * AngleAxisf(-dy*M_PI, Vector3f::UnitX()); 432c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (mCurrentTrackingMode==TM_LOCAL_ROTATE) 433c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.localRotate(q); 434c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 435c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.rotateAroundTarget(q); 436c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 437c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 438c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case TM_ZOOM : 439c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.zoom(dy*100); 440c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 441c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case TM_FLY_Z : 442c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.localTranslate(Vector3f(0, 0, -dy*200)); 443c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 444c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath case TM_FLY_PAN : 445c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.localTranslate(Vector3f(dx*200, dy*200, 0)); 446c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 447c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath default: 448c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath break; 449c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 450c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 451c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath updateGL(); 452c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 453c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 454c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mMouseCoords = Vector2i(e->pos().x(), e->pos().y()); 455c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 456c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 457c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::paintGL() 458c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 459c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glEnable(GL_DEPTH_TEST); 460c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_CULL_FACE); 461c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 462c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_COLOR_MATERIAL); 463c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_BLEND); 464c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_ALPHA_TEST); 465c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_TEXTURE_1D); 466c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_TEXTURE_2D); 467c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDisable(GL_TEXTURE_3D); 468c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 469c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // Clear buffers 470c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 471c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 472c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.activateGL(); 473c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 474c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath drawScene(); 475c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 476c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 477c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::initializeGL() 478c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 479c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glClearColor(1., 1., 1., 0.); 480c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); 481c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glDepthMask(GL_TRUE); 482c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 483c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 484c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setPosition(Vector3f(-200, -200, -200)); 485c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setTarget(Vector3f(0, 0, 0)); 486c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mInitFrame.orientation = mCamera.orientation().inverse(); 487c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mInitFrame.position = mCamera.viewMatrix().translation(); 488c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 489c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 490c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::resizeGL(int width, int height) 491c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 492c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setViewport(width,height); 493c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 494c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 495c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::setNavMode(int m) 496c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 497c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mNavMode = NavMode(m); 498c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 499c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 500c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::setLerpMode(int m) 501c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 502c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mLerpMode = LerpMode(m); 503c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 504c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 505c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::setRotationMode(int m) 506c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 507c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRotationMode = RotationMode(m); 508c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 509c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 510c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid RenderingWidget::resetCamera() 511c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 512c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (mAnimate) 513c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath stopAnimation(); 514c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline.clear(); 515c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Frame aux0 = mCamera.frame(); 516c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux0.orientation = aux0.orientation.inverse(); 517c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux0.position = mCamera.viewMatrix().translation(); 518c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline[0] = aux0; 519c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 520c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Vector3f currentTarget = mCamera.target(); 521c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setTarget(Vector3f::Zero()); 522c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 523c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // compute the rotation duration to move the camera to the target 524c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Frame aux1 = mCamera.frame(); 525c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.orientation = aux1.orientation.inverse(); 526c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.position = mCamera.viewMatrix().translation(); 527c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath float duration = aux0.orientation.angularDistance(aux1.orientation) * 0.9; 528c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if (duration<0.1) duration = 0.1; 529c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 530c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // put the camera at that time step: 531c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1 = aux0.lerp(duration/2,mInitFrame); 532c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // and make it look at the target again 533c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.orientation = aux1.orientation.inverse(); 534c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.position = - (aux1.orientation * aux1.position); 535c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setFrame(aux1); 536c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mCamera.setTarget(Vector3f::Zero()); 537c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 538c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // add this camera keyframe 539c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.orientation = aux1.orientation.inverse(); 540c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath aux1.position = mCamera.viewMatrix().translation(); 541c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline[duration] = aux1; 542c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 543c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timeline[2] = mInitFrame; 544c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_alpha = 0; 545c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath animate(); 546c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate())); 547c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath m_timer.start(1000/30); 548c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mAnimate = true; 549c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 550c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 551c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathQWidget* RenderingWidget::createNavigationControlWidget() 552c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 553c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QWidget* panel = new QWidget(); 554c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QVBoxLayout* layout = new QVBoxLayout(); 555c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 556c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 557c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QPushButton* but = new QPushButton("reset"); 558c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("move the camera to initial position (with animation)"); 559c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath layout->addWidget(but); 560c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(but, SIGNAL(clicked()), this, SLOT(resetCamera())); 561c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 562c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 563c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // navigation mode 564c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QGroupBox* box = new QGroupBox("navigation mode"); 565c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QVBoxLayout* boxLayout = new QVBoxLayout; 566c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QButtonGroup* group = new QButtonGroup(panel); 567c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QRadioButton* but; 568c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("turn around"); 569c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("look around an object"); 570c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, NavTurnAround); 571c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 572c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("fly"); 573c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("free navigation like a spaceship\n(this mode can also be enabled pressing the \"shift\" key)"); 574c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, NavFly); 575c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 576c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->button(mNavMode)->setChecked(true); 577c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setNavMode(int))); 578c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath box->setLayout(boxLayout); 579c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath layout->addWidget(box); 580c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 581c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 582c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // track ball, rotation mode 583c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QGroupBox* box = new QGroupBox("rotation mode"); 584c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QVBoxLayout* boxLayout = new QVBoxLayout; 585c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QButtonGroup* group = new QButtonGroup(panel); 586c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QRadioButton* but; 587c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("stable trackball"); 588c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, RotationStable); 589c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 590c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("use the stable trackball implementation mapping\nthe 2D coordinates to 3D points on a sphere"); 591c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("standard rotation"); 592c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, RotationStandard); 593c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 594c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("standard approach mapping the x and y displacements\nas rotations around the camera's X and Y axes"); 595c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->button(mRotationMode)->setChecked(true); 596c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setRotationMode(int))); 597c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath box->setLayout(boxLayout); 598c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath layout->addWidget(box); 599c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 600c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 601c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath // interpolation mode 602c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QGroupBox* box = new QGroupBox("spherical interpolation"); 603c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QVBoxLayout* boxLayout = new QVBoxLayout; 604c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QButtonGroup* group = new QButtonGroup(panel); 605c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QRadioButton* but; 606c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("quaternion slerp"); 607c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, LerpQuaternion); 608c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 609c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("use quaternion spherical interpolation\nto interpolate orientations"); 610c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but = new QRadioButton("euler angles"); 611c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->addButton(but, LerpEulerAngles); 612c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath boxLayout->addWidget(but); 613c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath but->setToolTip("use Euler angles to interpolate orientations"); 614c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath group->button(mNavMode)->setChecked(true); 615c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setLerpMode(int))); 616c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath box->setLayout(boxLayout); 617c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath layout->addWidget(box); 618c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 619c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath layout->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding)); 620c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath panel->setLayout(layout); 621c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return panel; 622c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 623c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 624c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathQuaternionDemo::QuaternionDemo() 625c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 626c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mRenderingWidget = new RenderingWidget(); 627c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath setCentralWidget(mRenderingWidget); 628c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 629c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QDockWidget* panel = new QDockWidget("navigation", this); 630c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath panel->setAllowedAreas((QFlags<Qt::DockWidgetArea>)(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea)); 631c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath addDockWidget(Qt::RightDockWidgetArea, panel); 632c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath panel->setWidget(mRenderingWidget->createNavigationControlWidget()); 633c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 634c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 635c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathint main(int argc, char *argv[]) 636c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 637c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << "Navigation:\n"; 638c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << " left button: rotate around the target\n"; 639c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << " middle button: zoom\n"; 640c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << " left button + ctrl quake rotate (rotate around camera position)\n"; 641c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << " middle button + ctrl walk (progress along camera's z direction)\n"; 642c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << " left button: pan (translate in the XY camera's plane)\n\n"; 643c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << "R : move the camera to initial position\n"; 644c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << "A : start/stop animation\n"; 645c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << "C : clear the animation\n"; 646c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath std::cout << "G : add a key frame\n"; 647c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 648c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QApplication app(argc, argv); 649c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath QuaternionDemo demo; 650c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath demo.resize(600,500); 651c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath demo.show(); 652c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return app.exec(); 653c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 654c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 655c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "quaternion_demo.moc" 656c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 657