[Aqsis-commits] [SCM] Aqsis Renderer branch, pointrender, updated. Release_1.6.0_Phase2-498-ge481a3
Brought to you by:
ltatkinson,
pgregory
From: Chris F. <c4...@us...> - 2011-04-10 14:23:50
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Aqsis Renderer". The branch, pointrender has been updated via e481a38803729052aa217742404c2672722ca047 (commit) via 627e1e10e33d86709331a2c7069078e2de7bda50 (commit) from 8d57ca71141d04af54fc8572997ea9b0ac9b6d35 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e481a38803729052aa217742404c2672722ca047 Author: Chris Foster <chr...@gm...> Date: Sun Apr 10 23:39:36 2011 +1000 Minor cleanups to point array represnetation * Rename PointCloud to PointArray and move into its own file (there's many ways to store a "point cloud", this is just one). * Use shared_ptr to return an array of points * Fix build to add -Wall and to avoid silently setting build type to Release diff --git a/libs/pointrender/CMakeLists.txt b/libs/pointrender/CMakeLists.txt index a60f67c..c95ec80 100644 --- a/libs/pointrender/CMakeLists.txt +++ b/libs/pointrender/CMakeLists.txt @@ -3,7 +3,14 @@ find_package(Qt4 COMPONENTS QtGui QtOpenGL REQUIRED) find_path(ILMBASE_INCLUDE_DIR OpenEXR/ImathBox.h) include_directories(${QT_INCLUDES} ${ILMBASE_INCLUDE_DIR}) -set(CMAKE_BUILD_TYPE Release) +if(UNIX) + if("${CMAKE_CXX_FLAGS}" STREQUAL "") + set(CMAKE_CXX_FLAGS "-Wall -Werror" CACHE STRING + "Flags used by the compiler during all build types." FORCE) + endif() +endif() + +#set(CMAKE_BUILD_TYPE Release) qt4_wrap_cpp(moc_srcs ptview.h) diff --git a/libs/pointrender/cornellbox.cpp b/libs/pointrender/cornellbox.cpp index c0182d2..854e0b0 100644 --- a/libs/pointrender/cornellbox.cpp +++ b/libs/pointrender/cornellbox.cpp @@ -32,6 +32,7 @@ #include <OpenEXR/ImathVec.h> #include "cornellbox.h" +#include "pointcloud.h" using Imath::V3f; @@ -51,8 +52,8 @@ inline T bilerp(float u, float v, T x1, T x2, T x3, T x4) /// Generate a set of points from a bilinear patch static void makeBilinearPatch(std::vector<float>& outData, - const float* patchData, int dataLen, - float spatialRes, float scale) + const float* patchData, int dataLen, + float spatialRes, float scale) { // Get positions of points const float* d1 = patchData; @@ -61,7 +62,7 @@ static void makeBilinearPatch(std::vector<float>& outData, const float* d4 = patchData + 3*dataLen; V3f p1 = scale*ptov3(d1); V3f p2 = scale*ptov3(d2); V3f p3 = scale*ptov3(d3); V3f p4 = scale*ptov3(d4); - spatialRes *= scale; + spatialRes *= scale; int nu = int(std::max((p1 - p2).length(), (p3 - p4).length()) / spatialRes); int nv = int(std::max((p1 - p3).length(), (p2 - p4).length()) / spatialRes); float du = 1.0f/nu; @@ -90,27 +91,19 @@ static void makeBilinearPatch(std::vector<float>& outData, } -/// Generate a pointcloud representing the cornell box. -/// -/// Cornell box data from -/// http://www.graphics.cornell.edu/online/box/data.html -/// Approximate RGB colors from RIB version of data found online. -/// -/// \param data - output point data is stored here as [P1 N1 r1 P2 N2 r2 ...] -/// \param spatialRes - the desired spatial distance between adjacent points. -void cornellBoxPoints(std::vector<float>& data, int& stride, float spatialRes) +boost::shared_ptr<PointArray> cornellBoxPoints(float spatialRes) { - data.clear(); + boost::shared_ptr<PointArray> points(new PointArray()); const int userDataLen = 3; - const float scale = 0.01; - stride = 7 + userDataLen; + const float scale = 0.01; + points->stride = 7 + userDataLen; const int dataLen = userDataLen + 3; #define PATCH_BEGIN \ { \ float d[] = { #define PATCH_END \ }; \ - makeBilinearPatch(data, d, dataLen, spatialRes, scale); \ + makeBilinearPatch(points->data, d, dataLen, spatialRes, scale); \ } //-------------------------------------------------- @@ -218,7 +211,9 @@ void cornellBoxPoints(std::vector<float>& data, int& stride, float spatialRes) 82.0, 0.0, 225.0, 1,1,1, 82.0, 165.0, 225.0, 1,1,1 PATCH_END + + return points; } -// vi: set et +// vi: set et: diff --git a/libs/pointrender/cornellbox.h b/libs/pointrender/cornellbox.h index b7d9326..ad63fc7 100644 --- a/libs/pointrender/cornellbox.h +++ b/libs/pointrender/cornellbox.h @@ -31,8 +31,24 @@ #ifndef AQSIS_CORNELLBOX_H_INCLUDED #define AQSIS_CORNELLBOX_H_INCLUDED +#include <boost/shared_ptr.hpp> -void cornellBoxPoints(std::vector<float>& data, int& stride, float spatialRes); +class PointArray; + + +/// Generate a pointcloud representing the cornell box. +/// +/// Cornell box data from +/// http://www.graphics.cornell.edu/online/box/data.html +/// Approximate RGB colors from RIB version of data found online. +/// +/// \param spatialRes - the desired spatial distance between adjacent points. +/// (The full box is roughly of size 550.) +/// +/// \return Discretized cornell box as an array of points +boost::shared_ptr<PointArray> cornellBoxPoints(float spatialRes); #endif // AQSIS_CORNELLBOX_H_INCLUDED + +// vi: set et: diff --git a/libs/pointrender/ptview.h b/libs/pointrender/pointcloud.h similarity index 50% copy from libs/pointrender/ptview.h copy to libs/pointrender/pointcloud.h index 73bf4b0..3d39826 100644 --- a/libs/pointrender/ptview.h +++ b/libs/pointrender/pointcloud.h @@ -27,24 +27,29 @@ // // (This is the New BSD license) -#ifndef AQSIS_PTVIEW_H_INCLUDED -#define AQSIS_PTVIEW_H_INCLUDED -#include <cmath> +#ifndef AQSIS_POINTCLOUD_H_INCLUDED +#define AQSIS_POINTCLOUD_H_INCLUDED -#include <QtGui/QMainWindow> -#include <QtGui/QKeyEvent> -#include <QtOpenGL/QGLWidget> +#include <cassert> #include <OpenEXR/ImathVec.h> +#include <boost/shared_ptr.hpp> using Imath::V3f; -inline float deg2rad(float d) { return (M_PI/180) * d; } - - +/// Array of surface elements +/// /// TODO: Make into a class, etc. -struct PointCloud +/// +/// Point data is stored in a flat array as +/// +/// [P1 N1 r1 user1 P2 N2 r2 user2 ... ] +/// +/// where user1 user2... is extra "user data" appended after the position +/// normal, and radius data. +/// +struct PointArray { int stride; std::vector<float> data; @@ -64,87 +69,77 @@ struct PointCloud //------------------------------------------------------------------------------ -/// OpenGL-based viewer widget for point clouds (or more precisely, clouds of -/// disk-like surface elements). -class PointView : public QGLWidget -{ - Q_OBJECT - - public: - /// Point (surface element) visualization mode - enum VisMode - { - Vis_Points, ///< Draw surfels using GL_POINTS - Vis_Disks ///< Draw surfels as disks - }; - - PointView(QWidget *parent = NULL); - - /// Set points to be rendered - void setPoints(const PointCloud* points); - - protected: - // Qt OpenGL callbacks - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); +// Musings on abstraction for point array class... not sure what the best +// abstraction is yet. - // Qt event callbacks - void mousePressEvent(QMouseEvent* event); - void mouseMoveEvent(QMouseEvent* event); - void wheelEvent(QWheelEvent* event); - void keyPressEvent(QKeyEvent *event); +#if 0 +/// Reference to data for a single surface element +class Point +{ + public: + Point(const float* data) : m_data(data) {} + /// Get point position + V3f P() const { return V3f(m_data[0], m_data[1], m_data[2]); } + /// Get normal + V3f N() const { return V3f(m_data[3], m_data[4], m_data[5]); } + /// Get radius + float r() const { return m_data[6]; } + /// Get any additional attached data + const float* userData() const { return &m_data[7]; } private: - /// Draw point cloud using OpenGL - static void drawPoints(const PointCloud& points, VisMode visMode); - - /// Mouse-based camera positioning - int m_prev_x; - int m_prev_y; - bool m_zooming; - float m_theta; - float m_phi; - float m_dist; - V3f m_centre; - /// Type of visualization - VisMode m_visMode; - /// Point cloud data - const PointCloud* m_points; - V3f m_cloudCenter; + const float* m_data; }; -//------------------------------------------------------------------------------ -/// Main window for point cloud viewer application -class PointViewerWindow : public QMainWindow +/// Array of surface elements ("points") +class PointArray { - Q_OBJECT - public: - PointViewerWindow() + PointArray(int stride) + : m_stride(stride) + { } + + const Point operator[](size_t i) const { - m_pointView = new PointView(); - m_pointView->setMinimumSize(QSize(640, 480)); - setCentralWidget(m_pointView); - setWindowTitle("Aqsis point cloud viewer"); + assert(i < data.size()); + return &data[i*m_stride]; } - PointView& pointView() { return *m_pointView; } + int stride() const { return m_stride; } - protected: - void keyReleaseEvent(QKeyEvent* event) + void addPoint(const float* data) { - if(event->key() == Qt::Key_Escape) - close(); + m_data.insert(m_data.end(), data, data + m_stride); + } + + // Get centroid of the point cloud. + V3f centroid() const + { + V3f sum(0); + for(std::vector<float>::const_iterator p = data.begin(); + p < data.end(); p += stride) + { + sum += V3f(p[0], p[1], p[2]); + } + return (1.0f/data.size()*stride) * sum; } private: - PointView* m_pointView; +// struct Channel +// { +// int index; +// int size; +// std::string name; +// }; + + int m_stride; +// std::vector<Channel> m_channelData; + std::vector<float> m_data; }; +#endif - -#endif // AQSIS_PTVIEW_H_INCLUDED +#endif // AQSIS_POINTCLOUD_H_INCLUDED // vi: set et: diff --git a/libs/pointrender/ptview.cpp b/libs/pointrender/ptview.cpp index ecd710d..53af8e2 100644 --- a/libs/pointrender/ptview.cpp +++ b/libs/pointrender/ptview.cpp @@ -56,14 +56,14 @@ PointView::PointView(QWidget *parent) m_dist(5), m_centre(0), m_visMode(Vis_Points), - m_points(0), + m_points(), m_cloudCenter(0) { setFocusPolicy(Qt::StrongFocus); } -void PointView::setPoints(const PointCloud* points) +void PointView::setPoints(const boost::shared_ptr<const PointArray>& points) { m_points = points; if(m_points) @@ -228,7 +228,7 @@ void PointView::keyPressEvent(QKeyEvent *event) event->ignore(); } -void PointView::drawPoints(const PointCloud& points, VisMode visMode) +void PointView::drawPoints(const PointArray& points, VisMode visMode) { int ptStride = points.stride; int npoints = points.data.size()/ptStride; @@ -322,14 +322,8 @@ int main(int argc, char *argv[]) f.setSampleBuffers(true); QGLFormat::setDefaultFormat(f); - // Generate points. - PointCloud points; - cornellBoxPoints(points.data, points.stride, 5); - // Translate the model - //glTranslatef(-2.5, -2.5, -2.5); - PointViewerWindow window; - window.pointView().setPoints(&points); + window.pointView().setPoints(cornellBoxPoints(5)); window.show(); return app.exec(); diff --git a/libs/pointrender/ptview.h b/libs/pointrender/ptview.h index 73bf4b0..f35fc96 100644 --- a/libs/pointrender/ptview.h +++ b/libs/pointrender/ptview.h @@ -38,29 +38,12 @@ #include <OpenEXR/ImathVec.h> -using Imath::V3f; +#include "pointcloud.h" -inline float deg2rad(float d) { return (M_PI/180) * d; } +using Imath::V3f; -/// TODO: Make into a class, etc. -struct PointCloud -{ - int stride; - std::vector<float> data; - - // Get centroid of point cloud. - V3f centroid() const - { - V3f sum(0); - for(std::vector<float>::const_iterator p = data.begin(); - p < data.end(); p += stride) - { - sum += V3f(p[0], p[1], p[2]); - } - return (1.0f/data.size()*stride) * sum; - } -}; +inline float deg2rad(float d) { return (M_PI/180) * d; } //------------------------------------------------------------------------------ @@ -81,7 +64,7 @@ class PointView : public QGLWidget PointView(QWidget *parent = NULL); /// Set points to be rendered - void setPoints(const PointCloud* points); + void setPoints(const boost::shared_ptr<const PointArray>& points); protected: // Qt OpenGL callbacks @@ -97,7 +80,7 @@ class PointView : public QGLWidget private: /// Draw point cloud using OpenGL - static void drawPoints(const PointCloud& points, VisMode visMode); + static void drawPoints(const PointArray& points, VisMode visMode); /// Mouse-based camera positioning int m_prev_x; @@ -110,7 +93,7 @@ class PointView : public QGLWidget /// Type of visualization VisMode m_visMode; /// Point cloud data - const PointCloud* m_points; + boost::shared_ptr<const PointArray> m_points; V3f m_cloudCenter; }; commit 627e1e10e33d86709331a2c7069078e2de7bda50 Author: Chris Foster <chr...@gm...> Date: Sun Apr 10 17:08:41 2011 +1000 Disk visualization for surfels in point viewer Pressing 'v' now toggles the visualization of surfels between a GL_POINT-based one. The disk-based visualization uses disks constructed of triangles to correctly show the normal and radius information. diff --git a/libs/pointrender/cornellbox.cpp b/libs/pointrender/cornellbox.cpp index 38aad53..c0182d2 100644 --- a/libs/pointrender/cornellbox.cpp +++ b/libs/pointrender/cornellbox.cpp @@ -52,24 +52,25 @@ inline T bilerp(float u, float v, T x1, T x2, T x3, T x4) /// Generate a set of points from a bilinear patch static void makeBilinearPatch(std::vector<float>& outData, const float* patchData, int dataLen, - float spatialRes) + float spatialRes, float scale) { // Get positions of points const float* d1 = patchData; const float* d2 = patchData + dataLen; const float* d3 = patchData + 2*dataLen; const float* d4 = patchData + 3*dataLen; - V3f p1 = ptov3(d1); V3f p2 = ptov3(d2); - V3f p3 = ptov3(d3); V3f p4 = ptov3(d4); + V3f p1 = scale*ptov3(d1); V3f p2 = scale*ptov3(d2); + V3f p3 = scale*ptov3(d3); V3f p4 = scale*ptov3(d4); + spatialRes *= scale; int nu = int(std::max((p1 - p2).length(), (p3 - p4).length()) / spatialRes); int nv = int(std::max((p1 - p3).length(), (p2 - p4).length()) / spatialRes); - float du = 1.0f/(nu-1); - float dv = 1.0f/(nv-1); + float du = 1.0f/nu; + float dv = 1.0f/nv; for(int j = 0; j < nv; ++j) for(int i = 0; i < nu; ++i) { - float u = i*du; - float v = j*dv; + float u = (0.5f + i)*du; + float v = (0.5f + j)*dv; // Compute position V3f p = bilerp(u,v, p1, p2, p3, p4); // Compute normal - dp/du x dp/dv @@ -101,6 +102,7 @@ void cornellBoxPoints(std::vector<float>& data, int& stride, float spatialRes) { data.clear(); const int userDataLen = 3; + const float scale = 0.01; stride = 7 + userDataLen; const int dataLen = userDataLen + 3; #define PATCH_BEGIN \ @@ -108,7 +110,7 @@ void cornellBoxPoints(std::vector<float>& data, int& stride, float spatialRes) float d[] = { #define PATCH_END \ }; \ - makeBilinearPatch(data, d, dataLen, spatialRes); \ + makeBilinearPatch(data, d, dataLen, spatialRes, scale); \ } //-------------------------------------------------- diff --git a/libs/pointrender/ptview.cpp b/libs/pointrender/ptview.cpp index 8ef7695..ecd710d 100644 --- a/libs/pointrender/ptview.cpp +++ b/libs/pointrender/ptview.cpp @@ -32,12 +32,21 @@ #include <QtGui/QApplication> +#include <OpenEXR/ImathVec.h> +#include <OpenEXR/ImathGL.h> + #include "ptview.h" #include "cornellbox.h" +using Imath::V3f; + +inline float rad2deg(float r) +{ + return r*180/M_PI; +} //------------------------------------------------------------------------------ -PointViewport::PointViewport(QWidget *parent) +PointView::PointView(QWidget *parent) : QGLWidget(parent), m_prev_x(0), m_prev_y(0), @@ -45,14 +54,26 @@ PointViewport::PointViewport(QWidget *parent) m_theta(0), m_phi(0), m_dist(5), - m_centre(0) + m_centre(0), + m_visMode(Vis_Points), + m_points(0), + m_cloudCenter(0) { setFocusPolicy(Qt::StrongFocus); } -void PointViewport::initializeGL() +void PointView::setPoints(const PointCloud* points) { + m_points = points; + if(m_points) + m_cloudCenter = m_points->centroid(); +} + + +void PointView::initializeGL() +{ + glLoadIdentity(); // background colour glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); @@ -60,10 +81,41 @@ void PointViewport::initializeGL() glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); + + switch(m_visMode) + { + case Vis_Points: + { + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHT0); + } + break; + case Vis_Disks: + { + // Materials + glShadeModel(GL_SMOOTH); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + // Lighting + // light0 + GLfloat lightPos[] = {0, 0, 0, 1}; + GLfloat whiteCol[] = {1, 1, 1, 1}; + glLightfv(GL_LIGHT0, GL_POSITION, lightPos); + glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteCol); + // whole-scene ambient + GLfloat ambientCol[] = {0.1, 0.1, 0.1, 1}; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientCol); + glEnable(GL_LIGHT0); + glEnable(GL_RESCALE_NORMAL); + } + break; + } + + glEnable(GL_MULTISAMPLE); } -void PointViewport::resizeGL(int w, int h) +void PointView::resizeGL(int w, int h) { // Draw on full window glViewport(0, 0, w, h); @@ -79,69 +131,47 @@ void PointViewport::resizeGL(int w, int h) } -void PointViewport::paintGL() +void PointView::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Camera -> world transform. Need to do this here rather than in // GL_PROJECTION mode, otherwise the point size scaling won't work - // correctly. (Standard GL practise?) + // correctly. (Hmm, maybe this is standard GL practise?) glLoadIdentity(); glTranslatef(0, 0, m_dist); glRotatef(m_theta, 1, 0, 0); glRotatef(m_phi, 0, 1, 0); - glTranslatef(m_centre.x, m_centre.y, m_centre.z); - - glEnable(GL_MULTISAMPLE); + glTranslate(m_centre); + // Center on the point cloud + glTranslate(-m_cloudCenter); // Draw axes - glColor3f(1.0,0.0,1.0); glEnable(GL_LINE_SMOOTH); glLineWidth(1); - glColor3f(1.0, 0.7, 0.7); + glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(1, 0, 0); glEnd(); - glColor3f(0.7, 1.0, 0.7); + glColor3f(0.0, 1.0, 0.0); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(0, 1, 0); glEnd(); - glColor3f(0.7, 0.7, 1.0); + glColor3f(0.0, 0.0, 1.0); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(0, 0, 1); glEnd(); - // Generate points. TODO - store these as instance data - std::vector<float> ptData; - int ptStride; - cornellBoxPoints(ptData, ptStride, 5); - - // Draw points - glPointSize(10); - glColor3f(1,1,1); - // Set distance attenuation for points, following the usual 1/z law. - GLfloat attenParams[3] = {0, 0, 1}; - glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, attenParams); - glPointParameterf(GL_POINT_SIZE_MIN, 0); - glPointParameterf(GL_POINT_SIZE_MAX, 100); - // Scale down model - the Cornell box is measured in mm. - glTranslatef(-2.5, -2.5, -2.5); - glScalef(0.01, 0.01, 0.01); - // Draw all points at once using vertex arrays. - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, ptStride*sizeof(float), &ptData[0]); - glColorPointer(3, GL_FLOAT, ptStride*sizeof(float), &ptData[0]+7); - glDrawArrays(GL_POINTS, 0, ptData.size()/ptStride); - - glDisable(GL_MULTISAMPLE); + // Draw point cloud + if(m_points) + drawPoints(*m_points, m_visMode); } -void PointViewport::mousePressEvent(QMouseEvent* event) +void PointView::mousePressEvent(QMouseEvent* event) { m_zooming = event->button() == Qt::RightButton; m_prev_x = event->x(); @@ -149,7 +179,7 @@ void PointViewport::mousePressEvent(QMouseEvent* event) } -void PointViewport::mouseMoveEvent(QMouseEvent* event) +void PointView::mouseMoveEvent(QMouseEvent* event) { int dx = m_prev_x - event->x(); int dy = m_prev_y - event->y(); @@ -177,7 +207,7 @@ void PointViewport::mouseMoveEvent(QMouseEvent* event) } -void PointViewport::wheelEvent(QWheelEvent* event) +void PointView::wheelEvent(QWheelEvent* event) { double degrees = event->delta()/8.0; double steps = degrees / 15.0; @@ -186,11 +216,100 @@ void PointViewport::wheelEvent(QWheelEvent* event) } -void PointViewport::keyPressEvent(QKeyEvent *event) +void PointView::keyPressEvent(QKeyEvent *event) { - event->ignore(); + if(event->key() == Qt::Key_V) + { + m_visMode = (m_visMode == Vis_Points) ? Vis_Disks : Vis_Points; + initializeGL(); + repaint(); + } + else + event->ignore(); } +void PointView::drawPoints(const PointCloud& points, VisMode visMode) +{ + int ptStride = points.stride; + int npoints = points.data.size()/ptStride; + const float* ptData = &points.data[0]; + + switch(visMode) + { + case Vis_Points: + { + // Draw points + glPointSize(10); + glColor3f(1,1,1); + // Set distance attenuation for points, following the usual 1/z + // law. + GLfloat attenParams[3] = {0, 0, 1}; + glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, attenParams); + glPointParameterf(GL_POINT_SIZE_MIN, 0); + glPointParameterf(GL_POINT_SIZE_MAX, 100); + // Draw all points at once using vertex arrays. + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, ptStride*sizeof(float), ptData); + glColorPointer(3, GL_FLOAT, ptStride*sizeof(float), ptData+7); + glDrawArrays(GL_POINTS, 0, npoints); + } + break; + case Vis_Disks: + { + // Compile radius 1 disk primitive + V3f p0(0); + V3f t1(1,0,0); + V3f t2(0,1,0); + V3f diskNormal(0,0,1); + GLuint disk = glGenLists(1); + glNewList(disk, GL_COMPILE); + glBegin(GL_TRIANGLE_FAN); + const int nSegs = 20; + // Scale so that _min_ radius of polygon approx is 1. + float scale = 1/cos(M_PI/nSegs); + glVertex3f(0,0,0); + for(int i = 0; i <= nSegs; ++i) + { + float angle = 2*M_PI*float(i)/nSegs; + glVertex3f(scale*cos(angle), scale*sin(angle), 0); + } + glEnd(); + glEndList(); + // Draw points as disks. + // TODO: Doing this in immediate mode is really slow! Using + // vertex shaders would probably be a much better method, or + // perhaps just compile into a display list? + glEnable(GL_LIGHTING); + for(int i = 0; i < npoints; ++i) + { + const float* data = ptData + i*ptStride; + V3f p(data[0], data[1], data[2]); + V3f n(data[3], data[4], data[5]); + float r = data[6]; + glColor3f(data[7], data[8], data[9]); + glPushMatrix(); + // Translate disk to point location and scale + glTranslate(p); + glScalef(r,r,r); + // Transform the disk normal (0,0,1) into the correct normal + // direction for the current point. The appropriate transform + // is a rotation about a direction perpendicular to both + // normals: + V3f v = diskNormal % n; + // via the angle given by the dot product: + float angle = rad2deg(acosf(diskNormal^n)); + glRotatef(angle, v.x, v.y, v.z); + // Instance the disk + glCallList(disk); + glPopMatrix(); + } + glDeleteLists(disk, 1); + glDisable(GL_LIGHTING); + } + break; + } +} //------------------------------------------------------------------------------ int main(int argc, char *argv[]) @@ -203,7 +322,14 @@ int main(int argc, char *argv[]) f.setSampleBuffers(true); QGLFormat::setDefaultFormat(f); + // Generate points. + PointCloud points; + cornellBoxPoints(points.data, points.stride, 5); + // Translate the model + //glTranslatef(-2.5, -2.5, -2.5); + PointViewerWindow window; + window.pointView().setPoints(&points); window.show(); return app.exec(); diff --git a/libs/pointrender/ptview.h b/libs/pointrender/ptview.h index c7a8ed7..73bf4b0 100644 --- a/libs/pointrender/ptview.h +++ b/libs/pointrender/ptview.h @@ -43,14 +43,45 @@ using Imath::V3f; inline float deg2rad(float d) { return (M_PI/180) * d; } +/// TODO: Make into a class, etc. +struct PointCloud +{ + int stride; + std::vector<float> data; + + // Get centroid of point cloud. + V3f centroid() const + { + V3f sum(0); + for(std::vector<float>::const_iterator p = data.begin(); + p < data.end(); p += stride) + { + sum += V3f(p[0], p[1], p[2]); + } + return (1.0f/data.size()*stride) * sum; + } +}; + + //------------------------------------------------------------------------------ -/// OpenGL-based viewer widget for point clouds. -class PointViewport : public QGLWidget +/// OpenGL-based viewer widget for point clouds (or more precisely, clouds of +/// disk-like surface elements). +class PointView : public QGLWidget { Q_OBJECT public: - PointViewport(QWidget *parent = NULL); + /// Point (surface element) visualization mode + enum VisMode + { + Vis_Points, ///< Draw surfels using GL_POINTS + Vis_Disks ///< Draw surfels as disks + }; + + PointView(QWidget *parent = NULL); + + /// Set points to be rendered + void setPoints(const PointCloud* points); protected: // Qt OpenGL callbacks @@ -65,7 +96,10 @@ class PointViewport : public QGLWidget void keyPressEvent(QKeyEvent *event); private: - // Mouse-based view positioning + /// Draw point cloud using OpenGL + static void drawPoints(const PointCloud& points, VisMode visMode); + + /// Mouse-based camera positioning int m_prev_x; int m_prev_y; bool m_zooming; @@ -73,6 +107,11 @@ class PointViewport : public QGLWidget float m_phi; float m_dist; V3f m_centre; + /// Type of visualization + VisMode m_visMode; + /// Point cloud data + const PointCloud* m_points; + V3f m_cloudCenter; }; @@ -85,12 +124,14 @@ class PointViewerWindow : public QMainWindow public: PointViewerWindow() { - m_pointViewport = new PointViewport(); - m_pointViewport->setMinimumSize(QSize(640, 480)); - setCentralWidget(m_pointViewport); + m_pointView = new PointView(); + m_pointView->setMinimumSize(QSize(640, 480)); + setCentralWidget(m_pointView); setWindowTitle("Aqsis point cloud viewer"); } + PointView& pointView() { return *m_pointView; } + protected: void keyReleaseEvent(QKeyEvent* event) { @@ -99,7 +140,7 @@ class PointViewerWindow : public QMainWindow } private: - PointViewport* m_pointViewport; + PointView* m_pointView; }; ----------------------------------------------------------------------- Summary of changes: libs/pointrender/CMakeLists.txt | 9 ++- libs/pointrender/cornellbox.cpp | 39 ++++---- libs/pointrender/cornellbox.h | 18 +++- libs/pointrender/pointcloud.h | 145 +++++++++++++++++++++++++++ libs/pointrender/ptview.cpp | 204 +++++++++++++++++++++++++++++++-------- libs/pointrender/ptview.h | 40 ++++++-- 6 files changed, 382 insertions(+), 73 deletions(-) create mode 100644 libs/pointrender/pointcloud.h hooks/post-receive -- Aqsis Renderer |