├── Makefile ├── CMakeLists.txt ├── src ├── point.cpp ├── main.cpp ├── visiblepoint.cpp ├── visiblepoint.h ├── imagelist.h ├── CMakeLists.txt ├── photo.h ├── plane.h ├── point.h ├── bundleparser.h ├── commonplane.h ├── plane.cpp ├── mainwindow.h ├── triangulation.h ├── glwidget.h ├── imagelist.cpp ├── camera.cpp ├── camera.h ├── triangulation.cpp ├── photo.cpp ├── bundleparser.cpp ├── commonplane.cpp ├── mainwindow.cpp └── glwidget.cpp ├── cmake └── FindCGAL.cmake ├── README └── COPYING /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | mkdir -p build 3 | cd build && cmake .. && $(MAKE) 4 | cp build/src/pixelstruct . 5 | 6 | clean: 7 | rm -rf build pixelstruct 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(pixelstruct) 2 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 3 | SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 4 | #SET(CMAKE_VERBOSE_MAKEFILE ON) 5 | ADD_SUBDIRECTORY(src) 6 | -------------------------------------------------------------------------------- /src/point.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "point.h" 17 | 18 | Point::Point() { 19 | } 20 | 21 | Point::Point(const double x, const double y, const double z) 22 | : m_x(x), m_y(y), m_z(z) { 23 | } 24 | 25 | Point::~Point() { 26 | } 27 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include 17 | 18 | #include "mainwindow.h" 19 | 20 | int main(int argc, char *argv[]) { 21 | QApplication app(argc, argv); 22 | MainWindow window; 23 | window.show(); 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /src/visiblepoint.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "visiblepoint.h" 17 | 18 | VisiblePoint::VisiblePoint() { 19 | } 20 | 21 | VisiblePoint::VisiblePoint(const Point p, const QColor col) 22 | : Point(p), m_col(col) { 23 | } 24 | 25 | VisiblePoint::~VisiblePoint() { 26 | } 27 | -------------------------------------------------------------------------------- /src/visiblepoint.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef VISIBLEPOINT_H 17 | #define VISIBLEPOINT_H 18 | 19 | #include "point.h" 20 | 21 | #include 22 | 23 | class VisiblePoint : public Point { 24 | public: 25 | VisiblePoint(); 26 | VisiblePoint(const Point, const QColor); 27 | ~VisiblePoint(); 28 | QColor col() const {return m_col;} 29 | 30 | private: 31 | QColor m_col; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/imagelist.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef IMAGELIST_H 17 | #define IMAGELIST_H 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | class ImageList { 25 | public: 26 | ImageList(const char*, const char*, int); 27 | ImageList(QString, QString, int); 28 | ~ImageList(); 29 | 30 | const QImage loadImage(int) const; 31 | 32 | protected: 33 | void parse(const char*, const char*); 34 | 35 | private: 36 | int m_num_images; 37 | std::string* m_filenames; 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FIND_PACKAGE(Qt4 REQUIRED) 2 | FIND_PACKAGE(OpenGL REQUIRED) 3 | FIND_PACKAGE(CGAL REQUIRED) 4 | SET(QT_USE_QTOPENGL ON) 5 | INCLUDE(${QT_USE_FILE}) 6 | ADD_DEFINITIONS(${QT_DEFINITIONS} -Wall -O2) 7 | 8 | INCLUDE_DIRECTORIES( 9 | ${CMAKE_CURRENT_BINARY_DIR} 10 | ${QT_INCLUDE_DIR} 11 | # including the following directory causes conflicts with GMP headers 12 | #${CGAL_INCLUDE_DIR} 13 | ) 14 | ADD_DEFINITIONS(${CGAL_DEFINITIONS}) 15 | 16 | SET(SOURCES 17 | main.cpp 18 | glwidget.cpp 19 | camera.cpp 20 | point.cpp 21 | bundleparser.cpp 22 | visiblepoint.cpp 23 | mainwindow.cpp 24 | imagelist.cpp 25 | plane.cpp 26 | commonplane.cpp 27 | triangulation.cpp 28 | photo.cpp 29 | ) 30 | SET(HEADERS 31 | glwidget.h 32 | camera.h 33 | point.h 34 | bundleparser.h 35 | visiblepoint.h 36 | mainwindow.h 37 | imagelist.h 38 | plane.h 39 | commonplane.h 40 | triangulation.h 41 | photo.h 42 | ) 43 | 44 | QT4_AUTOMOC(${SOURCES}) 45 | 46 | ADD_EXECUTABLE(pixelstruct ${SOURCES} ${HEADERS}) 47 | TARGET_LINK_LIBRARIES(pixelstruct 48 | ${QT_QTCORE_LIBRARY} 49 | ${QT_QTGUI_LIBRARY} 50 | ${QT_QTMAIN_LIBRARY} 51 | ${QT_QTOPENGL_LIBRARY} 52 | ${OPENGL_gl_LIBRARY} 53 | ${OPENGL_glu_LIBRARY} 54 | ${CGAL_LIBRARIES} 55 | ) 56 | -------------------------------------------------------------------------------- /src/photo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef PHOTO_H 17 | #define PHOTO_H 18 | 19 | #include 20 | 21 | #include "triangulation.h" 22 | 23 | class Photo { 24 | public: 25 | Photo(const int, const int, const Camera *); 26 | 27 | void paintSimple() const; 28 | void paintPlane(const Plane &) const; 29 | void paintTriangulation() const; 30 | 31 | const Camera *camera() const {return m_camera;} 32 | 33 | GLuint texture; 34 | double opacity; 35 | 36 | private: 37 | const int m_width, m_height; 38 | const Camera *m_camera; 39 | Triangulation m_triangulation; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/plane.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef PLANE_H 17 | #define PLANE_H 18 | 19 | #include "point.h" 20 | 21 | class Plane { 22 | public: 23 | Plane(); 24 | Plane(double, double, double, double); 25 | ~Plane(); 26 | 27 | Plane transform(const double*) const; 28 | double distance(const Point&) const; 29 | double shortest_sqdist(const Point&) const; 30 | 31 | double a() const {return m_a;} 32 | double b() const {return m_b;} 33 | double c() const {return m_c;} 34 | double d() const {return m_d;} 35 | 36 | bool is_valid() const {return !(m_a == 0 && m_b == 0 && m_c == 0);} 37 | 38 | protected: 39 | double m_a, m_b, m_c, m_d; // m_a*x + m_b*y + m_c*z = m_d 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/point.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef POINT_H 17 | #define POINT_H 18 | 19 | #include 20 | 21 | class Point { 22 | public: 23 | Point(); 24 | Point(const double, const double, const double); 25 | ~Point(); 26 | double x() const {return m_x;} 27 | double y() const {return m_y;} 28 | double z() const {return m_z;} 29 | double sqdist() const { // square of the distance from the origin 30 | return m_x*m_x + m_y*m_y + m_z*m_z; 31 | } 32 | double dist() const { // distance from the origin 33 | return sqrt(sqdist()); 34 | } 35 | 36 | bool operator<(const Point &p) const { 37 | return sqdist() < p.sqdist(); 38 | } 39 | 40 | private: 41 | double m_x, m_y, m_z; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/bundleparser.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef BUNDLEPARSER_H 17 | #define BUNDLEPARSER_H 18 | 19 | #include "camera.h" 20 | #include "visiblepoint.h" 21 | 22 | #include 23 | 24 | class BundleParser { 25 | public: 26 | BundleParser(const char* file); 27 | BundleParser(QString file); 28 | ~BundleParser(); 29 | const Camera* cameras() const {return m_cameras;} 30 | const VisiblePoint* points() const {return m_points;} 31 | int num_cameras() const {return m_num_cameras;} 32 | int num_points() const {return m_num_points;} 33 | 34 | protected: 35 | void parse(const char* file); 36 | 37 | private: 38 | Camera* m_cameras; 39 | VisiblePoint* m_points; 40 | int m_num_cameras, m_num_points; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/commonplane.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef COMMONPLANE_H 17 | #define COMMONPLANE_H 18 | 19 | #include "plane.h" 20 | 21 | #include "camera.h" 22 | #include "visiblepoint.h" 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | class CommonPlane : public Plane { 30 | public: 31 | typedef CGAL::Cartesian::Point_3 CGAL_Point; 32 | 33 | CommonPlane(); 34 | CommonPlane(const Camera&, const Camera&); 35 | CommonPlane(const std::vector&); 36 | ~CommonPlane(); 37 | 38 | double fitting_quality() {return m_fitting_quality;} 39 | 40 | protected: 41 | void best_fit_plane(const std::vector&); 42 | void ransac(std::vector); 43 | 44 | private: 45 | double m_fitting_quality; 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /cmake/FindCGAL.cmake: -------------------------------------------------------------------------------- 1 | # - Find CGAL 2 | # adapted from 3 | # 4 | # Find the CGAL includes and client library 5 | # This module defines 6 | # CGAL_DEFINITIONS: compiler flags for compiling with CGAL 7 | # CGAL_INCLUDE_DIR: where to find CGAL.h 8 | # CGAL_LIBRARIES: the libraries needed to use CGAL 9 | # CGAL_FOUND: if false, do not try to use CGAL 10 | 11 | SET(CGAL_DEFINITIONS -frounding-math) 12 | 13 | IF(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 14 | SET(CGAL_FOUND TRUE) 15 | ELSE(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 16 | FIND_PATH(CGAL_INCLUDE_DIR basic.h 17 | /usr/include/CGAL 18 | /usr/local/include/CGAL 19 | $ENV{ProgramFiles}/CGAL/*/include/CGAL 20 | $ENV{SystemDrive}/CGAL/*/include/CGAL 21 | ) 22 | FIND_LIBRARY(CGAL_LIBRARIES NAMES CGAL libCGAL 23 | PATHS 24 | /usr/lib 25 | /usr/local/lib 26 | /usr/lib/CGAL 27 | /usr/lib64 28 | /usr/local/lib64 29 | /usr/lib64/CGAL 30 | $ENV{ProgramFiles}/CGAL/*/lib/ms 31 | $ENV{SystemDrive}/CGAL/*/lib/ms 32 | ) 33 | 34 | IF(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 35 | SET(CGAL_FOUND TRUE) 36 | MESSAGE(STATUS "Found CGAL: ${CGAL_INCLUDE_DIR}, ${CGAL_LIBRARIES}") 37 | ELSE(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 38 | SET(CGAL_FOUND FALSE) 39 | MESSAGE(STATUS "CGAL not found.") 40 | ENDIF(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 41 | 42 | MARK_AS_ADVANCED(CGAL_INCLUDE_DIR CGAL_LIBRARIES) 43 | ENDIF(CGAL_INCLUDE_DIR AND CGAL_LIBRARIES) 44 | -------------------------------------------------------------------------------- /src/plane.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "plane.h" 17 | 18 | Plane::Plane() { 19 | } 20 | 21 | Plane::Plane(double a, double b, double c, double d) 22 | : m_a(a), m_b(b), m_c(c), m_d(d) { 23 | } 24 | 25 | Plane::~Plane() { 26 | } 27 | 28 | Plane Plane::transform(const double* m) const { 29 | return Plane( 30 | m_a*m[ 0], 31 | m_b*m[ 5], 32 | m_c*m[10], 33 | m_d - m_a*m[12] - m_b*m[13] - m_c*m[14] 34 | ); 35 | } 36 | 37 | double Plane::distance(const Point& p) const { 38 | /// For a line that begins at the origin, passes through Point p, and ends 39 | /// at this Plane. The length of the line is equal to distance(p) times the 40 | /// distance between p and the origin. 41 | return m_d / (m_a*p.x() + m_b*p.y() + m_c*p.z()); 42 | } 43 | 44 | double Plane::shortest_sqdist(const Point& p) const { 45 | /// square of shortest distance between this Plane and Point p 46 | double n = m_a*p.x() + m_b*p.y() + m_c*p.z() - m_d; 47 | return (n*n) / (m_a*m_a + m_b*m_b + m_c*m_c); 48 | } 49 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef MAINWINDOW_H 17 | #define MAINWINDOW_H 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "glwidget.h" 24 | #include "bundleparser.h" 25 | #include "imagelist.h" 26 | 27 | class MainWindow : public QMainWindow { 28 | Q_OBJECT 29 | 30 | public: 31 | MainWindow(); 32 | ~MainWindow(); 33 | 34 | void openImageDirectory(const QString& image_directory); 35 | 36 | QSize minimumSizeHint() const {return QSize(50, 50);} 37 | QSize sizeHint() const {return QSize(800, 600);} 38 | 39 | protected: 40 | void createActions(); 41 | void createMenus(); 42 | 43 | protected Q_SLOTS: 44 | void openImageDirectoryDialog(); 45 | void setTransMode(QAction*); 46 | void about(); 47 | 48 | private: 49 | GLWidget *m_glwidget; 50 | BundleParser *m_bundleparser; 51 | ImageList *m_imagelist; 52 | 53 | QAction *m_openAct, *m_exitAct, *m_aboutAct, *m_aboutQtAct, 54 | *m_transmode_none, *m_transmode_0, *m_transmode_1, *m_transmode_2; 55 | QActionGroup *m_transmode_group; 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/triangulation.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef TRIANGULATION_H 17 | #define TRIANGULATION_H 18 | 19 | #include "camera.h" 20 | #include "visiblepoint.h" 21 | #include "commonplane.h" 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | class Triangulation { 30 | public: 31 | typedef CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 32 | CGAL_Point; 33 | typedef CGAL::Delaunay_triangulation_2< 34 | CGAL::Triangulation_euclidean_traits_xy_3< 35 | CGAL::Exact_predicates_inexact_constructions_kernel> > 36 | DelaunayTriangulation; 37 | 38 | Triangulation(); 39 | Triangulation(const Camera &); 40 | ~Triangulation(); 41 | 42 | typedef DelaunayTriangulation::Finite_faces_iterator face_iterator; 43 | face_iterator faces_begin() const {return m_dt.finite_faces_begin();} 44 | face_iterator faces_end() const {return m_dt.finite_faces_end();} 45 | 46 | int num_vertices() const {return m_dt.number_of_vertices();} 47 | 48 | void insert_point(double x, double y, double z); 49 | Point get_point(const face_iterator& f, int i) const; 50 | void add_image_corners(double maxx, double maxy); 51 | 52 | private: 53 | DelaunayTriangulation m_dt; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/glwidget.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef GLWIDGET_H 17 | #define GLWIDGET_H 18 | 19 | #include 20 | 21 | #include "bundleparser.h" 22 | #include "imagelist.h" 23 | #include "commonplane.h" 24 | #include "triangulation.h" 25 | #include "photo.h" 26 | 27 | class GLWidget : public QGLWidget { 28 | Q_OBJECT 29 | 30 | public: 31 | GLWidget(BundleParser*, ImageList*, QWidget* = 0); 32 | ~GLWidget(); 33 | 34 | QSize minimumSizeHint() const {return QSize(50, 50);} 35 | 36 | void setTransMode(int transmode); 37 | 38 | protected: 39 | void initializeGL(); 40 | void paintImage(const Photo *); 41 | void paintGL(); 42 | void resizeGL(int width, int height); 43 | void mousePressEvent(QMouseEvent* event); 44 | void mouseMoveEvent(QMouseEvent* event); 45 | void mouseReleaseEvent(QMouseEvent* event); 46 | void keyPressEvent(QKeyEvent* event); 47 | void keyReleaseEvent(QKeyEvent* event); 48 | void focusInEvent(QFocusEvent* event); 49 | void focusOutEvent(QFocusEvent* event); 50 | void gotoCamera(int); 51 | void gotoNextCamera(); 52 | void gotoDirection(int); 53 | 54 | private: 55 | void handleGLError(int); 56 | 57 | GLuint m_pointcloud; 58 | BundleParser* m_parser; 59 | ImageList* m_imagelist; 60 | int m_transmode; 61 | Photo *m_cur_image; 62 | Photo *m_prev_image; 63 | CommonPlane m_common_plane; 64 | GLint texSize; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/imagelist.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "imagelist.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | using std::string; 23 | using std::cerr; 24 | using std::endl; 25 | using std::getline; 26 | using std::ifstream; 27 | 28 | ImageList::ImageList(const char* file, const char* directory, int num_images) 29 | : m_num_images(num_images) { 30 | m_filenames = new string[m_num_images]; 31 | parse(file, directory); 32 | } 33 | 34 | ImageList::ImageList(QString file, QString directory, int num_images) 35 | : m_num_images(num_images) { 36 | m_filenames = new string[m_num_images]; 37 | parse(file.toStdString().c_str(), directory.toStdString().c_str()); 38 | } 39 | 40 | 41 | ImageList::~ImageList() { 42 | } 43 | 44 | void ImageList::parse(const char* file, const char* directory) { 45 | ifstream fin(file); 46 | if(!fin) { 47 | cerr << "[ImageList::parse] Unable to open file " << file << endl; 48 | exit(1); 49 | } else { 50 | cerr << "[ImageList::parse] Successfully opened file " << file << endl; 51 | } 52 | 53 | for(int i = 0; i < m_num_images; i++) { 54 | fin >> m_filenames[i]; 55 | if(m_filenames[i][0] != '/') // relative path 56 | m_filenames[i] = string(directory) + "/" + m_filenames[i]; 57 | 58 | string image_args; 59 | getline(fin, image_args); 60 | } 61 | } 62 | 63 | const QImage ImageList::loadImage(int index) const { 64 | return QImage(m_filenames[index].c_str()); 65 | } 66 | -------------------------------------------------------------------------------- /src/camera.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "camera.h" 17 | 18 | const double IDENTITY_MATRIX_4[16] = { 19 | 1.0, 0.0, 0.0, 0.0, 20 | 0.0, 1.0, 0.0, 0.0, 21 | 0.0, 0.0, 1.0, 0.0, 22 | 0.0, 0.0, 0.0, 1.0 23 | }; 24 | const Camera Camera::Identity(-1, 1.0, 1.0, 1.0, IDENTITY_MATRIX_4); 25 | 26 | Camera::Camera() { 27 | } 28 | 29 | Camera::Camera(const int index, const double f, const double k1, 30 | const double k2, const double* m1) 31 | : m_index(index), m_f(f), m_k1(k1), m_k2(k2), m_matrix_w2l(m1) { 32 | m_matrix_l2w = new double[16]; 33 | double* m2 = m_matrix_l2w; 34 | 35 | /** 36 | * m2 is the inverse of m1 37 | * therefore the rotation block of m2 is equal to the transpose of its 38 | * counterpart in m1, and the translation block of m2 is equal to the 39 | * negative of the rotation block of m2 multiplied by the translation block 40 | * of m1 the translation block of m2 is equal to the coordinates of the 41 | * camera in 3D space 42 | */ 43 | m2[0] = m1[0]; m2[4] = m1[1]; m2[ 8] = m1[ 2]; m2[12] = 44 | -(m2[0]*m1[12] + m2[4]*m1[13] + m2[ 8]*m1[14]); 45 | m2[1] = m1[4]; m2[5] = m1[5]; m2[ 9] = m1[ 6]; m2[13] = 46 | -(m2[1]*m1[12] + m2[5]*m1[13] + m2[ 9]*m1[14]); 47 | m2[2] = m1[8]; m2[6] = m1[9]; m2[10] = m1[10]; m2[14] = 48 | -(m2[2]*m1[12] + m2[6]*m1[13] + m2[10]*m1[14]); 49 | m2[3] = 0.0; m2[7] = 0.0; m2[11] = 0.0; m2[15] = 1.0; 50 | } 51 | 52 | 53 | Camera::~Camera() { 54 | } 55 | 56 | Point Camera::point_transform(const Point p, const double* m) const { 57 | double x, y, z; 58 | 59 | x = m[0]*p.x() + m[4]*p.y() + m[ 8]*p.z() + m[12]; 60 | y = m[1]*p.x() + m[5]*p.y() + m[ 9]*p.z() + m[13]; 61 | z = m[2]*p.x() + m[6]*p.y() + m[10]*p.z() + m[14]; 62 | 63 | return Point(x, y, z); 64 | } 65 | 66 | void Camera::add_visible_point(Point p) { 67 | m_visible_points.push_back(p); 68 | } 69 | -------------------------------------------------------------------------------- /src/camera.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #ifndef CAMERA_H 17 | #define CAMERA_H 18 | 19 | #include "point.h" 20 | 21 | #include 22 | 23 | class Camera { 24 | public: 25 | Camera(); 26 | Camera(const int, const double, const double, const double, const double*); 27 | ~Camera(); 28 | 29 | void add_visible_point(Point); 30 | 31 | int index() const {return m_index;} 32 | const double* matrix_w2l() const {return m_matrix_w2l;} 33 | const double* matrix_l2w() const {return m_matrix_l2w;} 34 | double focal_length() const {return m_f;} 35 | Point unit_x() const { // first column of m_matrix_l2w 36 | return Point(m_matrix_l2w[ 0], m_matrix_l2w[ 1], m_matrix_l2w[ 2]);} 37 | Point unit_y() const { // second column of m_matrix_l2w 38 | return Point(m_matrix_l2w[ 4], m_matrix_l2w[ 5], m_matrix_l2w[ 6]);} 39 | Point unit_z() const { // third column of m_matrix_l2w 40 | return Point(m_matrix_l2w[ 8], m_matrix_l2w[ 9], m_matrix_l2w[10]);} 41 | Point pos() const { // fourth column of m_matrix_l2w 42 | return Point(m_matrix_l2w[12], m_matrix_l2w[13], m_matrix_l2w[14]);} 43 | Point point_w2l(const Point p) const { 44 | return point_transform(p, m_matrix_w2l);} 45 | Point point_l2w(const Point p) const { 46 | return point_transform(p, m_matrix_l2w);} 47 | const std::vector &visible_points() const {return m_visible_points;} 48 | 49 | static const Camera Identity; 50 | 51 | protected: 52 | Point point_transform(const Point, const double*) const; 53 | 54 | private: 55 | int m_index; 56 | double m_f; // focal length 57 | double m_k1, m_k2; // radial distortion coefficients 58 | // transformation matrix: world coords to local coords 59 | // (for transforming the view) 60 | const double* m_matrix_w2l; 61 | // transformation matrix: local coords to world coords 62 | // (for transforming objects) 63 | double* m_matrix_l2w; 64 | std::vector m_visible_points; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/triangulation.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "triangulation.h" 17 | 18 | using std::vector; 19 | using std::cerr; 20 | using std::endl; 21 | 22 | const unsigned int MAX_POINTS = 300; 23 | 24 | Triangulation::Triangulation() { 25 | } 26 | 27 | Triangulation::Triangulation(const Camera &c) { 28 | vector visible_points = c.visible_points(); 29 | if(visible_points.size() > MAX_POINTS) 30 | visible_points.resize(MAX_POINTS); 31 | for(vector::const_iterator i = visible_points.begin(); 32 | i != visible_points.end(); i++) { 33 | const Point& p = c.point_w2l(*i); 34 | // divide by z to correct for perspective 35 | insert_point(p.x()/p.z(), p.y()/p.z(), p.z()); 36 | } 37 | } 38 | 39 | Triangulation::~Triangulation() { 40 | m_dt.clear(); 41 | } 42 | 43 | void Triangulation::insert_point(double x, double y, double z) { 44 | //cerr << "[Triangulation::insert_point] Inserting point (" 45 | // << x << "," << y << "," << z << ")" << endl; 46 | try { 47 | m_dt.insert(CGAL_Point(x, y, z)); 48 | } catch(const std::logic_error& e) { 49 | // this seems to be (maybe) a bug in CGAL which throws an error when 50 | // the same point is inserted twice, even though the documentation says 51 | // that the library handles such situations 52 | cerr << "[Triangulation::insert_point] caught std::logic_error " 53 | "from DelaunayTriangulation::insert" << endl; 54 | } 55 | } 56 | 57 | Point Triangulation::get_point(const face_iterator& f, int i) const { 58 | const DelaunayTriangulation::Point p = f->vertex(i)->point(); 59 | return Point(p.x()*p.z(), p.y()*p.z(), p.z()); 60 | } 61 | 62 | void Triangulation::add_image_corners(double maxx, double maxy) { 63 | double average_depth = 0; 64 | int num_points = 0; 65 | 66 | DelaunayTriangulation::Vertex_circulator vc = 67 | m_dt.incident_vertices(m_dt.infinite_vertex()), vc_init = vc; 68 | if(vc != 0) do { // traverse the convex hull 69 | average_depth += vc->point().z(); 70 | num_points++; 71 | } while(++vc != vc_init); 72 | average_depth /= num_points; 73 | 74 | insert_point(+maxx,+maxy,average_depth); 75 | insert_point(-maxx,+maxy,average_depth); 76 | insert_point(-maxx,-maxy,average_depth); 77 | insert_point(+maxx,-maxy,average_depth); 78 | } 79 | -------------------------------------------------------------------------------- /src/photo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "photo.h" 17 | 18 | using std::cerr; 19 | using std::endl; 20 | 21 | Photo::Photo(const int width, const int height, const Camera *camera) 22 | : m_width(width), m_height(height), m_camera(camera) { 23 | cerr << "Generating triangulation" << endl; 24 | m_triangulation = Triangulation(*m_camera); 25 | m_triangulation.add_image_corners( 26 | 0.5 * m_width / m_camera->focal_length(), 27 | 0.5 * m_height / m_camera->focal_length()); 28 | } 29 | 30 | void Photo::paintSimple() const { 31 | double maxx = 0.5 * m_width / m_camera->focal_length(); 32 | double maxy = 0.5 * m_height / m_camera->focal_length(); 33 | glBegin(GL_QUADS); 34 | glTexCoord2d(0.0,0.0); glVertex3d(-maxx,-maxy,-1.0); 35 | glTexCoord2d(1.0,0.0); glVertex3d(+maxx,-maxy,-1.0); 36 | glTexCoord2d(1.0,1.0); glVertex3d(+maxx,+maxy,-1.0); 37 | glTexCoord2d(0.0,1.0); glVertex3d(-maxx,+maxy,-1.0); 38 | glEnd(); 39 | } 40 | 41 | void Photo::paintPlane(const Plane &local_plane) const { 42 | double maxx = 0.5 * m_width / m_camera->focal_length(); 43 | double maxy = 0.5 * m_height / m_camera->focal_length(); 44 | double d0 = local_plane.distance(Point(-maxx,-maxy,-1.0)); 45 | double d1 = local_plane.distance(Point(+maxx,-maxy,-1.0)); 46 | double d2 = local_plane.distance(Point(+maxx,+maxy,-1.0)); 47 | double d3 = local_plane.distance(Point(-maxx,+maxy,-1.0)); 48 | 49 | if(!local_plane.is_valid() || 50 | d0 <= 0.0 || d1 <= 0.0 || d2 <= 0.0 || d3 <= 0.0) { 51 | // if part or all of the image projected onto the common plane lies 52 | // behind the camera, then revert to simple image plane 53 | paintSimple(); 54 | return; 55 | } 56 | 57 | glBegin(GL_QUADS); 58 | glTexCoord4d(0.0,0.0,0.0,d0); glVertex3d(d0*-maxx,d0*-maxy,-d0); 59 | glTexCoord4d( d1,0.0,0.0,d1); glVertex3d(d1*+maxx,d1*-maxy,-d1); 60 | glTexCoord4d( d2, d2,0.0,d2); glVertex3d(d2*+maxx,d2*+maxy,-d2); 61 | glTexCoord4d(0.0, d3,0.0,d3); glVertex3d(d3*-maxx,d3*+maxy,-d3); 62 | glEnd(); 63 | } 64 | 65 | void Photo::paintTriangulation() const { 66 | double xrange = m_width / m_camera->focal_length(); 67 | double yrange = m_height / m_camera->focal_length(); 68 | glBegin(GL_TRIANGLES); 69 | for(Triangulation::face_iterator f = m_triangulation.faces_begin(); 70 | f != m_triangulation.faces_end(); f++) { 71 | for(int i = 0; i < 3; i++) { 72 | Point p = m_triangulation.get_point(f,i); 73 | double d = p.dist(); 74 | double tx = (p.x() / -p.z()) / xrange + 0.5; 75 | double ty = (p.y() / -p.z()) / yrange + 0.5; 76 | glTexCoord4d(tx*d,ty*d,0.0,d); 77 | glVertex3d(p.x(), p.y(), p.z()); 78 | } 79 | } 80 | glEnd(); 81 | } 82 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | PixelStruct[1] is an opensource tool for visualizing 3D scenes reconstructed 3 | from photographs. It uses the opensource structure-from-motion system 4 | Bundler[2], which is based on the same research as Microsoft Live Labs 5 | Photosynth[3]. 6 | 7 | HOW TO COMPILE 8 | PixelStruct requires the following libraries: 9 | - Qt4 (with OpenGL support) 10 | - CGAL 11 | 12 | You will also need to install CMake in order to build PixelStruct. 13 | 14 | All of the above can be installed in Ubuntu (and likely other Debian-based 15 | distributions) by running 16 | sudo aptitude install libqt4-dev libcgal-dev cmake 17 | 18 | Once you have installed these, compile the program by running `make` in the 19 | project root directory. 20 | 21 | This will create a binary called 'pixelstruct' in the current directory. 22 | You can either copy this executable into your PATH for system-wide access, or 23 | just run it immediately by either calling `./pixelstruct` in a terminal or by 24 | opening it with your file browser. 25 | 26 | USAGE 27 | PixelStruct requires Bundler, which can be downloaded from [2]. First, you need 28 | to manually run Bundler on a directory of images as described in the README.txt 29 | file contained in the Bundler distribution. Once Bundler has completed 30 | processing the images, the image set can be loaded into PixelStruct. 31 | 32 | If you do not want to manually run Bundler, and would rather view a 33 | pre-processed dataset, you have two options: 34 | - download the small (3.6MB) Kermit example from [4], untar it, and open the 35 | kermit/ directory in PixelStruct 36 | - download the very large (1.8GB) Notre Dame example from [5], unzip it, create 37 | a bundle/ directory inside the NotreDame/ directory, copy/move notredame.out 38 | to bundle/bundle.out, and open the NotreDame/ directory in PixelStruct 39 | 40 | To view a processed dataset, launch PixelStruct as described above, and go to 41 | "File>Open image directory". Navigate into the image directory you ran Bundler 42 | on, and hit "Choose"/"Open". Alternatively you can specify the image directory 43 | as a command-line argument when launching PixelStruct. The 3D point cloud will 44 | be loaded into the window, and once the viewer has focus (you may have to click 45 | on it for this), the camera will focus on the first image. 46 | 47 | You can now hit your Return key to move to the next image, or use your arrow 48 | keys to move to another image in the chosen direction. Pressing Page Up and 49 | Page Down will attempt to move the camera closer to and further away from the 50 | photographed object respectively. 51 | 52 | The View menu allows you to choose between several transition modes, as 53 | described in section 5.3 of [6]. 54 | 55 | QPL-GPL INCOMPATIBILITY NOTICE 56 | As portions of CGAL are licensed under the QPL[7] which is incompatible with 57 | the GPL (see the QPL secction of [8]), the following notice is required: 58 | As a special exception, you have permission to link this program 59 | with the CGAL library and distribute executables, as long as you 60 | follow the requirements of the GNU GPL in regard to all of the 61 | software in the executable aside from CGAL. 62 | 63 | [1] http://da.vidr.cc/projects/pixelstruct/ 64 | [2] http://phototour.cs.washington.edu/bundler/ 65 | [3] http://photosynth.net/ 66 | [4] http://pixelstruct.googlecode.com/files/kermit-example-bundler0.3.tar.gz 67 | [5] http://phototour.cs.washington.edu/datasets/NotreDame.zip 68 | [6] http://phototour.cs.washington.edu/Photo_Tourism.pdf 69 | [7] http://doc.trolltech.com/4.3/qpl.html 70 | [8] http://www.fsf.org/licensing/licenses/index_html 71 | -------------------------------------------------------------------------------- /src/bundleparser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "bundleparser.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | using std::cerr; 25 | using std::endl; 26 | using std::ifstream; 27 | using std::string; 28 | using std::getline; 29 | 30 | BundleParser::BundleParser(const char* file) { 31 | parse(file); 32 | } 33 | 34 | BundleParser::BundleParser(QString file) { 35 | parse(file.toStdString().c_str()); 36 | } 37 | 38 | 39 | BundleParser::~BundleParser() { 40 | delete [] m_cameras; 41 | delete [] m_points; 42 | } 43 | 44 | void BundleParser::parse(const char* file) { 45 | ifstream fin(file); 46 | if(!fin) { 47 | cerr << "[BundleParser::parse] Unable to open file " << file << endl; 48 | exit(1); 49 | } else { 50 | cerr << "[BundleParser::parse] Successfully opened file " << file 51 | << endl; 52 | } 53 | 54 | string header; 55 | getline(fin, header); 56 | cerr << "[BundleParser::parse] Bundle header: " << header << endl; 57 | 58 | fin >> m_num_cameras >> m_num_points; 59 | 60 | cerr << "[BundleParser::parse] " << m_num_cameras << " cameras" << endl; 61 | cerr << "[BundleParser::parse] " << m_num_points << " points" << endl; 62 | 63 | m_cameras = new Camera[m_num_cameras]; 64 | for(int i = 0; i < m_num_cameras; i++) { 65 | double f, k1, k2; 66 | fin >> f >> k1 >> k2; 67 | 68 | double* m = new double[16]; 69 | 70 | /// given rotation matrix R and translation vector t, 71 | /// column-major matrix m is equal to: 72 | /// [ R11 R12 R13 t.x ] 73 | /// | R21 R22 R23 t.y | 74 | /// | R31 R32 R33 t.z | 75 | /// [ 0.0 0.0 0.0 1.0 ] 76 | 77 | fin >> m[0] >> m[4] >> m[ 8] 78 | >> m[1] >> m[5] >> m[ 9] 79 | >> m[2] >> m[6] >> m[10]; 80 | m[3] = 0.0; m[7] = 0.0; m[11] = 0.0; 81 | 82 | fin >> m[12] 83 | >> m[13] 84 | >> m[14]; 85 | m[15] = 1.0; 86 | 87 | Camera camera(i, f, k1, k2, m); 88 | m_cameras[i] = camera; 89 | } 90 | 91 | cerr << "[BundleParser::parse] Finished loading cameras" << endl; 92 | 93 | m_points = new VisiblePoint[m_num_points]; 94 | for(int i = 0; i < m_num_points; i++) { 95 | double pos_x, pos_y, pos_z; 96 | fin >> pos_x >> pos_y >> pos_z; 97 | 98 | int col_r, col_g, col_b; 99 | fin >> col_r >> col_g >> col_b; 100 | 101 | int num_views; 102 | fin >> num_views; 103 | 104 | VisiblePoint point(Point(pos_x, pos_y, pos_z), 105 | QColor(col_r, col_g, col_b)); 106 | m_points[i] = point; 107 | 108 | for(int j = 0; j < num_views; j++) { 109 | int camera, key; 110 | float px, py; 111 | fin >> camera >> key >> px >> py; 112 | // TODO store this information somewhere 113 | m_cameras[camera].add_visible_point(point); 114 | } 115 | } 116 | 117 | cerr << "[BundleParser::parse] Finished loading points" << endl; 118 | 119 | fin.close(); 120 | } 121 | -------------------------------------------------------------------------------- /src/commonplane.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "commonplane.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | using std::vector; 24 | using std::cerr; 25 | using std::endl; 26 | 27 | const unsigned int MIN_POINTS = 3; 28 | const unsigned int MAX_POINTS = 300; 29 | const int MAX_ITERATIONS = 5000; 30 | const double ERROR_THRESHOLD = 0.1; 31 | 32 | CommonPlane::CommonPlane() { 33 | } 34 | 35 | CommonPlane::CommonPlane(const Camera& c1, const Camera& c2) { 36 | vector intersection(c1.visible_points().size() 37 | + c2.visible_points().size()); 38 | vector::const_iterator intersection_end = 39 | set_intersection(c1.visible_points().begin(), 40 | c1.visible_points().end(), 41 | c2.visible_points().begin(), 42 | c2.visible_points().end(), 43 | intersection.begin()); 44 | 45 | int num_elements = intersection_end - intersection.begin(); 46 | if(num_elements > 0) { 47 | vector cgal_points; 48 | for(vector::const_iterator i = intersection.begin(); 49 | i != intersection_end; i++) 50 | cgal_points.push_back(CGAL_Point( 51 | i->x(), i->y(), i->z())); 52 | ransac(cgal_points); 53 | } 54 | } 55 | 56 | CommonPlane::CommonPlane(const vector& cgal_points) { 57 | best_fit_plane(cgal_points); 58 | } 59 | 60 | CommonPlane::~CommonPlane() { 61 | } 62 | 63 | void CommonPlane::best_fit_plane(const vector& cgal_points) { 64 | CGAL::Cartesian::Plane_3 plane; 65 | CGAL_Point centroid; 66 | m_fitting_quality = linear_least_squares_fitting_3( 67 | cgal_points.begin(), cgal_points.end(), plane, centroid 68 | #if CGAL_VERSION_NR >= CGAL_VERSION_NUMBER(3,4,0) 69 | , CGAL::Dimension_tag<0>() 70 | #endif 71 | ); 72 | m_a = plane.a(); m_b = plane.b(); m_c = plane.c(); m_d = -plane.d(); 73 | } 74 | 75 | void CommonPlane::ransac(vector cgal_points) { 76 | srand(time(NULL)); 77 | 78 | const unsigned int num_points = cgal_points.size(); 79 | if(num_points <= MIN_POINTS) 80 | return; 81 | else if(num_points > MAX_POINTS) 82 | cgal_points.resize(MAX_POINTS); 83 | 84 | const unsigned int REQD_POINTS = 0.2*num_points; 85 | 86 | double m_fitting_quality = 0.0; 87 | 88 | for(int i = 0; i < MAX_ITERATIONS; i++) { 89 | //if(i % 100 == 0 && i > 0) 90 | // cerr << i << " iterations" << endl; 91 | 92 | // MIN_POINTS random elements from cgal_points 93 | vector maybe_inliers; 94 | while(maybe_inliers.size() < MIN_POINTS) { 95 | CGAL_Point p = cgal_points[rand() % num_points]; 96 | if(find(maybe_inliers.begin(), maybe_inliers.end(), p) 97 | == maybe_inliers.end()) // unique element 98 | maybe_inliers.push_back(p); 99 | } 100 | 101 | CommonPlane maybe_model(maybe_inliers); 102 | vector consensus_set = maybe_inliers; 103 | 104 | for(vector::const_iterator p = cgal_points.begin(); 105 | p != cgal_points.end(); p++) { 106 | if(find(consensus_set.begin(), consensus_set.end(), *p) 107 | != consensus_set.end()) // *p is already in consensus_set 108 | continue; 109 | double error = maybe_model.shortest_sqdist(Point( 110 | p->x(), p->y(), p->z())); 111 | if(error < ERROR_THRESHOLD) 112 | consensus_set.push_back(*p); 113 | } 114 | 115 | if(consensus_set.size() >= REQD_POINTS) { 116 | CommonPlane better_model(consensus_set); 117 | double this_quality = better_model.fitting_quality(); 118 | if(this_quality > m_fitting_quality) { 119 | m_fitting_quality = this_quality; 120 | m_a = better_model.a(); 121 | m_b = better_model.b(); 122 | m_c = better_model.c(); 123 | m_d = better_model.d(); 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "mainwindow.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using std::cerr; 25 | using std::endl; 26 | 27 | MainWindow::MainWindow() 28 | : m_bundleparser(0), m_imagelist(0) { 29 | setWindowTitle(tr("PixelStruct")); 30 | resize(sizeHint()); 31 | createActions(); 32 | createMenus(); 33 | 34 | m_transmode_2->setChecked(true); 35 | 36 | if(qApp->arguments().size() > 1) 37 | openImageDirectory(qApp->arguments().at(1)); 38 | } 39 | 40 | MainWindow::~MainWindow() { 41 | } 42 | 43 | void MainWindow::openImageDirectory(const QString& image_directory) { 44 | cerr << "[MainWindow::openImageDirectory] opening " 45 | << image_directory.toStdString() << endl; 46 | 47 | if(m_bundleparser != 0) delete m_bundleparser; 48 | if(m_imagelist != 0) delete m_imagelist; 49 | 50 | m_bundleparser = new BundleParser(image_directory + "/bundle/bundle.out"); 51 | m_imagelist = new ImageList(image_directory + "/list.txt", image_directory, 52 | m_bundleparser->num_cameras()); 53 | 54 | m_glwidget = new GLWidget(m_bundleparser, m_imagelist, this); 55 | setCentralWidget(m_glwidget); 56 | setTransMode(m_transmode_group->checkedAction()); 57 | m_glwidget->show(); 58 | m_glwidget->setFocus(); 59 | } 60 | 61 | void MainWindow::createActions() { 62 | m_openAct = new QAction(tr("&Open image directory"), this); 63 | m_openAct->setShortcut(tr("Ctrl+O")); 64 | connect(m_openAct, SIGNAL(triggered()), 65 | this, SLOT(openImageDirectoryDialog())); 66 | 67 | m_exitAct = new QAction(tr("&Quit"), this); 68 | m_exitAct->setShortcut(Qt::Key_Escape); 69 | connect(m_exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); 70 | 71 | m_transmode_group = new QActionGroup(this); 72 | m_transmode_none = new QAction(tr("Do&n't display images"), this); 73 | m_transmode_none->setCheckable(true); 74 | m_transmode_group->addAction(m_transmode_none); 75 | m_transmode_0 = new QAction(tr("&Simple transitions"), this); 76 | m_transmode_0->setCheckable(true); 77 | m_transmode_group->addAction(m_transmode_0); 78 | m_transmode_1 = new QAction(tr("&Common Plane transitions"), this); 79 | m_transmode_1->setCheckable(true); 80 | m_transmode_group->addAction(m_transmode_1); 81 | m_transmode_2 = new QAction(tr("&Triangulated transitions"), this); 82 | m_transmode_2->setCheckable(true); 83 | m_transmode_group->addAction(m_transmode_2); 84 | connect(m_transmode_group, SIGNAL(triggered(QAction*)), 85 | this, SLOT(setTransMode(QAction*))); 86 | 87 | m_aboutAct = new QAction(tr("&About"), this); 88 | connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about())); 89 | 90 | m_aboutQtAct = new QAction(tr("About &Qt"), this); 91 | connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); 92 | } 93 | 94 | void MainWindow::createMenus() { 95 | QMenu* fileMenu = menuBar()->addMenu(tr("&File")); 96 | fileMenu->addAction(m_openAct); 97 | fileMenu->addAction(m_exitAct); 98 | 99 | QMenu* viewMenu = menuBar()->addMenu(tr("&View")); 100 | viewMenu->addActions(m_transmode_group->actions()); 101 | 102 | QMenu* helpMenu = menuBar()->addMenu(tr("&Help")); 103 | helpMenu->addAction(m_aboutAct); 104 | helpMenu->addAction(m_aboutQtAct); 105 | } 106 | 107 | void MainWindow::openImageDirectoryDialog() { 108 | QString image_directory = QFileDialog::getExistingDirectory(this, 109 | tr("Select image directory"), "", QFileDialog::ShowDirsOnly); 110 | if(image_directory.isEmpty()) return; 111 | openImageDirectory(image_directory); 112 | } 113 | 114 | void MainWindow::setTransMode(QAction* act) { 115 | if(act == m_transmode_none) 116 | m_glwidget->setTransMode(-1); 117 | else if(act == m_transmode_0) 118 | m_glwidget->setTransMode(0); 119 | else if(act == m_transmode_1) 120 | m_glwidget->setTransMode(1); 121 | else if(act == m_transmode_2) 122 | m_glwidget->setTransMode(2); 123 | } 124 | 125 | void MainWindow::about() { 126 | QMessageBox::about(this, "PixelStruct 0.2", 127 | "\nCopyright (c) 2009 David Roberts \n\n" 128 | "This program is free software; you can redistribute it and/or modify\n" 129 | "it under the terms of the GNU General Public License as published by\n" 130 | "the Free Software Foundation; either version 2 of the License, or\n" 131 | "(at your option) any later version.\n\n" 132 | "For more information visit the PixelStruct homepage at:\n" 133 | "http://da.vidr.cc/projects/pixelstruct/\n"); 134 | } 135 | 136 | #include "mainwindow.moc" 137 | -------------------------------------------------------------------------------- /src/glwidget.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 David Roberts 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "glwidget.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | using std::cerr; 31 | using std::endl; 32 | 33 | #define CAPPED_TEXTURE_SIZE 2048 34 | 35 | GLWidget::GLWidget(BundleParser* parser, ImageList* imagelist, QWidget* parent) 36 | : QGLWidget(parent), m_parser(parser), m_imagelist(imagelist), 37 | m_transmode(0), m_cur_image(NULL), m_prev_image(NULL) { 38 | setFocusPolicy(Qt::ClickFocus); 39 | } 40 | 41 | GLWidget::~GLWidget() { 42 | } 43 | 44 | void GLWidget::setTransMode(int transmode) { 45 | m_transmode = transmode; 46 | updateGL(); 47 | } 48 | 49 | void GLWidget::initializeGL() { 50 | glEnable(GL_DEPTH_TEST); 51 | glEnable(GL_CULL_FACE); 52 | glDisable(GL_LIGHTING); 53 | 54 | m_pointcloud = glGenLists(1); 55 | glLoadIdentity(); 56 | glNewList(m_pointcloud, GL_COMPILE); 57 | glBegin(GL_POINTS); 58 | for(int i = 0; i < m_parser->num_points(); i++) { 59 | const VisiblePoint& p = m_parser->points()[i]; 60 | qglColor(p.col()); 61 | glVertex3d(p.x(), p.y(), p.z()); 62 | } 63 | glEnd(); 64 | glEndList(); 65 | 66 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize); 67 | cerr << "GL_MAX_TEXTURE_SIZE = " << texSize << endl; 68 | 69 | handleGLError(__LINE__); 70 | } 71 | 72 | void GLWidget::paintImage(const Photo *image) { 73 | glPushMatrix(); 74 | glMultMatrixd(image->camera()->matrix_l2w()); 75 | 76 | glEnable(GL_TEXTURE_2D); 77 | glBindTexture(GL_TEXTURE_2D, image->texture); 78 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 79 | glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); 80 | glColor4f(1.0,1.0,1.0,image->opacity); 81 | 82 | switch(m_transmode) { 83 | case 0: image->paintSimple(); break; 84 | case 1: image->paintPlane(m_common_plane.transform( 85 | image->camera()->matrix_w2l())); 86 | break; 87 | case 2: image->paintTriangulation(); break; 88 | default: image->paintSimple(); break; 89 | } 90 | 91 | glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); 92 | glDisable(GL_TEXTURE_2D); 93 | glPopMatrix(); 94 | } 95 | 96 | void GLWidget::paintGL() { 97 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 98 | 99 | glCallList(m_pointcloud); 100 | 101 | handleGLError(__LINE__); 102 | 103 | if(m_transmode != -1) { 104 | if(m_prev_image && m_prev_image->opacity > 0.01) 105 | paintImage(m_prev_image); 106 | if(m_cur_image && m_cur_image->opacity > 0.01) 107 | paintImage(m_cur_image); 108 | } 109 | 110 | handleGLError(__LINE__); 111 | } 112 | 113 | void GLWidget::resizeGL (int width, int height) { 114 | cerr << "[GLWidget::resizeGL] Resizing GLWidget to " << width << "x" 115 | << height << endl; 116 | 117 | if(height == 0) height = 1; // prevent division by 0 118 | 119 | glMatrixMode(GL_PROJECTION); 120 | glLoadIdentity(); 121 | glViewport(0, 0, width, height); // entire window 122 | gluPerspective(60.0, (double)width/height, 1e-20, 1e5); 123 | 124 | glMatrixMode(GL_MODELVIEW); 125 | 126 | //cerr << "[GLWidget::resizeGL] end" << endl; 127 | } 128 | 129 | void GLWidget::keyPressEvent (QKeyEvent* event) { 130 | //cerr << "[GLWidget::keyPressEvent] begin" << endl; 131 | 132 | switch (event->key()) { 133 | case Qt::Key_Right: 134 | gotoDirection(0); break; 135 | case Qt::Key_Up: 136 | gotoDirection(1); break; 137 | case Qt::Key_PageDown: 138 | gotoDirection(2); break; 139 | case Qt::Key_Left: 140 | gotoDirection(3); break; 141 | case Qt::Key_Down: 142 | gotoDirection(4); break; 143 | case Qt::Key_PageUp: 144 | gotoDirection(5); break; 145 | case Qt::Key_Return: 146 | gotoNextCamera(); break; 147 | } 148 | 149 | //cerr << "[GLWidget::keyPressEvent] end" << endl; 150 | } 151 | 152 | void GLWidget::keyReleaseEvent (QKeyEvent* event) {} 153 | 154 | void GLWidget::mousePressEvent (QMouseEvent* event) {} 155 | 156 | void GLWidget::mouseMoveEvent (QMouseEvent* event) {} 157 | 158 | void GLWidget::mouseReleaseEvent (QMouseEvent* event) {} 159 | 160 | void GLWidget::focusInEvent(QFocusEvent* event) { 161 | //cerr << "[GLWidget::focusInEvent] begin" << endl; 162 | if(m_cur_image == NULL) 163 | gotoNextCamera(); 164 | //cerr << "[GLWidget::focusInEvent] end" << endl; 165 | } 166 | 167 | void GLWidget::focusOutEvent(QFocusEvent* event) {} 168 | 169 | void GLWidget::gotoCamera(int target_camera) { 170 | cerr << "[GLWidget::gotoCamera] Moving to camera " 171 | << target_camera << endl; 172 | 173 | const Camera& c1 = m_cur_image == NULL 174 | ? Camera::Identity 175 | : *(m_cur_image->camera()); 176 | const Camera& c2 = m_parser->cameras()[target_camera]; 177 | 178 | //glDeleteTextures(1, &(m_prev_image.texture)); 179 | if(m_prev_image) { 180 | deleteTexture(m_prev_image->texture); 181 | delete m_prev_image; 182 | } 183 | m_prev_image = m_cur_image; 184 | 185 | QImage image = m_imagelist->loadImage(target_camera); 186 | m_cur_image = new Photo(image.width(), image.height(), &c2); 187 | int size = texSize < CAPPED_TEXTURE_SIZE ? texSize : CAPPED_TEXTURE_SIZE; 188 | image = image.scaled(size, size); 189 | //image = convertToGLFormat(image); 190 | //glGenTextures(1, &(m_cur_image.texture)); 191 | //glBindTexture(GL_TEXTURE_2D, m_cur_image.texture); 192 | //glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width(), image.height(), 193 | // 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); 194 | m_cur_image->texture = bindTexture(image); 195 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 196 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 197 | 198 | handleGLError(__LINE__); 199 | 200 | if(m_transmode == 1) { 201 | cerr << "[GLWidget::gotoCamera] Generating common plane" << endl; 202 | m_common_plane = CommonPlane(c1, c2); 203 | } 204 | 205 | for(double i = 0.0; i < 1.001; i += 0.1) { 206 | usleep(1000000/25); // sleep for 1 frame @ 25fps 207 | 208 | if(m_prev_image) m_prev_image->opacity = 1.0 - i; 209 | m_cur_image->opacity = i; 210 | 211 | double cx = c1.pos().x()*(1.0-i) + c2.pos().x()*i; 212 | double cy = c1.pos().y()*(1.0-i) + c2.pos().y()*i; 213 | double cz = c1.pos().z()*(1.0-i) + c2.pos().z()*i; 214 | double dx = -c1.unit_z().x()*(1.0-i) + -c2.unit_z().x()*i; 215 | double dy = -c1.unit_z().y()*(1.0-i) + -c2.unit_z().y()*i; 216 | double dz = -c1.unit_z().z()*(1.0-i) + -c2.unit_z().z()*i; 217 | double ux = c1.unit_y().x()*(1.0-i) + c2.unit_y().x()*i; 218 | double uy = c1.unit_y().y()*(1.0-i) + c2.unit_y().y()*i; 219 | double uz = c1.unit_y().z()*(1.0-i) + c2.unit_y().z()*i; 220 | 221 | glLoadIdentity(); 222 | gluLookAt(cx,cy,cz, cx+dx,cy+dy,cz+dz, ux,uy,uz); 223 | updateGL(); 224 | } 225 | 226 | //cerr << "[GLWidget::gotoCamera] end" << endl; 227 | } 228 | 229 | void GLWidget::gotoNextCamera() { 230 | cerr << "[GLWidget::gotoNextCamera] Moving to next camera" << endl; 231 | int target_camera = m_cur_image == NULL 232 | ? 0 : m_cur_image->camera()->index() + 1; 233 | while(m_parser->cameras()[target_camera].focal_length() == 0.0) 234 | target_camera++; 235 | if(target_camera >= m_parser->num_cameras()) target_camera = 0; 236 | while(m_parser->cameras()[target_camera].focal_length() == 0.0) 237 | target_camera++; 238 | gotoCamera(target_camera); 239 | //cerr << "[GLWidget::gotoNextCamera] end" << endl; 240 | } 241 | 242 | void GLWidget::gotoDirection(int target_direction) { 243 | cerr << "[GLWidget::gotoDirection] Moving in direction " 244 | << target_direction << endl; 245 | 246 | double closest_dist = DBL_MAX; 247 | int closest_camera = -1; 248 | const Camera& c1 = *(m_cur_image->camera()); 249 | 250 | for(int candidate_camera = 0; candidate_camera < m_parser->num_cameras(); 251 | candidate_camera++) { 252 | if(m_cur_image == NULL) break; 253 | if(candidate_camera == m_cur_image->camera()->index()) continue; 254 | 255 | const Camera& c2 = m_parser->cameras()[candidate_camera]; 256 | if(c2.focal_length() == 0.0) continue; 257 | 258 | Point relative_pos = c1.point_w2l(c2.pos()); 259 | 260 | double dist = DBL_MAX; 261 | if(relative_pos.x() > 0.0 && target_direction == 0) 262 | dist = relative_pos.y()*relative_pos.y() 263 | + relative_pos.z()*relative_pos.z(); 264 | if(relative_pos.y() > 0.0 && target_direction == 1) 265 | dist = relative_pos.x()*relative_pos.x() 266 | + relative_pos.z()*relative_pos.z(); 267 | if(relative_pos.z() > 0.0 && target_direction == 2) 268 | dist = relative_pos.x()*relative_pos.x() 269 | + relative_pos.y()*relative_pos.y(); 270 | if(relative_pos.x() < 0.0 && target_direction == 3) 271 | dist = relative_pos.y()*relative_pos.y() 272 | + relative_pos.z()*relative_pos.z(); 273 | if(relative_pos.y() < 0.0 && target_direction == 4) 274 | dist = relative_pos.x()*relative_pos.x() 275 | + relative_pos.z()*relative_pos.z(); 276 | if(relative_pos.z() < 0.0 && target_direction == 5) 277 | dist = relative_pos.x()*relative_pos.x() 278 | + relative_pos.y()*relative_pos.y(); 279 | 280 | if(closest_dist > dist) { 281 | closest_dist = dist; 282 | closest_camera = candidate_camera; 283 | } 284 | } 285 | 286 | if(closest_camera >= 0) gotoCamera(closest_camera); 287 | 288 | //cerr << "[GLWidget::gotoDirection] end" << endl; 289 | } 290 | 291 | void GLWidget::handleGLError(int line) { 292 | GLenum errCode = glGetError(); 293 | if(errCode != GL_NO_ERROR) 294 | cerr << "OpenGL Error (line " << line << "): " 295 | << errCode << ": " << gluErrorString(errCode) << endl; 296 | } 297 | 298 | #include "glwidget.moc" 299 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------