Disabled external gits
This commit is contained in:
		
							
								
								
									
										13
									
								
								cs440-acg/ext/eigen/demos/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cs440-acg/ext/eigen/demos/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
project(EigenDemos)
 | 
			
		||||
 | 
			
		||||
add_custom_target(demos)
 | 
			
		||||
 | 
			
		||||
if(NOT EIGEN_TEST_NOQT)
 | 
			
		||||
  find_package(Qt4)
 | 
			
		||||
  if(QT4_FOUND)
 | 
			
		||||
    add_subdirectory(mandelbrot)
 | 
			
		||||
    add_subdirectory(opengl)
 | 
			
		||||
  else(QT4_FOUND)
 | 
			
		||||
    message(STATUS "Qt4 not found, so disabling the mandelbrot and opengl demos")
 | 
			
		||||
  endif(QT4_FOUND)
 | 
			
		||||
endif()
 | 
			
		||||
							
								
								
									
										21
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
find_package(Qt4 REQUIRED)
 | 
			
		||||
 | 
			
		||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
 | 
			
		||||
 | 
			
		||||
if (CMAKE_COMPILER_IS_GNUCXX)
 | 
			
		||||
   set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
 | 
			
		||||
   add_definitions ( "-DNDEBUG" )
 | 
			
		||||
endif (CMAKE_COMPILER_IS_GNUCXX)
 | 
			
		||||
 | 
			
		||||
include_directories( ${QT_INCLUDE_DIR} )
 | 
			
		||||
 | 
			
		||||
set(mandelbrot_SRCS
 | 
			
		||||
    mandelbrot.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
qt4_automoc(${mandelbrot_SRCS})
 | 
			
		||||
 | 
			
		||||
add_executable(mandelbrot ${mandelbrot_SRCS})
 | 
			
		||||
add_dependencies(demos mandelbrot)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(mandelbrot ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
 | 
			
		||||
							
								
								
									
										10
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
*** Mandelbrot demo ***
 | 
			
		||||
 | 
			
		||||
Controls:
 | 
			
		||||
* Left mouse button to center view at a point.
 | 
			
		||||
* Drag vertically with left mouse button to zoom in and out.
 | 
			
		||||
 | 
			
		||||
Be sure to enable SSE2 or AltiVec to improve performance.
 | 
			
		||||
 | 
			
		||||
The number of iterations, and the choice between single and double precision, are
 | 
			
		||||
determined at runtime depending on the zoom level.
 | 
			
		||||
							
								
								
									
										213
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/mandelbrot.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/mandelbrot.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
// This file is part of Eigen, a lightweight C++ template library
 | 
			
		||||
// for linear algebra.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "mandelbrot.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include<QtGui/QPainter>
 | 
			
		||||
#include<QtGui/QImage>
 | 
			
		||||
#include<QtGui/QMouseEvent>
 | 
			
		||||
#include<QtCore/QTime>
 | 
			
		||||
 | 
			
		||||
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];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
  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);
 | 
			
		||||
  total_iter = 0;
 | 
			
		||||
 | 
			
		||||
  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, 
 | 
			
		||||
    // 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 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();
 | 
			
		||||
 | 
			
		||||
      // 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
 | 
			
		||||
        {
 | 
			
		||||
#         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_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
 | 
			
		||||
 | 
			
		||||
      // 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;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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;
 | 
			
		||||
  }
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MandelbrotThread::run()
 | 
			
		||||
{
 | 
			
		||||
  setTerminationEnabled(true);
 | 
			
		||||
  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;
 | 
			
		||||
  single_precision = resolution > 1e-7f;
 | 
			
		||||
 | 
			
		||||
  if(single_precision)
 | 
			
		||||
    render<float>(img_width, img_height);
 | 
			
		||||
  else
 | 
			
		||||
    render<double>(img_width, img_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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++)
 | 
			
		||||
  {
 | 
			
		||||
    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;
 | 
			
		||||
    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)));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  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)
 | 
			
		||||
  {
 | 
			
		||||
    draft /= 2;
 | 
			
		||||
    setWindowTitle(QString("recomputing at 1/%1 resolution...").arg(draft));
 | 
			
		||||
    update();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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());
 | 
			
		||||
    draft = 16;
 | 
			
		||||
    for(int th = 0; th < threadcount; th++)
 | 
			
		||||
      threads[th]->terminate();
 | 
			
		||||
    update();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  QPoint delta = event->pos() - lastpos;
 | 
			
		||||
  lastpos = event->pos();
 | 
			
		||||
  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;
 | 
			
		||||
    xradius *= t;
 | 
			
		||||
    draft = 16;
 | 
			
		||||
    for(int th = 0; th < threadcount; th++)
 | 
			
		||||
      threads[th]->terminate();
 | 
			
		||||
    update();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  QApplication app(argc, argv);
 | 
			
		||||
  MandelbrotWidget w;
 | 
			
		||||
  w.show();
 | 
			
		||||
  return app.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "mandelbrot.moc"
 | 
			
		||||
							
								
								
									
										71
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/mandelbrot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								cs440-acg/ext/eigen/demos/mandelbrot/mandelbrot.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
// This file is part of Eigen, a lightweight C++ template library
 | 
			
		||||
// for linear algebra.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef MANDELBROT_H
 | 
			
		||||
#define MANDELBROT_H
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Core>
 | 
			
		||||
#include <QtGui/QApplication>
 | 
			
		||||
#include <QtGui/QWidget>
 | 
			
		||||
#include <QtCore/QThread>
 | 
			
		||||
 | 
			
		||||
class MandelbrotWidget;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MANDELBROT_H
 | 
			
		||||
							
								
								
									
										9
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
This is an example of how one can wrap some of Eigen into a C library.
 | 
			
		||||
 | 
			
		||||
To try this with GCC, do:
 | 
			
		||||
 | 
			
		||||
  g++ -c binary_library.cpp -O2 -msse2 -I ../..
 | 
			
		||||
  gcc example.c binary_library.o -o example -lstdc++
 | 
			
		||||
  ./example
 | 
			
		||||
 | 
			
		||||
TODO: add CMakeLists, add more explanations here
 | 
			
		||||
							
								
								
									
										185
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/binary_library.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/binary_library.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
// This file is part of Eigen, a lightweight C++ template library
 | 
			
		||||
// for linear algebra.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
// This C++ file compiles to binary code that can be linked to by your C program,
 | 
			
		||||
// thanks to the extern "C" syntax used in the declarations in binary_library.h.
 | 
			
		||||
 | 
			
		||||
#include "binary_library.h"
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Core>
 | 
			
		||||
 | 
			
		||||
using namespace Eigen;
 | 
			
		||||
 | 
			
		||||
/************************* pointer conversion methods **********************************************/
 | 
			
		||||
 | 
			
		||||
////// class MatrixXd //////
 | 
			
		||||
 | 
			
		||||
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 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////// class Map<MatrixXd> //////
 | 
			
		||||
 | 
			
		||||
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 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************* implementation of classes **********************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
////// class MatrixXd //////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_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_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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_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)
 | 
			
		||||
{
 | 
			
		||||
  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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_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_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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
  c_to_eigen(result) = c_to_eigen(m1) + c_to_eigen(m2);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/binary_library.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/binary_library.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
// This file is part of Eigen, a lightweight C++ template library
 | 
			
		||||
// for linear algebra.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
// This is a pure C header, no C++ here.
 | 
			
		||||
// The functions declared here will be implemented in C++ but
 | 
			
		||||
// we don't have to know, because thanks to the extern "C" syntax,
 | 
			
		||||
// they will be compiled to C object code.
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
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 {};
 | 
			
		||||
 | 
			
		||||
  // 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"
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										65
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/example.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								cs440-acg/ext/eigen/demos/mix_eigen_and_c/example.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
// This file is part of Eigen, a lightweight C++ template library
 | 
			
		||||
// for linear algebra.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
 | 
			
		||||
//
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "binary_library.h"
 | 
			
		||||
#include "stdio.h"
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
  MatrixXd_set_coeff(matrix1, 1, 0, 1.4);
 | 
			
		||||
  printf("Here is matrix1:\n");
 | 
			
		||||
  MatrixXd_print(matrix1);
 | 
			
		||||
 | 
			
		||||
  matrix2 = MatrixXd_new(3, 3);
 | 
			
		||||
  MatrixXd_multiply(matrix1, matrix1, matrix2);
 | 
			
		||||
  printf("Here is matrix1*matrix1:\n");
 | 
			
		||||
  MatrixXd_print(matrix2);
 | 
			
		||||
 | 
			
		||||
  MatrixXd_delete(matrix1);
 | 
			
		||||
  MatrixXd_delete(matrix2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// this helper function takes a plain C array and prints it in one line
 | 
			
		||||
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()
 | 
			
		||||
{
 | 
			
		||||
  struct C_Map_MatrixXd *map;
 | 
			
		||||
  double array[5];
 | 
			
		||||
  int i;
 | 
			
		||||
  printf("*** demo_Map_MatrixXd ***\n");
 | 
			
		||||
  
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  printf("Now the array is:\n");
 | 
			
		||||
  print_array(array, 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  demo_MatrixXd();
 | 
			
		||||
  demo_Map_MatrixXd();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								cs440-acg/ext/eigen/demos/opengl/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cs440-acg/ext/eigen/demos/opengl/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
find_package(Qt4)
 | 
			
		||||
find_package(OpenGL)
 | 
			
		||||
 | 
			
		||||
if(QT4_FOUND AND OPENGL_FOUND)
 | 
			
		||||
 | 
			
		||||
  set(QT_USE_QTOPENGL TRUE)
 | 
			
		||||
  include(${QT_USE_FILE})
 | 
			
		||||
 | 
			
		||||
  set(CMAKE_INCLUDE_CURRENT_DIR ON)
 | 
			
		||||
 | 
			
		||||
  include_directories( ${QT_INCLUDE_DIR} )
 | 
			
		||||
 | 
			
		||||
  set(quaternion_demo_SRCS  gpuhelper.cpp icosphere.cpp camera.cpp trackball.cpp quaternion_demo.cpp)
 | 
			
		||||
 | 
			
		||||
  qt4_automoc(${quaternion_demo_SRCS})
 | 
			
		||||
 | 
			
		||||
  add_executable(quaternion_demo ${quaternion_demo_SRCS})
 | 
			
		||||
  add_dependencies(demos quaternion_demo)
 | 
			
		||||
 | 
			
		||||
  target_link_libraries(quaternion_demo
 | 
			
		||||
    ${QT_QTCORE_LIBRARY}    ${QT_QTGUI_LIBRARY}
 | 
			
		||||
    ${QT_QTOPENGL_LIBRARY}  ${OPENGL_LIBRARIES} )
 | 
			
		||||
 | 
			
		||||
else()
 | 
			
		||||
 | 
			
		||||
  message(STATUS "OpenGL demo disabled because Qt4 and/or OpenGL have not been found.")
 | 
			
		||||
 | 
			
		||||
endif()
 | 
			
		||||
							
								
								
									
										13
									
								
								cs440-acg/ext/eigen/demos/opengl/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cs440-acg/ext/eigen/demos/opengl/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
 | 
			
		||||
Navigation:
 | 
			
		||||
 left button:           rotate around the target
 | 
			
		||||
 middle button:         zoom
 | 
			
		||||
 left button + ctrl     quake rotate (rotate around camera position)
 | 
			
		||||
 middle button + ctrl   walk (progress along camera's z direction)
 | 
			
		||||
 left button:           pan (translate in the XY camera's plane)
 | 
			
		||||
 | 
			
		||||
R : move the camera to initial position
 | 
			
		||||
A : start/stop animation
 | 
			
		||||
C : clear the animation
 | 
			
		||||
G : add a key frame
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										264
									
								
								cs440-acg/ext/eigen/demos/opengl/camera.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								cs440-acg/ext/eigen/demos/opengl/camera.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,264 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "camera.h"
 | 
			
		||||
 | 
			
		||||
#include "gpuhelper.h"
 | 
			
		||||
#include <GL/glu.h>
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    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()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height)
 | 
			
		||||
{
 | 
			
		||||
    mVpX = offsetx;
 | 
			
		||||
    mVpY = offsety;
 | 
			
		||||
    mVpWidth = width;
 | 
			
		||||
    mVpHeight = height;
 | 
			
		||||
    
 | 
			
		||||
    mProjIsUptodate = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Camera::setViewport(uint width, uint height)
 | 
			
		||||
{
 | 
			
		||||
    mVpWidth = width;
 | 
			
		||||
    mVpHeight = height;
 | 
			
		||||
    
 | 
			
		||||
    mProjIsUptodate = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Camera::setFovY(float value)
 | 
			
		||||
{
 | 
			
		||||
    mFovY = value;
 | 
			
		||||
    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::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)
 | 
			
		||||
{
 | 
			
		||||
  mFrame = f;
 | 
			
		||||
  mViewIsUptodate = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Camera::rotateAroundTarget(const Quaternionf& q)
 | 
			
		||||
{
 | 
			
		||||
    Matrix4f mrot, mt, mtm;
 | 
			
		||||
    
 | 
			
		||||
    // update the transform matrix
 | 
			
		||||
    updateViewMatrix();
 | 
			
		||||
    Vector3f t = mViewMatrix * mTarget;
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
  Vector3f trans = orientation() * t;
 | 
			
		||||
  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());
 | 
			
		||||
 | 
			
		||||
        mViewIsUptodate = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Affine3f& Camera::viewMatrix(void) const
 | 
			
		||||
{
 | 
			
		||||
  updateViewMatrix();
 | 
			
		||||
  return mViewMatrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Camera::updateProjectionMatrix(void) const
 | 
			
		||||
{
 | 
			
		||||
  if(!mProjIsUptodate)
 | 
			
		||||
  {
 | 
			
		||||
    mProjectionMatrix.setIdentity();
 | 
			
		||||
    float aspect = float(mVpWidth)/float(mVpHeight);
 | 
			
		||||
    float theta = mFovY*0.5;
 | 
			
		||||
    float range = mFarDist - mNearDist;
 | 
			
		||||
    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;
 | 
			
		||||
    
 | 
			
		||||
    mProjIsUptodate = true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Matrix4f& Camera::projectionMatrix(void) const
 | 
			
		||||
{
 | 
			
		||||
  updateProjectionMatrix();
 | 
			
		||||
  return mProjectionMatrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Camera::activateGL(void)
 | 
			
		||||
{
 | 
			
		||||
  glViewport(vpX(), vpY(), vpWidth(), vpHeight());
 | 
			
		||||
  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& 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());
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										118
									
								
								cs440-acg/ext/eigen/demos/opengl/camera.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								cs440-acg/ext/eigen/demos/opengl/camera.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef EIGEN_CAMERA_H
 | 
			
		||||
#define EIGEN_CAMERA_H
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Geometry>
 | 
			
		||||
#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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Eigen::Quaternionf orientation;
 | 
			
		||||
    Eigen::Vector3f position;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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; }
 | 
			
		||||
 | 
			
		||||
    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; }
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
							
								
								
									
										126
									
								
								cs440-acg/ext/eigen/demos/opengl/gpuhelper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								cs440-acg/ext/eigen/demos/opengl/gpuhelper.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "gpuhelper.h"
 | 
			
		||||
#include "icosphere.h"
 | 
			
		||||
#include <GL/glu.h>
 | 
			
		||||
// PLEASE don't look at this old code... ;)
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
GpuHelper gpu;
 | 
			
		||||
 | 
			
		||||
GpuHelper::GpuHelper()
 | 
			
		||||
{
 | 
			
		||||
    mVpWidth = mVpHeight = 0;
 | 
			
		||||
    mCurrentMatrixTarget = 0;
 | 
			
		||||
    mInitialized = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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::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::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::drawUnitSphere(int level)
 | 
			
		||||
{
 | 
			
		||||
  static IcoSphere sphere;
 | 
			
		||||
  sphere.draw(level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										207
									
								
								cs440-acg/ext/eigen/demos/opengl/gpuhelper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								cs440-acg/ext/eigen/demos/opengl/gpuhelper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef EIGEN_GPUHELPER_H
 | 
			
		||||
#define EIGEN_GPUHELPER_H
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Geometry>
 | 
			
		||||
#include <GL/gl.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
using namespace Eigen;
 | 
			
		||||
 | 
			
		||||
typedef Vector4f Color;
 | 
			
		||||
 | 
			
		||||
class GpuHelper
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
 | 
			
		||||
    GpuHelper();
 | 
			
		||||
 | 
			
		||||
    ~GpuHelper();
 | 
			
		||||
 | 
			
		||||
    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 your're 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 your're 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);
 | 
			
		||||
 | 
			
		||||
    /** 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);
 | 
			
		||||
 | 
			
		||||
    /** 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);
 | 
			
		||||
 | 
			
		||||
    /** Push and clone the OpenGL matrix \a matrixTarget
 | 
			
		||||
    */
 | 
			
		||||
    inline void pushMatrix(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);
 | 
			
		||||
 | 
			
		||||
    /// 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 an indexed subset
 | 
			
		||||
    inline void draw(GLenum mode, const std::vector<uint>* pIndexes);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    void update(void);
 | 
			
		||||
 | 
			
		||||
    GLuint mColorBufferId;
 | 
			
		||||
    int mVpWidth, mVpHeight;
 | 
			
		||||
    GLenum mCurrentMatrixTarget;
 | 
			
		||||
    bool mInitialized;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Singleton shortcut
 | 
			
		||||
*/
 | 
			
		||||
extern GpuHelper gpu;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** \internal
 | 
			
		||||
*/
 | 
			
		||||
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<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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, 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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, 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
 | 
			
		||||
							
								
								
									
										120
									
								
								cs440-acg/ext/eigen/demos/opengl/icosphere.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								cs440-acg/ext/eigen/demos/opengl/icosphere.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "icosphere.h"
 | 
			
		||||
 | 
			
		||||
#include <GL/gl.h>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
using namespace Eigen;
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------------------
 | 
			
		||||
// icosahedron data
 | 
			
		||||
//--------------------------------------------------------------------------------
 | 
			
		||||
#define X .525731112119133606
 | 
			
		||||
#define Z .850650808352039932
 | 
			
		||||
 | 
			
		||||
static GLfloat vdata[12][3] = {
 | 
			
		||||
   {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
 | 
			
		||||
   {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
 | 
			
		||||
   {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GLint tindices[20][3] = {
 | 
			
		||||
   {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
 | 
			
		||||
   {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
 | 
			
		||||
   {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
 | 
			
		||||
   {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
 | 
			
		||||
//--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
IcoSphere::IcoSphere(unsigned int levels)
 | 
			
		||||
{
 | 
			
		||||
  // init with an icosahedron
 | 
			
		||||
  for (int i = 0; i < 12; i++)
 | 
			
		||||
    mVertices.push_back(Map<Vector3f>(vdata[i]));
 | 
			
		||||
  mIndices.push_back(new std::vector<int>);
 | 
			
		||||
  std::vector<int>& indices = *mIndices.back();
 | 
			
		||||
  for (int i = 0; i < 20; i++)
 | 
			
		||||
  {
 | 
			
		||||
    for (int k = 0; k < 3; k++)
 | 
			
		||||
      indices.push_back(tindices[i][k]);
 | 
			
		||||
  }
 | 
			
		||||
  mListIds.push_back(0);
 | 
			
		||||
 | 
			
		||||
  while(mIndices.size()<levels)
 | 
			
		||||
    _subdivide();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::vector<int>& IcoSphere::indices(int level) const
 | 
			
		||||
{
 | 
			
		||||
  while (level>=int(mIndices.size()))
 | 
			
		||||
    const_cast<IcoSphere*>(this)->_subdivide();
 | 
			
		||||
  return *mIndices[level];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IcoSphere::_subdivide(void)
 | 
			
		||||
{
 | 
			
		||||
  typedef unsigned long long Key;
 | 
			
		||||
  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)
 | 
			
		||||
  {
 | 
			
		||||
    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];
 | 
			
		||||
      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())
 | 
			
		||||
      {
 | 
			
		||||
        ids1[k] = mVertices.size();
 | 
			
		||||
        edgeMap[edgeKey] = ids1[k];
 | 
			
		||||
        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]);
 | 
			
		||||
  }
 | 
			
		||||
  mListIds.push_back(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IcoSphere::draw(int level)
 | 
			
		||||
{
 | 
			
		||||
  while (level>=int(mIndices.size()))
 | 
			
		||||
    const_cast<IcoSphere*>(this)->_subdivide();
 | 
			
		||||
  if (mListIds[level]==0)
 | 
			
		||||
  {
 | 
			
		||||
    mListIds[level] = glGenLists(1);
 | 
			
		||||
    glNewList(mListIds[level], GL_COMPILE);
 | 
			
		||||
      glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
 | 
			
		||||
      glNormalPointer(GL_FLOAT, 0, mVertices[0].data());
 | 
			
		||||
      glEnableClientState(GL_VERTEX_ARRAY);
 | 
			
		||||
      glEnableClientState(GL_NORMAL_ARRAY);
 | 
			
		||||
      glDrawElements(GL_TRIANGLES, mIndices[level]->size(), GL_UNSIGNED_INT, &(mIndices[level]->at(0)));
 | 
			
		||||
      glDisableClientState(GL_VERTEX_ARRAY);
 | 
			
		||||
      glDisableClientState(GL_NORMAL_ARRAY);
 | 
			
		||||
    glEndList();
 | 
			
		||||
  }
 | 
			
		||||
  glCallList(mListIds[level]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								cs440-acg/ext/eigen/demos/opengl/icosphere.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								cs440-acg/ext/eigen/demos/opengl/icosphere.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef EIGEN_ICOSPHERE_H
 | 
			
		||||
#define EIGEN_ICOSPHERE_H
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Core>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
class IcoSphere
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    IcoSphere(unsigned int levels=1);
 | 
			
		||||
    const std::vector<Eigen::Vector3f>& vertices() const { return mVertices; }
 | 
			
		||||
    const std::vector<int>& indices(int level) const;
 | 
			
		||||
    void draw(int level);
 | 
			
		||||
  protected:
 | 
			
		||||
    void _subdivide();
 | 
			
		||||
    std::vector<Eigen::Vector3f> mVertices;
 | 
			
		||||
    std::vector<std::vector<int>*> mIndices;
 | 
			
		||||
    std::vector<int> mListIds;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // EIGEN_ICOSPHERE_H
 | 
			
		||||
							
								
								
									
										656
									
								
								cs440-acg/ext/eigen/demos/opengl/quaternion_demo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										656
									
								
								cs440-acg/ext/eigen/demos/opengl/quaternion_demo.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,656 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "quaternion_demo.h"
 | 
			
		||||
#include "icosphere.h"
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Geometry>
 | 
			
		||||
#include <Eigen/QR>
 | 
			
		||||
#include <Eigen/LU>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <QEvent>
 | 
			
		||||
#include <QMouseEvent>
 | 
			
		||||
#include <QInputDialog>
 | 
			
		||||
#include <QGridLayout>
 | 
			
		||||
#include <QButtonGroup>
 | 
			
		||||
#include <QRadioButton>
 | 
			
		||||
#include <QDockWidget>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include <QGroupBox>
 | 
			
		||||
 | 
			
		||||
using namespace Eigen;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
      {
 | 
			
		||||
        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;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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>
 | 
			
		||||
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:
 | 
			
		||||
  enum { Dim = 3 };
 | 
			
		||||
  typedef _Scalar Scalar;
 | 
			
		||||
  typedef Matrix<Scalar,3,3> Matrix3;
 | 
			
		||||
  typedef Matrix<Scalar,3,1> Vector3;
 | 
			
		||||
  typedef Quaternion<Scalar> QuaternionType;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
  Vector3 m_angles;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
  EulerAngles() {}
 | 
			
		||||
  inline EulerAngles(Scalar a0, Scalar a1, Scalar a2) : m_angles(a0, a1, a2) {}
 | 
			
		||||
  inline EulerAngles(const QuaternionType& q) { *this = q; }
 | 
			
		||||
 | 
			
		||||
  const Vector3& coeffs() const { return m_angles; }
 | 
			
		||||
  Vector3& coeffs() { return m_angles; }
 | 
			
		||||
 | 
			
		||||
  EulerAngles& operator=(const QuaternionType& q)
 | 
			
		||||
  {
 | 
			
		||||
    Matrix3 m = q.toRotationMatrix();
 | 
			
		||||
    return *this = 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));
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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();
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  operator QuaternionType() { return QuaternionType(toRotationMatrix()); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Euler angles slerp
 | 
			
		||||
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()
 | 
			
		||||
{
 | 
			
		||||
  mAnimate = false;
 | 
			
		||||
  mCurrentTrackingMode = TM_NO_TRACK;
 | 
			
		||||
  mNavMode = NavTurnAround;
 | 
			
		||||
  mLerpMode = LerpQuaternion;
 | 
			
		||||
  mRotationMode = RotationStable;
 | 
			
		||||
  mTrackball.setCamera(&mCamera);
 | 
			
		||||
 | 
			
		||||
  // required to capture key press events
 | 
			
		||||
  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::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));
 | 
			
		||||
 | 
			
		||||
  // 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_LIGHT1, GL_AMBIENT, Vector4f(0,0,0,1).data());
 | 
			
		||||
  glLightfv(GL_LIGHT1, GL_DIFFUSE, Vector4f(1,0.5,0.5,1).data());
 | 
			
		||||
  glLightfv(GL_LIGHT1, GL_SPECULAR, Vector4f(1,1,1,1).data());
 | 
			
		||||
  glLightfv(GL_LIGHT1, GL_POSITION, Vector4f(-sqrt3,sqrt3,-sqrt3,0).data());
 | 
			
		||||
 | 
			
		||||
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Vector4f(0.7, 0.7, 0.7, 1).data());
 | 
			
		||||
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Vector4f(0.8, 0.75, 0.6, 1).data());
 | 
			
		||||
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Vector4f(1, 1, 1, 1).data());
 | 
			
		||||
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
 | 
			
		||||
 | 
			
		||||
  glEnable(GL_LIGHTING);
 | 
			
		||||
  glEnable(GL_LIGHT0);
 | 
			
		||||
  glEnable(GL_LIGHT1);
 | 
			
		||||
 | 
			
		||||
  sFancySpheres.draw();
 | 
			
		||||
  glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
 | 
			
		||||
  glNormalPointer(GL_FLOAT, 0, mNormals[0].data());
 | 
			
		||||
  glEnableClientState(GL_VERTEX_ARRAY);
 | 
			
		||||
  glEnableClientState(GL_NORMAL_ARRAY);
 | 
			
		||||
  glDrawArrays(GL_TRIANGLES, 0, mVertices.size());
 | 
			
		||||
  glDisableClientState(GL_VERTEX_ARRAY);
 | 
			
		||||
  glDisableClientState(GL_NORMAL_ARRAY);
 | 
			
		||||
 | 
			
		||||
  glDisable(GL_LIGHTING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::animate()
 | 
			
		||||
{
 | 
			
		||||
  m_alpha += double(m_timer.interval()) * 1e-3;
 | 
			
		||||
 | 
			
		||||
  TimeLine::const_iterator hi = m_timeline.upper_bound(m_alpha);
 | 
			
		||||
  TimeLine::const_iterator lo = hi;
 | 
			
		||||
  --lo;
 | 
			
		||||
 | 
			
		||||
  Frame currentFrame;
 | 
			
		||||
 | 
			
		||||
  if(hi==m_timeline.end())
 | 
			
		||||
  {
 | 
			
		||||
    // end
 | 
			
		||||
    currentFrame = lo->second;
 | 
			
		||||
    stopAnimation();
 | 
			
		||||
  }
 | 
			
		||||
  else if(hi==m_timeline.begin())
 | 
			
		||||
  {
 | 
			
		||||
    // start
 | 
			
		||||
    currentFrame = hi->second;
 | 
			
		||||
  }
 | 
			
		||||
  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)
 | 
			
		||||
      currentFrame = ::lerpFrame<Eigen::Quaternionf>(s, lo->second, hi->second);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      std::cerr << "Invalid rotation interpolation mode (abort)\n";
 | 
			
		||||
      exit(2);
 | 
			
		||||
    }
 | 
			
		||||
    currentFrame.orientation.coeffs().normalize();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  currentFrame.orientation = currentFrame.orientation.inverse();
 | 
			
		||||
  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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateGL();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::stopAnimation()
 | 
			
		||||
{
 | 
			
		||||
  disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
 | 
			
		||||
  m_timer.stop();
 | 
			
		||||
  mAnimate = false;
 | 
			
		||||
  m_alpha = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::mousePressEvent(QMouseEvent* e)
 | 
			
		||||
{
 | 
			
		||||
  mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
 | 
			
		||||
  bool fly = (mNavMode==NavFly) || (e->modifiers()&Qt::ControlModifier);
 | 
			
		||||
  switch(e->button())
 | 
			
		||||
  {
 | 
			
		||||
    case Qt::LeftButton:
 | 
			
		||||
      if(fly)
 | 
			
		||||
      {
 | 
			
		||||
        mCurrentTrackingMode = TM_LOCAL_ROTATE;
 | 
			
		||||
        mTrackball.start(Trackball::Local);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        mCurrentTrackingMode = TM_ROTATE_AROUND;
 | 
			
		||||
        mTrackball.start(Trackball::Around);
 | 
			
		||||
      }
 | 
			
		||||
      mTrackball.track(mMouseCoords);
 | 
			
		||||
      break;
 | 
			
		||||
    case Qt::MidButton:
 | 
			
		||||
      if(fly)
 | 
			
		||||
        mCurrentTrackingMode = TM_FLY_Z;
 | 
			
		||||
      else
 | 
			
		||||
        mCurrentTrackingMode = TM_ZOOM;
 | 
			
		||||
      break;
 | 
			
		||||
    case Qt::RightButton:
 | 
			
		||||
        mCurrentTrackingMode = TM_FLY_PAN;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
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());
 | 
			
		||||
 | 
			
		||||
        // 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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mMouseCoords = Vector2i(e->pos().x(), e->pos().y());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::paintGL()
 | 
			
		||||
{
 | 
			
		||||
  glEnable(GL_DEPTH_TEST);
 | 
			
		||||
  glDisable(GL_CULL_FACE);
 | 
			
		||||
  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 | 
			
		||||
  glDisable(GL_COLOR_MATERIAL);
 | 
			
		||||
  glDisable(GL_BLEND);
 | 
			
		||||
  glDisable(GL_ALPHA_TEST);
 | 
			
		||||
  glDisable(GL_TEXTURE_1D);
 | 
			
		||||
  glDisable(GL_TEXTURE_2D);
 | 
			
		||||
  glDisable(GL_TEXTURE_3D);
 | 
			
		||||
 | 
			
		||||
  // Clear buffers
 | 
			
		||||
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
			
		||||
 | 
			
		||||
  mCamera.activateGL();
 | 
			
		||||
 | 
			
		||||
  drawScene();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::initializeGL()
 | 
			
		||||
{
 | 
			
		||||
  glClearColor(1., 1., 1., 0.);
 | 
			
		||||
  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
 | 
			
		||||
  glDepthMask(GL_TRUE);
 | 
			
		||||
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 | 
			
		||||
 | 
			
		||||
  mCamera.setPosition(Vector3f(-200, -200, -200));
 | 
			
		||||
  mCamera.setTarget(Vector3f(0, 0, 0));
 | 
			
		||||
  mInitFrame.orientation = mCamera.orientation().inverse();
 | 
			
		||||
  mInitFrame.position = mCamera.viewMatrix().translation();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::resizeGL(int width, int height)
 | 
			
		||||
{
 | 
			
		||||
    mCamera.setViewport(width,height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::setNavMode(int m)
 | 
			
		||||
{
 | 
			
		||||
  mNavMode = NavMode(m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::setLerpMode(int m)
 | 
			
		||||
{
 | 
			
		||||
  mLerpMode = LerpMode(m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::setRotationMode(int m)
 | 
			
		||||
{
 | 
			
		||||
  mRotationMode = RotationMode(m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingWidget::resetCamera()
 | 
			
		||||
{
 | 
			
		||||
  if (mAnimate)
 | 
			
		||||
    stopAnimation();
 | 
			
		||||
  m_timeline.clear();
 | 
			
		||||
  Frame aux0 = mCamera.frame();
 | 
			
		||||
  aux0.orientation = aux0.orientation.inverse();
 | 
			
		||||
  aux0.position = mCamera.viewMatrix().translation();
 | 
			
		||||
  m_timeline[0] = aux0;
 | 
			
		||||
 | 
			
		||||
  Vector3f currentTarget = mCamera.target();
 | 
			
		||||
  mCamera.setTarget(Vector3f::Zero());
 | 
			
		||||
 | 
			
		||||
  // compute the rotation duration to move the camera to the target
 | 
			
		||||
  Frame aux1 = mCamera.frame();
 | 
			
		||||
  aux1.orientation = aux1.orientation.inverse();
 | 
			
		||||
  aux1.position = mCamera.viewMatrix().translation();
 | 
			
		||||
  float 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;
 | 
			
		||||
 | 
			
		||||
  m_timeline[2] = mInitFrame;
 | 
			
		||||
  m_alpha = 0;
 | 
			
		||||
  animate();
 | 
			
		||||
  connect(&m_timer, SIGNAL(timeout()), this, SLOT(animate()));
 | 
			
		||||
  m_timer.start(1000/30);
 | 
			
		||||
  mAnimate = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QWidget* RenderingWidget::createNavigationControlWidget()
 | 
			
		||||
{
 | 
			
		||||
  QWidget* panel = new QWidget();
 | 
			
		||||
  QVBoxLayout* layout = new QVBoxLayout();
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
  QDockWidget* panel = new QDockWidget("navigation", this);
 | 
			
		||||
  panel->setAllowedAreas((QFlags<Qt::DockWidgetArea>)(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea));
 | 
			
		||||
  addDockWidget(Qt::RightDockWidgetArea, panel);
 | 
			
		||||
  panel->setWidget(mRenderingWidget->createNavigationControlWidget());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  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";
 | 
			
		||||
 | 
			
		||||
  QApplication app(argc, argv);
 | 
			
		||||
  QuaternionDemo demo;
 | 
			
		||||
  demo.resize(600,500);
 | 
			
		||||
  demo.show();
 | 
			
		||||
  return app.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "quaternion_demo.moc"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										114
									
								
								cs440-acg/ext/eigen/demos/opengl/quaternion_demo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								cs440-acg/ext/eigen/demos/opengl/quaternion_demo.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef EIGEN_QUATERNION_DEMO_H
 | 
			
		||||
#define EIGEN_QUATERNION_DEMO_H
 | 
			
		||||
 | 
			
		||||
#include "gpuhelper.h"
 | 
			
		||||
#include "camera.h"
 | 
			
		||||
#include "trackball.h"
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QtGui/QApplication>
 | 
			
		||||
#include <QtOpenGL/QGLWidget>
 | 
			
		||||
#include <QtGui/QMainWindow>
 | 
			
		||||
 | 
			
		||||
class RenderingWidget : public QGLWidget
 | 
			
		||||
{
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    typedef std::map<float,Frame> TimeLine;
 | 
			
		||||
    TimeLine m_timeline;
 | 
			
		||||
    Frame lerpFrame(float t);
 | 
			
		||||
 | 
			
		||||
    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 NavMode {
 | 
			
		||||
      NavTurnAround,
 | 
			
		||||
      NavFly
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum LerpMode {
 | 
			
		||||
      LerpQuaternion,
 | 
			
		||||
      LerpEulerAngles
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum RotationMode {
 | 
			
		||||
      RotationStable,
 | 
			
		||||
      RotationStandard
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Camera mCamera;
 | 
			
		||||
    TrackMode mCurrentTrackingMode;
 | 
			
		||||
    NavMode mNavMode;
 | 
			
		||||
    LerpMode mLerpMode;
 | 
			
		||||
    RotationMode mRotationMode;
 | 
			
		||||
    Vector2i mMouseCoords;
 | 
			
		||||
    Trackball mTrackball;
 | 
			
		||||
 | 
			
		||||
    QTimer m_timer;
 | 
			
		||||
 | 
			
		||||
    void setupCamera();
 | 
			
		||||
 | 
			
		||||
    std::vector<Vector3f> mVertices;
 | 
			
		||||
    std::vector<Vector3f> mNormals;
 | 
			
		||||
    std::vector<int> mIndices;
 | 
			
		||||
 | 
			
		||||
  protected slots:
 | 
			
		||||
 | 
			
		||||
    virtual void animate(void);
 | 
			
		||||
    virtual void drawScene(void);
 | 
			
		||||
 | 
			
		||||
    virtual void grabFrame(void);
 | 
			
		||||
    virtual void stopAnimation();
 | 
			
		||||
 | 
			
		||||
    virtual void setNavMode(int);
 | 
			
		||||
    virtual void setLerpMode(int);
 | 
			
		||||
    virtual void setRotationMode(int);
 | 
			
		||||
    virtual void resetCamera();
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    //--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  public: 
 | 
			
		||||
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 | 
			
		||||
    
 | 
			
		||||
    RenderingWidget();
 | 
			
		||||
    ~RenderingWidget() { }
 | 
			
		||||
 | 
			
		||||
    QWidget* createNavigationControlWidget();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QuaternionDemo : public QMainWindow
 | 
			
		||||
{
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
  public:
 | 
			
		||||
    QuaternionDemo();
 | 
			
		||||
  protected:
 | 
			
		||||
    RenderingWidget* mRenderingWidget;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // EIGEN_QUATERNION_DEMO_H
 | 
			
		||||
							
								
								
									
										59
									
								
								cs440-acg/ext/eigen/demos/opengl/trackball.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								cs440-acg/ext/eigen/demos/opengl/trackball.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#include "trackball.h"
 | 
			
		||||
#include "camera.h"
 | 
			
		||||
 | 
			
		||||
using namespace Eigen;
 | 
			
		||||
 | 
			
		||||
void Trackball::track(const Vector2i& point2D)
 | 
			
		||||
{
 | 
			
		||||
  if (mpCamera==0)
 | 
			
		||||
    return;
 | 
			
		||||
  Vector3f newPoint3D;
 | 
			
		||||
  bool newPointOk = mapToSphere(point2D, newPoint3D);
 | 
			
		||||
 | 
			
		||||
  if (mLastPointOk && newPointOk)
 | 
			
		||||
  {
 | 
			
		||||
    Vector3f axis = mLastPoint3D.cross(newPoint3D).normalized();
 | 
			
		||||
    float cos_angle = mLastPoint3D.dot(newPoint3D);
 | 
			
		||||
    if ( std::abs(cos_angle) < 1.0 )
 | 
			
		||||
    {
 | 
			
		||||
      float angle = 2. * acos(cos_angle);
 | 
			
		||||
      if (mMode==Around)
 | 
			
		||||
        mpCamera->rotateAroundTarget(Quaternionf(AngleAxisf(angle, axis)));
 | 
			
		||||
      else
 | 
			
		||||
        mpCamera->localRotate(Quaternionf(AngleAxisf(-angle, axis)));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mLastPoint3D = newPoint3D;
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
    v3.x() = sinx;
 | 
			
		||||
    v3.y() = siny;
 | 
			
		||||
    v3.z() = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								cs440-acg/ext/eigen/demos/opengl/trackball.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								cs440-acg/ext/eigen/demos/opengl/trackball.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
// 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/.
 | 
			
		||||
 | 
			
		||||
#ifndef EIGEN_TRACKBALL_H
 | 
			
		||||
#define EIGEN_TRACKBALL_H
 | 
			
		||||
 | 
			
		||||
#include <Eigen/Geometry>
 | 
			
		||||
 | 
			
		||||
class Camera;
 | 
			
		||||
 | 
			
		||||
class Trackball
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
 | 
			
		||||
    enum Mode {Around, Local};
 | 
			
		||||
 | 
			
		||||
    Trackball() : mpCamera(0) {}
 | 
			
		||||
 | 
			
		||||
    void start(Mode m = Around) { mMode = m; mLastPointOk = false; }
 | 
			
		||||
 | 
			
		||||
    void setCamera(Camera* pCam) { mpCamera = pCam; }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // EIGEN_TRACKBALL_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user