// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// generate other levels int start = 1; for (int l=1; l<levels; l++)
{
radius *= scale; int end = mCenters.size(); for (int i=start; i<end; ++i)
{
Vector3f c = mCenters[i];
Vector3f ax0 = (c - mCenters[parents[i]]).normalized();
Vector3f ax1 = ax0.unitOrthogonal();
Quaternionf q;
q.setFromTwoVectors(Vector3f::UnitZ(), ax0);
Affine3f t = Translation3f(c) * q * Scaling(mRadii[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)
* (mRadii[i] + radius*0.8);
mCenters.push_back(newC);
mRadii.push_back(radius);
parents.push_back(i);
}
}
start = end;
}
}
void draw()
{ int end = mCenters.size();
glEnable(GL_NORMALIZE); for (int i=0; i<end; ++i)
{
Affine3f t = Translation3f(mCenters[i]) * Scaling(mRadii[i]);
gpu.pushMatrix(GL_MODELVIEW);
gpu.multMatrix(t.matrix(),GL_MODELVIEW);
mIcoSphere.draw(2);
gpu.popMatrix(GL_MODELVIEW);
}
glDisable(GL_NORMALIZE);
} protected:
std::vector<Vector3f> mCenters;
std::vector<float> mRadii;
IcoSphere mIcoSphere;
};
// generic linear interpolation method template<typename T> T lerp(float t, const T& a, const T& b)
{ return a*(1-t) + b*t;
}
// quaternion slerp template<> Quaternionf lerp(float t, const Quaternionf& a, const Quaternionf& b)
{ return a.slerp(t,b); }
// linear interpolation of a frame using the type OrientationType // to perform the interpolation of the orientations template<typename OrientationType> inlinestatic Frame lerpFrame(float alpha, const Frame& a, const Frame& b)
{ return Frame(lerp(alpha,a.position,b.position),
Quaternionf(lerp(alpha,OrientationType(a.orientation),OrientationType(b.orientation))));
}
void RenderingWidget::keyPressEvent(QKeyEvent * e)
{ switch(e->key())
{ case Qt::Key_Up:
mCamera.zoom(2); break; case Qt::Key_Down:
mCamera.zoom(-2); break; // add a frame case Qt::Key_G:
grabFrame(); break; // clear the time line case Qt::Key_C:
m_timeline.clear(); break; // move the camera to initial pos case Qt::Key_R:
resetCamera(); break; // start/stop the animation case Qt::Key_A: if (mAnimate)
{
stopAnimation();
} else
{
m_alpha = 0;
connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
m_timer.start(1000/30);
mAnimate = true;
} break; default: break;
}
// speedup the transformations if(e->modifiers() & Qt::ShiftModifier)
{
dx *= 10.;
dy *= 10.;
}
switch(mCurrentTrackingMode)
{ case TM_ROTATE_AROUND: case TM_LOCAL_ROTATE: if (mRotationMode==RotationStable)
{ // use the stable trackball implementation mapping // the 2D coordinates to 3D points on a sphere.
mTrackball.track(Vector2i(e->pos().x(), e->pos().y()));
} else
{ // standard approach mapping the x and y displacements as rotations // around the camera's X and Y axes.
Quaternionf q = AngleAxisf( dx*M_PI, Vector3f::UnitY())
* AngleAxisf(-dy*M_PI, Vector3f::UnitX()); if (mCurrentTrackingMode==TM_LOCAL_ROTATE)
mCamera.localRotate(q); else
mCamera.rotateAroundTarget(q);
} break; case TM_ZOOM :
mCamera.zoom(dy*100); break; case TM_FLY_Z :
mCamera.localTranslate(Vector3f(0, 0, -dy*200)); break; case TM_FLY_PAN :
mCamera.localTranslate(Vector3f(dx*200, dy*200, 0)); break; default: break;
}
// 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 duration = aux0.orientation.angularDistance(aux1.orientation) * 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 the 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;
QWidget* RenderingWidget::createNavigationControlWidget()
{
QWidget* panel = new QWidget();
QVBoxLayout* layout = new QVBoxLayout();
{
QPushButton* but = new QPushButton("reset");
but->setToolTip("move the camera to initial position (with animation)");
layout->addWidget(but);
connect(but, SIGNAL(clicked()), this, SLOT(resetCamera()));
}
{ // navigation mode
QGroupBox* box = new QGroupBox("navigation mode");
QVBoxLayout* boxLayout = new QVBoxLayout;
QButtonGroup* group = new QButtonGroup(panel);
QRadioButton* but;
but = new QRadioButton("turn around");
but->setToolTip("look around an object");
group->addButton(but, NavTurnAround);
boxLayout->addWidget(but);
but = new QRadioButton("fly");
but->setToolTip("free navigation like a spaceship\n(this mode can also be enabled pressing the \"shift\" key)");
group->addButton(but, NavFly);
boxLayout->addWidget(but);
group->button(mNavMode)->setChecked(true);
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setNavMode(int)));
box->setLayout(boxLayout);
layout->addWidget(box);
}
{ // track ball, rotation mode
QGroupBox* box = new QGroupBox("rotation mode");
QVBoxLayout* boxLayout = new QVBoxLayout;
QButtonGroup* group = new QButtonGroup(panel);
QRadioButton* but;
but = new QRadioButton("stable trackball");
group->addButton(but, RotationStable);
boxLayout->addWidget(but);
but->setToolTip("use the stable trackball implementation mapping\nthe 2D coordinates to 3D points on a sphere");
but = new QRadioButton("standard rotation");
group->addButton(but, RotationStandard);
boxLayout->addWidget(but);
but->setToolTip("standard approach mapping the x and y displacements\nas rotations around the camera's X and Y axes");
group->button(mRotationMode)->setChecked(true);
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setRotationMode(int)));
box->setLayout(boxLayout);
layout->addWidget(box);
}
{ // interpolation mode
QGroupBox* box = new QGroupBox("spherical interpolation");
QVBoxLayout* boxLayout = new QVBoxLayout;
QButtonGroup* group = new QButtonGroup(panel);
QRadioButton* but;
but = new QRadioButton("quaternion slerp");
group->addButton(but, LerpQuaternion);
boxLayout->addWidget(but);
but->setToolTip("use quaternion spherical interpolation\nto interpolate orientations");
but = new QRadioButton("euler angles");
group->addButton(but, LerpEulerAngles);
boxLayout->addWidget(but);
but->setToolTip("use Euler angles to interpolate orientations");
group->button(mNavMode)->setChecked(true);
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(setLerpMode(int)));
box->setLayout(boxLayout);
layout->addWidget(box);
}
layout->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding));
panel->setLayout(layout); return panel;
}
QuaternionDemo::QuaternionDemo()
{
mRenderingWidget = new RenderingWidget();
setCentralWidget(mRenderingWidget);
int main(int argc, char *argv[])
{
std::cout << "Navigation:\n";
std::cout << " left button: rotate around the target\n";
std::cout << " middle button: zoom\n";
std::cout << " left button + ctrl quake rotate (rotate around camera position)\n";
std::cout << " middle button + ctrl walk (progress along camera's z direction)\n";
std::cout << " left button: pan (translate in the XY camera's plane)\n\n";
std::cout << "R : move the camera to initial position\n";
std::cout << "A : start/stop animation\n";
std::cout << "C : clear the animation\n";
std::cout << "G : add a key frame\n";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.