Clang-format tests, examples, libraries, benchmarks, etc.

This commit is contained in:
Antonio Sánchez
2023-12-05 21:22:55 +00:00
committed by Rasmus Munk Larsen
parent 3252ecc7a4
commit 46e9cdb7fe
876 changed files with 33453 additions and 37795 deletions

View File

@@ -9,201 +9,184 @@
#include "mandelbrot.h"
#include <iostream>
#include<QtGui/QPainter>
#include<QtGui/QImage>
#include<QtGui/QMouseEvent>
#include<QtCore/QTime>
#include <QtGui/QPainter>
#include <QtGui/QImage>
#include <QtGui/QMouseEvent>
#include <QtCore/QTime>
void MandelbrotWidget::resizeEvent(QResizeEvent *)
{
if(size < width() * height())
{
void MandelbrotWidget::resizeEvent(QResizeEvent *) {
if (size < width() * height()) {
std::cout << "reallocate buffer" << std::endl;
size = width() * height();
if(buffer) delete[]buffer;
buffer = new unsigned char[4*size];
if (buffer) delete[] buffer;
buffer = new unsigned char[4 * size];
}
}
template<typename T> struct iters_before_test { enum { ret = 8 }; };
template<> struct iters_before_test<double> { enum { ret = 16 }; };
template <typename T>
struct iters_before_test {
enum { ret = 8 };
};
template <>
struct iters_before_test<double> {
enum { ret = 16 };
};
template<typename Real> void MandelbrotThread::render(int img_width, int img_height)
{
enum { packetSize = Eigen::internal::packet_traits<Real>::size }; // number of reals in a Packet
typedef Eigen::Array<Real, packetSize, 1> Packet; // wrap a Packet as a vector
template <typename Real>
void MandelbrotThread::render(int img_width, int img_height) {
enum { packetSize = Eigen::internal::packet_traits<Real>::size }; // number of reals in a Packet
typedef Eigen::Array<Real, packetSize, 1> Packet; // wrap a Packet as a vector
enum { iters_before_test = iters_before_test<Real>::ret };
max_iter = (max_iter / iters_before_test) * iters_before_test;
const int alignedWidth = (img_width/packetSize)*packetSize;
const int alignedWidth = (img_width / packetSize) * packetSize;
unsigned char *const buffer = widget->buffer;
const double xradius = widget->xradius;
const double yradius = xradius * img_height / img_width;
const int threadcount = widget->threadcount;
typedef Eigen::Array<Real, 2, 1> Vector2;
Vector2 start(widget->center.x() - widget->xradius, widget->center.y() - yradius);
Vector2 step(2*widget->xradius/img_width, 2*yradius/img_height);
Vector2 step(2 * widget->xradius / img_width, 2 * yradius / img_height);
total_iter = 0;
for(int y = id; y < img_height; y += threadcount)
{
for (int y = id; y < img_height; y += threadcount) {
int pix = y * img_width;
// for each pixel, we're going to do the iteration z := z^2 + c where z and c are complex numbers,
// for each pixel, we're going to do the iteration z := z^2 + c where z and c are complex numbers,
// starting with z = c = complex coord of the pixel. pzi and pzr denote the real and imaginary parts of z.
// pci and pcr denote the real and imaginary parts of c.
Packet pzi_start, pci_start;
for(int i = 0; i < packetSize; i++) pzi_start[i] = pci_start[i] = start.y() + y * step.y();
for (int i = 0; i < packetSize; i++) pzi_start[i] = pci_start[i] = start.y() + y * step.y();
for(int x = 0; x < alignedWidth; x += packetSize, pix += packetSize)
{
for (int x = 0; x < alignedWidth; x += packetSize, pix += packetSize) {
Packet pcr, pci = pci_start, pzr, pzi = pzi_start, pzr_buf;
for(int i = 0; i < packetSize; i++) pzr[i] = pcr[i] = start.x() + (x+i) * step.x();
for (int i = 0; i < packetSize; i++) pzr[i] = pcr[i] = start.x() + (x + i) * step.x();
// do the iterations. Every iters_before_test iterations we check for divergence,
// in which case we can stop iterating.
int j = 0;
typedef Eigen::Matrix<int, packetSize, 1> Packeti;
Packeti pix_iter = Packeti::Zero(), // number of iteration per pixel in the packet
pix_dont_diverge; // whether or not each pixel has already diverged
do
{
for(int i = 0; i < iters_before_test/4; i++) // peel the inner loop by 4
Packeti pix_iter = Packeti::Zero(), // number of iteration per pixel in the packet
pix_dont_diverge; // whether or not each pixel has already diverged
do {
for (int i = 0; i < iters_before_test / 4; i++) // peel the inner loop by 4
{
# define ITERATE \
pzr_buf = pzr; \
pzr = pzr.square(); \
pzr -= pzi.square(); \
pzr += pcr; \
pzi = (2*pzr_buf)*pzi; \
pzi += pci;
#define ITERATE \
pzr_buf = pzr; \
pzr = pzr.square(); \
pzr -= pzi.square(); \
pzr += pcr; \
pzi = (2 * pzr_buf) * pzi; \
pzi += pci;
ITERATE ITERATE ITERATE ITERATE
}
pix_dont_diverge = ((pzr.square() + pzi.square())
.eval() // temporary fix as what follows is not yet vectorized by Eigen
<= Packet::Constant(4))
// the 4 here is not a magic value, it's a math fact that if
// the square modulus is >4 then divergence is inevitable.
.template cast<int>();
pix_dont_diverge =
((pzr.square() + pzi.square()).eval() // temporary fix as what follows is not yet vectorized by Eigen
<= Packet::Constant(4))
// the 4 here is not a magic value, it's a math fact that if
// the square modulus is >4 then divergence is inevitable.
.template cast<int>();
pix_iter += iters_before_test * pix_dont_diverge;
j++;
total_iter += iters_before_test * packetSize;
}
while(j < max_iter/iters_before_test && pix_dont_diverge.any()); // any() is not yet vectorized by Eigen
} while (j < max_iter / iters_before_test && pix_dont_diverge.any()); // any() is not yet vectorized by Eigen
// compute pixel colors
for(int i = 0; i < packetSize; i++)
{
buffer[4*(pix+i)] = 255*pix_iter[i]/max_iter;
buffer[4*(pix+i)+1] = 0;
buffer[4*(pix+i)+2] = 0;
for (int i = 0; i < packetSize; i++) {
buffer[4 * (pix + i)] = 255 * pix_iter[i] / max_iter;
buffer[4 * (pix + i) + 1] = 0;
buffer[4 * (pix + i) + 2] = 0;
}
}
// if the width is not a multiple of packetSize, fill the remainder in black
for(int x = alignedWidth; x < img_width; x++, pix++)
buffer[4*pix] = buffer[4*pix+1] = buffer[4*pix+2] = 0;
for (int x = alignedWidth; x < img_width; x++, pix++)
buffer[4 * pix] = buffer[4 * pix + 1] = buffer[4 * pix + 2] = 0;
}
return;
}
void MandelbrotThread::run()
{
void MandelbrotThread::run() {
setTerminationEnabled(true);
double resolution = widget->xradius*2/widget->width();
double resolution = widget->xradius * 2 / widget->width();
max_iter = 128;
if(resolution < 1e-4f) max_iter += 128 * ( - 4 - std::log10(resolution));
int img_width = widget->width()/widget->draft;
int img_height = widget->height()/widget->draft;
if (resolution < 1e-4f) max_iter += 128 * (-4 - std::log10(resolution));
int img_width = widget->width() / widget->draft;
int img_height = widget->height() / widget->draft;
single_precision = resolution > 1e-7f;
if(single_precision)
if (single_precision)
render<float>(img_width, img_height);
else
render<double>(img_width, img_height);
}
void MandelbrotWidget::paintEvent(QPaintEvent *)
{
void MandelbrotWidget::paintEvent(QPaintEvent *) {
static float max_speed = 0;
long long total_iter = 0;
QTime time;
time.start();
for(int th = 0; th < threadcount; th++)
threads[th]->start(QThread::LowPriority);
for(int th = 0; th < threadcount; th++)
{
for (int th = 0; th < threadcount; th++) threads[th]->start(QThread::LowPriority);
for (int th = 0; th < threadcount; th++) {
threads[th]->wait();
total_iter += threads[th]->total_iter;
}
int elapsed = time.elapsed();
if(draft == 1)
{
float speed = elapsed ? float(total_iter)*1000/elapsed : 0;
if (draft == 1) {
float speed = elapsed ? float(total_iter) * 1000 / elapsed : 0;
max_speed = std::max(max_speed, speed);
std::cout << threadcount << " threads, "
<< elapsed << " ms, "
<< speed << " iters/s (max " << max_speed << ")" << std::endl;
int packetSize = threads[0]->single_precision
? int(Eigen::internal::packet_traits<float>::size)
: int(Eigen::internal::packet_traits<double>::size);
setWindowTitle(QString("resolution ")+QString::number(xradius*2/width(), 'e', 2)
+QString(", %1 iterations per pixel, ").arg(threads[0]->max_iter)
+(threads[0]->single_precision ? QString("single ") : QString("double "))
+QString("precision, ")
+(packetSize==1 ? QString("no vectorization")
: QString("vectorized (%1 per packet)").arg(packetSize)));
std::cout << threadcount << " threads, " << elapsed << " ms, " << speed << " iters/s (max " << max_speed << ")"
<< std::endl;
int packetSize = threads[0]->single_precision ? int(Eigen::internal::packet_traits<float>::size)
: int(Eigen::internal::packet_traits<double>::size);
setWindowTitle(
QString("resolution ") + QString::number(xradius * 2 / width(), 'e', 2) +
QString(", %1 iterations per pixel, ").arg(threads[0]->max_iter) +
(threads[0]->single_precision ? QString("single ") : QString("double ")) + QString("precision, ") +
(packetSize == 1 ? QString("no vectorization") : QString("vectorized (%1 per packet)").arg(packetSize)));
}
QImage image(buffer, width()/draft, height()/draft, QImage::Format_RGB32);
QImage image(buffer, width() / draft, height() / draft, QImage::Format_RGB32);
QPainter painter(this);
painter.drawImage(QPoint(0, 0), image.scaled(width(), height()));
if(draft>1)
{
if (draft > 1) {
draft /= 2;
setWindowTitle(QString("recomputing at 1/%1 resolution...").arg(draft));
update();
}
}
void MandelbrotWidget::mousePressEvent(QMouseEvent *event)
{
if( event->buttons() & Qt::LeftButton )
{
void MandelbrotWidget::mousePressEvent(QMouseEvent *event) {
if (event->buttons() & Qt::LeftButton) {
lastpos = event->pos();
double yradius = xradius * height() / width();
center = Eigen::Vector2d(center.x() + (event->pos().x() - width()/2) * xradius * 2 / width(),
center.y() + (event->pos().y() - height()/2) * yradius * 2 / height());
center = Eigen::Vector2d(center.x() + (event->pos().x() - width() / 2) * xradius * 2 / width(),
center.y() + (event->pos().y() - height() / 2) * yradius * 2 / height());
draft = 16;
for(int th = 0; th < threadcount; th++)
threads[th]->terminate();
for (int th = 0; th < threadcount; th++) threads[th]->terminate();
update();
}
}
void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event)
{
void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event) {
QPoint delta = event->pos() - lastpos;
lastpos = event->pos();
if( event->buttons() & Qt::LeftButton )
{
if (event->buttons() & Qt::LeftButton) {
double t = 1 + 5 * double(delta.y()) / height();
if(t < 0.5) t = 0.5;
if(t > 2) t = 2;
if (t < 0.5) t = 0.5;
if (t > 2) t = 2;
xradius *= t;
draft = 16;
for(int th = 0; th < threadcount; th++)
threads[th]->terminate();
for (int th = 0; th < threadcount; th++) threads[th]->terminate();
update();
}
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MandelbrotWidget w;
w.show();

View File

@@ -17,55 +17,51 @@
class MandelbrotWidget;
class MandelbrotThread : public QThread
{
friend class MandelbrotWidget;
MandelbrotWidget *widget;
long long total_iter;
int id, max_iter;
bool single_precision;
class MandelbrotThread : public QThread {
friend class MandelbrotWidget;
MandelbrotWidget *widget;
long long total_iter;
int id, max_iter;
bool single_precision;
public:
MandelbrotThread(MandelbrotWidget *w, int i) : widget(w), id(i) {}
void run();
template<typename Real> void render(int img_width, int img_height);
public:
MandelbrotThread(MandelbrotWidget *w, int i) : widget(w), id(i) {}
void run();
template <typename Real>
void render(int img_width, int img_height);
};
class MandelbrotWidget : public QWidget
{
Q_OBJECT
class MandelbrotWidget : public QWidget {
Q_OBJECT
friend class MandelbrotThread;
Eigen::Vector2d center;
double xradius;
int size;
unsigned char *buffer;
QPoint lastpos;
int draft;
MandelbrotThread **threads;
int threadcount;
friend class MandelbrotThread;
Eigen::Vector2d center;
double xradius;
int size;
unsigned char *buffer;
QPoint lastpos;
int draft;
MandelbrotThread **threads;
int threadcount;
protected:
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
protected:
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
public:
MandelbrotWidget() : QWidget(), center(0,0), xradius(2),
size(0), buffer(0), draft(16)
{
setAutoFillBackground(false);
threadcount = QThread::idealThreadCount();
threads = new MandelbrotThread*[threadcount];
for(int th = 0; th < threadcount; th++) threads[th] = new MandelbrotThread(this, th);
}
~MandelbrotWidget()
{
if(buffer) delete[]buffer;
for(int th = 0; th < threadcount; th++) delete threads[th];
delete[] threads;
}
public:
MandelbrotWidget() : QWidget(), center(0, 0), xradius(2), size(0), buffer(0), draft(16) {
setAutoFillBackground(false);
threadcount = QThread::idealThreadCount();
threads = new MandelbrotThread *[threadcount];
for (int th = 0; th < threadcount; th++) threads[th] = new MandelbrotThread(this, th);
}
~MandelbrotWidget() {
if (buffer) delete[] buffer;
for (int th = 0; th < threadcount; th++) delete threads[th];
delete[] threads;
}
};
#endif // MANDELBROT_H
#endif // MANDELBROT_H

View File

@@ -20,166 +20,84 @@ using namespace Eigen;
////// class MatrixXd //////
inline MatrixXd& c_to_eigen(C_MatrixXd* ptr)
{
return *reinterpret_cast<MatrixXd*>(ptr);
}
inline MatrixXd &c_to_eigen(C_MatrixXd *ptr) { return *reinterpret_cast<MatrixXd *>(ptr); }
inline const MatrixXd& c_to_eigen(const C_MatrixXd* ptr)
{
return *reinterpret_cast<const MatrixXd*>(ptr);
}
inline const MatrixXd &c_to_eigen(const C_MatrixXd *ptr) { return *reinterpret_cast<const MatrixXd *>(ptr); }
inline C_MatrixXd* eigen_to_c(MatrixXd& ref)
{
return reinterpret_cast<C_MatrixXd*>(&ref);
}
inline C_MatrixXd *eigen_to_c(MatrixXd &ref) { return reinterpret_cast<C_MatrixXd *>(&ref); }
inline const C_MatrixXd* eigen_to_c(const MatrixXd& ref)
{
return reinterpret_cast<const C_MatrixXd*>(&ref);
}
inline const C_MatrixXd *eigen_to_c(const MatrixXd &ref) { return reinterpret_cast<const C_MatrixXd *>(&ref); }
////// class Map<MatrixXd> //////
inline Map<MatrixXd>& c_to_eigen(C_Map_MatrixXd* ptr)
{
return *reinterpret_cast<Map<MatrixXd>*>(ptr);
inline Map<MatrixXd> &c_to_eigen(C_Map_MatrixXd *ptr) { return *reinterpret_cast<Map<MatrixXd> *>(ptr); }
inline const Map<MatrixXd> &c_to_eigen(const C_Map_MatrixXd *ptr) {
return *reinterpret_cast<const Map<MatrixXd> *>(ptr);
}
inline const Map<MatrixXd>& c_to_eigen(const C_Map_MatrixXd* ptr)
{
return *reinterpret_cast<const Map<MatrixXd>*>(ptr);
}
inline C_Map_MatrixXd *eigen_to_c(Map<MatrixXd> &ref) { return reinterpret_cast<C_Map_MatrixXd *>(&ref); }
inline C_Map_MatrixXd* eigen_to_c(Map<MatrixXd>& ref)
{
return reinterpret_cast<C_Map_MatrixXd*>(&ref);
inline const C_Map_MatrixXd *eigen_to_c(const Map<MatrixXd> &ref) {
return reinterpret_cast<const C_Map_MatrixXd *>(&ref);
}
inline const C_Map_MatrixXd* eigen_to_c(const Map<MatrixXd>& ref)
{
return reinterpret_cast<const C_Map_MatrixXd*>(&ref);
}
/************************* implementation of classes **********************************************/
////// class MatrixXd //////
C_MatrixXd *MatrixXd_new(int rows, int cols) { return eigen_to_c(*new MatrixXd(rows, cols)); }
C_MatrixXd* MatrixXd_new(int rows, int cols)
{
return eigen_to_c(*new MatrixXd(rows,cols));
}
void MatrixXd_delete(C_MatrixXd *m) { delete &c_to_eigen(m); }
void MatrixXd_delete(C_MatrixXd *m)
{
delete &c_to_eigen(m);
}
double *MatrixXd_data(C_MatrixXd *m) { return c_to_eigen(m).data(); }
double* MatrixXd_data(C_MatrixXd *m)
{
return c_to_eigen(m).data();
}
void MatrixXd_set_zero(C_MatrixXd *m) { c_to_eigen(m).setZero(); }
void MatrixXd_set_zero(C_MatrixXd *m)
{
c_to_eigen(m).setZero();
}
void MatrixXd_resize(C_MatrixXd *m, int rows, int cols) { c_to_eigen(m).resize(rows, cols); }
void MatrixXd_resize(C_MatrixXd *m, int rows, int cols)
{
c_to_eigen(m).resize(rows,cols);
}
void MatrixXd_copy(C_MatrixXd *dst, const C_MatrixXd *src) { c_to_eigen(dst) = c_to_eigen(src); }
void MatrixXd_copy(C_MatrixXd *dst, const C_MatrixXd *src)
{
c_to_eigen(dst) = c_to_eigen(src);
}
void MatrixXd_copy_map(C_MatrixXd *dst, const C_Map_MatrixXd *src) { c_to_eigen(dst) = c_to_eigen(src); }
void MatrixXd_copy_map(C_MatrixXd *dst, const C_Map_MatrixXd *src)
{
c_to_eigen(dst) = c_to_eigen(src);
}
void MatrixXd_set_coeff(C_MatrixXd *m, int i, int j, double coeff) { c_to_eigen(m)(i, j) = coeff; }
void MatrixXd_set_coeff(C_MatrixXd *m, int i, int j, double coeff)
{
c_to_eigen(m)(i,j) = coeff;
}
double MatrixXd_get_coeff(const C_MatrixXd *m, int i, int j) { return c_to_eigen(m)(i, j); }
double MatrixXd_get_coeff(const C_MatrixXd *m, int i, int j)
{
return c_to_eigen(m)(i,j);
}
void MatrixXd_print(const C_MatrixXd *m) { std::cout << c_to_eigen(m) << std::endl; }
void MatrixXd_print(const C_MatrixXd *m)
{
std::cout << c_to_eigen(m) << std::endl;
}
void MatrixXd_multiply(const C_MatrixXd *m1, const C_MatrixXd *m2, C_MatrixXd *result)
{
void MatrixXd_multiply(const C_MatrixXd *m1, const C_MatrixXd *m2, C_MatrixXd *result) {
c_to_eigen(result) = c_to_eigen(m1) * c_to_eigen(m2);
}
void MatrixXd_add(const C_MatrixXd *m1, const C_MatrixXd *m2, C_MatrixXd *result)
{
void MatrixXd_add(const C_MatrixXd *m1, const C_MatrixXd *m2, C_MatrixXd *result) {
c_to_eigen(result) = c_to_eigen(m1) + c_to_eigen(m2);
}
////// class Map_MatrixXd //////
C_Map_MatrixXd* Map_MatrixXd_new(double *array, int rows, int cols)
{
return eigen_to_c(*new Map<MatrixXd>(array,rows,cols));
C_Map_MatrixXd *Map_MatrixXd_new(double *array, int rows, int cols) {
return eigen_to_c(*new Map<MatrixXd>(array, rows, cols));
}
void Map_MatrixXd_delete(C_Map_MatrixXd *m)
{
delete &c_to_eigen(m);
}
void Map_MatrixXd_delete(C_Map_MatrixXd *m) { delete &c_to_eigen(m); }
void Map_MatrixXd_set_zero(C_Map_MatrixXd *m)
{
c_to_eigen(m).setZero();
}
void Map_MatrixXd_set_zero(C_Map_MatrixXd *m) { c_to_eigen(m).setZero(); }
void Map_MatrixXd_copy(C_Map_MatrixXd *dst, const C_Map_MatrixXd *src)
{
c_to_eigen(dst) = c_to_eigen(src);
}
void Map_MatrixXd_copy(C_Map_MatrixXd *dst, const C_Map_MatrixXd *src) { c_to_eigen(dst) = c_to_eigen(src); }
void Map_MatrixXd_copy_matrix(C_Map_MatrixXd *dst, const C_MatrixXd *src)
{
c_to_eigen(dst) = c_to_eigen(src);
}
void Map_MatrixXd_copy_matrix(C_Map_MatrixXd *dst, const C_MatrixXd *src) { c_to_eigen(dst) = c_to_eigen(src); }
void Map_MatrixXd_set_coeff(C_Map_MatrixXd *m, int i, int j, double coeff)
{
c_to_eigen(m)(i,j) = coeff;
}
void Map_MatrixXd_set_coeff(C_Map_MatrixXd *m, int i, int j, double coeff) { c_to_eigen(m)(i, j) = coeff; }
double Map_MatrixXd_get_coeff(const C_Map_MatrixXd *m, int i, int j)
{
return c_to_eigen(m)(i,j);
}
double Map_MatrixXd_get_coeff(const C_Map_MatrixXd *m, int i, int j) { return c_to_eigen(m)(i, j); }
void Map_MatrixXd_print(const C_Map_MatrixXd *m)
{
std::cout << c_to_eigen(m) << std::endl;
}
void Map_MatrixXd_print(const C_Map_MatrixXd *m) { std::cout << c_to_eigen(m) << std::endl; }
void Map_MatrixXd_multiply(const C_Map_MatrixXd *m1, const C_Map_MatrixXd *m2, C_Map_MatrixXd *result)
{
void Map_MatrixXd_multiply(const C_Map_MatrixXd *m1, const C_Map_MatrixXd *m2, C_Map_MatrixXd *result) {
c_to_eigen(result) = c_to_eigen(m1) * c_to_eigen(m2);
}
void Map_MatrixXd_add(const C_Map_MatrixXd *m1, const C_Map_MatrixXd *m2, C_Map_MatrixXd *result)
{
void Map_MatrixXd_add(const C_Map_MatrixXd *m1, const C_Map_MatrixXd *m2, C_Map_MatrixXd *result) {
c_to_eigen(result) = c_to_eigen(m1) + c_to_eigen(m2);
}

View File

@@ -13,59 +13,43 @@
// they will be compiled to C object code.
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
// just dummy empty structs to give different pointer types,
// instead of using void* which would be type unsafe
struct C_MatrixXd {};
struct C_Map_MatrixXd {};
// just dummy empty structs to give different pointer types,
// instead of using void* which would be type unsafe
struct C_MatrixXd {};
struct C_Map_MatrixXd {};
// the C_MatrixXd class, wraps some of the functionality
// of Eigen::MatrixXd.
struct C_MatrixXd* MatrixXd_new(int rows, int cols);
void MatrixXd_delete (struct C_MatrixXd *m);
double* MatrixXd_data (struct C_MatrixXd *m);
void MatrixXd_set_zero (struct C_MatrixXd *m);
void MatrixXd_resize (struct C_MatrixXd *m, int rows, int cols);
void MatrixXd_copy (struct C_MatrixXd *dst,
const struct C_MatrixXd *src);
void MatrixXd_copy_map (struct C_MatrixXd *dst,
const struct C_Map_MatrixXd *src);
void MatrixXd_set_coeff (struct C_MatrixXd *m,
int i, int j, double coeff);
double MatrixXd_get_coeff (const struct C_MatrixXd *m,
int i, int j);
void MatrixXd_print (const struct C_MatrixXd *m);
void MatrixXd_add (const struct C_MatrixXd *m1,
const struct C_MatrixXd *m2,
struct C_MatrixXd *result);
void MatrixXd_multiply (const struct C_MatrixXd *m1,
const struct C_MatrixXd *m2,
struct C_MatrixXd *result);
// the C_Map_MatrixXd class, wraps some of the functionality
// of Eigen::Map<MatrixXd>
struct C_Map_MatrixXd* Map_MatrixXd_new(double *array, int rows, int cols);
void Map_MatrixXd_delete (struct C_Map_MatrixXd *m);
void Map_MatrixXd_set_zero (struct C_Map_MatrixXd *m);
void Map_MatrixXd_copy (struct C_Map_MatrixXd *dst,
const struct C_Map_MatrixXd *src);
void Map_MatrixXd_copy_matrix(struct C_Map_MatrixXd *dst,
const struct C_MatrixXd *src);
void Map_MatrixXd_set_coeff (struct C_Map_MatrixXd *m,
int i, int j, double coeff);
double Map_MatrixXd_get_coeff (const struct C_Map_MatrixXd *m,
int i, int j);
void Map_MatrixXd_print (const struct C_Map_MatrixXd *m);
void Map_MatrixXd_add (const struct C_Map_MatrixXd *m1,
const struct C_Map_MatrixXd *m2,
struct C_Map_MatrixXd *result);
void Map_MatrixXd_multiply (const struct C_Map_MatrixXd *m1,
const struct C_Map_MatrixXd *m2,
struct C_Map_MatrixXd *result);
// the C_MatrixXd class, wraps some of the functionality
// of Eigen::MatrixXd.
struct C_MatrixXd *MatrixXd_new(int rows, int cols);
void MatrixXd_delete(struct C_MatrixXd *m);
double *MatrixXd_data(struct C_MatrixXd *m);
void MatrixXd_set_zero(struct C_MatrixXd *m);
void MatrixXd_resize(struct C_MatrixXd *m, int rows, int cols);
void MatrixXd_copy(struct C_MatrixXd *dst, const struct C_MatrixXd *src);
void MatrixXd_copy_map(struct C_MatrixXd *dst, const struct C_Map_MatrixXd *src);
void MatrixXd_set_coeff(struct C_MatrixXd *m, int i, int j, double coeff);
double MatrixXd_get_coeff(const struct C_MatrixXd *m, int i, int j);
void MatrixXd_print(const struct C_MatrixXd *m);
void MatrixXd_add(const struct C_MatrixXd *m1, const struct C_MatrixXd *m2, struct C_MatrixXd *result);
void MatrixXd_multiply(const struct C_MatrixXd *m1, const struct C_MatrixXd *m2, struct C_MatrixXd *result);
// the C_Map_MatrixXd class, wraps some of the functionality
// of Eigen::Map<MatrixXd>
struct C_Map_MatrixXd *Map_MatrixXd_new(double *array, int rows, int cols);
void Map_MatrixXd_delete(struct C_Map_MatrixXd *m);
void Map_MatrixXd_set_zero(struct C_Map_MatrixXd *m);
void Map_MatrixXd_copy(struct C_Map_MatrixXd *dst, const struct C_Map_MatrixXd *src);
void Map_MatrixXd_copy_matrix(struct C_Map_MatrixXd *dst, const struct C_MatrixXd *src);
void Map_MatrixXd_set_coeff(struct C_Map_MatrixXd *m, int i, int j, double coeff);
double Map_MatrixXd_get_coeff(const struct C_Map_MatrixXd *m, int i, int j);
void Map_MatrixXd_print(const struct C_Map_MatrixXd *m);
void Map_MatrixXd_add(const struct C_Map_MatrixXd *m1, const struct C_Map_MatrixXd *m2, struct C_Map_MatrixXd *result);
void Map_MatrixXd_multiply(const struct C_Map_MatrixXd *m1, const struct C_Map_MatrixXd *m2,
struct C_Map_MatrixXd *result);
#ifdef __cplusplus
} // end extern "C"
} // end extern "C"
#endif

View File

@@ -10,11 +10,10 @@
#include "binary_library.h"
#include "stdio.h"
void demo_MatrixXd()
{
void demo_MatrixXd() {
struct C_MatrixXd *matrix1, *matrix2, *result;
printf("*** demo_MatrixXd ***\n");
matrix1 = MatrixXd_new(3, 3);
MatrixXd_set_zero(matrix1);
MatrixXd_set_coeff(matrix1, 0, 1, 2.5);
@@ -32,24 +31,22 @@ void demo_MatrixXd()
}
// this helper function takes a plain C array and prints it in one line
void print_array(double *array, int n)
{
void print_array(double *array, int n) {
struct C_Map_MatrixXd *m = Map_MatrixXd_new(array, 1, n);
Map_MatrixXd_print(m);
Map_MatrixXd_delete(m);
}
void demo_Map_MatrixXd()
{
void demo_Map_MatrixXd() {
struct C_Map_MatrixXd *map;
double array[5];
int i;
printf("*** demo_Map_MatrixXd ***\n");
for(i = 0; i < 5; ++i) array[i] = i;
for (i = 0; i < 5; ++i) array[i] = i;
printf("Initially, the array is:\n");
print_array(array, 5);
map = Map_MatrixXd_new(array, 5, 1);
Map_MatrixXd_add(map, map, map);
Map_MatrixXd_delete(map);
@@ -58,8 +55,7 @@ void demo_Map_MatrixXd()
print_array(array, 5);
}
int main()
{
int main() {
demo_MatrixXd();
demo_Map_MatrixXd();
}

View File

@@ -15,250 +15,205 @@
#include "Eigen/LU"
using namespace Eigen;
Camera::Camera()
: mViewIsUptodate(false), mProjIsUptodate(false)
{
mViewMatrix.setIdentity();
mFovY = M_PI/3.;
mNearDist = 1.;
mFarDist = 50000.;
mVpX = 0;
mVpY = 0;
Camera::Camera() : mViewIsUptodate(false), mProjIsUptodate(false) {
mViewMatrix.setIdentity();
setPosition(Vector3f::Constant(100.));
setTarget(Vector3f::Zero());
mFovY = M_PI / 3.;
mNearDist = 1.;
mFarDist = 50000.;
mVpX = 0;
mVpY = 0;
setPosition(Vector3f::Constant(100.));
setTarget(Vector3f::Zero());
}
Camera& Camera::operator=(const Camera& other)
{
mViewIsUptodate = false;
mProjIsUptodate = false;
mVpX = other.mVpX;
mVpY = other.mVpY;
mVpWidth = other.mVpWidth;
mVpHeight = other.mVpHeight;
Camera& Camera::operator=(const Camera& other) {
mViewIsUptodate = false;
mProjIsUptodate = false;
mTarget = other.mTarget;
mFovY = other.mFovY;
mNearDist = other.mNearDist;
mFarDist = other.mFarDist;
mViewMatrix = other.mViewMatrix;
mProjectionMatrix = other.mProjectionMatrix;
mVpX = other.mVpX;
mVpY = other.mVpY;
mVpWidth = other.mVpWidth;
mVpHeight = other.mVpHeight;
return *this;
mTarget = other.mTarget;
mFovY = other.mFovY;
mNearDist = other.mNearDist;
mFarDist = other.mFarDist;
mViewMatrix = other.mViewMatrix;
mProjectionMatrix = other.mProjectionMatrix;
return *this;
}
Camera::Camera(const Camera& other)
{
*this = other;
Camera::Camera(const Camera& other) { *this = other; }
Camera::~Camera() {}
void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height) {
mVpX = offsetx;
mVpY = offsety;
mVpWidth = width;
mVpHeight = height;
mProjIsUptodate = false;
}
Camera::~Camera()
{
void Camera::setViewport(uint width, uint height) {
mVpWidth = width;
mVpHeight = height;
mProjIsUptodate = false;
}
void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height)
{
mVpX = offsetx;
mVpY = offsety;
mVpWidth = width;
mVpHeight = height;
mProjIsUptodate = false;
void Camera::setFovY(float value) {
mFovY = value;
mProjIsUptodate = false;
}
void Camera::setViewport(uint width, uint height)
{
mVpWidth = width;
mVpHeight = height;
mProjIsUptodate = false;
Vector3f Camera::direction(void) const { return -(orientation() * Vector3f::UnitZ()); }
Vector3f Camera::up(void) const { return orientation() * Vector3f::UnitY(); }
Vector3f Camera::right(void) const { return orientation() * Vector3f::UnitX(); }
void Camera::setDirection(const Vector3f& newDirection) {
// TODO implement it computing the rotation between newDirection and current dir ?
Vector3f up = this->up();
Matrix3f camAxes;
camAxes.col(2) = (-newDirection).normalized();
camAxes.col(0) = up.cross(camAxes.col(2)).normalized();
camAxes.col(1) = camAxes.col(2).cross(camAxes.col(0)).normalized();
setOrientation(Quaternionf(camAxes));
mViewIsUptodate = false;
}
void Camera::setFovY(float value)
{
mFovY = value;
mProjIsUptodate = false;
void Camera::setTarget(const Vector3f& target) {
mTarget = target;
if (!mTarget.isApprox(position())) {
Vector3f newDirection = mTarget - position();
setDirection(newDirection.normalized());
}
}
Vector3f Camera::direction(void) const
{
return - (orientation() * Vector3f::UnitZ());
}
Vector3f Camera::up(void) const
{
return orientation() * Vector3f::UnitY();
}
Vector3f Camera::right(void) const
{
return orientation() * Vector3f::UnitX();
void Camera::setPosition(const Vector3f& p) {
mFrame.position = p;
mViewIsUptodate = false;
}
void Camera::setDirection(const Vector3f& newDirection)
{
// TODO implement it computing the rotation between newDirection and current dir ?
Vector3f up = this->up();
Matrix3f camAxes;
camAxes.col(2) = (-newDirection).normalized();
camAxes.col(0) = up.cross( camAxes.col(2) ).normalized();
camAxes.col(1) = camAxes.col(2).cross( camAxes.col(0) ).normalized();
setOrientation(Quaternionf(camAxes));
mViewIsUptodate = false;
void Camera::setOrientation(const Quaternionf& q) {
mFrame.orientation = q;
mViewIsUptodate = false;
}
void Camera::setTarget(const Vector3f& target)
{
mTarget = target;
if (!mTarget.isApprox(position()))
{
Vector3f newDirection = mTarget - position();
setDirection(newDirection.normalized());
}
}
void Camera::setPosition(const Vector3f& p)
{
mFrame.position = p;
mViewIsUptodate = false;
}
void Camera::setOrientation(const Quaternionf& q)
{
mFrame.orientation = q;
mViewIsUptodate = false;
}
void Camera::setFrame(const Frame& f)
{
void Camera::setFrame(const Frame& f) {
mFrame = f;
mViewIsUptodate = false;
}
void Camera::rotateAroundTarget(const Quaternionf& q)
{
Matrix4f mrot, mt, mtm;
// update the transform matrix
updateViewMatrix();
Vector3f t = mViewMatrix * mTarget;
void Camera::rotateAroundTarget(const Quaternionf& q) {
Matrix4f mrot, mt, mtm;
mViewMatrix = Translation3f(t)
* q
* Translation3f(-t)
* mViewMatrix;
Quaternionf qa(mViewMatrix.linear());
qa = qa.conjugate();
setOrientation(qa);
setPosition(- (qa * mViewMatrix.translation()) );
// update the transform matrix
updateViewMatrix();
Vector3f t = mViewMatrix * mTarget;
mViewIsUptodate = true;
mViewMatrix = Translation3f(t) * q * Translation3f(-t) * mViewMatrix;
Quaternionf qa(mViewMatrix.linear());
qa = qa.conjugate();
setOrientation(qa);
setPosition(-(qa * mViewMatrix.translation()));
mViewIsUptodate = true;
}
void Camera::localRotate(const Quaternionf& q)
{
float dist = (position() - mTarget).norm();
setOrientation(orientation() * q);
mTarget = position() + dist * direction();
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) {
float dist = (position() - mTarget).norm();
if (dist > d) {
setPosition(position() + direction() * d);
mViewIsUptodate = false;
}
}
void Camera::zoom(float d)
{
float dist = (position() - mTarget).norm();
if(dist > d)
{
setPosition(position() + direction() * d);
mViewIsUptodate = false;
}
}
void Camera::localTranslate(const Vector3f& t)
{
void Camera::localTranslate(const Vector3f& t) {
Vector3f trans = orientation() * t;
setPosition( position() + trans );
setTarget( mTarget + trans );
setPosition(position() + trans);
setTarget(mTarget + trans);
mViewIsUptodate = false;
}
void Camera::updateViewMatrix(void) const
{
if(!mViewIsUptodate)
{
Quaternionf q = orientation().conjugate();
mViewMatrix.linear() = q.toRotationMatrix();
mViewMatrix.translation() = - (mViewMatrix.linear() * position());
void Camera::updateViewMatrix(void) const {
if (!mViewIsUptodate) {
Quaternionf q = orientation().conjugate();
mViewMatrix.linear() = q.toRotationMatrix();
mViewMatrix.translation() = -(mViewMatrix.linear() * position());
mViewIsUptodate = true;
}
mViewIsUptodate = true;
}
}
const Affine3f& Camera::viewMatrix(void) const
{
const Affine3f& Camera::viewMatrix(void) const {
updateViewMatrix();
return mViewMatrix;
}
void Camera::updateProjectionMatrix(void) const
{
if(!mProjIsUptodate)
{
void Camera::updateProjectionMatrix(void) const {
if (!mProjIsUptodate) {
mProjectionMatrix.setIdentity();
float aspect = float(mVpWidth)/float(mVpHeight);
float theta = mFovY*0.5;
float aspect = float(mVpWidth) / float(mVpHeight);
float theta = mFovY * 0.5;
float range = mFarDist - mNearDist;
float invtan = 1./tan(theta);
float invtan = 1. / tan(theta);
mProjectionMatrix(0, 0) = invtan / aspect;
mProjectionMatrix(1, 1) = invtan;
mProjectionMatrix(2, 2) = -(mNearDist + mFarDist) / range;
mProjectionMatrix(3, 2) = -1;
mProjectionMatrix(2, 3) = -2 * mNearDist * mFarDist / range;
mProjectionMatrix(3, 3) = 0;
mProjectionMatrix(0,0) = invtan / aspect;
mProjectionMatrix(1,1) = invtan;
mProjectionMatrix(2,2) = -(mNearDist + mFarDist) / range;
mProjectionMatrix(3,2) = -1;
mProjectionMatrix(2,3) = -2 * mNearDist * mFarDist / range;
mProjectionMatrix(3,3) = 0;
mProjIsUptodate = true;
}
}
const Matrix4f& Camera::projectionMatrix(void) const
{
const Matrix4f& Camera::projectionMatrix(void) const {
updateProjectionMatrix();
return mProjectionMatrix;
}
void Camera::activateGL(void)
{
void Camera::activateGL(void) {
glViewport(vpX(), vpY(), vpWidth(), vpHeight());
gpu.loadMatrix(projectionMatrix(),GL_PROJECTION);
gpu.loadMatrix(viewMatrix().matrix(),GL_MODELVIEW);
gpu.loadMatrix(projectionMatrix(), GL_PROJECTION);
gpu.loadMatrix(viewMatrix().matrix(), GL_MODELVIEW);
}
Vector3f Camera::unProject(const Vector2f& uv, float depth) const
{
Matrix4f inv = mViewMatrix.inverse().matrix();
return unProject(uv, depth, inv);
Vector3f Camera::unProject(const Vector2f& uv, float depth) const {
Matrix4f inv = mViewMatrix.inverse().matrix();
return unProject(uv, depth, inv);
}
Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const
{
updateViewMatrix();
updateProjectionMatrix();
Vector3f a(2.*uv.x()/float(mVpWidth)-1., 2.*uv.y()/float(mVpHeight)-1., 1.);
a.x() *= depth/mProjectionMatrix(0,0);
a.y() *= depth/mProjectionMatrix(1,1);
a.z() = -depth;
// FIXME /\/|
Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
return Vector3f(b.x(), b.y(), b.z());
Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const {
updateViewMatrix();
updateProjectionMatrix();
Vector3f a(2. * uv.x() / float(mVpWidth) - 1., 2. * uv.y() / float(mVpHeight) - 1., 1.);
a.x() *= depth / mProjectionMatrix(0, 0);
a.y() *= depth / mProjectionMatrix(1, 1);
a.z() = -depth;
// FIXME /\/|
Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
return Vector3f(b.x(), b.y(), b.z());
}

View File

@@ -14,105 +14,98 @@
#include <QObject>
// #include <frame.h>
class Frame
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
inline Frame(const Eigen::Vector3f& pos = Eigen::Vector3f::Zero(),
const Eigen::Quaternionf& o = Eigen::Quaternionf())
: orientation(o), position(pos)
{}
Frame lerp(float alpha, const Frame& other) const
{
return Frame((1.f-alpha)*position + alpha * other.position,
orientation.slerp(alpha,other.orientation));
}
class Frame {
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Eigen::Quaternionf orientation;
Eigen::Vector3f position;
inline Frame(const Eigen::Vector3f& pos = Eigen::Vector3f::Zero(), const Eigen::Quaternionf& o = Eigen::Quaternionf())
: orientation(o), position(pos) {}
Frame lerp(float alpha, const Frame& other) const {
return Frame((1.f - alpha) * position + alpha * other.position, orientation.slerp(alpha, other.orientation));
}
Eigen::Quaternionf orientation;
Eigen::Vector3f position;
};
class Camera
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
class Camera {
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Camera(void);
Camera(const Camera& other);
virtual ~Camera();
Camera& operator=(const Camera& other);
void setViewport(uint offsetx, uint offsety, uint width, uint height);
void setViewport(uint width, uint height);
inline uint vpX(void) const { return mVpX; }
inline uint vpY(void) const { return mVpY; }
inline uint vpWidth(void) const { return mVpWidth; }
inline uint vpHeight(void) const { return mVpHeight; }
Camera(void);
inline float fovY(void) const { return mFovY; }
void setFovY(float value);
void setPosition(const Eigen::Vector3f& pos);
inline const Eigen::Vector3f& position(void) const { return mFrame.position; }
Camera(const Camera& other);
void setOrientation(const Eigen::Quaternionf& q);
inline const Eigen::Quaternionf& orientation(void) const { return mFrame.orientation; }
virtual ~Camera();
void setFrame(const Frame& f);
const Frame& frame(void) const { return mFrame; }
void setDirection(const Eigen::Vector3f& newDirection);
Eigen::Vector3f direction(void) const;
void setUp(const Eigen::Vector3f& vectorUp);
Eigen::Vector3f up(void) const;
Eigen::Vector3f right(void) const;
void setTarget(const Eigen::Vector3f& target);
inline const Eigen::Vector3f& target(void) { return mTarget; }
const Eigen::Affine3f& viewMatrix(void) const;
const Eigen::Matrix4f& projectionMatrix(void) const;
void rotateAroundTarget(const Eigen::Quaternionf& q);
void localRotate(const Eigen::Quaternionf& q);
void zoom(float d);
void localTranslate(const Eigen::Vector3f& t);
/** Setup OpenGL matrices and viewport */
void activateGL(void);
Eigen::Vector3f unProject(const Eigen::Vector2f& uv, float depth, const Eigen::Matrix4f& invModelview) const;
Eigen::Vector3f unProject(const Eigen::Vector2f& uv, float depth) const;
protected:
void updateViewMatrix(void) const;
void updateProjectionMatrix(void) const;
Camera& operator=(const Camera& other);
protected:
void setViewport(uint offsetx, uint offsety, uint width, uint height);
void setViewport(uint width, uint height);
uint mVpX, mVpY;
uint mVpWidth, mVpHeight;
inline uint vpX(void) const { return mVpX; }
inline uint vpY(void) const { return mVpY; }
inline uint vpWidth(void) const { return mVpWidth; }
inline uint vpHeight(void) const { return mVpHeight; }
Frame mFrame;
mutable Eigen::Affine3f mViewMatrix;
mutable Eigen::Matrix4f mProjectionMatrix;
inline float fovY(void) const { return mFovY; }
void setFovY(float value);
mutable bool mViewIsUptodate;
mutable bool mProjIsUptodate;
void setPosition(const Eigen::Vector3f& pos);
inline const Eigen::Vector3f& position(void) const { return mFrame.position; }
// used by rotateAroundTarget
Eigen::Vector3f mTarget;
float mFovY;
float mNearDist;
float mFarDist;
void setOrientation(const Eigen::Quaternionf& q);
inline const Eigen::Quaternionf& orientation(void) const { return mFrame.orientation; }
void setFrame(const Frame& f);
const Frame& frame(void) const { return mFrame; }
void setDirection(const Eigen::Vector3f& newDirection);
Eigen::Vector3f direction(void) const;
void setUp(const Eigen::Vector3f& vectorUp);
Eigen::Vector3f up(void) const;
Eigen::Vector3f right(void) const;
void setTarget(const Eigen::Vector3f& target);
inline const Eigen::Vector3f& target(void) { return mTarget; }
const Eigen::Affine3f& viewMatrix(void) const;
const Eigen::Matrix4f& projectionMatrix(void) const;
void rotateAroundTarget(const Eigen::Quaternionf& q);
void localRotate(const Eigen::Quaternionf& q);
void zoom(float d);
void localTranslate(const Eigen::Vector3f& t);
/** Setup OpenGL matrices and viewport */
void activateGL(void);
Eigen::Vector3f unProject(const Eigen::Vector2f& uv, float depth, const Eigen::Matrix4f& invModelview) const;
Eigen::Vector3f unProject(const Eigen::Vector2f& uv, float depth) const;
protected:
void updateViewMatrix(void) const;
void updateProjectionMatrix(void) const;
protected:
uint mVpX, mVpY;
uint mVpWidth, mVpHeight;
Frame mFrame;
mutable Eigen::Affine3f mViewMatrix;
mutable Eigen::Matrix4f mProjectionMatrix;
mutable bool mViewIsUptodate;
mutable bool mProjIsUptodate;
// used by rotateAroundTarget
Eigen::Vector3f mTarget;
float mFovY;
float mNearDist;
float mFarDist;
};
#endif // EIGEN_CAMERA_H
#endif // EIGEN_CAMERA_H

View File

@@ -17,110 +17,111 @@
GpuHelper gpu;
GpuHelper::GpuHelper()
{
mVpWidth = mVpHeight = 0;
mCurrentMatrixTarget = 0;
mInitialized = false;
GpuHelper::GpuHelper() {
mVpWidth = mVpHeight = 0;
mCurrentMatrixTarget = 0;
mInitialized = false;
}
GpuHelper::~GpuHelper()
{
GpuHelper::~GpuHelper() {}
void GpuHelper::pushProjectionMode2D(ProjectionMode2D pm) {
// switch to 2D projection
pushMatrix(Matrix4f::Identity(), GL_PROJECTION);
if (pm == PM_Normalized) {
// glOrtho(-1., 1., -1., 1., 0., 1.);
} else if (pm == PM_Viewport) {
GLint vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
glOrtho(0., vp[2], 0., vp[3], -1., 1.);
}
pushMatrix(Matrix4f::Identity(), GL_MODELVIEW);
}
void GpuHelper::pushProjectionMode2D(ProjectionMode2D pm)
{
// switch to 2D projection
pushMatrix(Matrix4f::Identity(),GL_PROJECTION);
if(pm==PM_Normalized)
{
//glOrtho(-1., 1., -1., 1., 0., 1.);
}
else if(pm==PM_Viewport)
{
GLint vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
glOrtho(0., vp[2], 0., vp[3], -1., 1.);
}
pushMatrix(Matrix4f::Identity(),GL_MODELVIEW);
void GpuHelper::popProjectionMode2D(void) {
popMatrix(GL_PROJECTION);
popMatrix(GL_MODELVIEW);
}
void GpuHelper::popProjectionMode2D(void)
{
popMatrix(GL_PROJECTION);
popMatrix(GL_MODELVIEW);
void GpuHelper::drawVector(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect /* = 50.*/) {
static GLUquadricObj* cylindre = gluNewQuadric();
glColor4fv(color.data());
float length = vec.norm();
pushMatrix(GL_MODELVIEW);
glTranslatef(position.x(), position.y(), position.z());
Vector3f ax = Matrix3f::Identity().col(2).cross(vec);
ax.normalize();
Vector3f tmp = vec;
tmp.normalize();
float angle = 180.f / M_PI * acos(tmp.z());
if (angle > 1e-3) glRotatef(angle, ax.x(), ax.y(), ax.z());
gluCylinder(cylindre, length / aspect, length / aspect, 0.8 * length, 10, 10);
glTranslatef(0.0, 0.0, 0.8 * length);
gluCylinder(cylindre, 2.0 * length / aspect, 0.0, 0.2 * length, 10, 10);
popMatrix(GL_MODELVIEW);
}
void GpuHelper::drawVector(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect /* = 50.*/)
{
static GLUquadricObj *cylindre = gluNewQuadric();
glColor4fv(color.data());
float length = vec.norm();
pushMatrix(GL_MODELVIEW);
glTranslatef(position.x(), position.y(), position.z());
Vector3f ax = Matrix3f::Identity().col(2).cross(vec);
ax.normalize();
Vector3f tmp = vec;
tmp.normalize();
float angle = 180.f/M_PI * acos(tmp.z());
if (angle>1e-3)
glRotatef(angle, ax.x(), ax.y(), ax.z());
gluCylinder(cylindre, length/aspect, length/aspect, 0.8*length, 10, 10);
glTranslatef(0.0,0.0,0.8*length);
gluCylinder(cylindre, 2.0*length/aspect, 0.0, 0.2*length, 10, 10);
popMatrix(GL_MODELVIEW);
void GpuHelper::drawVectorBox(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect) {
static GLUquadricObj* cylindre = gluNewQuadric();
glColor4fv(color.data());
float length = vec.norm();
pushMatrix(GL_MODELVIEW);
glTranslatef(position.x(), position.y(), position.z());
Vector3f ax = Matrix3f::Identity().col(2).cross(vec);
ax.normalize();
Vector3f tmp = vec;
tmp.normalize();
float angle = 180.f / M_PI * acos(tmp.z());
if (angle > 1e-3) glRotatef(angle, ax.x(), ax.y(), ax.z());
gluCylinder(cylindre, length / aspect, length / aspect, 0.8 * length, 10, 10);
glTranslatef(0.0, 0.0, 0.8 * length);
glScalef(4.0 * length / aspect, 4.0 * length / aspect, 4.0 * length / aspect);
drawUnitCube();
popMatrix(GL_MODELVIEW);
}
void GpuHelper::drawVectorBox(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect)
{
static GLUquadricObj *cylindre = gluNewQuadric();
glColor4fv(color.data());
float length = vec.norm();
pushMatrix(GL_MODELVIEW);
glTranslatef(position.x(), position.y(), position.z());
Vector3f ax = Matrix3f::Identity().col(2).cross(vec);
ax.normalize();
Vector3f tmp = vec;
tmp.normalize();
float angle = 180.f/M_PI * acos(tmp.z());
if (angle>1e-3)
glRotatef(angle, ax.x(), ax.y(), ax.z());
gluCylinder(cylindre, length/aspect, length/aspect, 0.8*length, 10, 10);
glTranslatef(0.0,0.0,0.8*length);
glScalef(4.0*length/aspect,4.0*length/aspect,4.0*length/aspect);
drawUnitCube();
popMatrix(GL_MODELVIEW);
void GpuHelper::drawUnitCube(void) {
static float vertices[][3] = {{-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, {0.5, 0.5, -0.5},
{-0.5, -0.5, 0.5}, {0.5, -0.5, 0.5}, {-0.5, 0.5, 0.5}, {0.5, 0.5, 0.5}};
glBegin(GL_QUADS);
glNormal3f(0, 0, -1);
glVertex3fv(vertices[0]);
glVertex3fv(vertices[2]);
glVertex3fv(vertices[3]);
glVertex3fv(vertices[1]);
glNormal3f(0, 0, 1);
glVertex3fv(vertices[4]);
glVertex3fv(vertices[5]);
glVertex3fv(vertices[7]);
glVertex3fv(vertices[6]);
glNormal3f(0, -1, 0);
glVertex3fv(vertices[0]);
glVertex3fv(vertices[1]);
glVertex3fv(vertices[5]);
glVertex3fv(vertices[4]);
glNormal3f(0, 1, 0);
glVertex3fv(vertices[2]);
glVertex3fv(vertices[6]);
glVertex3fv(vertices[7]);
glVertex3fv(vertices[3]);
glNormal3f(-1, 0, 0);
glVertex3fv(vertices[0]);
glVertex3fv(vertices[4]);
glVertex3fv(vertices[6]);
glVertex3fv(vertices[2]);
glNormal3f(1, 0, 0);
glVertex3fv(vertices[1]);
glVertex3fv(vertices[3]);
glVertex3fv(vertices[7]);
glVertex3fv(vertices[5]);
glEnd();
}
void GpuHelper::drawUnitCube(void)
{
static float vertices[][3] = {
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5}};
glBegin(GL_QUADS);
glNormal3f(0,0,-1); glVertex3fv(vertices[0]); glVertex3fv(vertices[2]); glVertex3fv(vertices[3]); glVertex3fv(vertices[1]);
glNormal3f(0,0, 1); glVertex3fv(vertices[4]); glVertex3fv(vertices[5]); glVertex3fv(vertices[7]); glVertex3fv(vertices[6]);
glNormal3f(0,-1,0); glVertex3fv(vertices[0]); glVertex3fv(vertices[1]); glVertex3fv(vertices[5]); glVertex3fv(vertices[4]);
glNormal3f(0, 1,0); glVertex3fv(vertices[2]); glVertex3fv(vertices[6]); glVertex3fv(vertices[7]); glVertex3fv(vertices[3]);
glNormal3f(-1,0,0); glVertex3fv(vertices[0]); glVertex3fv(vertices[4]); glVertex3fv(vertices[6]); glVertex3fv(vertices[2]);
glNormal3f( 1,0,0); glVertex3fv(vertices[1]); glVertex3fv(vertices[3]); glVertex3fv(vertices[7]); glVertex3fv(vertices[5]);
glEnd();
}
void GpuHelper::drawUnitSphere(int level)
{
void GpuHelper::drawUnitSphere(int level) {
static IcoSphere sphere;
sphere.draw(level);
}

View File

@@ -18,190 +18,170 @@ using namespace Eigen;
typedef Vector4f Color;
class GpuHelper
{
public:
class GpuHelper {
public:
GpuHelper();
GpuHelper();
~GpuHelper();
~GpuHelper();
enum ProjectionMode2D { PM_Normalized = 1, PM_Viewport = 2 };
void pushProjectionMode2D(ProjectionMode2D pm);
void popProjectionMode2D();
enum ProjectionMode2D { PM_Normalized = 1, PM_Viewport = 2 };
void pushProjectionMode2D(ProjectionMode2D pm);
void popProjectionMode2D();
/** Multiply the OpenGL matrix \a matrixTarget by the matrix \a mat.
Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
and does a proper call to the right glMultMatrix*() function according to the scalar type
and storage order.
\warning glMatrixMode() must never be called directly. If you are unsure, use forceMatrixMode().
\sa Matrix, loadMatrix(), forceMatrixMode()
*/
template <typename Scalar, int Flags_>
void multMatrix(const Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget);
/** Multiply the OpenGL matrix \a matrixTarget by the matrix \a mat.
Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
and does a proper call to the right glMultMatrix*() function according to the scalar type
and storage order.
\warning glMatrixMode() must never be called directly. If you are unsure, use forceMatrixMode().
\sa Matrix, loadMatrix(), forceMatrixMode()
*/
template<typename Scalar, int Flags_>
void multMatrix(const Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget);
/** Load the matrix \a mat to the OpenGL matrix \a matrixTarget.
Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
and does a proper call to the right glLoadMatrix*() or glLoadIdentity() function according to the scalar type
and storage order.
\warning glMatrixMode() must never be called directly. If you are unsure, use forceMatrixMode().
\sa Matrix, multMatrix(), forceMatrixMode()
*/
template <typename Scalar, int Flags_>
void loadMatrix(const Eigen::Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget);
/** Load the matrix \a mat to the OpenGL matrix \a matrixTarget.
Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
and does a proper call to the right glLoadMatrix*() or glLoadIdentity() function according to the scalar type
and storage order.
\warning glMatrixMode() must never be called directly. If you are unsure, use forceMatrixMode().
\sa Matrix, multMatrix(), forceMatrixMode()
*/
template<typename Scalar, int Flags_>
void loadMatrix(const Eigen::Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget);
template <typename Scalar, typename Derived>
void loadMatrix(const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>, Derived>&,
GLenum matrixTarget);
template<typename Scalar, typename Derived>
void loadMatrix(
const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>,Derived>&,
GLenum matrixTarget);
/** Make the matrix \a matrixTarget the current OpenGL matrix target.
Call this function before loadMatrix() or multMatrix() if you cannot guarantee that glMatrixMode()
has never been called after the last loadMatrix() or multMatrix() calls.
\todo provides a debug mode checking the sanity of the cached matrix mode.
*/
inline void forceMatrixTarget(GLenum matrixTarget) { glMatrixMode(mCurrentMatrixTarget = matrixTarget); }
/** Make the matrix \a matrixTarget the current OpenGL matrix target.
Call this function before loadMatrix() or multMatrix() if you cannot guarantee that glMatrixMode()
has never been called after the last loadMatrix() or multMatrix() calls.
\todo provides a debug mode checking the sanity of the cached matrix mode.
*/
inline void forceMatrixTarget(GLenum matrixTarget) {glMatrixMode(mCurrentMatrixTarget=matrixTarget);}
inline void setMatrixTarget(GLenum matrixTarget);
inline void setMatrixTarget(GLenum matrixTarget);
/** Push the OpenGL matrix \a matrixTarget and load \a mat.
*/
template <typename Scalar, int Flags_>
inline void pushMatrix(const Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget);
/** Push the OpenGL matrix \a matrixTarget and load \a mat.
*/
template<typename Scalar, int Flags_>
inline void pushMatrix(const Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget);
template <typename Scalar, typename Derived>
void pushMatrix(const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>, Derived>&,
GLenum matrixTarget);
template<typename Scalar, typename Derived>
void pushMatrix(
const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>,Derived>&,
GLenum matrixTarget);
/** Push and clone the OpenGL matrix \a matrixTarget
*/
inline void pushMatrix(GLenum matrixTarget);
/** Push and clone the OpenGL matrix \a matrixTarget
*/
inline void pushMatrix(GLenum matrixTarget);
/** Pop the OpenGL matrix \a matrixTarget
*/
inline void popMatrix(GLenum matrixTarget);
/** Pop the OpenGL matrix \a matrixTarget
*/
inline void popMatrix(GLenum matrixTarget);
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 drawUnitCube(void);
void drawUnitSphere(int level = 0);
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 drawUnitCube(void);
void drawUnitSphere(int level=0);
/// draw the \a nofElement first elements
inline void draw(GLenum mode, uint nofElement);
/// draw the \a nofElement first elements
inline void draw(GLenum mode, uint nofElement);
/// draw a range of elements
inline void draw(GLenum mode, uint start, uint end);
/// draw a range of elements
inline void draw(GLenum mode, uint start, uint end);
/// draw an indexed subset
inline void draw(GLenum mode, const std::vector<uint>* pIndexes);
/// draw an indexed subset
inline void draw(GLenum mode, const std::vector<uint>* pIndexes);
protected:
void update(void);
protected:
void update(void);
GLuint mColorBufferId;
int mVpWidth, mVpHeight;
GLenum mCurrentMatrixTarget;
bool mInitialized;
GLuint mColorBufferId;
int mVpWidth, mVpHeight;
GLenum mCurrentMatrixTarget;
bool mInitialized;
};
/** Singleton shortcut
*/
*/
extern GpuHelper gpu;
/** \internal
*/
template<bool RowMajor, int Flags_> struct GlMatrixHelper;
*/
template <bool RowMajor, int Flags_>
struct GlMatrixHelper;
template<int Flags_> struct GlMatrixHelper<false,Flags_>
{
static void loadMatrix(const Matrix<float, 4,4, Flags_, 4,4>& mat) { glLoadMatrixf(mat.data()); }
static void loadMatrix(const Matrix<double,4,4, Flags_, 4,4>& mat) { glLoadMatrixd(mat.data()); }
static void multMatrix(const Matrix<float, 4,4, Flags_, 4,4>& mat) { glMultMatrixf(mat.data()); }
static void multMatrix(const Matrix<double,4,4, Flags_, 4,4>& mat) { glMultMatrixd(mat.data()); }
template <int Flags_>
struct GlMatrixHelper<false, Flags_> {
static void loadMatrix(const Matrix<float, 4, 4, Flags_, 4, 4>& mat) { glLoadMatrixf(mat.data()); }
static void loadMatrix(const Matrix<double, 4, 4, Flags_, 4, 4>& mat) { glLoadMatrixd(mat.data()); }
static void multMatrix(const Matrix<float, 4, 4, Flags_, 4, 4>& mat) { glMultMatrixf(mat.data()); }
static void multMatrix(const Matrix<double, 4, 4, Flags_, 4, 4>& mat) { glMultMatrixd(mat.data()); }
};
template<int Flags_> struct GlMatrixHelper<true,Flags_>
{
static void loadMatrix(const Matrix<float, 4,4, Flags_, 4,4>& mat) { glLoadMatrixf(mat.transpose().eval().data()); }
static void loadMatrix(const Matrix<double,4,4, Flags_, 4,4>& mat) { glLoadMatrixd(mat.transpose().eval().data()); }
static void multMatrix(const Matrix<float, 4,4, Flags_, 4,4>& mat) { glMultMatrixf(mat.transpose().eval().data()); }
static void multMatrix(const Matrix<double,4,4, Flags_, 4,4>& mat) { glMultMatrixd(mat.transpose().eval().data()); }
template <int Flags_>
struct GlMatrixHelper<true, Flags_> {
static void loadMatrix(const Matrix<float, 4, 4, Flags_, 4, 4>& mat) { glLoadMatrixf(mat.transpose().eval().data()); }
static void loadMatrix(const Matrix<double, 4, 4, Flags_, 4, 4>& mat) {
glLoadMatrixd(mat.transpose().eval().data());
}
static void multMatrix(const Matrix<float, 4, 4, Flags_, 4, 4>& mat) { glMultMatrixf(mat.transpose().eval().data()); }
static void multMatrix(const Matrix<double, 4, 4, Flags_, 4, 4>& mat) {
glMultMatrixd(mat.transpose().eval().data());
}
};
inline void GpuHelper::setMatrixTarget(GLenum matrixTarget)
{
if (matrixTarget != mCurrentMatrixTarget)
glMatrixMode(mCurrentMatrixTarget=matrixTarget);
inline void GpuHelper::setMatrixTarget(GLenum matrixTarget) {
if (matrixTarget != mCurrentMatrixTarget) glMatrixMode(mCurrentMatrixTarget = matrixTarget);
}
template<typename Scalar, int Flags_>
void GpuHelper::multMatrix(const Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget)
{
setMatrixTarget(matrixTarget);
GlMatrixHelper<Flags_&Eigen::RowMajorBit, Flags_>::multMatrix(mat);
template <typename Scalar, int Flags_>
void GpuHelper::multMatrix(const Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget) {
setMatrixTarget(matrixTarget);
GlMatrixHelper<Flags_ & Eigen::RowMajorBit, Flags_>::multMatrix(mat);
}
template<typename Scalar, typename Derived>
void GpuHelper::loadMatrix(
const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>,Derived>&,
GLenum matrixTarget)
{
setMatrixTarget(matrixTarget);
glLoadIdentity();
template <typename Scalar, typename Derived>
void GpuHelper::loadMatrix(const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>, Derived>&,
GLenum matrixTarget) {
setMatrixTarget(matrixTarget);
glLoadIdentity();
}
template<typename Scalar, int Flags_>
void GpuHelper::loadMatrix(const Eigen::Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget)
{
setMatrixTarget(matrixTarget);
GlMatrixHelper<(Flags_&Eigen::RowMajorBit)!=0, Flags_>::loadMatrix(mat);
template <typename Scalar, int Flags_>
void GpuHelper::loadMatrix(const Eigen::Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget) {
setMatrixTarget(matrixTarget);
GlMatrixHelper<(Flags_ & Eigen::RowMajorBit) != 0, Flags_>::loadMatrix(mat);
}
inline void GpuHelper::pushMatrix(GLenum matrixTarget)
{
setMatrixTarget(matrixTarget);
glPushMatrix();
inline void GpuHelper::pushMatrix(GLenum matrixTarget) {
setMatrixTarget(matrixTarget);
glPushMatrix();
}
template<typename Scalar, int Flags_>
inline void GpuHelper::pushMatrix(const Matrix<Scalar,4,4, Flags_, 4,4>& mat, GLenum matrixTarget)
{
pushMatrix(matrixTarget);
GlMatrixHelper<Flags_&Eigen::RowMajorBit,Flags_>::loadMatrix(mat);
template <typename Scalar, int Flags_>
inline void GpuHelper::pushMatrix(const Matrix<Scalar, 4, 4, Flags_, 4, 4>& mat, GLenum matrixTarget) {
pushMatrix(matrixTarget);
GlMatrixHelper<Flags_ & Eigen::RowMajorBit, Flags_>::loadMatrix(mat);
}
template<typename Scalar, typename Derived>
void GpuHelper::pushMatrix(
const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>,Derived>&,
GLenum matrixTarget)
{
pushMatrix(matrixTarget);
glLoadIdentity();
template <typename Scalar, typename Derived>
void GpuHelper::pushMatrix(const Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<Scalar>, Derived>&,
GLenum matrixTarget) {
pushMatrix(matrixTarget);
glLoadIdentity();
}
inline void GpuHelper::popMatrix(GLenum matrixTarget)
{
setMatrixTarget(matrixTarget);
glPopMatrix();
inline void GpuHelper::popMatrix(GLenum matrixTarget) {
setMatrixTarget(matrixTarget);
glPopMatrix();
}
inline void GpuHelper::draw(GLenum mode, uint nofElement)
{
glDrawArrays(mode, 0, nofElement);
inline void GpuHelper::draw(GLenum mode, uint nofElement) { glDrawArrays(mode, 0, nofElement); }
inline void GpuHelper::draw(GLenum mode, const std::vector<uint>* pIndexes) {
glDrawElements(mode, pIndexes->size(), GL_UNSIGNED_INT, &(pIndexes->front()));
}
inline void GpuHelper::draw(GLenum mode, uint start, uint end) { glDrawArrays(mode, start, end - start); }
inline void GpuHelper::draw(GLenum mode, const std::vector<uint>* pIndexes)
{
glDrawElements(mode, pIndexes->size(), GL_UNSIGNED_INT, &(pIndexes->front()));
}
inline void GpuHelper::draw(GLenum mode, uint start, uint end)
{
glDrawArrays(mode, start, end-start);
}
#endif // EIGEN_GPUHELPER_H
#endif // EIGEN_GPUHELPER_H

View File

@@ -20,101 +20,86 @@ using namespace Eigen;
#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 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} };
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)
{
IcoSphere::IcoSphere(unsigned int levels) {
// init with an icosahedron
for (int i = 0; i < 12; i++)
mVertices.push_back(Map<Vector3f>(vdata[i]));
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]);
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();
while (mIndices.size() < levels) _subdivide();
}
const std::vector<int>& IcoSphere::indices(int level) const
{
while (level>=int(mIndices.size()))
const_cast<IcoSphere*>(this)->_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)
{
void IcoSphere::_subdivide(void) {
typedef unsigned long long Key;
std::map<Key,int> edgeMap;
std::map<Key, int> edgeMap;
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)
{
for (int i = 0; i < end; i += 3) {
int ids0[3], // indices of outer vertices
ids1[3]; // indices of edge vertices
for (int k=0; k<3; ++k)
{
int k1 = (k+1)%3;
int e0 = indices[i+k];
int e1 = indices[i+k1];
for (int k = 0; k < 3; ++k) {
int k1 = (k + 1) % 3;
int e0 = indices[i + k];
int e1 = indices[i + k1];
ids0[k] = e0;
if (e1>e0)
std::swap(e0,e1);
Key edgeKey = Key(e0) | (Key(e1)<<32);
std::map<Key,int>::iterator it = edgeMap.find(edgeKey);
if (it==edgeMap.end())
{
if (e1 > e0) std::swap(e0, e1);
Key edgeKey = Key(e0) | (Key(e1) << 32);
std::map<Key, int>::iterator it = edgeMap.find(edgeKey);
if (it == edgeMap.end()) {
ids1[k] = mVertices.size();
edgeMap[edgeKey] = ids1[k];
mVertices.push_back( (mVertices[e0]+mVertices[e1]).normalized() );
}
else
mVertices.push_back((mVertices[e0] + mVertices[e1]).normalized());
} else
ids1[k] = it->second;
}
refinedIndices.push_back(ids0[0]); refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[2]);
refinedIndices.push_back(ids0[1]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[0]);
refinedIndices.push_back(ids0[2]); refinedIndices.push_back(ids1[2]); refinedIndices.push_back(ids1[1]);
refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[2]);
refinedIndices.push_back(ids0[0]);
refinedIndices.push_back(ids1[0]);
refinedIndices.push_back(ids1[2]);
refinedIndices.push_back(ids0[1]);
refinedIndices.push_back(ids1[1]);
refinedIndices.push_back(ids1[0]);
refinedIndices.push_back(ids0[2]);
refinedIndices.push_back(ids1[2]);
refinedIndices.push_back(ids1[1]);
refinedIndices.push_back(ids1[0]);
refinedIndices.push_back(ids1[1]);
refinedIndices.push_back(ids1[2]);
}
mListIds.push_back(0);
}
void IcoSphere::draw(int level)
{
while (level>=int(mIndices.size()))
const_cast<IcoSphere*>(this)->_subdivide();
if (mListIds[level]==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);
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]);
}

View File

@@ -13,18 +13,18 @@
#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;
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
#endif // EIGEN_ICOSPHERE_H

View File

@@ -27,126 +27,112 @@
using namespace Eigen;
class FancySpheres
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
FancySpheres()
class FancySpheres {
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
FancySpheres() {
const int levels = 4;
const float scale = 0.33;
float radius = 100;
std::vector<int> parents;
// leval 0
mCenters.push_back(Vector3f::Zero());
parents.push_back(-1);
mRadii.push_back(radius);
// generate level 1 using icosphere vertices
radius *= 0.45;
{
const int levels = 4;
const float scale = 0.33;
float radius = 100;
std::vector<int> parents;
// leval 0
mCenters.push_back(Vector3f::Zero());
parents.push_back(-1);
mRadii.push_back(radius);
// generate level 1 using icosphere vertices
radius *= 0.45;
{
float dist = mRadii[0]*0.9;
for (int i=0; i<12; ++i)
{
mCenters.push_back(mIcoSphere.vertices()[i] * dist);
mRadii.push_back(radius);
parents.push_back(0);
}
}
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;
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;
float dist = mRadii[0] * 0.9;
for (int i = 0; i < 12; ++i) {
mCenters.push_back(mIcoSphere.vertices()[i] * dist);
mRadii.push_back(radius);
parents.push_back(0);
}
}
void draw()
{
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;
for (int l = 1; l < levels; l++) {
radius *= scale;
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);
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);
}
}
glDisable(GL_NORMALIZE);
start = end;
}
protected:
std::vector<Vector3f> mCenters;
std::vector<float> mRadii;
IcoSphere mIcoSphere;
}
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;
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); }
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>
inline static 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))));
template <typename OrientationType>
inline static 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))));
}
template<typename Scalar_> class EulerAngles
{
public:
template <typename Scalar_>
class EulerAngles {
public:
enum { Dim = 3 };
typedef Scalar_ Scalar;
typedef Matrix<Scalar,3,3> Matrix3;
typedef Matrix<Scalar,3,1> Vector3;
typedef Matrix<Scalar, 3, 3> Matrix3;
typedef Matrix<Scalar, 3, 1> Vector3;
typedef Quaternion<Scalar> QuaternionType;
protected:
protected:
Vector3 m_angles;
public:
public:
EulerAngles() {}
inline EulerAngles(Scalar a0, Scalar a1, Scalar a2) : m_angles(a0, a1, a2) {}
inline EulerAngles(const QuaternionType& q) { *this = q; }
@@ -154,31 +140,28 @@ public:
const Vector3& coeffs() const { return m_angles; }
Vector3& coeffs() { return m_angles; }
EulerAngles& operator=(const QuaternionType& q)
{
EulerAngles& operator=(const QuaternionType& q) {
Matrix3 m = q.toRotationMatrix();
return *this = m;
}
EulerAngles& operator=(const Matrix3& m)
{
EulerAngles& operator=(const Matrix3& m) {
// mat = cy*cz -cy*sz sy
// cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
m_angles.coeffRef(1) = std::asin(m.coeff(0,2));
m_angles.coeffRef(0) = std::atan2(-m.coeff(1,2),m.coeff(2,2));
m_angles.coeffRef(2) = std::atan2(-m.coeff(0,1),m.coeff(0,0));
m_angles.coeffRef(1) = std::asin(m.coeff(0, 2));
m_angles.coeffRef(0) = std::atan2(-m.coeff(1, 2), m.coeff(2, 2));
m_angles.coeffRef(2) = std::atan2(-m.coeff(0, 1), m.coeff(0, 0));
return *this;
}
Matrix3 toRotationMatrix(void) const
{
Matrix3 toRotationMatrix(void) const {
Vector3 c = m_angles.array().cos();
Vector3 s = m_angles.array().sin();
Matrix3 res;
res << c.y()*c.z(), -c.y()*s.z(), s.y(),
c.z()*s.x()*s.y()+c.x()*s.z(), c.x()*c.z()-s.x()*s.y()*s.z(), -c.y()*s.x(),
-c.x()*c.z()*s.y()+s.x()*s.z(), c.z()*s.x()+c.x()*s.y()*s.z(), c.x()*c.y();
res << c.y() * c.z(), -c.y() * s.z(), s.y(), c.z() * s.x() * s.y() + c.x() * s.z(),
c.x() * c.z() - s.x() * s.y() * s.z(), -c.y() * s.x(), -c.x() * c.z() * s.y() + s.x() * s.z(),
c.z() * s.x() + c.x() * s.y() * s.z(), c.x() * c.y();
return res;
}
@@ -186,16 +169,14 @@ public:
};
// Euler angles slerp
template<> EulerAngles<float> lerp(float t, const EulerAngles<float>& a, const EulerAngles<float>& b)
{
template <>
EulerAngles<float> lerp(float t, const EulerAngles<float>& a, const EulerAngles<float>& b) {
EulerAngles<float> res;
res.coeffs() = lerp(t, a.coeffs(), b.coeffs());
return res;
}
RenderingWidget::RenderingWidget()
{
RenderingWidget::RenderingWidget() {
mAnimate = false;
mCurrentTrackingMode = TM_NO_TRACK;
mNavMode = NavTurnAround;
@@ -207,43 +188,38 @@ RenderingWidget::RenderingWidget()
setFocusPolicy(Qt::ClickFocus);
}
void RenderingWidget::grabFrame(void)
{
// ask user for a time
bool ok = false;
double t = 0;
if (!m_timeline.empty())
t = (--m_timeline.end())->first + 1.;
t = QInputDialog::getDouble(this, "Eigen's RenderingWidget", "time value: ",
t, 0, 1e3, 1, &ok);
if (ok)
{
Frame aux;
aux.orientation = mCamera.viewMatrix().linear();
aux.position = mCamera.viewMatrix().translation();
m_timeline[t] = aux;
}
void RenderingWidget::grabFrame(void) {
// ask user for a time
bool ok = false;
double t = 0;
if (!m_timeline.empty()) t = (--m_timeline.end())->first + 1.;
t = QInputDialog::getDouble(this, "Eigen's RenderingWidget", "time value: ", t, 0, 1e3, 1, &ok);
if (ok) {
Frame aux;
aux.orientation = mCamera.viewMatrix().linear();
aux.position = mCamera.viewMatrix().translation();
m_timeline[t] = aux;
}
}
void RenderingWidget::drawScene()
{
void RenderingWidget::drawScene() {
static FancySpheres sFancySpheres;
float length = 50;
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::UnitZ(), Color(0,0,1,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::UnitZ(), Color(0, 0, 1, 1));
// draw the fractal object
float sqrt3 = std::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_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());
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());
@@ -266,8 +242,7 @@ void RenderingWidget::drawScene()
glDisable(GL_LIGHTING);
}
void RenderingWidget::animate()
{
void RenderingWidget::animate() {
m_alpha += double(m_timer.interval()) * 1e-3;
TimeLine::const_iterator hi = m_timeline.upper_bound(m_alpha);
@@ -276,26 +251,20 @@ void RenderingWidget::animate()
Frame currentFrame;
if(hi==m_timeline.end())
{
if (hi == m_timeline.end()) {
// end
currentFrame = lo->second;
stopAnimation();
}
else if(hi==m_timeline.begin())
{
} else if (hi == m_timeline.begin()) {
// start
currentFrame = hi->second;
}
else
{
float s = (m_alpha - lo->first)/(hi->first - lo->first);
if (mLerpMode==LerpEulerAngles)
} else {
float s = (m_alpha - lo->first) / (hi->first - lo->first);
if (mLerpMode == LerpEulerAngles)
currentFrame = ::lerpFrame<EulerAngles<float> >(s, lo->second, hi->second);
else if (mLerpMode==LerpQuaternion)
else if (mLerpMode == LerpQuaternion)
currentFrame = ::lerpFrame<Eigen::Quaternionf>(s, lo->second, hi->second);
else
{
else {
std::cerr << "Invalid rotation interpolation mode (abort)\n";
exit(2);
}
@@ -303,162 +272,141 @@ void RenderingWidget::animate()
}
currentFrame.orientation = currentFrame.orientation.inverse();
currentFrame.position = - (currentFrame.orientation * currentFrame.position);
currentFrame.position = -(currentFrame.orientation * currentFrame.position);
mCamera.setFrame(currentFrame);
updateGL();
}
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;
}
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;
}
updateGL();
updateGL();
}
void RenderingWidget::stopAnimation()
{
void RenderingWidget::stopAnimation() {
disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
m_timer.stop();
mAnimate = false;
m_alpha = 0;
}
void RenderingWidget::mousePressEvent(QMouseEvent* e)
{
void RenderingWidget::mousePressEvent(QMouseEvent* e) {
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
bool fly = (mNavMode==NavFly) || (e->modifiers()&Qt::ControlModifier);
switch(e->button())
{
bool fly = (mNavMode == NavFly) || (e->modifiers() & Qt::ControlModifier);
switch (e->button()) {
case Qt::LeftButton:
if(fly)
{
if (fly) {
mCurrentTrackingMode = TM_LOCAL_ROTATE;
mTrackball.start(Trackball::Local);
}
else
{
} else {
mCurrentTrackingMode = TM_ROTATE_AROUND;
mTrackball.start(Trackball::Around);
}
mTrackball.track(mMouseCoords);
break;
case Qt::MidButton:
if(fly)
if (fly)
mCurrentTrackingMode = TM_FLY_Z;
else
mCurrentTrackingMode = TM_ZOOM;
break;
case Qt::RightButton:
mCurrentTrackingMode = TM_FLY_PAN;
mCurrentTrackingMode = TM_FLY_PAN;
break;
default:
break;
}
}
void RenderingWidget::mouseReleaseEvent(QMouseEvent*)
{
mCurrentTrackingMode = TM_NO_TRACK;
updateGL();
void RenderingWidget::mouseReleaseEvent(QMouseEvent*) {
mCurrentTrackingMode = TM_NO_TRACK;
updateGL();
}
void RenderingWidget::mouseMoveEvent(QMouseEvent* e)
{
// tracking
if(mCurrentTrackingMode != TM_NO_TRACK)
{
float dx = float(e->x() - mMouseCoords.x()) / float(mCamera.vpWidth());
float dy = - float(e->y() - mMouseCoords.y()) / float(mCamera.vpHeight());
void RenderingWidget::mouseMoveEvent(QMouseEvent* e) {
// tracking
if (mCurrentTrackingMode != TM_NO_TRACK) {
float dx = float(e->x() - mMouseCoords.x()) / float(mCamera.vpWidth());
float dy = -float(e->y() - mMouseCoords.y()) / float(mCamera.vpHeight());
// 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;
}
updateGL();
// speedup the transformations
if (e->modifiers() & Qt::ShiftModifier) {
dx *= 10.;
dy *= 10.;
}
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
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;
}
updateGL();
}
mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
}
void RenderingWidget::paintGL()
{
void RenderingWidget::paintGL() {
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
@@ -474,8 +422,7 @@ void RenderingWidget::paintGL()
drawScene();
}
void RenderingWidget::initializeGL()
{
void RenderingWidget::initializeGL() {
glClearColor(1., 1., 1., 0.);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glDepthMask(GL_TRUE);
@@ -487,30 +434,16 @@ void RenderingWidget::initializeGL()
mInitFrame.position = mCamera.viewMatrix().translation();
}
void RenderingWidget::resizeGL(int width, int height)
{
mCamera.setViewport(width,height);
}
void RenderingWidget::resizeGL(int width, int height) { mCamera.setViewport(width, height); }
void RenderingWidget::setNavMode(int m)
{
mNavMode = NavMode(m);
}
void RenderingWidget::setNavMode(int m) { mNavMode = NavMode(m); }
void RenderingWidget::setLerpMode(int m)
{
mLerpMode = LerpMode(m);
}
void RenderingWidget::setLerpMode(int m) { mLerpMode = LerpMode(m); }
void RenderingWidget::setRotationMode(int m)
{
mRotationMode = RotationMode(m);
}
void RenderingWidget::setRotationMode(int m) { mRotationMode = RotationMode(m); }
void RenderingWidget::resetCamera()
{
if (mAnimate)
stopAnimation();
void RenderingWidget::resetCamera() {
if (mAnimate) stopAnimation();
m_timeline.clear();
Frame aux0 = mCamera.frame();
aux0.orientation = aux0.orientation.inverse();
@@ -525,13 +458,13 @@ void RenderingWidget::resetCamera()
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;
if (duration < 0.1) duration = 0.1;
// put the camera at that time step:
aux1 = aux0.lerp(duration/2,mInitFrame);
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);
aux1.position = -(aux1.orientation * aux1.position);
mCamera.setFrame(aux1);
mCamera.setTarget(Vector3f::Zero());
@@ -544,12 +477,11 @@ void RenderingWidget::resetCamera()
m_alpha = 0;
animate();
connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
m_timer.start(1000/30);
m_timer.start(1000 / 30);
mAnimate = true;
}
QWidget* RenderingWidget::createNavigationControlWidget()
{
QWidget* RenderingWidget::createNavigationControlWidget() {
QWidget* panel = new QWidget();
QVBoxLayout* layout = new QVBoxLayout();
@@ -591,7 +523,8 @@ QWidget* RenderingWidget::createNavigationControlWidget()
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");
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);
@@ -616,13 +549,12 @@ QWidget* RenderingWidget::createNavigationControlWidget()
box->setLayout(boxLayout);
layout->addWidget(box);
}
layout->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding));
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
panel->setLayout(layout);
return panel;
}
QuaternionDemo::QuaternionDemo()
{
QuaternionDemo::QuaternionDemo() {
mRenderingWidget = new RenderingWidget();
setCentralWidget(mRenderingWidget);
@@ -632,8 +564,7 @@ QuaternionDemo::QuaternionDemo()
panel->setWidget(mRenderingWidget->createNavigationControlWidget());
}
int main(int argc, char *argv[])
{
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";
@@ -647,10 +578,9 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
QuaternionDemo demo;
demo.resize(600,500);
demo.resize(600, 500);
demo.show();
return app.exec();
}
#include "quaternion_demo.moc"

View File

@@ -19,96 +19,82 @@
#include <QtOpenGL/QGLWidget>
#include <QtGui/QMainWindow>
class RenderingWidget : public QGLWidget
{
class RenderingWidget : public QGLWidget {
Q_OBJECT
typedef std::map<float,Frame> TimeLine;
TimeLine m_timeline;
Frame lerpFrame(float t);
typedef std::map<float, Frame> TimeLine;
TimeLine m_timeline;
Frame lerpFrame(float t);
Frame mInitFrame;
bool mAnimate;
float m_alpha;
Frame mInitFrame;
bool mAnimate;
float m_alpha;
enum TrackMode {
TM_NO_TRACK=0, TM_ROTATE_AROUND, TM_ZOOM,
TM_LOCAL_ROTATE, TM_FLY_Z, TM_FLY_PAN
};
enum TrackMode { TM_NO_TRACK = 0, TM_ROTATE_AROUND, TM_ZOOM, TM_LOCAL_ROTATE, TM_FLY_Z, TM_FLY_PAN };
enum NavMode {
NavTurnAround,
NavFly
};
enum NavMode { NavTurnAround, NavFly };
enum LerpMode {
LerpQuaternion,
LerpEulerAngles
};
enum LerpMode { LerpQuaternion, LerpEulerAngles };
enum RotationMode {
RotationStable,
RotationStandard
};
enum RotationMode { RotationStable, RotationStandard };
Camera mCamera;
TrackMode mCurrentTrackingMode;
NavMode mNavMode;
LerpMode mLerpMode;
RotationMode mRotationMode;
Vector2i mMouseCoords;
Trackball mTrackball;
Camera mCamera;
TrackMode mCurrentTrackingMode;
NavMode mNavMode;
LerpMode mLerpMode;
RotationMode mRotationMode;
Vector2i mMouseCoords;
Trackball mTrackball;
QTimer m_timer;
QTimer m_timer;
void setupCamera();
void setupCamera();
std::vector<Vector3f> mVertices;
std::vector<Vector3f> mNormals;
std::vector<int> mIndices;
std::vector<Vector3f> mVertices;
std::vector<Vector3f> mNormals;
std::vector<int> mIndices;
protected slots:
protected slots:
virtual void animate(void);
virtual void drawScene(void);
virtual void animate(void);
virtual void drawScene(void);
virtual void grabFrame(void);
virtual void stopAnimation();
virtual void grabFrame(void);
virtual void stopAnimation();
virtual void setNavMode(int);
virtual void setLerpMode(int);
virtual void setRotationMode(int);
virtual void resetCamera();
virtual void setNavMode(int);
virtual void setLerpMode(int);
virtual void setRotationMode(int);
virtual void resetCamera();
protected:
protected:
virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
//--------------------------------------------------------------------------------
virtual void mousePressEvent(QMouseEvent * e);
virtual void mouseReleaseEvent(QMouseEvent * e);
virtual void mouseMoveEvent(QMouseEvent * e);
virtual void keyPressEvent(QKeyEvent * e);
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
virtual void mousePressEvent(QMouseEvent* e);
virtual void mouseReleaseEvent(QMouseEvent* e);
virtual void mouseMoveEvent(QMouseEvent* e);
virtual void keyPressEvent(QKeyEvent* e);
//--------------------------------------------------------------------------------
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
RenderingWidget();
~RenderingWidget() { }
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
QWidget* createNavigationControlWidget();
RenderingWidget();
~RenderingWidget() {}
QWidget* createNavigationControlWidget();
};
class QuaternionDemo : public QMainWindow
{
class QuaternionDemo : public QMainWindow {
Q_OBJECT
public:
QuaternionDemo();
protected:
RenderingWidget* mRenderingWidget;
public:
QuaternionDemo();
protected:
RenderingWidget* mRenderingWidget;
};
#endif // EIGEN_QUATERNION_DEMO_H
#endif // EIGEN_QUATERNION_DEMO_H

View File

@@ -12,21 +12,17 @@
using namespace Eigen;
void Trackball::track(const Vector2i& point2D)
{
if (mpCamera==0)
return;
void Trackball::track(const Vector2i& point2D) {
if (mpCamera == 0) return;
Vector3f newPoint3D;
bool newPointOk = mapToSphere(point2D, newPoint3D);
if (mLastPointOk && newPointOk)
{
if (mLastPointOk && newPointOk) {
Vector3f axis = mLastPoint3D.cross(newPoint3D).normalized();
float cos_angle = mLastPoint3D.dot(newPoint3D);
if ( std::abs(cos_angle) < 1.0 )
{
if (std::abs(cos_angle) < 1.0) {
float angle = 2. * acos(cos_angle);
if (mMode==Around)
if (mMode == Around)
mpCamera->rotateAroundTarget(Quaternionf(AngleAxisf(angle, axis)));
else
mpCamera->localRotate(Quaternionf(AngleAxisf(-angle, axis)));
@@ -37,23 +33,19 @@ void Trackball::track(const Vector2i& point2D)
mLastPointOk = newPointOk;
}
bool Trackball::mapToSphere(const Vector2i& p2, Vector3f& v3)
{
if ((p2.x() >= 0) && (p2.x() <= int(mpCamera->vpWidth())) &&
(p2.y() >= 0) && (p2.y() <= int(mpCamera->vpHeight())) )
{
double x = (double)(p2.x() - 0.5*mpCamera->vpWidth()) / (double)mpCamera->vpWidth();
double y = (double)(0.5*mpCamera->vpHeight() - p2.y()) / (double)mpCamera->vpHeight();
double sinx = sin(M_PI * x * 0.5);
double siny = sin(M_PI * y * 0.5);
double sinx2siny2 = sinx * sinx + siny * siny;
bool Trackball::mapToSphere(const Vector2i& p2, Vector3f& v3) {
if ((p2.x() >= 0) && (p2.x() <= int(mpCamera->vpWidth())) && (p2.y() >= 0) && (p2.y() <= int(mpCamera->vpHeight()))) {
double x = (double)(p2.x() - 0.5 * mpCamera->vpWidth()) / (double)mpCamera->vpWidth();
double y = (double)(0.5 * mpCamera->vpHeight() - p2.y()) / (double)mpCamera->vpHeight();
double sinx = sin(M_PI * x * 0.5);
double siny = sin(M_PI * y * 0.5);
double sinx2siny2 = sinx * sinx + siny * siny;
v3.x() = sinx;
v3.y() = siny;
v3.z() = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
return true;
}
else
} else
return false;
}

View File

@@ -14,29 +14,28 @@
class Camera;
class Trackball
{
public:
class Trackball {
public:
enum Mode { Around, Local };
enum Mode {Around, Local};
Trackball() : mpCamera(0) {}
Trackball() : mpCamera(0) {}
void start(Mode m = Around) {
mMode = m;
mLastPointOk = false;
}
void start(Mode m = Around) { mMode = m; mLastPointOk = false; }
void setCamera(Camera* pCam) { mpCamera = pCam; }
void setCamera(Camera* pCam) { mpCamera = pCam; }
void track(const Eigen::Vector2i& newPoint2D);
void track(const Eigen::Vector2i& newPoint2D);
protected:
bool mapToSphere( const Eigen::Vector2i& p2, Eigen::Vector3f& v3);
Camera* mpCamera;
Eigen::Vector3f mLastPoint3D;
Mode mMode;
bool mLastPointOk;
protected:
bool mapToSphere(const Eigen::Vector2i& p2, Eigen::Vector3f& v3);
Camera* mpCamera;
Eigen::Vector3f mLastPoint3D;
Mode mMode;
bool mLastPointOk;
};
#endif // EIGEN_TRACKBALL_H
#endif // EIGEN_TRACKBALL_H