mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-09-24 23:33:13 +08:00
various stuff in opengl demos such as a better model,
stable trackball for the fly navigation mode, and started to put some GUI elements...
This commit is contained in:
parent
d3a70b7fac
commit
146c9e4494
@ -9,7 +9,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
|
|
||||||
include_directories( ${QT_INCLUDE_DIR} )
|
include_directories( ${QT_INCLUDE_DIR} )
|
||||||
|
|
||||||
set(quaternion_demo_SRCS gpuhelper.cpp camera.cpp trackball.cpp quaternion_demo.cpp)
|
set(quaternion_demo_SRCS gpuhelper.cpp icosphere.cpp camera.cpp trackball.cpp quaternion_demo.cpp)
|
||||||
|
|
||||||
qt4_automoc(${quaternion_demo_SRCS})
|
qt4_automoc(${quaternion_demo_SRCS})
|
||||||
|
|
||||||
|
@ -42,8 +42,7 @@ Camera::Camera()
|
|||||||
mVpX = 0;
|
mVpX = 0;
|
||||||
mVpY = 0;
|
mVpY = 0;
|
||||||
|
|
||||||
setPosition(Vector3f::Constant(50.));
|
setPosition(Vector3f::Constant(100.));
|
||||||
|
|
||||||
setTarget(Vector3f::Zero());
|
setTarget(Vector3f::Zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +178,14 @@ void Camera::rotateAroundTarget(const Quaternionf& q)
|
|||||||
mViewIsUptodate = true;
|
mViewIsUptodate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::localRotate(const Quaternionf& q)
|
||||||
|
{
|
||||||
|
float dist = (position() - mTarget).norm();
|
||||||
|
setOrientation(orientation() * q);
|
||||||
|
mTarget = position() + dist * direction();
|
||||||
|
mViewIsUptodate = false;
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::zoom(float d)
|
void Camera::zoom(float d)
|
||||||
{
|
{
|
||||||
float dist = (position() - mTarget).norm();
|
float dist = (position() - mTarget).norm();
|
||||||
|
@ -91,6 +91,7 @@ class Camera
|
|||||||
const Eigen::Matrix4f& projectionMatrix(void) const;
|
const Eigen::Matrix4f& projectionMatrix(void) const;
|
||||||
|
|
||||||
void rotateAroundTarget(const Eigen::Quaternionf& q);
|
void rotateAroundTarget(const Eigen::Quaternionf& q);
|
||||||
|
void localRotate(const Eigen::Quaternionf& q);
|
||||||
void zoom(float d);
|
void zoom(float d);
|
||||||
|
|
||||||
void localTranslate(const Eigen::Vector3f& t);
|
void localTranslate(const Eigen::Vector3f& t);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "gpuhelper.h"
|
#include "gpuhelper.h"
|
||||||
|
#include "icosphere.h"
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
// PLEASE don't look at this old code... ;)
|
// PLEASE don't look at this old code... ;)
|
||||||
|
|
||||||
@ -31,26 +32,6 @@
|
|||||||
|
|
||||||
GpuHelper gpu;
|
GpuHelper gpu;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// icosahedron
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
#define X .525731112119133606
|
|
||||||
#define Z .850650808352039932
|
|
||||||
|
|
||||||
static GLfloat vdata[12][3] = {
|
|
||||||
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
|
|
||||||
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
|
|
||||||
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static GLint tindices[20][3] = {
|
|
||||||
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
|
|
||||||
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
|
|
||||||
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
|
|
||||||
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
GpuHelper::GpuHelper()
|
GpuHelper::GpuHelper()
|
||||||
{
|
{
|
||||||
mVpWidth = mVpHeight = 0;
|
mVpWidth = mVpHeight = 0;
|
||||||
@ -151,61 +132,10 @@ void GpuHelper::drawUnitCube(void)
|
|||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _normalize(float* v)
|
void GpuHelper::drawUnitSphere(int level)
|
||||||
{
|
{
|
||||||
float s = 1.f/ei_sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
static IcoSphere sphere;
|
||||||
for (uint k=0; k<3; ++k)
|
sphere.draw(level);
|
||||||
v[k] *= s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _subdivide(float *v1, float *v2, float *v3, long depth)
|
|
||||||
{
|
|
||||||
GLfloat v12[3], v23[3], v31[3];
|
|
||||||
GLint i;
|
|
||||||
|
|
||||||
if (depth == 0) {
|
|
||||||
//drawtriangle(v1, v2, v3);
|
|
||||||
glNormal3fv(v1);
|
|
||||||
glVertex3fv(v1);
|
|
||||||
|
|
||||||
glNormal3fv(v3);
|
|
||||||
glVertex3fv(v3);
|
|
||||||
|
|
||||||
glNormal3fv(v2);
|
|
||||||
glVertex3fv(v2);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
v12[i] = v1[i]+v2[i];
|
|
||||||
v23[i] = v2[i]+v3[i];
|
|
||||||
v31[i] = v3[i]+v1[i];
|
|
||||||
}
|
|
||||||
_normalize(v12);
|
|
||||||
_normalize(v23);
|
|
||||||
_normalize(v31);
|
|
||||||
_subdivide(v1, v12, v31, depth-1);
|
|
||||||
_subdivide(v2, v23, v12, depth-1);
|
|
||||||
_subdivide(v3, v31, v23, depth-1);
|
|
||||||
_subdivide(v12, v23, v31, depth-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GpuHelper::drawUnitLightSphere(int level)
|
|
||||||
{
|
|
||||||
static int dlId = 0;
|
|
||||||
if (!dlId)
|
|
||||||
{
|
|
||||||
dlId = glGenLists(1);
|
|
||||||
glNewList(dlId, GL_COMPILE);
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
_subdivide(&vdata[tindices[i][0]][0], &vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0], 1);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
glEndList();
|
|
||||||
}
|
|
||||||
glCallList(dlId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ class GpuHelper
|
|||||||
void drawVector(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
|
void drawVector(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
|
||||||
void drawVectorBox(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
|
void drawVectorBox(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
|
||||||
void drawUnitCube(void);
|
void drawUnitCube(void);
|
||||||
void drawUnitLightSphere(int level=0);
|
void drawUnitSphere(int level=0);
|
||||||
|
|
||||||
/// draw the \a nofElement first elements
|
/// draw the \a nofElement first elements
|
||||||
inline void draw(GLenum mode, uint nofElement);
|
inline void draw(GLenum mode, uint nofElement);
|
||||||
|
119
demos/opengl/icosphere.cpp
Normal file
119
demos/opengl/icosphere.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra. Eigen itself is part of the KDE project.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||||
|
//
|
||||||
|
// Eigen is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Alternatively, you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License and a copy of the GNU General Public License along with
|
||||||
|
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "icosphere.h"
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
using namespace Eigen;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// icosahedron data
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
#define X .525731112119133606
|
||||||
|
#define Z .850650808352039932
|
||||||
|
|
||||||
|
static GLfloat vdata[12][3] = {
|
||||||
|
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
|
||||||
|
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
|
||||||
|
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLint tindices[20][3] = {
|
||||||
|
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
|
||||||
|
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
|
||||||
|
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
|
||||||
|
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
IcoSphere::IcoSphere(unsigned int levels)
|
||||||
|
{
|
||||||
|
// init with an icosahedron
|
||||||
|
for (int i = 0; i < 12; i++)
|
||||||
|
mVertices.push_back(Map<Vector3f>(vdata[i]));
|
||||||
|
mIndices.push_back(new std::vector<int>);
|
||||||
|
std::vector<int>& indices = *mIndices.back();
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
indices.push_back(tindices[i][k]);
|
||||||
|
}
|
||||||
|
mListIds.push_back(0);
|
||||||
|
|
||||||
|
while(mIndices.size()<levels)
|
||||||
|
_subdivide();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<int>& IcoSphere::indices(int level) const
|
||||||
|
{
|
||||||
|
while (level>=int(mIndices.size()))
|
||||||
|
const_cast<IcoSphere*>(this)->_subdivide();
|
||||||
|
return *mIndices[level];
|
||||||
|
}
|
||||||
|
|
||||||
|
void IcoSphere::_subdivide(void)
|
||||||
|
{
|
||||||
|
const std::vector<int>& indices = *mIndices.back();
|
||||||
|
mIndices.push_back(new std::vector<int>);
|
||||||
|
std::vector<int>& refinedIndices = *mIndices.back();
|
||||||
|
int end = indices.size();
|
||||||
|
for (int i=0; i<end; i+=3)
|
||||||
|
{
|
||||||
|
int i0, i1, i2;
|
||||||
|
Vector3f v0 = mVertices[i0=indices[i+0]];
|
||||||
|
Vector3f v1 = mVertices[i1=indices[i+1]];
|
||||||
|
Vector3f v2 = mVertices[i2=indices[i+2]];
|
||||||
|
int start = mVertices.size();
|
||||||
|
mVertices.push_back( (v0+v1).normalized() );
|
||||||
|
mVertices.push_back( (v1+v2).normalized() );
|
||||||
|
mVertices.push_back( (v2+v0).normalized() );
|
||||||
|
refinedIndices.push_back(i0); refinedIndices.push_back(start+0); refinedIndices.push_back(start+2);
|
||||||
|
refinedIndices.push_back(i1); refinedIndices.push_back(start+1); refinedIndices.push_back(start+0);
|
||||||
|
refinedIndices.push_back(i2); refinedIndices.push_back(start+2); refinedIndices.push_back(start+1);
|
||||||
|
refinedIndices.push_back(start+0); refinedIndices.push_back(start+1); refinedIndices.push_back(start+2);
|
||||||
|
}
|
||||||
|
mListIds.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IcoSphere::draw(int level)
|
||||||
|
{
|
||||||
|
while (level>=int(mIndices.size()))
|
||||||
|
const_cast<IcoSphere*>(this)->_subdivide();
|
||||||
|
if (mListIds[level]==0)
|
||||||
|
{
|
||||||
|
mListIds[level] = glGenLists(1);
|
||||||
|
glNewList(mListIds[level], GL_COMPILE);
|
||||||
|
glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
|
||||||
|
glNormalPointer(GL_FLOAT, 0, mVertices[0].data());
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDrawElements(GL_TRIANGLES, mIndices[level]->size(), GL_UNSIGNED_INT, &(mIndices[level]->at(0)));
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
glCallList(mListIds[level]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
45
demos/opengl/icosphere.h
Normal file
45
demos/opengl/icosphere.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra. Eigen itself is part of the KDE project.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||||
|
//
|
||||||
|
// Eigen is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Alternatively, you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License and a copy of the GNU General Public License along with
|
||||||
|
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef EIGEN_ICOSPHERE_H
|
||||||
|
#define EIGEN_ICOSPHERE_H
|
||||||
|
|
||||||
|
#include <Eigen/Core>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class IcoSphere
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IcoSphere(unsigned int levels=1);
|
||||||
|
const std::vector<Eigen::Vector3f>& vertices() const { return mVertices; }
|
||||||
|
const std::vector<int>& indices(int level) const;
|
||||||
|
void draw(int level);
|
||||||
|
protected:
|
||||||
|
void _subdivide();
|
||||||
|
std::vector<Eigen::Vector3f> mVertices;
|
||||||
|
std::vector<std::vector<int>*> mIndices;
|
||||||
|
std::vector<int> mListIds;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EIGEN_ICOSPHERE_H
|
@ -23,6 +23,7 @@
|
|||||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "quaternion_demo.h"
|
#include "quaternion_demo.h"
|
||||||
|
#include "icosphere.h"
|
||||||
|
|
||||||
#include <Eigen/Array>
|
#include <Eigen/Array>
|
||||||
#include <Eigen/QR>
|
#include <Eigen/QR>
|
||||||
@ -31,6 +32,11 @@
|
|||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QButtonGroup>
|
||||||
|
#include <QRadioButton>
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
using namespace Eigen;
|
using namespace Eigen;
|
||||||
|
|
||||||
@ -57,21 +63,27 @@ inline static Frame lerpFrame(float alpha, const Frame& a, const Frame& b)
|
|||||||
Quaternionf(::lerp(alpha,OrientationType(a.orientation),OrientationType(b.orientation))));
|
Quaternionf(::lerp(alpha,OrientationType(a.orientation),OrientationType(b.orientation))));
|
||||||
}
|
}
|
||||||
|
|
||||||
QuaternionDemo::QuaternionDemo()
|
RenderingWidget::RenderingWidget()
|
||||||
{
|
{
|
||||||
mAnimate = false;
|
mAnimate = false;
|
||||||
mTrackMode = TM_NO_TRACK;
|
mCurrentTrackingMode = TM_NO_TRACK;
|
||||||
|
mNavMode = NavTurnAround;
|
||||||
|
mLerpMode = LerpQuaternion;
|
||||||
|
mRotationMode = RotationStable;
|
||||||
mTrackball.setCamera(&mCamera);
|
mTrackball.setCamera(&mCamera);
|
||||||
|
|
||||||
|
// required to capture key press events
|
||||||
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::grabFrame(void)
|
void RenderingWidget::grabFrame(void)
|
||||||
{
|
{
|
||||||
// ask user for a time
|
// ask user for a time
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
double t = 0;
|
double t = 0;
|
||||||
if (!m_timeline.empty())
|
if (!m_timeline.empty())
|
||||||
t = (--m_timeline.end())->first + 1.;
|
t = (--m_timeline.end())->first + 1.;
|
||||||
t = QInputDialog::getDouble(this, "Eigen's QuaternionDemo", "time value: ",
|
t = QInputDialog::getDouble(this, "Eigen's RenderingWidget", "time value: ",
|
||||||
t, 0, 1e3, 1, &ok);
|
t, 0, 1e3, 1, &ok);
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
@ -82,20 +94,47 @@ void QuaternionDemo::grabFrame(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::drawScene()
|
void RenderingWidget::drawScene()
|
||||||
{
|
{
|
||||||
float length = 50;
|
float length = 50;
|
||||||
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitX(), Color(1,0,0,1));
|
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitX(), Color(1,0,0,1));
|
||||||
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitY(), Color(0,1,0,1));
|
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitY(), Color(0,1,0,1));
|
||||||
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitZ(), Color(0,0,1,1));
|
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitZ(), Color(0,0,1,1));
|
||||||
|
|
||||||
|
// draw the fractal object
|
||||||
|
float sqrt3 = ei_sqrt(3.);
|
||||||
|
glLightfv(GL_LIGHT0, GL_AMBIENT, Vector4f(0.5,0.5,0.5,1).data());
|
||||||
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, Vector4f(0.5,1,0.5,1).data());
|
||||||
|
glLightfv(GL_LIGHT0, GL_SPECULAR, Vector4f(1,1,1,1).data());
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, Vector4f(-sqrt3,-sqrt3,sqrt3,0).data());
|
||||||
|
|
||||||
|
glLightfv(GL_LIGHT1, GL_AMBIENT, Vector4f(0,0,0,1).data());
|
||||||
|
glLightfv(GL_LIGHT1, GL_DIFFUSE, Vector4f(1,0.5,0.5,1).data());
|
||||||
|
glLightfv(GL_LIGHT1, GL_SPECULAR, Vector4f(1,1,1,1).data());
|
||||||
|
glLightfv(GL_LIGHT1, GL_POSITION, Vector4f(-sqrt3,sqrt3,-sqrt3,0).data());
|
||||||
|
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Vector4f(0.7, 0.7, 0.7, 1).data());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Vector4f(0.8, 0.75, 0.6, 1).data());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Vector4f(1, 1, 1, 1).data());
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
glEnable(GL_LIGHT1);
|
||||||
|
|
||||||
|
glColor3f(0.4, 0.7, 0.4);
|
||||||
|
glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
|
||||||
|
glNormalPointer(GL_FLOAT, 0, mNormals[0].data());
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, mVertices.size());
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::drawPath()
|
void RenderingWidget::animate()
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void QuaternionDemo::animate()
|
|
||||||
{
|
{
|
||||||
m_alpha += double(m_timer.interval()) * 1e-3;
|
m_alpha += double(m_timer.interval()) * 1e-3;
|
||||||
|
|
||||||
@ -130,7 +169,7 @@ void QuaternionDemo::animate()
|
|||||||
updateGL();
|
updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::keyPressEvent(QKeyEvent * e)
|
void RenderingWidget::keyPressEvent(QKeyEvent * e)
|
||||||
{
|
{
|
||||||
switch(e->key())
|
switch(e->key())
|
||||||
{
|
{
|
||||||
@ -150,18 +189,8 @@ void QuaternionDemo::keyPressEvent(QKeyEvent * e)
|
|||||||
break;
|
break;
|
||||||
// move the camera to initial pos
|
// move the camera to initial pos
|
||||||
case Qt::Key_R:
|
case Qt::Key_R:
|
||||||
{
|
resetCamera();
|
||||||
if (mAnimate)
|
break;
|
||||||
stopAnimation();
|
|
||||||
m_timeline.clear();
|
|
||||||
float duration = 3/*AngleAxisf(mCamera.orientation().inverse()
|
|
||||||
* mInitFrame.orientation).angle()*/;
|
|
||||||
Frame aux = mCamera.frame();
|
|
||||||
aux.orientation = aux.orientation.inverse();
|
|
||||||
aux.position = mCamera.viewMatrix().translation();
|
|
||||||
m_timeline[0] = aux;
|
|
||||||
m_timeline[duration] = mInitFrame;
|
|
||||||
}
|
|
||||||
// start/stop the animation
|
// start/stop the animation
|
||||||
case Qt::Key_A:
|
case Qt::Key_A:
|
||||||
if (mAnimate)
|
if (mAnimate)
|
||||||
@ -183,7 +212,7 @@ void QuaternionDemo::keyPressEvent(QKeyEvent * e)
|
|||||||
updateGL();
|
updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::stopAnimation()
|
void RenderingWidget::stopAnimation()
|
||||||
{
|
{
|
||||||
disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
|
disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
|
||||||
m_timer.stop();
|
m_timer.stop();
|
||||||
@ -191,46 +220,48 @@ void QuaternionDemo::stopAnimation()
|
|||||||
m_alpha = 0;
|
m_alpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::mousePressEvent(QMouseEvent* e)
|
void RenderingWidget::mousePressEvent(QMouseEvent* e)
|
||||||
{
|
{
|
||||||
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
|
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
|
||||||
|
bool fly = (mNavMode==NavFly) || (e->modifiers()&Qt::ControlModifier);
|
||||||
switch(e->button())
|
switch(e->button())
|
||||||
{
|
{
|
||||||
case Qt::LeftButton:
|
case Qt::LeftButton:
|
||||||
if(e->modifiers()&Qt::ControlModifier)
|
if(fly)
|
||||||
{
|
{
|
||||||
mTrackMode = TM_QUAKE_ROTATE;
|
mCurrentTrackingMode = TM_LOCAL_ROTATE;
|
||||||
|
mTrackball.start(Trackball::Local);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTrackMode = TM_ROTATE_AROUND;
|
mCurrentTrackingMode = TM_ROTATE_AROUND;
|
||||||
mTrackball.reset();
|
mTrackball.start(Trackball::Around);
|
||||||
mTrackball.track(mMouseCoords);
|
|
||||||
}
|
}
|
||||||
|
mTrackball.track(mMouseCoords);
|
||||||
break;
|
break;
|
||||||
case Qt::MidButton:
|
case Qt::MidButton:
|
||||||
if(e->modifiers()&Qt::ControlModifier)
|
if(fly)
|
||||||
mTrackMode = TM_QUAKE_WALK;
|
mCurrentTrackingMode = TM_FLY_Z;
|
||||||
else
|
else
|
||||||
mTrackMode = TM_ZOOM;
|
mCurrentTrackingMode = TM_ZOOM;
|
||||||
break;
|
break;
|
||||||
case Qt::RightButton:
|
case Qt::RightButton:
|
||||||
mTrackMode = TM_QUAKE_PAN;
|
mCurrentTrackingMode = TM_FLY_PAN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void QuaternionDemo::mouseReleaseEvent(QMouseEvent*)
|
void RenderingWidget::mouseReleaseEvent(QMouseEvent*)
|
||||||
{
|
{
|
||||||
mTrackMode = TM_NO_TRACK;
|
mCurrentTrackingMode = TM_NO_TRACK;
|
||||||
updateGL();
|
updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::mouseMoveEvent(QMouseEvent* e)
|
void RenderingWidget::mouseMoveEvent(QMouseEvent* e)
|
||||||
{
|
{
|
||||||
// tracking
|
// tracking
|
||||||
if(mTrackMode != TM_NO_TRACK)
|
if(mCurrentTrackingMode != TM_NO_TRACK)
|
||||||
{
|
{
|
||||||
float dx = float(e->x() - mMouseCoords.x()) / float(mCamera.vpWidth());
|
float dx = float(e->x() - mMouseCoords.x()) / float(mCamera.vpWidth());
|
||||||
float dy = - float(e->y() - mMouseCoords.y()) / float(mCamera.vpHeight());
|
float dy = - float(e->y() - mMouseCoords.y()) / float(mCamera.vpHeight());
|
||||||
@ -241,23 +272,21 @@ void QuaternionDemo::mouseMoveEvent(QMouseEvent* e)
|
|||||||
dy *= 10.;
|
dy *= 10.;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(mTrackMode)
|
switch(mCurrentTrackingMode)
|
||||||
{
|
{
|
||||||
case TM_ROTATE_AROUND :
|
case TM_ROTATE_AROUND:
|
||||||
|
case TM_LOCAL_ROTATE:
|
||||||
mTrackball.track(Vector2i(e->pos().x(), e->pos().y()));
|
mTrackball.track(Vector2i(e->pos().x(), e->pos().y()));
|
||||||
break;
|
break;
|
||||||
case TM_ZOOM :
|
case TM_ZOOM :
|
||||||
mCamera.zoom(dy*50);
|
mCamera.zoom(dy*50);
|
||||||
break;
|
break;
|
||||||
case TM_QUAKE_WALK :
|
case TM_FLY_Z :
|
||||||
mCamera.localTranslate(Vector3f(0, 0, dy*100));
|
mCamera.localTranslate(Vector3f(0, 0, -dy*100));
|
||||||
break;
|
break;
|
||||||
case TM_QUAKE_PAN :
|
case TM_FLY_PAN :
|
||||||
mCamera.localTranslate(Vector3f(dx*100, dy*100, 0));
|
mCamera.localTranslate(Vector3f(dx*100, dy*100, 0));
|
||||||
break;
|
break;
|
||||||
case TM_QUAKE_ROTATE :
|
|
||||||
mCamera.localRotate(-dx*M_PI, dy*M_PI);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -268,7 +297,7 @@ void QuaternionDemo::mouseMoveEvent(QMouseEvent* e)
|
|||||||
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
|
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::paintGL()
|
void RenderingWidget::paintGL()
|
||||||
{
|
{
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
@ -288,26 +317,242 @@ void QuaternionDemo::paintGL()
|
|||||||
drawScene();
|
drawScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::initializeGL()
|
void RenderingWidget::initializeGL()
|
||||||
{
|
{
|
||||||
glClearColor(1., 1., 1., 0.);
|
glClearColor(1., 1., 1., 0.);
|
||||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
|
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
mInitFrame.orientation = mCamera.viewMatrix().linear();
|
mCamera.setPosition(Vector3f(-200, -200, -200));
|
||||||
|
mCamera.setTarget(Vector3f(0, 0, 0));
|
||||||
|
mInitFrame.orientation = mCamera.orientation().inverse();
|
||||||
mInitFrame.position = mCamera.viewMatrix().translation();
|
mInitFrame.position = mCamera.viewMatrix().translation();
|
||||||
|
|
||||||
|
// create a kind of fractal sphere
|
||||||
|
{
|
||||||
|
IcoSphere pattern;
|
||||||
|
|
||||||
|
int levels = 3;
|
||||||
|
float scale = 0.45;
|
||||||
|
float radius = 100;
|
||||||
|
std::vector<Vector3f> centers;
|
||||||
|
std::vector<int> parents;
|
||||||
|
std::vector<float> radii;
|
||||||
|
centers.push_back(Vector3f::Zero());
|
||||||
|
parents.push_back(-1);
|
||||||
|
radii.push_back(radius);
|
||||||
|
radius *= scale;
|
||||||
|
|
||||||
|
// generate level 1 using icosphere vertices
|
||||||
|
{
|
||||||
|
float dist = radii[0]*0.9;
|
||||||
|
for (int i=0; i<12; ++i)
|
||||||
|
{
|
||||||
|
centers.push_back(pattern.vertices()[i] * dist);
|
||||||
|
radii.push_back(radius);
|
||||||
|
parents.push_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = 0.33;
|
||||||
|
static const float angles [10] = {
|
||||||
|
0, 0,
|
||||||
|
M_PI, 0.*M_PI,
|
||||||
|
M_PI, 0.5*M_PI,
|
||||||
|
M_PI, 1.*M_PI,
|
||||||
|
M_PI, 1.5*M_PI};
|
||||||
|
|
||||||
|
// generate other levels
|
||||||
|
int start = 1;
|
||||||
|
float maxAngle = M_PI/2;
|
||||||
|
for (int l=1; l<levels; l++)
|
||||||
|
{
|
||||||
|
radius *= scale;
|
||||||
|
int end = centers.size();
|
||||||
|
for (int i=start; i<end; ++i)
|
||||||
|
{
|
||||||
|
Vector3f c = centers[i];
|
||||||
|
Vector3f ax0, ax1;
|
||||||
|
if (parents[i]==-1)
|
||||||
|
ax0 = Vector3f::UnitZ();
|
||||||
|
else
|
||||||
|
ax0 = (c - centers[parents[i]]).normalized();
|
||||||
|
ax1 = ax0.unitOrthogonal();
|
||||||
|
Quaternionf q;
|
||||||
|
q.setFromTwoVectors(Vector3f::UnitZ(), ax0);
|
||||||
|
Transform3f t = Translation3f(c) * q * Scaling3f(radii[i]+radius);
|
||||||
|
for (int j=0; j<5; ++j)
|
||||||
|
{
|
||||||
|
Vector3f newC = c + ( (AngleAxisf(angles[j*2+1], ax0)
|
||||||
|
* AngleAxisf(angles[j*2+0] * (l==1 ? 0.35 : 0.5), ax1)) * ax0)*(radii[i] + radius*0.8);
|
||||||
|
centers.push_back(newC);
|
||||||
|
radii.push_back(radius);
|
||||||
|
parents.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start = end;
|
||||||
|
maxAngle = M_PI/2;
|
||||||
|
}
|
||||||
|
parents.clear();
|
||||||
|
// instanciate the geometry
|
||||||
|
{
|
||||||
|
const std::vector<int>& sphereIndices = pattern.indices(2);
|
||||||
|
std::cout << "instanciate geometry... (" << sphereIndices.size() * centers.size() << " vertices)\n";
|
||||||
|
mVertices.reserve(sphereIndices.size() * centers.size());
|
||||||
|
mNormals.reserve(sphereIndices.size() * centers.size());
|
||||||
|
int end = centers.size();
|
||||||
|
for (int i=0; i<end; ++i)
|
||||||
|
{
|
||||||
|
Transform3f t = Translation3f(centers[i]) * Scaling3f(radii[i]);
|
||||||
|
// copy vertices
|
||||||
|
for (unsigned int j=0; j<sphereIndices.size(); ++j)
|
||||||
|
{
|
||||||
|
Vector3f v = pattern.vertices()[sphereIndices[j]];
|
||||||
|
mVertices.push_back(t * v);
|
||||||
|
mNormals.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuaternionDemo::resizeGL(int width, int height)
|
void RenderingWidget::resizeGL(int width, int height)
|
||||||
{
|
{
|
||||||
mCamera.setViewport(width,height);
|
mCamera.setViewport(width,height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingWidget::setNavMode(int m)
|
||||||
|
{
|
||||||
|
mNavMode = NavMode(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingWidget::setLerpMode(int m)
|
||||||
|
{
|
||||||
|
mLerpMode = LerpMode(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingWidget::setRotationMode(int m)
|
||||||
|
{
|
||||||
|
mRotationMode = RotationMode(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingWidget::resetCamera()
|
||||||
|
{
|
||||||
|
if (mAnimate)
|
||||||
|
stopAnimation();
|
||||||
|
m_timeline.clear();
|
||||||
|
Frame aux0 = mCamera.frame();
|
||||||
|
aux0.orientation = aux0.orientation.inverse();
|
||||||
|
aux0.position = mCamera.viewMatrix().translation();
|
||||||
|
m_timeline[0] = aux0;
|
||||||
|
|
||||||
|
Vector3f currentTarget = mCamera.target();
|
||||||
|
mCamera.setTarget(Vector3f::Zero());
|
||||||
|
|
||||||
|
// compute the rotation duration to move the camera to the target
|
||||||
|
Frame aux1 = mCamera.frame();
|
||||||
|
aux1.orientation = aux1.orientation.inverse();
|
||||||
|
aux1.position = mCamera.viewMatrix().translation();
|
||||||
|
float rangle = AngleAxisf(aux0.orientation.inverse() * aux1.orientation).angle();
|
||||||
|
if (rangle>M_PI)
|
||||||
|
rangle = 2.*M_PI - rangle;
|
||||||
|
float duration = rangle * 0.9;
|
||||||
|
if (duration<0.1) duration = 0.1;
|
||||||
|
|
||||||
|
// put the camera at that time step:
|
||||||
|
aux1 = aux0.lerp(duration/2,mInitFrame);
|
||||||
|
// and make it look at teh target again
|
||||||
|
aux1.orientation = aux1.orientation.inverse();
|
||||||
|
aux1.position = - (aux1.orientation * aux1.position);
|
||||||
|
mCamera.setFrame(aux1);
|
||||||
|
mCamera.setTarget(Vector3f::Zero());
|
||||||
|
|
||||||
|
// add this camera keyframe
|
||||||
|
aux1.orientation = aux1.orientation.inverse();
|
||||||
|
aux1.position = mCamera.viewMatrix().translation();
|
||||||
|
m_timeline[duration] = aux1;
|
||||||
|
|
||||||
|
m_timeline[2] = mInitFrame;
|
||||||
|
m_alpha = 0;
|
||||||
|
animate();
|
||||||
|
connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
|
||||||
|
m_timer.start(1000/30);
|
||||||
|
mAnimate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* RenderingWidget::createNavigationControlWidget()
|
||||||
|
{
|
||||||
|
QWidget* panel = new QWidget();
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout();
|
||||||
|
|
||||||
|
{
|
||||||
|
// navigation mode
|
||||||
|
QButtonGroup* group = new QButtonGroup(panel);
|
||||||
|
QRadioButton* but;
|
||||||
|
but = new QRadioButton("turn around");
|
||||||
|
group->addButton(but, NavTurnAround);
|
||||||
|
layout->addWidget(but);
|
||||||
|
but = new QRadioButton("fly");
|
||||||
|
group->addButton(but, NavFly);
|
||||||
|
layout->addWidget(but);
|
||||||
|
group->button(mNavMode)->setChecked(true);
|
||||||
|
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setNavMode(int)));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QPushButton* but = new QPushButton("reset");
|
||||||
|
layout->addWidget(but);
|
||||||
|
connect(but, SIGNAL(clicked()), this, SLOT(resetCamera()));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// track ball, rotation mode
|
||||||
|
QButtonGroup* group = new QButtonGroup(panel);
|
||||||
|
QRadioButton* but;
|
||||||
|
but = new QRadioButton("stable trackball");
|
||||||
|
group->addButton(but, RotationStable);
|
||||||
|
layout->addWidget(but);
|
||||||
|
but = new QRadioButton("standard rotation");
|
||||||
|
group->addButton(but, RotationStandard);
|
||||||
|
layout->addWidget(but);
|
||||||
|
but->setEnabled(false);
|
||||||
|
group->button(mRotationMode)->setChecked(true);
|
||||||
|
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setRotationMode(int)));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// interpolation mode
|
||||||
|
QButtonGroup* group = new QButtonGroup(panel);
|
||||||
|
QRadioButton* but;
|
||||||
|
but = new QRadioButton("quaternion slerp");
|
||||||
|
group->addButton(but, LerpQuaternion);
|
||||||
|
layout->addWidget(but);
|
||||||
|
but = new QRadioButton("euler angles");
|
||||||
|
group->addButton(but, LerpEulerAngles);
|
||||||
|
layout->addWidget(but);
|
||||||
|
but->setEnabled(false);
|
||||||
|
group->button(mNavMode)->setChecked(true);
|
||||||
|
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setLerpMode(int)));
|
||||||
|
}
|
||||||
|
layout->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding));
|
||||||
|
panel->setLayout(layout);
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
QuaternionDemo::QuaternionDemo()
|
||||||
|
{
|
||||||
|
mRenderingWidget = new RenderingWidget();
|
||||||
|
setCentralWidget(mRenderingWidget);
|
||||||
|
|
||||||
|
QDockWidget* panel = new QDockWidget("navigation", this);
|
||||||
|
panel->setAllowedAreas((QFlags<Qt::DockWidgetArea>)(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea));
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, panel);
|
||||||
|
panel->setWidget(mRenderingWidget->createNavigationControlWidget());
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
QuaternionDemo demo;
|
QuaternionDemo demo;
|
||||||
|
demo.resize(600,500);
|
||||||
demo.show();
|
demo.show();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,9 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QtGui/QApplication>
|
#include <QtGui/QApplication>
|
||||||
#include <QtOpenGL/QGLWidget>
|
#include <QtOpenGL/QGLWidget>
|
||||||
|
#include <QtGui/QMainWindow>
|
||||||
|
|
||||||
class QuaternionDemo : public QGLWidget
|
class RenderingWidget : public QGLWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -45,14 +46,31 @@ class QuaternionDemo : public QGLWidget
|
|||||||
bool mAnimate;
|
bool mAnimate;
|
||||||
float m_alpha;
|
float m_alpha;
|
||||||
|
|
||||||
|
|
||||||
enum TrackMode {
|
enum TrackMode {
|
||||||
TM_NO_TRACK=0, TM_ROTATE_AROUND, TM_ZOOM,
|
TM_NO_TRACK=0, TM_ROTATE_AROUND, TM_ZOOM,
|
||||||
TM_QUAKE_ROTATE, TM_QUAKE_WALK, TM_QUAKE_PAN
|
TM_LOCAL_ROTATE, TM_FLY_Z, TM_FLY_PAN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NavMode {
|
||||||
|
NavTurnAround,
|
||||||
|
NavFly
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LerpMode {
|
||||||
|
LerpQuaternion,
|
||||||
|
LerpEulerAngles
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RotationMode {
|
||||||
|
RotationStable,
|
||||||
|
RotationStandard
|
||||||
};
|
};
|
||||||
|
|
||||||
Camera mCamera;
|
Camera mCamera;
|
||||||
TrackMode mTrackMode;
|
TrackMode mCurrentTrackingMode;
|
||||||
|
NavMode mNavMode;
|
||||||
|
LerpMode mLerpMode;
|
||||||
|
RotationMode mRotationMode;
|
||||||
Vector2i mMouseCoords;
|
Vector2i mMouseCoords;
|
||||||
Trackball mTrackball;
|
Trackball mTrackball;
|
||||||
|
|
||||||
@ -60,15 +78,23 @@ class QuaternionDemo : public QGLWidget
|
|||||||
|
|
||||||
void setupCamera();
|
void setupCamera();
|
||||||
|
|
||||||
|
std::vector<Vector3f> mVertices;
|
||||||
|
std::vector<Vector3f> mNormals;
|
||||||
|
std::vector<int> mIndices;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
virtual void animate(void);
|
virtual void animate(void);
|
||||||
virtual void drawScene(void);
|
virtual void drawScene(void);
|
||||||
virtual void drawPath(void);
|
|
||||||
|
|
||||||
virtual void grabFrame(void);
|
virtual void grabFrame(void);
|
||||||
virtual void stopAnimation();
|
virtual void stopAnimation();
|
||||||
|
|
||||||
|
virtual void setNavMode(int);
|
||||||
|
virtual void setLerpMode(int);
|
||||||
|
virtual void setRotationMode(int);
|
||||||
|
virtual void resetCamera();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void initializeGL();
|
virtual void initializeGL();
|
||||||
@ -82,9 +108,20 @@ class QuaternionDemo : public QGLWidget
|
|||||||
virtual void keyPressEvent(QKeyEvent * e);
|
virtual void keyPressEvent(QKeyEvent * e);
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderingWidget();
|
||||||
|
~RenderingWidget() { }
|
||||||
|
|
||||||
|
QWidget* createNavigationControlWidget();
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuaternionDemo : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QuaternionDemo();
|
QuaternionDemo();
|
||||||
~QuaternionDemo() { }
|
protected:
|
||||||
|
RenderingWidget* mRenderingWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EIGEN_QUATERNION_DEMO_H
|
#endif // EIGEN_QUATERNION_DEMO_H
|
||||||
|
@ -27,12 +27,12 @@
|
|||||||
|
|
||||||
using namespace Eigen;
|
using namespace Eigen;
|
||||||
|
|
||||||
void Trackball::track(const Vector2i& newPoint2D)
|
void Trackball::track(const Vector2i& point2D)
|
||||||
{
|
{
|
||||||
if (mpCamera==0)
|
if (mpCamera==0)
|
||||||
return;
|
return;
|
||||||
Vector3f newPoint3D;
|
Vector3f newPoint3D;
|
||||||
bool newPointOk = mapToSphere(newPoint2D, newPoint3D);
|
bool newPointOk = mapToSphere(point2D, newPoint3D);
|
||||||
|
|
||||||
if (mLastPointOk && newPointOk)
|
if (mLastPointOk && newPointOk)
|
||||||
{
|
{
|
||||||
@ -40,12 +40,14 @@ void Trackball::track(const Vector2i& newPoint2D)
|
|||||||
float cos_angle = mLastPoint3D.dot(newPoint3D);
|
float cos_angle = mLastPoint3D.dot(newPoint3D);
|
||||||
if ( ei_abs(cos_angle) < 1.0 )
|
if ( ei_abs(cos_angle) < 1.0 )
|
||||||
{
|
{
|
||||||
float angle = 2.0 * acos(cos_angle);
|
float angle = acos(cos_angle);
|
||||||
mpCamera->rotateAroundTarget(Quaternionf(AngleAxisf(angle, axis)));
|
if (mMode==Around)
|
||||||
|
mpCamera->rotateAroundTarget(Quaternionf(AngleAxisf(2.*angle, axis))); // *2 to speedup the rotation
|
||||||
|
else
|
||||||
|
mpCamera->localRotate(Quaternionf(AngleAxisf(-angle, axis)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastPoint2D = newPoint2D;
|
|
||||||
mLastPoint3D = newPoint3D;
|
mLastPoint3D = newPoint3D;
|
||||||
mLastPointOk = newPointOk;
|
mLastPointOk = newPointOk;
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,11 @@ class Trackball
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum Mode {Around, Local};
|
||||||
|
|
||||||
Trackball() : mpCamera(0) {}
|
Trackball() : mpCamera(0) {}
|
||||||
|
|
||||||
void reset() { mLastPointOk = false; }
|
void start(Mode m = Around) { mMode = m; mLastPointOk = false; }
|
||||||
|
|
||||||
void setCamera(Camera* pCam) { mpCamera = pCam; }
|
void setCamera(Camera* pCam) { mpCamera = pCam; }
|
||||||
|
|
||||||
@ -46,8 +48,8 @@ class Trackball
|
|||||||
bool mapToSphere( const Eigen::Vector2i& p2, Eigen::Vector3f& v3);
|
bool mapToSphere( const Eigen::Vector2i& p2, Eigen::Vector3f& v3);
|
||||||
|
|
||||||
Camera* mpCamera;
|
Camera* mpCamera;
|
||||||
Eigen::Vector2i mLastPoint2D;
|
|
||||||
Eigen::Vector3f mLastPoint3D;
|
Eigen::Vector3f mLastPoint3D;
|
||||||
|
Mode mMode;
|
||||||
bool mLastPointOk;
|
bool mLastPointOk;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user