This commit is contained in:
PodmogilnyjIvan
2021-12-03 03:34:31 -08:00
commit ff4acf84be
542 changed files with 136810 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/glfont.h>
#ifdef HAVE_GLES
GLfloat g_raster_pos[4];
inline void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z)
{
// find object point (x,y,z)' in pixel coords
GLdouble projection[16];
GLdouble modelview[16];
GLint view[4];
#ifdef HAVE_GLES_2
std::copy(pangolin::glEngine().projection.top().m, pangolin::glEngine().projection.top().m+16, projection);
std::copy(pangolin::glEngine().modelview.top().m, pangolin::glEngine().modelview.top().m+16, modelview);
#else
glGetDoublev(GL_PROJECTION_MATRIX, projection );
glGetDoublev(GL_MODELVIEW_MATRIX, modelview );
#endif
glGetIntegerv(GL_VIEWPORT, view );
pangolin::glProject(x, y, z, modelview, projection, view,
g_raster_pos, g_raster_pos + 1, g_raster_pos + 2);
}
inline void glRasterPos2f(GLfloat x, GLfloat y)
{
glRasterPos3f(x,y,1.0f);
}
inline void glRasterPos2i(GLint x, GLint y)
{
glRasterPos3f((GLfloat)x, (GLfloat)y, 1.0f );
}
inline void glRasterPos3fv(const GLfloat *v){
glRasterPos3f(v[0],v[1],v[2]);
}
inline void glRasterPos2fv(const GLfloat *v){
glRasterPos3f(v[0],v[1],1.0f);
}
#endif // HAVE_GLES
inline void glutBitmapString(void * /*font*/, const unsigned char *str)
{
#ifndef HAVE_GLES
float g_raster_pos[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, g_raster_pos);
#endif
pangolin::GlFont::I().Text( (const char *)str ).DrawWindow(
g_raster_pos[0], g_raster_pos[1], g_raster_pos[2]
);
}
inline int glutBitmapLength(void * /*font*/, const unsigned char *str)
{
return (int)(pangolin::GlFont::I().Text((const char *)str).Width());
}
#define GLUT_BITMAP_HELVETICA_12 0;

View File

@@ -0,0 +1,20 @@
#pragma once
#include <pangolin/platform.h>
// Use either C++17 optional, or the standalone backwards compatible version
#if (__cplusplus >= 201703L)
# include <optional>
#else
# include <experimental/optional.hpp>
#endif
namespace pangolin {
#if (__cplusplus >= 201703L)
template <typename T>
using optional = std::optional<T>;
#else
template <typename T>
using optional = std::experimental::optional<T>;
#endif
}

View File

@@ -0,0 +1,49 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <typeinfo>
#include <type_traits>
// enable_if From Boost
namespace pangolin
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <pangolin/platform.h>
// Use either C++17 variant, or the standalone backwards compatible version
// of M. Park.
#if (__cplusplus >= 201703L)
# include <variant>
#else
# include <mpark/variant.hpp>
#endif
namespace pangolin {
#if (__cplusplus >= 201703L)
using std::variant;
using std::get;
using std::get_if;
using std::visit;
#else
using mpark::variant;
using mpark::get;
using mpark::get_if;
using mpark::visit;
#endif
}

View File

@@ -0,0 +1,80 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <vector>
#include <string>
namespace pangolin
{
enum ConsoleLineType
{
ConsoleLineTypeCmd,
ConsoleLineTypeCmdOptions,
ConsoleLineTypeStdout,
ConsoleLineTypeStderr,
ConsoleLineTypeOutput,
ConsoleLineTypeHelp,
};
class ConsoleLine
{
public:
inline ConsoleLine()
: linetype(ConsoleLineTypeCmd)
{
}
inline ConsoleLine(std::string text, ConsoleLineType linetype = ConsoleLineTypeOutput)
: text(text), linetype(linetype)
{
}
std::string text;
ConsoleLineType linetype;
};
class ConsoleInterpreter
{
public:
inline virtual ~ConsoleInterpreter()
{
}
virtual void PushCommand(const std::string& cmd) = 0;
virtual bool PullLine(ConsoleLine& line) = 0;
virtual std::vector<std::string> Complete(
const std::string& cmd, int max_options = 20
) = 0;
};
}

View File

@@ -0,0 +1,109 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <deque>
#include <pangolin/platform.h>
#include <pangolin/gl/glfont.h>
#include <pangolin/var/var.h>
#include <pangolin/display/view.h>
#include <pangolin/handler/handler.h>
#include <pangolin/gl/colour.h>
#include <pangolin/console/ConsoleInterpreter.h>
namespace pangolin
{
class ConsoleView : public pangolin::View, pangolin::Handler
{
public:
struct Line
{
Line()
: linetype(ConsoleLineTypeCmd)
{
}
Line(const GlText& text, ConsoleLineType linetype = ConsoleLineTypeCmd )
: text(text), linetype(linetype)
{
}
GlText text;
ConsoleLineType linetype;
};
// Construct with interpreter (and take ownership)
ConsoleView(ConsoleInterpreter* interpreter);
~ConsoleView();
View& ShowWithoutAnimation(bool show=true);
// Replace implementation in View to account for hiding animation
View& Show(bool show=true);
// Replace implementation in View to account for hiding animation
void ToggleShow();
// Replace implementation in View to account for hiding animation
bool IsShown() const;
void Render() override;
void Keyboard(View&, unsigned char key, int x, int y, bool pressed) override;
private:
void DrawLine(const ConsoleView::Line& l, int carat);
void ProcessOutputLines();
void AddLine(const std::string& text, ConsoleLineType linetype = ConsoleLineTypeCmd);
Line* GetLine(int id, ConsoleLineType line_type, const std::string& prefix = "");
ConsoleInterpreter* interpreter;
GlFont& font;
int carat;
Line current_line;
std::deque<Line> line_buffer;
bool hiding;
GLfloat bottom;
Colour background_colour;
std::map<ConsoleLineType,pangolin::Colour> line_colours;
float animation_speed;
};
}

View File

@@ -0,0 +1,86 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <iostream>
#include <string>
#include <cmath>
namespace pangolin
{
/// Units for measuring screen distances.
enum Unit {
Fraction,
Pixel,
ReversePixel
};
/// Defines absolute or relative position from parent viewport edge.
/// Constructors distinguised by whole pixels, or floating
/// fraction in interval [0,1]
struct PANGOLIN_EXPORT Attach {
/// Attach to Left/Bottom edge
Attach() : unit(Fraction), p(0) {}
/// General constructor
Attach(Unit unit, GLfloat p) : unit(unit), p(p) {}
/// Specify relative position in range [0,1].
/// 0 represents leftmost / bottom-most edge,
/// 1 represents rightmost / topmost edge
Attach(GLfloat p) : unit(Fraction), p(p) {
// Allow for numerical imprecision when checking usage.
if( p < -1E-3 || 1.001 < p ) {
std::cerr << "Pangolin API Change: Display::SetBounds must be used with Attach::Pix or Attach::ReversePix to specify pixel bounds relative to an edge. See the code samples for details." << std::endl;
throw std::exception();
}
}
/// Specify absolute position from leftmost / bottom-most edge.
static Attach Pix(int p) {
return Attach(p >=0 ? Pixel : ReversePixel, std::abs((float)p));
}
/// Specify absolute position from rightmost / topmost edge.
static Attach ReversePix(int p) {
return Attach(ReversePixel, (GLfloat)p);
}
/// Specify relative position in range [0,1].
/// 0 represents leftmost / bottom-most edge,
/// 1 represents rightmost / topmost edge
static Attach Frac(float frac) {
return Attach(frac);
}
Unit unit;
GLfloat p;
};
} // namespace pangolin

View File

@@ -0,0 +1,68 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <pangolin/display/device/PangolinNSApplication.h>
#include <pangolin/display/device/PangolinNSGLView.h>
namespace pangolin
{
struct OsxWindow : public PangolinGl
{
OsxWindow(const std::string& title, int width, int height, bool USE_RETINA);
~OsxWindow();
void StartFullScreen();
void StopFullScreen();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
private:
NSWindow* _window;
PangolinNSGLView *view;
};
}

View File

@@ -0,0 +1,59 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
////////////////////////////////////////////////////////////////////
// PangolinNSApplication
////////////////////////////////////////////////////////////////////
@interface PangolinNSApplication : NSObject {
}
+ (void)run_pre;
+ (void)run_step;
@end
////////////////////////////////////////////////////////////////////
// PangolinWindowDelegate
////////////////////////////////////////////////////////////////////
@interface PangolinWindowDelegate : NSObject <NSWindowDelegate>
@end
////////////////////////////////////////////////////////////////////
// PangolinAppDelegate
////////////////////////////////////////////////////////////////////
@interface PangolinAppDelegate : NSObject <NSApplicationDelegate>
@end

View File

@@ -0,0 +1,45 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <pangolin/display/display_internal.h>
////////////////////////////////////////////////////////////////////
// PangolinNSGLView
////////////////////////////////////////////////////////////////////
@interface PangolinNSGLView : NSOpenGLView
{
pangolin::PangolinGl* context;
float backing_scale;
}
@end

View File

@@ -0,0 +1,89 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <string>
#include <windowsx.h>
namespace pangolin
{
struct WinWindow : public PangolinGl
{
WinWindow(
const std::string& title, int width, int height
);
~WinWindow();
void StartFullScreen();
void StopFullScreen();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
HGLRC GetGLRenderContext()
{
return hGLRC;
}
private:
static LRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam);
void RegisterThisClass(HMODULE hCurrentInst);
void SetupPixelFormat(HDC hdc);
void SetupPalette(HDC hDC);
// Owns the Window
HWND hWnd;
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
};
}

View File

@@ -0,0 +1,109 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <stdexcept>
#include <string>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
namespace pangolin
{
struct X11Display
{
X11Display(const char* name = 0) {
XInitThreads();
display = XOpenDisplay(name);
if (!display) {
throw std::runtime_error("Pangolin X11: Failed to open X display");
}
}
~X11Display() {
XCloseDisplay(display);
}
// Owns the display
::Display* display;
};
struct X11GlContext : public GlContextInterface
{
X11GlContext(std::shared_ptr<X11Display> &d, ::GLXFBConfig chosenFbc, std::shared_ptr<X11GlContext> shared_context = std::shared_ptr<X11GlContext>() );
~X11GlContext();
std::shared_ptr<X11Display> display;
std::shared_ptr<X11GlContext> shared_context;
// Owns the OpenGl Context
::GLXContext glcontext;
};
struct X11Window : public PangolinGl
{
X11Window(
const std::string& title, int width, int height,
std::shared_ptr<X11Display>& display, ::GLXFBConfig chosenFbc
);
~X11Window();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent(GLXContext ctx);
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
// References the X11 display and context.
std::shared_ptr<X11Display> display;
std::shared_ptr<X11GlContext> glcontext;
// Owns the X11 Window and Colourmap
::Window win;
::Colormap cmap;
Atom delete_message;
};
}

View File

@@ -0,0 +1,333 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#include <android/log.h>
#include <string>
#include <pangolin/utils/type_convert.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "pango", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "pango", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__))
/* For debug builds, always enable the debug traces in this library */
#undef NDEBUG
#ifndef NDEBUG
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "pango", __VA_ARGS__))
#else
# define LOGV(...) ((void)0)
#endif
template<typename T> inline
void Log(T v) {
const std::string sv = pangolin::Convert<std::string,T>::Do(v);
LOGI(sv.c_str());
}
template<typename T> inline
void Log(const std::string& str, T v)
{
const std::string sv = pangolin::Convert<std::string,T>::Do(v);
LOGI((str + ":" + sv).c_str());
}
namespace pangolin
{
void CreateAndroidWindowAndBind(std::string name);
void ProcessAndroidEvents();
void FinishAndroidFrame();
}
#ifdef __cplusplus
extern "C" {
#endif
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
const char* application_so;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,219 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/gl/glinclude.h>
#include <pangolin/handler/handler_enums.h>
#include <pangolin/utils/params.h>
#include <pangolin/display/window.h>
#include <functional>
#include <string>
#include <memory>
/*! \file display.h
* This file contains a number of global methods for creating and
* querying window state as well as handling user input.
*/
namespace pangolin
{
// CreateWindowAndBind parameter key names.
// X11 Window options:
extern const char* PARAM_DISPLAYNAME; // std::string
extern const char* PARAM_DOUBLEBUFFER; // bool
extern const char* PARAM_SAMPLE_BUFFERS; // int
extern const char* PARAM_SAMPLES; // int
extern const char* PARAM_HIGHRES; // bool - Apple Retina screens only
// Forward Declarations
struct View;
struct Viewport;
class UserApp;
/// Give this OpenGL context a name or switch contexts.
/// This is required to initialise Pangolin for use with an
/// externally defined OpenGL context. You needn't call it
/// if you have used CreateWindowAndBind() to create a window
/// or launched a pangolin::UserApp
PANGOLIN_EXPORT
WindowInterface& BindToContext(std::string name);
/// Initialise OpenGL window (determined by platform) and bind context.
/// This method will choose an available windowing system if one is present.
PANGOLIN_EXPORT
WindowInterface& CreateWindowAndBind(std::string window_title, int w = 640, int h = 480, const Params& params = Params());
/// Return pointer to current Pangolin Window context, or nullptr if none bound.
PANGOLIN_EXPORT
WindowInterface* GetBoundWindow();
PANGOLIN_EXPORT
void DestroyWindow(const std::string& window_title);
/// Launch users derived UserApp, controlling OpenGL event loop.
/// This method will block until the application exits, calling app's
/// Init() method to start and Render() method subsequently to draw each frame.
/// @return exit code for use when returning from main. Currently always 0.
PANGOLIN_EXPORT
int LaunchUserApp(UserApp& app);
/// Perform any post rendering, event processing and frame swapping.
PANGOLIN_EXPORT
void FinishFrame();
/// Request that the window close.
PANGOLIN_EXPORT
void Quit();
/// Request that all windows close.
PANGOLIN_EXPORT
void QuitAll();
/// Returns true if user has requested to close OpenGL window.
PANGOLIN_EXPORT
bool ShouldQuit();
/// Returns true if user has interacted with the window since this was last called.
PANGOLIN_EXPORT
bool HadInput();
/// Returns true if user has resized the window.
PANGOLIN_EXPORT
bool HasResized();
/// Renders any views with default draw methods.
PANGOLIN_EXPORT
void RenderViews();
/// Perform any post render events, such as screen recording.
PANGOLIN_EXPORT
void PostRender();
/// Request to be notified via functor when key is pressed.
/// Functor may take one parameter which will equal the key pressed
PANGOLIN_EXPORT
void RegisterKeyPressCallback(int key, std::function<void(void)> func);
/// Save window contents to image.
PANGOLIN_EXPORT
void SaveWindowOnRender(std::string filename_prefix);
PANGOLIN_EXPORT
void SaveFramebuffer(std::string prefix, const Viewport& v);
namespace process
{
/// Tell pangolin to process input to drive display.
/// You will need to call this manually if you haven't let
/// Pangolin register callbacks from your windowing system
PANGOLIN_EXPORT
void Keyboard( unsigned char key, int x, int y);
PANGOLIN_EXPORT
void KeyboardUp(unsigned char key, int x, int y);
PANGOLIN_EXPORT
void SpecialFunc(int key, int x, int y);
PANGOLIN_EXPORT
void SpecialFuncUp(int key, int x, int y);
/// Tell pangolin base window size has changed
/// You will need to call this manually if you haven't let
/// Pangolin register callbacks from your windowing system
PANGOLIN_EXPORT
void Resize(int width, int height);
/// Event based rendering entry point. Not currently supported.
PANGOLIN_EXPORT
void Display();
PANGOLIN_EXPORT
void Mouse( int button, int state, int x, int y);
PANGOLIN_EXPORT
void MouseMotion( int x, int y);
PANGOLIN_EXPORT
void PassiveMouseMotion(int x, int y);
PANGOLIN_EXPORT
void Scroll(float x, float y);
PANGOLIN_EXPORT
void Zoom(float m);
PANGOLIN_EXPORT
void Rotate(float r);
PANGOLIN_EXPORT
void SubpixMotion(float x, float y, float pressure, float rotation, float tiltx, float tilty);
PANGOLIN_EXPORT
void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4);
}
/// Retrieve 'base' display, corresponding to entire window.
PANGOLIN_EXPORT
View& DisplayBase();
/// Create or retrieve named display managed by pangolin (automatically deleted).
PANGOLIN_EXPORT
View& Display(const std::string& name);
/// Create unnamed display managed by pangolin (automatically deleted).
PANGOLIN_EXPORT
View& CreateDisplay();
/// Switch between windowed and fullscreen mode.
PANGOLIN_EXPORT
void ToggleFullscreen();
/// Switch windows/fullscreenmode = fullscreen.
PANGOLIN_EXPORT
void SetFullscreen(bool fullscreen = true);
/// Toggle display of Pangolin console
PANGOLIN_EXPORT
void ToggleConsole();
/// Convenience functor for toggling pangolin::View.
/// Use with RegisterKeyPressCallback for example
struct ToggleViewFunctor {
inline ToggleViewFunctor(View& view);
inline ToggleViewFunctor(const std::string& name);
void operator()();
View& view;
};
}

View File

@@ -0,0 +1,138 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/window.h>
#include <pangolin/display/view.h>
#include <pangolin/display/user_app.h>
#include <functional>
#include <memory>
#include <map>
#include <queue>
#ifdef BUILD_PANGOLIN_VIDEO
# include <pangolin/video/video_output.h>
#endif // BUILD_PANGOLIN_VIDEO
namespace pangolin
{
// Forward Declarations
#ifdef HAVE_PYTHON
class ConsoleView;
#endif // HAVE_PYTHON
class GlFont;
typedef std::map<const std::string,View*> ViewMap;
typedef std::map<int,std::function<void(void)> > KeyhookMap;
struct PANGOLIN_EXPORT PangolinGl : public WindowInterface
{
PangolinGl();
~PangolinGl();
// Base container for displays
View base;
// Named views which are managed by pangolin (i.e. created / deleted by pangolin)
ViewMap named_managed_views;
// Optional user app
UserApp* user_app;
// Global keypress hooks
KeyhookMap keypress_hooks;
// Manage fullscreen (ToggleFullscreen is quite new)
bool is_double_buffered;
bool is_fullscreen;
GLint windowed_size[2];
bool is_high_res;
// State relating to interactivity
bool quit;
int had_input;
int has_resized;
int mouse_state;
View* activeDisplay;
std::queue<std::pair<std::string,Viewport> > screen_capture;
#ifdef BUILD_PANGOLIN_VIDEO
View* record_view;
VideoOutput recorder;
#endif
#ifdef HAVE_PYTHON
ConsoleView* console_view;
#endif
std::shared_ptr<GlFont> font;
virtual void ToggleFullscreen() override {
pango_print_warn("ToggleFullscreen: Not available with non-pangolin window.\n");
}
virtual void ProcessEvents() override {
pango_print_warn("ProcessEvents: Not available with non-pangolin window.\n");
}
virtual void SwapBuffers() override {
pango_print_warn("SwapBuffers: Not available with non-pangolin window.\n");
}
virtual void MakeCurrent() override {
pango_print_warn("MakeCurrent: Not available with non-pangolin window.\n");
}
virtual void RemoveCurrent() override {
pango_print_warn("RemoveCurrent: Not available with non-pangolin window.\n");
}
virtual void Move(int /*x*/, int /*y*/) override {
pango_print_warn("Move: Not available with non-pangolin window.\n");
}
virtual void Resize(unsigned int /*w*/, unsigned int /*h*/) override {
pango_print_warn("Resize: Not available with non-pangolin window.\n");
}
};
PangolinGl* GetCurrentContext();
void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext);
void DeleteContext(const std::string& name);
PangolinGl *FindContext(const std::string& name);
}

View File

@@ -0,0 +1,74 @@
#pragma once
#include <pangolin/display/display.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/gl/glsl.h>
#include <pangolin/handler/handler_image.h>
#include <pangolin/image/image_utils.h>
#include <mutex>
namespace pangolin
{
class ImageView : public pangolin::View, public pangolin::ImageViewHandler
{
public:
ImageView();
~ImageView();
void Render() override;
void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
void Keyboard(View& view, unsigned char key, int x, int y, bool pressed) override;
pangolin::GlTexture& Tex();
ImageView& SetImage(void* ptr, size_t w, size_t h, size_t pitch, pangolin::GlPixFormat img_fmt, bool delayed_upload = false);
ImageView& SetImage(const pangolin::Image<unsigned char>& img, const pangolin::GlPixFormat& glfmt, bool delayed_upload = false);
template<typename T> inline
ImageView& SetImage(const pangolin::Image<T>& img, bool delayed_upload = false)
{
return SetImage(img.template UnsafeReinterpret<unsigned char>(), GlPixFormat::FromType<T>(), delayed_upload);
}
ImageView& SetImage(const pangolin::TypedImage& img, bool delayed_upload = false);
ImageView& SetImage(const pangolin::GlTexture& texture);
void LoadPending();
ImageView& Clear();
std::pair<float, float>& GetOffsetScale();
bool MouseReleased() const;
bool MousePressed() const;
void SetRenderOverlay(const bool& val);
// private:
// img_to_load contains image data that should be uploaded to the texture on
// the next render cycle. The data is owned by this object and should be
// freed after use.
pangolin::ManagedImage<unsigned char> img_to_load;
pangolin::GlPixFormat img_fmt_to_load;
std::pair<float, float> offset_scale;
pangolin::GlPixFormat fmt;
pangolin::GlTexture tex;
bool lastPressed;
bool mouseReleased;
bool mousePressed;
bool overlayRender;
std::mutex texlock;
};
}

View File

@@ -0,0 +1,446 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/simple_math.h>
#include <vector>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#include <Eigen/Geometry>
#endif
#ifdef HAVE_TOON
#include <cstring>
#include <TooN/TooN.h>
#include <TooN/se3.h>
#endif
#ifdef HAVE_OCULUS
#include <pangolin/compat/ovr.h>
#endif
namespace pangolin {
#ifdef HAVE_GLES
typedef float GLprecision;
#else
typedef double GLprecision;
#endif
/// Capture OpenGL matrix types in enum to typing.
enum OpenGlStack {
GlModelViewStack = 0x1700, // GL_MODELVIEW
GlProjectionStack = 0x1701, // GL_PROJECTION
GlTextureStack = 0x1702 // GL_TEXTURE
};
enum AxisDirection
{
AxisNone,
AxisNegX, AxisX,
AxisNegY, AxisY,
AxisNegZ, AxisZ
};
struct CameraSpec {
GLprecision forward[3];
GLprecision up[3];
GLprecision right[3];
GLprecision img_up[2];
GLprecision img_right[2];
};
const static CameraSpec CameraSpecOpenGl = {{0,0,-1},{0,1,0},{1,0,0},{0,1},{1,0}};
const static CameraSpec CameraSpecYDownZForward = {{0,0,1},{0,-1,0},{1,0,0},{0,-1},{1,0}};
/// Direction vector for each AxisDirection enum
const static GLprecision AxisDirectionVector[7][3] = {
{0,0,0},
{-1,0,0}, {1,0,0},
{0,-1,0}, {0,1,0},
{0,0,-1}, {0,0,1}
};
/// Object representing OpenGl Matrix.
struct PANGOLIN_EXPORT OpenGlMatrix {
static OpenGlMatrix Translate(GLprecision x, GLprecision y, GLprecision z);
static OpenGlMatrix Scale(GLprecision x, GLprecision y, GLprecision z);
static OpenGlMatrix RotateX(GLprecision theta_rad);
static OpenGlMatrix RotateY(GLprecision theta_rad);
static OpenGlMatrix RotateZ(GLprecision theta_rad);
template<typename P>
static OpenGlMatrix ColMajor4x4(const P* col_major_4x4);
OpenGlMatrix();
#ifdef USE_EIGEN
template<typename P>
OpenGlMatrix(const Eigen::Matrix<P,4,4>& mat);
template<typename P>
OpenGlMatrix(const Eigen::Transform<P,3,Eigen::Affine>& mat) : OpenGlMatrix(mat.matrix()) { }
template<typename P>
operator Eigen::Matrix<P,4,4>() const;
template<typename P>
operator Eigen::Transform<P,3,Eigen::Affine>() const;
#endif // USE_EIGEN
#ifdef HAVE_TOON
OpenGlMatrix(const TooN::SE3<>& T);
OpenGlMatrix(const TooN::Matrix<4,4>& M);
operator const TooN::SE3<>() const;
operator const TooN::Matrix<4,4>() const;
#endif // HAVE_TOON
#ifdef HAVE_OCULUS
OpenGlMatrix(const OVR::Matrix4f& M);
operator const OVR::Matrix4f() const;
#endif // HAVE_OCULUS
// Load matrix on to OpenGl stack
void Load() const;
void Multiply() const;
void SetIdentity();
OpenGlMatrix Transpose() const;
OpenGlMatrix Inverse() const;
GLprecision& operator()(int r, int c) {
return m[4*c +r];
}
GLprecision operator()(int r, int c) const {
return m[4 * c + r];
}
// Column major Internal buffer
GLprecision m[16];
};
PANGOLIN_EXPORT
OpenGlMatrix operator*(const OpenGlMatrix& lhs, const OpenGlMatrix& rhs);
PANGOLIN_EXPORT
std::ostream& operator<<(std::ostream& os, const OpenGlMatrix& mat);
/// Deprecated.
struct PANGOLIN_EXPORT OpenGlMatrixSpec : public OpenGlMatrix {
// Specify which stack this refers to
OpenGlStack type;
};
/// Object representing attached OpenGl Matrices / transforms.
class PANGOLIN_EXPORT OpenGlRenderState
{
public:
OpenGlRenderState();
OpenGlRenderState(const OpenGlMatrix& projection_matrix);
OpenGlRenderState(const OpenGlMatrix& projection_matrix, const OpenGlMatrix& modelview_matrix);
static void ApplyIdentity();
void Apply() const;
OpenGlRenderState& SetProjectionMatrix(OpenGlMatrix m);
OpenGlRenderState& SetModelViewMatrix(OpenGlMatrix m);
OpenGlMatrix& GetProjectionMatrix();
OpenGlMatrix GetProjectionMatrix() const;
OpenGlMatrix& GetModelViewMatrix();
OpenGlMatrix GetModelViewMatrix() const;
OpenGlMatrix GetProjectionModelViewMatrix() const;
OpenGlMatrix GetProjectiveTextureMatrix() const;
void EnableProjectiveTexturing() const;
void DisableProjectiveTexturing() const;
//! Seemlessly move OpenGl camera relative to changes in T_wc,
//! whilst still enabling interaction
void Follow(const OpenGlMatrix& T_wc, bool follow = true);
void Unfollow();
// Experimental - subject to change
OpenGlMatrix& GetProjectionMatrix(unsigned int view);
OpenGlMatrix GetProjectionMatrix(unsigned int view) const;
OpenGlMatrix& GetViewOffset(unsigned int view);
OpenGlMatrix GetViewOffset(unsigned int view) const;
OpenGlMatrix GetModelViewMatrix(int i) const;
void ApplyNView(int view) const;
PANGOLIN_DEPRECATED
OpenGlRenderState& Set(OpenGlMatrixSpec spec);
protected:
OpenGlMatrix modelview;
std::vector<OpenGlMatrix> projection;
std::vector<OpenGlMatrix> modelview_premult;
OpenGlMatrix T_cw;
bool follow;
};
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRUB_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRUB_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_TopRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_BottomRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
//! Use OpenGl's default frame RUB_BottomLeft
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrix(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixOrthographic(GLprecision l, GLprecision r, GLprecision b, GLprecision t, GLprecision n, GLprecision f );
//! Generate glulookat style model view matrix, looking at (lx,ly,lz)
//! X-Right, Y-Up, Z-Back
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAtRUB(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
//! Generate glulookat style model view matrix, looking at (lx,ly,lz)
//! X-Right, Y-Down, Z-Forward
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAtRDF(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
//! Generate glulookat style model view matrix, OpenGL Default camera convention (XYZ=RUB), looking at (lx,ly,lz)
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAt(GLprecision x, GLprecision y, GLprecision z, GLprecision lx, GLprecision ly, GLprecision lz, AxisDirection up);
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAt(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
PANGOLIN_EXPORT
OpenGlMatrix IdentityMatrix();
PANGOLIN_EXPORT
OpenGlMatrixSpec IdentityMatrix(OpenGlStack type);
PANGOLIN_EXPORT
OpenGlMatrixSpec negIdentityMatrix(OpenGlStack type);
#ifdef HAVE_TOON
OpenGlMatrixSpec FromTooN(const TooN::SE3<>& T_cw);
OpenGlMatrixSpec FromTooN(OpenGlStack type, const TooN::Matrix<4,4>& M);
TooN::Matrix<4,4> ToTooN(const OpenGlMatrixSpec& ms);
TooN::SE3<> ToTooN_SE3(const OpenGlMatrixSpec& ms);
#endif
#ifdef HAVE_EIGEN
template<typename P>
Eigen::Matrix<P,4,4> ToEigen(const OpenGlMatrix& ms);
#endif
}
// Inline definitions
namespace pangolin
{
template<typename P>
inline OpenGlMatrix OpenGlMatrix::ColMajor4x4(const P* col_major_4x4)
{
OpenGlMatrix mat;
std::copy(col_major_4x4, col_major_4x4 + 16, mat.m);
return mat;
}
inline OpenGlMatrix::OpenGlMatrix() {
}
#ifdef USE_EIGEN
template<typename P> inline
OpenGlMatrix::OpenGlMatrix(const Eigen::Matrix<P,4,4>& mat)
{
for(int r=0; r<4; ++r ) {
for(int c=0; c<4; ++c ) {
m[c*4+r] = mat(r,c);
}
}
}
template<typename P>
OpenGlMatrix::operator Eigen::Matrix<P,4,4>() const
{
return ToEigen<P>(*this);
}
template<typename P>
OpenGlMatrix::operator Eigen::Transform<P,3,Eigen::Affine>() const
{
return Eigen::Transform<P,3,Eigen::Affine>(ToEigen<P>(*this));
}
template<typename P> inline
Eigen::Matrix<P,4,4> ToEigen(const OpenGlMatrix& ms)
{
Eigen::Matrix<P,4,4> mat;
for(int r=0; r<4; ++r ) {
for(int c=0; c<4; ++c ) {
mat(r,c) = (P)ms.m[c*4+r];
}
}
return mat;
}
#endif // USE_EIGEN
#ifdef HAVE_TOON
inline OpenGlMatrix::OpenGlMatrix(const TooN::SE3<>& T)
{
TooN::Matrix<4,4,GLprecision,TooN::ColMajor> M;
M.slice<0,0,3,3>() = T.get_rotation().get_matrix();
M.T()[3].slice<0,3>() = T.get_translation();
M[3] = TooN::makeVector(0,0,0,1);
std::memcpy(m, &(M[0][0]),16*sizeof(GLprecision));
}
inline OpenGlMatrix::OpenGlMatrix(const TooN::Matrix<4,4>& M)
{
// Read in remembering col-major convension for our matrices
int el = 0;
for(int c=0; c<4; ++c)
for(int r=0; r<4; ++r)
m[el++] = M[r][c];
}
inline OpenGlMatrix::operator const TooN::SE3<>() const
{
const TooN::Matrix<4,4> m = *this;
const TooN::SO3<> R(m.slice<0,0,3,3>());
const TooN::Vector<3> t = m.T()[3].slice<0,3>();
return TooN::SE3<>(R,t);
}
inline OpenGlMatrix::operator const TooN::Matrix<4,4>() const
{
TooN::Matrix<4,4> M;
int el = 0;
for( int c=0; c<4; ++c )
for( int r=0; r<4; ++r )
M(r,c) = m[el++];
return M;
}
PANGOLIN_DEPRECATED
inline OpenGlMatrixSpec FromTooN(const TooN::SE3<>& T_cw)
{
TooN::Matrix<4,4,GLprecision,TooN::ColMajor> M;
M.slice<0,0,3,3>() = T_cw.get_rotation().get_matrix();
M.T()[3].slice<0,3>() = T_cw.get_translation();
M[3] = TooN::makeVector(0,0,0,1);
OpenGlMatrixSpec P;
P.type = GlModelViewStack;
std::memcpy(P.m, &(M[0][0]),16*sizeof(GLprecision));
return P;
}
PANGOLIN_DEPRECATED
inline OpenGlMatrixSpec FromTooN(OpenGlStack type, const TooN::Matrix<4,4>& M)
{
// Read in remembering col-major convension for our matrices
OpenGlMatrixSpec P;
P.type = type;
int el = 0;
for(int c=0; c<4; ++c)
for(int r=0; r<4; ++r)
P.m[el++] = M[r][c];
return P;
}
PANGOLIN_DEPRECATED
inline TooN::Matrix<4,4> ToTooN(const OpenGlMatrix& ms)
{
TooN::Matrix<4,4> m;
int el = 0;
for( int c=0; c<4; ++c )
for( int r=0; r<4; ++r )
m(r,c) = ms.m[el++];
return m;
}
PANGOLIN_DEPRECATED
inline TooN::SE3<> ToTooN_SE3(const OpenGlMatrix& ms)
{
TooN::Matrix<4,4> m = ms;
const TooN::SO3<> R(m.slice<0,0,3,3>());
const TooN::Vector<3> t = m.T()[3].slice<0,3>();
return TooN::SE3<>(R,t);
}
#endif // HAVE_TOON
#ifdef HAVE_OCULUS
inline OpenGlMatrix::OpenGlMatrix(const OVR::Matrix4f& mat)
{
for(int r=0; r<4; ++r )
for(int c=0; c<4; ++c )
m[c*4+r] = mat.M[r][c];
}
inline OpenGlMatrix::operator const OVR::Matrix4f() const
{
OVR::Matrix4f mat;
for(int r=0; r<4; ++r )
for(int c=0; c<4; ++c )
mat.M[r][c] = m[c*4+r];
return mat;
}
#endif // HAVE_OCULUS
}

View File

@@ -0,0 +1,43 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
namespace pangolin
{
class PANGOLIN_EXPORT UserApp
{
public:
virtual ~UserApp() {}
virtual void Init() {}
virtual void Render() = 0;
};
}

View File

@@ -0,0 +1,235 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <functional>
#include <vector>
#include <pangolin/display/viewport.h>
#include <pangolin/display/attach.h>
namespace pangolin
{
enum Layout
{
LayoutOverlay,
LayoutVertical,
LayoutHorizontal,
LayoutEqual,
LayoutEqualVertical,
LayoutEqualHorizontal
};
enum Lock {
LockLeft = 0,
LockBottom = 0,
LockCenter = 1,
LockRight = 2,
LockTop = 2
};
// Forward declarations
struct Handler;
class OpenGlRenderState;
/// A Display manages the location and resizing of an OpenGl viewport.
struct PANGOLIN_EXPORT View
{
View(double aspect=0.0)
: aspect(aspect), top(1.0),left(0.0),right(1.0),bottom(0.0), hlock(LockCenter),vlock(LockCenter),
layout(LayoutOverlay), scroll_offset(0), show(1), zorder(0), handler(0), scroll_show(1) {}
virtual ~View() {}
//! Activate Displays viewport for drawing within this area
void Activate() const;
//! Activate Displays and set State Matrices
void Activate(const OpenGlRenderState& state ) const;
//! Activate Displays viewport and Scissor for drawing within this area
void ActivateAndScissor() const;
//! Activate Displays viewport and Scissor for drawing within this area
void ActivateScissorAndClear() const;
//! Activate Display and set State Matrices
void ActivateAndScissor(const OpenGlRenderState& state ) const;
//! Activate Display and set State Matrices
void ActivateScissorAndClear(const OpenGlRenderState& state ) const;
//! Activate Display and setup coordinate system for 2d pixel View coordinates
void ActivatePixelOrthographic() const;
//! Activate Display and reset coordinate system to OpenGL default
void ActivateIdentity() const;
//! Return closest depth buffer value within radius of window (winx,winy)
GLfloat GetClosestDepth(int winx, int winy, int radius) const;
//! Obtain camera space coordinates of scene at pixel (winx, winy, winzdepth)
//! winzdepth can be obtained from GetClosestDepth
void GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
//! Obtain object space coordinates of scene at pixel (winx, winy, winzdepth)
//! winzdepth can be obtained from GetClosestDepth
void GetObjectCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
//! Given the specification of Display, compute viewport
virtual void Resize(const Viewport& parent);
//! Instruct all children to resize
virtual void ResizeChildren();
//! Perform any automatic rendering for this View.
//! Default implementation simply instructs children to render themselves.
virtual void Render();
//! Instruct all children to render themselves if appropriate
virtual void RenderChildren();
//! Set this view as the active View to receive input
View& SetFocus();
//! Returns true iff this view currently has focus and will receive user input
bool HasFocus() const;
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right);
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, bool keep_aspect);
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect);
//! Designate handler for accepting mouse / keyboard input.
View& SetHandler(Handler* handler);
//! Set drawFunc as the drawing function for this view
View& SetDrawFunction(const std::function<void(View&)>& drawFunc);
//! Force this view to have the given aspect, whilst fitting snuggly
//! within the parent. A negative value with 'over-draw', fitting the
//! smaller side of the parent.
View& SetAspect(double aspect);
//! Set how this view should be positioned relative to its parent
View& SetLock(Lock horizontal, Lock vertical );
//! Set layout policy for this view
View& SetLayout(Layout layout);
//! Add view as child
View& AddDisplay(View& view);
//! Show / hide this view
View& Show(bool show=true);
//! Toggle this views visibility
void ToggleShow();
//! Return whether this view should be shown.
//! This method should be checked if drawing manually
bool IsShown() const;
//! Returns viewport reflecting space that will actually get drawn
//! The minimum of vp and v
Viewport GetBounds() const;
//! Specify that this views region in the framebuffer should be saved to
//! a file just before the buffer is flipped.
void SaveOnRender(const std::string& filename_prefix);
//! Specify that this views region in the framebuffer should be saved to
//! a video just before the buffer is flipped
void RecordOnRender(const std::string& record_uri);
//! Uses the views default render method to draw into an FBO 'scale' times
//! the size of the view and save to a file.
void SaveRenderNow(const std::string& filename_prefix, float scale = 1);
//! Return number of child views attached to this view
size_t NumChildren() const;
//! Return (i)th child of this view
View& operator[](size_t i);
//! Return number of visible child views attached to this view.
size_t NumVisibleChildren() const;
//! Return visible child by index.
View& VisibleChild(size_t i);
//! Return visible child at window coords x,y
View* FindChild(int x, int y);
// Desired width / height aspect (0 if dynamic)
double aspect;
// Bounds to fit display within
Attach top, left, right, bottom;
Lock hlock;
Lock vlock;
Layout layout;
int scroll_offset;
// Cached client area (space allocated from parent)
Viewport vp;
// Cached absolute viewport (recomputed on resize - respects aspect)
Viewport v;
// Should this view be displayed?
bool show;
// Child views are rendered in order of low to high z-order
// Views default to 0 z-order
int zorder;
// Input event handler (if any)
Handler* handler;
// Map for sub-displays (if any)
std::vector<View*> views;
// External draw function
std::function<void(View&)> extern_draw_function;
private:
// Private copy constructor
View(View&) { /* Do Not copy - take reference instead*/ }
bool scroll_show;
};
}

View File

@@ -0,0 +1,65 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin
{
/// Encapsulates OpenGl Viewport.
struct PANGOLIN_EXPORT Viewport
{
Viewport() : l(0),b(0),w(0),h(0) {}
Viewport(GLint l,GLint b,GLint w,GLint h) : l(l),b(b),w(w),h(h) {}
void Activate() const;
void ActivateIdentity() const;
void ActivatePixelOrthographic() const;
void Scissor() const;
void ActivateAndScissor() const;
bool Contains(int x, int y) const;
Viewport Inset(int i) const;
Viewport Inset(int horiz, int vert) const;
Viewport Intersect(const Viewport& vp) const;
void GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
static void DisableScissor();
GLint r() const { return l+w;}
GLint t() const { return b+h;}
GLfloat aspect() const { return (GLfloat)w / (GLfloat)h; }
GLint l,b,w,h;
};
}

View File

@@ -0,0 +1,141 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/view.h>
#include <pangolin/var/var.h>
#include <pangolin/handler/handler.h>
#include <pangolin/gl/glfont.h>
#include <functional>
namespace pangolin
{
PANGOLIN_EXPORT
View& CreatePanel(const std::string& name);
struct PANGOLIN_EXPORT Panel : public View
{
Panel();
Panel(const std::string& auto_register_var_prefix);
void Render();
void ResizeChildren();
static void AddVariable(void* data, const std::string& name, VarValueGeneric& var, bool brand_new);
};
template<typename T>
struct Widget : public View, Handler, Var<T>
{
Widget(std::string title, VarValueGeneric& tv)
: Var<T>(tv), title(title)
{
handler = this;
}
std::string title;
};
struct PANGOLIN_EXPORT Button : public Widget<bool>
{
Button(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool down;
};
struct PANGOLIN_EXPORT FunctionButton : public Widget<std::function<void(void)> >
{
FunctionButton(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool down;
};
struct PANGOLIN_EXPORT Checkbox : public Widget<bool>
{
Checkbox(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
Viewport vcb;
};
struct PANGOLIN_EXPORT Slider : public Widget<double>
{
Slider(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool lock_bounds;
bool logscale;
bool is_integral_type;
};
struct PANGOLIN_EXPORT TextInput : public Widget<std::string>
{
TextInput(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Render();
std::string edit;
GlText gledit;
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool can_edit;
bool do_edit;
int sel[2];
};
}

View File

@@ -0,0 +1,90 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2016 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <exception>
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
class GlContextInterface
{
public:
virtual ~GlContextInterface() {}
};
class WindowInterface
{
public:
virtual ~WindowInterface() {}
virtual void ToggleFullscreen() = 0;
virtual void Move(int x, int y) = 0;
virtual void Resize(unsigned int w, unsigned int h) = 0;
/**
* @brief MakeCurrent set the current context
* to be called in a thread before accessing OpenGL
*/
virtual void MakeCurrent() = 0;
/**
* @brief RemoveCurrent remove the current context
* to be called at the end of a thread
*/
virtual void RemoveCurrent() = 0;
virtual void ProcessEvents() = 0;
virtual void SwapBuffers() = 0;
};
struct PANGOLIN_EXPORT WindowException : std::exception
{
WindowException(std::string str) : desc(str) {}
WindowException(std::string str, std::string detail) {
desc = str + "\n\t" + detail;
}
~WindowException() throw() {}
const char* what() const throw() { return desc.c_str(); }
std::string desc;
};
struct PANGOLIN_EXPORT WindowExceptionNoKnownHandler : public WindowException
{
WindowExceptionNoKnownHandler(const std::string& scheme)
: WindowException("No known window handler for URI '" + scheme + "'")
{
}
};
}

View File

@@ -0,0 +1,114 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011-2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <memory>
#include <vector>
#include <algorithm>
#include <pangolin/utils/uri.h>
namespace pangolin
{
template<typename T>
struct FactoryInterface
{
typedef T FactoryItem;
virtual ~FactoryInterface() = default;
virtual std::unique_ptr<T> Open(const Uri& uri) = 0;
};
template<typename T>
class FactoryRegistry
{
public:
// IMPORTANT: Implement for each templated instantiation within a seperate compilation unit.
static FactoryRegistry<T>& I();
~FactoryRegistry()
{
}
void RegisterFactory(std::shared_ptr<FactoryInterface<T>> factory, uint32_t precedence, const std::string& scheme_name )
{
FactoryItem item = {precedence, scheme_name, factory};
factories.push_back( item );
std::sort(factories.begin(), factories.end());
}
void UnregisterFactory(FactoryInterface<T>* factory)
{
for( auto i = factories.end()-1; i != factories.begin(); --i)
{
if( i->factory.get() == factory ) {
factories.erase(i);
}
}
}
void UnregisterAllFactories()
{
factories.clear();
}
std::unique_ptr<T> Open(const Uri& uri)
{
// Iterate over all registered factories in order of precedence.
for(auto& item : factories) {
if( item.scheme == uri.scheme) {
std::unique_ptr<T> video = item.factory->Open(uri);
if(video) {
return video;
}
}
}
return std::unique_ptr<T>();
}
private:
struct FactoryItem
{
uint32_t precedence;
std::string scheme;
std::shared_ptr<FactoryInterface<T>> factory;
bool operator<(const FactoryItem& rhs) const {
return precedence < rhs.precedence;
}
};
// Priority, Factory tuple
std::vector<FactoryItem> factories;
};
#define PANGOLIN_REGISTER_FACTORY(x) void Register ## x ## Factory()
}

View File

@@ -0,0 +1,95 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PANGOLIN_GEOMETRY_H
#define PANGOLIN_GEOMETRY_H
#include <map>
#include <unordered_map>
#include <vector>
#include <pangolin/image/typed_image.h>
#include <pangolin/compat/variant.h>
#ifdef HAVE_EIGEN
#include <Eigen/Geometry>
#endif
namespace pangolin
{
struct Geometry
{
struct Element : public ManagedImage<uint8_t> {
Element() = default;
Element(Element&&) = default;
Element& operator=(Element&&) = default;
Element(size_t stride_bytes, size_t num_elements)
: ManagedImage<uint8_t>(stride_bytes, num_elements)
{}
using Attribute = variant<Image<float>,Image<uint32_t>,Image<uint16_t>,Image<uint8_t>>;
// "vertex", "rgb", "normal", "uv", "tris", "quads", ...
std::map<std::string, Attribute> attributes;
};
// Store vertices and attributes
std::map<std::string, Element> buffers;
// Stores index buffers for each sub-object
std::multimap<std::string, Element> objects;
// Stores pixmaps
std::map<std::string, TypedImage> textures;
};
pangolin::Geometry::Element::Attribute MakeAttribute(uint32_t gldatatype, size_t num_items, size_t count_per_item, void* ptr, size_t pitch_bytes);
pangolin::Geometry LoadGeometry(const std::string& filename);
#ifdef HAVE_EIGEN
inline Eigen::AlignedBox3f GetAxisAlignedBox(const Geometry& geom)
{
Eigen::AlignedBox3f box;
box.setEmpty();
for(const auto& b : geom.buffers) {
const auto& it_vert = b.second.attributes.find("vertex");
if(it_vert != b.second.attributes.end()) {
const Image<float>& vs = get<Image<float>>(it_vert->second);
for(size_t i=0; i < vs.h; ++i) {
const Eigen::Map<const Eigen::Vector3f> v(vs.RowPtr(i));
box.extend(v);
}
}
}
return box;
}
#endif
}
#endif // PANGOLIN_GEOMETRY_H

View File

@@ -0,0 +1,34 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/geometry/geometry.h>
namespace pangolin {
pangolin::Geometry LoadGeometryObj(const std::string& filename);
}

View File

@@ -0,0 +1,165 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/platform.h>
#include <pangolin/compat/variant.h>
#include <pangolin/geometry/geometry.h>
#include <fstream>
#include <vector>
#include <algorithm>
namespace pangolin
{
#define PLY_GROUP_LIST(m) m(PlyHeader) m(PlyFormat) m(PlyType)
#define PLY_HEADER_LIST(m) m(ply) m(format) m(comment) m(property) m(element) m(end_header)
#define PLY_FORMAT_LIST(m) m(ascii) m(binary_big_endian) m(binary_little_endian)
#define PLY_TYPE_LIST(m) m(char) m(int8) m(uchar) m(uint8) m(short) m(int16) m(ushort) m(uint16) m(int) m(int32) m(uint) m(uint32) m(float) m(float32) m(double) m(float64) m(list)
// Define Enums / strings
enum PlyHeader {
#define FORMAT_ENUM(x) PlyHeader_##x,
PLY_HEADER_LIST(FORMAT_ENUM)
PlyHeaderSize
#undef FORMAT_ENUM
};
enum PlyFormat {
#define FORMAT_ENUM(x) PlyFormat_##x,
PLY_FORMAT_LIST(FORMAT_ENUM)
PlyFormatSize
#undef FORMAT_ENUM
};
enum PlyType {
#define FORMAT_ENUM(x) PlyType_##x,
PLY_TYPE_LIST(FORMAT_ENUM)
PlyTypeSize
#undef FORMAT_ENUM
};
const size_t PlyTypeGl[] = {
// char, int8 -> GL_BYTE
0x1400, 0x1400,
// uchar, uint8 -> GL_UNSIGNED_BYTE
0x1401, 0x1401,
// short, int16 -> GL_SHORT
0x1402, 0x1402,
// ushort, uint16 -> GL_UNSIGNED_SHORT
0x1403, 0x1403,
// int, int32 -> GL_INT
0x1404, 0x1404,
// uint, uint32 -> GL_UNSIGNED_INT
0x1405, 0x1405,
// float, float32 -> GL_FLOAT
0x1406, 0x1406,
// double, float64 -> GL_DOUBLE
0x140A, 0x140A,
// list -> GL_NONE
0
};
#undef FORMAT_ENUM
struct PlyPropertyDetails
{
std::string name;
// Type of property (GLenum)
size_t type;
// Type of list index if a list, or 0 otherwise. (GLenum)
size_t list_index_type;
// Offset from element start
size_t offset_bytes;
// Number of items in the list. 1 if not a list. -1 if unknown.
int num_items;
bool isList() const {
return list_index_type > 0;
}
};
struct PlyElementDetails
{
std::string name;
int num_items;
int stride_bytes;
std::vector<PlyPropertyDetails> properties;
inline std::vector<PlyPropertyDetails>::iterator FindProperty(const std::string& name)
{
return std::find_if(properties.begin(), properties.end(),
[&name](const PlyPropertyDetails& p){ return p.name == name;}
);
}
};
struct PlyHeaderDetails
{
PlyFormat format;
std::string version;
std::vector<PlyElementDetails> elements;
inline std::vector<PlyElementDetails>::iterator FindElement(const std::string& name)
{
return std::find_if(elements.begin(), elements.end(),
[&name](const PlyElementDetails& el){ return el.name == name;}
);
}
};
void ParsePlyHeader(PlyHeaderDetails& ply, std::istream& is);
struct PlyBuffer
{
size_t index_size_bytes;
size_t element_item_size_bytes;
std::vector<unsigned char> data;
};
void ParsePlyAscii(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
// Convert Seperate "x","y","z" attributes into a single "vertex" attribute
void StandardizeXyzToVertex(pangolin::Geometry& geom);
// The Artec scanner saves with these attributes, for example
void StandardizeMultiTextureFaceToXyzuv(pangolin::Geometry& geom);
void Standardize(pangolin::Geometry& geom);
void ParsePlyLE(pangolin::Geometry& geom, PlyHeaderDetails& ply, std::istream& is);
void ParsePlyBE(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
void AttachAssociatedTexturesPly(pangolin::Geometry& geom, const std::string& filename);
pangolin::Geometry LoadGeometryPly(const std::string& filename);
}

View File

@@ -0,0 +1,87 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/geometry/geometry.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glsl.h>
namespace pangolin {
struct GlGeometry
{
GlGeometry() = default;
GlGeometry(GlGeometry&&) = default;
GlGeometry& operator=(GlGeometry&&) = default;
struct Element : public GlBufferData
{
Element() = default;
Element(Element&&) = default;
Element& operator=(Element&&) = default;
Element(GlBufferType buffer_type, size_t size_bytes, GLenum gluse, uint8_t* data)
: GlBufferData(buffer_type, size_bytes, gluse, data)
{}
inline bool HasAttribute(const std::string& name) const {
return attributes.find(name) != attributes.end();
}
struct Attribute {
// Stuff needed by glVertexAttribPointer
GLenum gltype;
size_t count_per_element;
size_t num_elements;
size_t offset;
size_t stride_bytes;
};
std::map<std::string, Attribute> attributes;
};
inline bool HasAttribute(const std::string& name) const
{
for(const auto& b : buffers) if(b.second.HasAttribute(name)) return true;
return false;
}
// Store vertices and attributes
std::map<std::string, Element> buffers;
// Stores index buffers for each sub-object
std::multimap<std::string, Element> objects;
// Stores pixmaps
std::map<std::string, GlTexture> textures;
};
GlGeometry::Element ToGlGeometry(const Geometry::Element& el, GlBufferType buffertype);
GlGeometry ToGlGeometry(const Geometry& geom);
void GlDraw(GlSlProgram& prog, const GlGeometry& geom, const GlTexture *matcap);
}

View File

@@ -0,0 +1,283 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
#include <algorithm>
// Cg includes
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include "gl.h"
#ifdef HAVE_TOON
#include <TooN/TooN.h>
#endif // HAVE_TOON
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
/// Lightweight object wrapper for NVidia Cg Shader program objects.
class CgProgram
{
friend class CgLoader;
public:
void SetUniform(const std::string& name, GlTexture& tex);
void SetUniform(const std::string& name, float f);
void SetUniform(const std::string& name, float v0, float v1);
void SetUniform(const std::string& name, float v0, float v1, float v2, float v3);
#ifdef HAVE_TOON
void SetUniform(const std::string& name, const TooN::Vector<2>& v );
void SetUniform(const std::string& name, const TooN::Vector<3>& v );
template <int R, int C>
void SetUniform(const std::string& name, const TooN::Matrix<R,C>& M );
#endif
void UpdateParams();
protected:
CGprogram mProg;
CGcontext mContext;
CGprofile mProfile;
};
class CgLoader
{
public:
CgLoader();
~CgLoader();
// Call AFTER glewInit (or similar)
void Initialise();
CgProgram LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader );
void EnableProgram(CgProgram program);
void DisablePrograms();
void RenderDummyQuad();
void RenderDummyQuadWithTexCoords(int w, int h);
protected:
CGcontext mContext;
CGprofile mFragmentProfile;
CGprofile mVertexProfile;
};
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline bool cgOkay()
{
CGerror error;
const char *string = cgGetLastErrorString(&error);
if (error != CG_NO_ERROR) {
std::cout << "CG Error: " << string << std::endl;
// assert(0);
return false;
}
return true;
}
inline CgLoader::CgLoader()
:mContext(0)
{
}
inline CgLoader::~CgLoader()
{
if(mContext)
{
// Destroying context destroys all programs associated with it
cgDestroyContext(mContext);
}
}
inline void CgLoader::Initialise()
{
mContext = cgCreateContext();
cgSetParameterSettingMode(mContext, CG_DEFERRED_PARAMETER_SETTING);
cgOkay();
mFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(mFragmentProfile);
cgOkay();
mVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
cgGLSetOptimalOptions(mVertexProfile);
cgOkay();
}
inline CgProgram CgLoader::LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader )
{
if( !mContext ) {
Initialise();
}
CgProgram prog;
prog.mContext = mContext;
prog.mProfile = isVertexShader ? mVertexProfile : mFragmentProfile;
prog.mProg = cgCreateProgramFromFile( prog.mContext, CG_SOURCE, file.c_str(), prog.mProfile, function.c_str(), NULL);
if( !cgOkay() )
{
std::cout << cgGetLastListing(mContext) << std::endl;
assert(0);
}
cgGLLoadProgram(prog.mProg);
if( !cgOkay() )
{
const char* err = cgGetProgramString( prog.mProg, CG_COMPILED_PROGRAM );
int pos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
std::cout << err << std::endl;
std::cout << "@ " << pos << std::endl;
assert(0);
}
return prog;
}
inline void CgLoader::EnableProgram(CgProgram program)
{
cgGLBindProgram(program.mProg);
cgGLEnableProfile(program.mProfile);
cgOkay();
}
inline void CgLoader::DisablePrograms()
{
cgGLDisableProfile(mFragmentProfile);
cgGLDisableProfile(mVertexProfile);
}
inline void CgLoader::RenderDummyQuad()
{
glBegin(GL_QUADS);
glVertex2d(-1,1);
glVertex2d(1,1);
glVertex2d(1,-1);
glVertex2d(-1,-1);
glEnd();
}
inline void CgLoader::RenderDummyQuadWithTexCoords(int w, int h)
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2d(-1,-1);
glTexCoord2f(w, 0);
glVertex2d(1,-1);
glTexCoord2f(w, h);
glVertex2d(1,1);
glTexCoord2f(0, h);
glVertex2d(-1,1);
glEnd();
}
void CgProgram::SetUniform(const std::string& name, float f)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgSetParameter1f( p, f );
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, GlTexture& tex)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetTextureParameter(p, tex.tid );
cgGLEnableTextureParameter(p);
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, float v0, float v1, float v2, float v3)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter4f(p, v0,v1,v2,v3);
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, float v0, float v1)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter2f(p, v0,v1);
cgUpdateProgramParameters(mProg);
}
#ifdef HAVE_TOON
void CgProgram::SetUniform(const std::string& name, const TooN::Vector<2>& v )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter2f(p, v[0],v[1] );
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, const TooN::Vector<3>& v )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter3f(p, v[0],v[1],v[2] );
cgUpdateProgramParameters(mProg);
}
template <int R, int C>
void CgProgram::SetUniform(const std::string& name, const TooN::Matrix<R,C>& M )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
float Mdata[R*C];
int i=0;
for( int r=0; r<R; ++r )
for( int c=0; c<C; ++c )
Mdata[i++] = (float)(M[r][c]);
cgGLSetMatrixParameterfr(p, Mdata );
cgUpdateProgramParameters(mProg);
}
#endif
void CgProgram::UpdateParams()
{
cgUpdateProgramParameters(mProg);
}
}

View File

@@ -0,0 +1,178 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <cmath>
#include <stdexcept>
namespace pangolin
{
/// Represent OpenGL floating point colour: Red, Green and Blue with alpha.
struct Colour
{
inline static Colour White() {
return Colour(1.0f,1.0f,1.0f,1.0f);
}
inline static Colour Black() {
return Colour(0.0f,0.0f,0.0f,1.0f);
}
inline static Colour Red() {
return Colour(1.0f,0.0f,0.0f,1.0f);
}
inline static Colour Green() {
return Colour(0.0f,1.0f,0.0f,1.0f);
}
inline static Colour Blue() {
return Colour(0.0f,0.0f,1.0f,1.0f);
}
inline static Colour Unspecified() {
return Colour(
std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::quiet_NaN()
);
}
/// Default constructs white.
inline Colour()
: red(1.0f), green(1.0f), blue(1.0f), alpha(1.0f)
{
}
/// Construct from component values
inline Colour(const float red, const float green, const float blue, const float alpha = 1.0f)
: red(red), green(green), blue(blue), alpha(alpha)
{
}
/// Construct from rgba array.
inline Colour(const float rgba[4])
{
r = rgba[0];
g = rgba[1];
b = rgba[2];
a = rgba[3];
}
/// Return pointer to OpenGL compatible RGBA array.
inline float* Get()
{
return c;
}
/// Return this colour with alpha adjusted.
inline Colour WithAlpha(const float alpha)
{
return Colour(r,g,b,alpha);
}
/// Construct from HSV Colour
/// @param hue Colour hue in range [0,1]
/// @param sat Saturation in range [0,1]
/// @param val Value / Brightness in range [0,1].
static inline Colour Hsv(const float hue, const float sat = 1.0f, const float val = 1.0f, const float alpha = 1.0f)
{
const float h = 6.0f * hue;
const int i = (int)floor(h);
const float f = (i%2 == 0) ? 1-(h-i) : h-i;
const float m = val * (1-sat);
const float n = val * (1-sat*f);
switch(i)
{
case 0: return Colour(val,n,m,alpha);
case 1: return Colour(n,val,m,alpha);
case 2: return Colour(m,val,n,alpha);
case 3: return Colour(m,n,val,alpha);
case 4: return Colour(n,m,val,alpha);
case 5: return Colour(val,m,n,alpha);
default:
throw std::runtime_error("Found extra colour in rainbow.");
}
}
union {
struct {
float red;
float green;
float blue;
float alpha;
};
struct {
float r;
float g;
float b;
float a;
};
float c[4];
};
};
/// A ColourWheel is like a continuous colour palate that can be sampled.
/// In the future, different ColourWheels will be supported, but this one
/// is based on sampling hues in HSV colourspace. An indefinite number of
/// unique colours are sampled using the golden angle.
class ColourWheel
{
public:
/// Construct ColourWheel with Saturation, Value and Alpha constant.
inline ColourWheel(float saturation = 0.5f, float value = 1.0f, float alpha = 1.0f)
: unique_colours(0), sat(saturation), val(value), alpha(alpha)
{
}
/// Use Golden ratio (/angle) to pick well spaced colours.
inline Colour GetColourBin(int i) const
{
float hue = i * 0.5f * (3.0f - sqrt(5.0f));
hue -= (int)hue;
return Colour::Hsv(hue,sat,val,alpha);
}
/// Return next unique colour from ColourWheel.
inline Colour GetUniqueColour()
{
return GetColourBin(unique_colours++);
}
/// Reset colour wheel counter to initial state
inline void Reset() {
unique_colours = 0;
}
protected:
int unique_colours;
float sat;
float val;
float alpha;
};
}

View File

@@ -0,0 +1,320 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <stack>
#include <pangolin/opengl_render_state.h>
#include <pangolin/glsl.h>
namespace pangolin {
class GlEngine
{
public:
const char* vert =
"attribute vec4 a_position;\n"
"attribute vec4 a_color;\n"
"attribute vec3 a_normal;\n"
"attribute vec2 a_texcoord;\n"
"uniform vec4 u_color;\n"
"uniform mat4 u_modelViewMatrix;\n"
"uniform mat4 u_modelViewProjectionMatrix;\n"
"varying vec4 v_frontColor;\n"
"varying vec2 v_texcoord;\n"
"void main() {\n"
" gl_Position = u_modelViewProjectionMatrix * a_position;\n"
" v_frontColor = u_color;\n"
" v_texcoord = a_texcoord;\n"
"}\n";
const char* frag =
#ifdef HAVE_GLES_2
"precision mediump float;\n"
#endif // HAVE_GLES_2
"varying vec4 v_frontColor;\n"
"varying vec2 v_texcoord;\n"
"uniform sampler2D u_texture;\n"
"uniform bool u_textureEnable;\n"
"void main() {\n"
" gl_FragColor = v_frontColor;\n"
" if(u_textureEnable) {\n"
" gl_FragColor *= texture2D(u_texture, v_texcoord);\n"
" }\n"
"}\n";
GlEngine()
{
// Initialise default state
projection.push(IdentityMatrix());
modelview.push(IdentityMatrix());
currentmatrix = &modelview;
// Set GL_TEXTURE0 as default active texture
glActiveTexture(GL_TEXTURE0);
// Compile and link shaders
prog_fixed.AddShader(GlSlVertexShader, vert);
prog_fixed.AddShader(GlSlFragmentShader, frag);
prog_fixed.BindPangolinDefaultAttribLocationsAndLink();
// Save locations of uniforms
u_color = prog_fixed.GetUniformHandle("u_color");
u_modelViewMatrix = prog_fixed.GetUniformHandle("u_modelViewMatrix");
u_modelViewProjectionMatrix = prog_fixed.GetUniformHandle("u_modelViewProjectionMatrix");
u_texture = prog_fixed.GetUniformHandle("u_texture");
u_textureEnable = prog_fixed.GetUniformHandle("u_textureEnable");
// Initialise default uniform values
UpdateMatrices();
SetColor(1.0,1.0,1.0,1.0);
}
void UpdateMatrices()
{
OpenGlMatrix pmv = projection.top() * modelview.top();
prog_fixed.SaveBind();
glUniformMatrix4fv( u_modelViewMatrix, 1, false, modelview.top().m );
glUniformMatrix4fv( u_modelViewProjectionMatrix, 1, false, pmv.m );
prog_fixed.Unbind();
}
void SetColor(float r, float g, float b, float a)
{
prog_fixed.SaveBind();
glUniform4f( u_color, r, g, b, a);
prog_fixed.Unbind();
}
void EnableTexturing(GLboolean v)
{
prog_fixed.SaveBind();
glUniform1i( u_textureEnable, v);
prog_fixed.Unbind();
}
//protected:
std::stack<OpenGlMatrix> projection;
std::stack<OpenGlMatrix> modelview;
std::stack<OpenGlMatrix>* currentmatrix;
GLenum matrixmode;
float color[4];
GlSlProgram prog_fixed;
GLint u_color;
GLint u_modelViewMatrix;
GLint u_modelViewProjectionMatrix;
GLint u_texture;
GLint u_textureEnable;
};
GlEngine& glEngine();
}
///////////////////////////////////////////////////////////////////////////////
// OpenGL 1.0 compatibility - Emulate fixed pipeline
///////////////////////////////////////////////////////////////////////////////
// Missing defines that we'll be using
#define GL_MODELVIEW 0x1700
#define GL_PROJECTION 0x1701
#define GL_SHADE_MODEL 0x0B54
#define GL_POINT_SIZE 0x0B11
#define GL_MULTISAMPLE 0x809D
#define GL_LIGHTING 0x0B50
#define GL_POINT_SMOOTH 0x0B10
#define GL_LINE_SMOOTH 0x0B20
#define GL_SCISSOR_TEST 0x0C11
#define GL_COLOR_MATERIAL 0x0B57
#define GL_FLAT 0x1D00
#define GL_SMOOTH 0x1D01
#define GL_MODULATE 0x2100
#define GL_DECAL 0x2101
#define GL_ADD 0x0104
#define GL_TEXTURE_ENV_MODE 0x2200
#define GL_TEXTURE_ENV_COLOR 0x2201
#define GL_TEXTURE_ENV 0x2300
#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
#define GL_POINT_SMOOTH_HINT 0x0C51
#define GL_LINE_SMOOTH_HINT 0x0C52
#define GL_VERTEX_ARRAY 0x8074
#define GL_NORMAL_ARRAY 0x8075
#define GL_COLOR_ARRAY 0x8076
#define GL_TEXTURE_COORD_ARRAY 0x8078
inline void glEnableClientState(GLenum cap)
{
pangolin::GlEngine& gl = pangolin::glEngine();
if(cap == GL_VERTEX_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
}else if(cap == GL_COLOR_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_COLOUR);
}else if(cap == GL_NORMAL_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_NORMAL);
}else if(cap == GL_TEXTURE_COORD_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
gl.EnableTexturing(true);
}else{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
}
inline void glDisableClientState(GLenum cap)
{
pangolin::GlEngine& gl = pangolin::glEngine();
if(cap == GL_VERTEX_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
}else if(cap == GL_COLOR_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_COLOUR);
}else if(cap == GL_NORMAL_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_NORMAL);
}else if(cap == GL_TEXTURE_COORD_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
gl.EnableTexturing(false);
}else{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
}
inline void glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
{
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_POSITION, size, type, GL_FALSE, stride, pointer);
}
inline void glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
{
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_TEXCOORD, size, type, GL_FALSE, stride, pointer);
}
inline void glMatrixMode(GLenum mode)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix = (mode == pangolin::GlProjectionStack) ? &gl.projection : &gl.modelview;
}
inline void glLoadIdentity()
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->top() = pangolin::IdentityMatrix();
gl.UpdateMatrices();
}
inline void glLoadMatrixf(const GLfloat* m)
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
for(int i=0; i<16; ++i) cm[i] = (pangolin::GLprecision)m[i];
gl.UpdateMatrices();
}
inline void glLoadMatrixd(const GLdouble* m)
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
for(int i=0; i<16; ++i) cm[i] = (pangolin::GLprecision)m[i];
gl.UpdateMatrices();
}
inline void glMultMatrixf(const GLfloat* m)
{
// pangolin::GlEngine& gl = pangolin::glEngine();
// float res[16];
// pangolin::MatMul<4,4,4,float>(res, m, gl.currentmatrix->m );
// std::memcpy(gl.currentmatrix->m, res, sizeof(float) * 16 );
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glMultMatrixd(const GLdouble* m)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glPushMatrix(void)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->push(gl.currentmatrix->top());
}
inline void glPopMatrix(void)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->pop();
gl.UpdateMatrices();
}
inline void glTranslatef(GLfloat x, GLfloat y, GLfloat z )
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
cm[12] += x;
cm[13] += y;
cm[14] += z;
gl.UpdateMatrices();
}
inline void glOrtho(
GLdouble l, GLdouble r,
GLdouble b, GLdouble t,
GLdouble n, GLdouble f)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->top() = pangolin::ProjectionMatrixOrthographic(l,r,b,t,n,f);
gl.UpdateMatrices();
}
inline void glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
pangolin::glEngine().SetColor(red,green,blue,alpha);
}
inline void glShadeModel( GLenum mode)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glPointSize(GLfloat size)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glTexEnvf( GLenum target,
GLenum pname,
GLfloat param)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include <pangolin/platform.h>
#define GLdouble GLfloat
#define glClearDepth glClearDepthf
#define glFrustum glFrustumf
#define glColor4fv(a) glColor4f(a[0], a[1], a[2], a[3])
#define glColor3fv(a) glColor4f(a[0], a[1], a[2], 1.0f)
#define glColor3f(a,b,c) glColor4f(a, b, c, 1.0f)
#define GL_CLAMP GL_CLAMP_TO_EDGE
#ifdef HAVE_GLES_2
#define glGenFramebuffersEXT glGenFramebuffers
#define glDeleteFramebuffersEXT glDeleteFramebuffers
#define glBindFramebufferEXT glBindFramebuffer
#define glDrawBuffers glDrawBuffers
#define glFramebufferTexture2DEXT glFramebufferTexture2D
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT16 // <----
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0
#define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT
#else
#define glOrtho glOrthof
#define glGenFramebuffersEXT glGenFramebuffersOES
#define glDeleteFramebuffersEXT glDeleteFramebuffersOES
#define glBindFramebufferEXT glBindFramebufferOES
#define glDrawBuffers glDrawBuffersOES
#define glFramebufferTexture2DEXT glFramebufferTexture2DOES
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0_OES
#endif
#define glGetDoublev glGetFloatv
#ifdef HAVE_GLES_2
#include <pangolin/gl2engine.h>
#endif
inline void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
GLfloat verts[] = { x1,y1, x2,y1, x2,y2, x1,y2 };
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glRecti(int x1, int y1, int x2, int y2)
{
GLfloat verts[] = { (float)x1,(float)y1, (float)x2,(float)y1,
(float)x2,(float)y2, (float)x1,(float)y2 };
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}

View File

@@ -0,0 +1,273 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/viewport.h>
#include <pangolin/gl/glinclude.h>
#include <pangolin/image/image_io.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
#include <cstdlib>
#include <iostream>
#include <math.h>
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
class PANGOLIN_EXPORT GlTexture
{
public:
//! internal_format normally one of GL_RGBA8, GL_LUMINANCE8, GL_INTENSITY16
GlTexture(GLint width, GLint height, GLint internal_format = GL_RGBA8, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL );
// Construct this texture from a CPU image
GlTexture(const TypedImage& img, bool sampling_linear=true);
//! Move Constructor / asignment
GlTexture(GlTexture&& tex);
GlTexture& operator=(GlTexture&& tex);
//! Default constructor represents 'no texture'
GlTexture();
virtual ~GlTexture();
bool IsValid() const;
//! Delete OpenGL resources and fall back to representing 'no texture'
void Delete();
//! Reinitialise teture width / height / format
virtual void Reinitialise(GLsizei width, GLsizei height, GLint internal_format = GL_RGBA8, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL );
void Bind() const;
void Unbind() const;
//! data_layout normally one of GL_LUMINANCE, GL_RGB, ...
//! data_type normally one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT
void Upload(const void* image, GLenum data_format = GL_LUMINANCE, GLenum data_type = GL_FLOAT);
//! Upload data to texture, overwriting a sub-region of it.
//! data ptr contains packed data_w x data_h of pixel data.
void Upload(const void* data,
GLsizei tex_x_offset, GLsizei tex_y_offset,
GLsizei data_w, GLsizei data_h,
GLenum data_format, GLenum data_type
);
void Load(const TypedImage& image, bool sampling_linear = true);
void LoadFromFile(const std::string& filename, bool sampling_linear = true);
void Download(void* image, GLenum data_layout = GL_LUMINANCE, GLenum data_type = GL_FLOAT) const;
void Download(TypedImage& image) const;
void CopyFrom(const GlTexture& tex);
void Save(const std::string& filename, bool top_line_first = true);
void SetLinear();
void SetNearestNeighbour();
void RenderToViewport(const bool flip) const;
void RenderToViewport() const;
void RenderToViewport(Viewport tex_vp, bool flipx=false, bool flipy=false) const;
void RenderToViewportFlipY() const;
void RenderToViewportFlipXFlipY() const;
GLint internal_format;
GLuint tid;
GLint width;
GLint height;
private:
// Private copy constructor
GlTexture(const GlTexture&) {}
};
struct PANGOLIN_EXPORT GlRenderBuffer
{
GlRenderBuffer();
GlRenderBuffer(GLint width, GLint height, GLint internal_format = GL_DEPTH_COMPONENT24);
void Reinitialise(GLint width, GLint height, GLint internal_format = GL_DEPTH_COMPONENT24);
//! Move Constructor
GlRenderBuffer(GlRenderBuffer&& tex);
~GlRenderBuffer();
GLint width;
GLint height;
GLuint rbid;
private:
// Private copy constructor
GlRenderBuffer(const GlRenderBuffer&) {}
};
struct PANGOLIN_EXPORT GlFramebuffer
{
GlFramebuffer();
~GlFramebuffer();
GlFramebuffer(GlTexture& colour, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlTexture& colour3, GlRenderBuffer& depth);
void Bind() const;
void Unbind() const;
void Reinitialise();
// Attach Colour texture to frame buffer
// Return attachment texture is bound to (e.g. GL_COLOR_ATTACHMENT0_EXT)
GLenum AttachColour(GlTexture& tex);
// Attach Depth render buffer to frame buffer
void AttachDepth(GlRenderBuffer& rb);
GLuint fbid;
unsigned attachments;
};
enum GlBufferType
{
GlUndefined = 0,
GlArrayBuffer = GL_ARRAY_BUFFER, // VBO's, CBO's, NBO's
GlElementArrayBuffer = GL_ELEMENT_ARRAY_BUFFER, // IBO's
#ifndef HAVE_GLES
GlPixelPackBuffer = GL_PIXEL_PACK_BUFFER, // PBO's
GlPixelUnpackBuffer = GL_PIXEL_UNPACK_BUFFER,
GlShaderStorageBuffer = GL_SHADER_STORAGE_BUFFER
#endif
};
// This encapsulates a GL Buffer object.
struct PANGOLIN_EXPORT GlBufferData
{
//! Default constructor represents 'no buffer'
GlBufferData();
GlBufferData(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse = GL_DYNAMIC_DRAW, const unsigned char* data = 0 );
virtual ~GlBufferData();
void Free();
//! Move Constructor
GlBufferData(GlBufferData&& tex);
GlBufferData& operator=(GlBufferData&& tex);
bool IsValid() const;
size_t SizeBytes() const;
void Reinitialise(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse = GL_DYNAMIC_DRAW, const unsigned char* data = 0 );
void Bind() const;
void Unbind() const;
void Upload(const GLvoid* data, GLsizeiptr size_bytes, GLintptr offset = 0);
void Download(GLvoid* ptr, GLsizeiptr size_bytes, GLintptr offset = 0) const;
GLuint bo;
GlBufferType buffer_type;
GLenum gluse;
GLuint size_bytes;
private:
GlBufferData(const GlBufferData&) {}
};
// This encapsulates a GL Buffer object, also storing information about its contents.
// You should try to use GlBufferData instead.
struct PANGOLIN_EXPORT GlBuffer : public GlBufferData
{
//! Default constructor represents 'no buffer'
GlBuffer();
GlBuffer(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse = GL_DYNAMIC_DRAW );
GlBuffer(const GlBuffer&) = delete;
//! Move Constructor
GlBuffer(GlBuffer&& tex);
GlBuffer& operator=(GlBuffer&& tex);
void Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse, const unsigned char* data = nullptr );
void Reinitialise(GlBuffer const& other );
void Resize(GLuint num_elements);
GLenum datatype;
GLuint num_elements;
GLuint count_per_element;
};
class PANGOLIN_EXPORT GlSizeableBuffer
: public pangolin::GlBuffer
{
public:
GlSizeableBuffer(pangolin::GlBufferType buffer_type, GLuint initial_num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse = GL_DYNAMIC_DRAW );
void Clear();
#ifdef USE_EIGEN
template<typename Derived>
void Add(const Eigen::DenseBase<Derived>& vec);
template<typename Derived>
void Update(const Eigen::DenseBase<Derived>& vec, size_t position = 0);
#endif
size_t start() const;
size_t size() const;
protected:
void CheckResize(size_t num_verts);
size_t NextSize(size_t min_size) const;
size_t m_num_verts;
};
size_t GlFormatChannels(GLenum data_layout);
size_t GlDataTypeBytes(GLenum type);
}
// Include implementation
#include <pangolin/gl/gl.hpp>

View File

@@ -0,0 +1,866 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/display/display.h>
#include <pangolin/image/image_io.h>
#include <algorithm>
#include <stdexcept>
namespace pangolin
{
////////////////////////////////////////////////
// Implementation of gl.h
////////////////////////////////////////////////
#ifndef HAVE_GLES
const int MAX_ATTACHMENTS = 8;
const static GLuint attachment_buffers[] = {
GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT,
GL_COLOR_ATTACHMENT2_EXT,
GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,
GL_COLOR_ATTACHMENT5_EXT,
GL_COLOR_ATTACHMENT6_EXT,
GL_COLOR_ATTACHMENT7_EXT
};
#else // HAVE_GLES
const int MAX_ATTACHMENTS = 1;
const static GLuint attachment_buffers[] = {
GL_COLOR_ATTACHMENT0_EXT
};
#endif // HAVE_GLES
const static size_t datatype_bytes[] = {
1, // #define GL_BYTE 0x1400
1, // #define GL_UNSIGNED_BYTE 0x1401
2, // #define GL_SHORT 0x1402
2, // #define GL_UNSIGNED_SHORT 0x1403
4, // #define GL_INT 0x1404
4, // #define GL_UNSIGNED_INT 0x1405
4, // #define GL_FLOAT 0x1406
2, // #define GL_2_BYTES 0x1407
3, // #define GL_3_BYTES 0x1408
4, // #define GL_4_BYTES 0x1409
8 // #define GL_DOUBLE 0x140A
};
const static size_t format_channels[] = {
1, // #define GL_RED 0x1903
1, // #define GL_GREEN 0x1904
1, // #define GL_BLUE 0x1905
1, // #define GL_ALPHA 0x1906
3, // #define GL_RGB 0x1907
4, // #define GL_RGBA 0x1908
1, // #define GL_LUMINANCE 0x1909
2 // #define GL_LUMINANCE_ALPHA 0x190A
};
inline size_t GlDataTypeBytes(GLenum type)
{
return datatype_bytes[type - GL_BYTE];
}
inline size_t GlFormatChannels(GLenum data_layout)
{
if (data_layout == GL_BGR) return 3;
if (data_layout == GL_BGRA) return 4;
return format_channels[data_layout - GL_RED];
}
//template<typename T>
//struct GlDataTypeTrait {};
//template<> struct GlDataTypeTrait<float>{ static const GLenum type = GL_FLOAT; };
//template<> struct GlDataTypeTrait<int>{ static const GLenum type = GL_INT; };
//template<> struct GlDataTypeTrait<unsigned char>{ static const GLenum type = GL_UNSIGNED_BYTE; };
inline GlTexture::GlTexture()
: internal_format(0), tid(0), width(0), height(0)
{
// Not a texture constructor
}
inline GlTexture::GlTexture(GLint width, GLint height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data )
: internal_format(0), tid(0)
{
Reinitialise(width,height,internal_format,sampling_linear,border,glformat,gltype,data);
}
inline GlTexture::GlTexture(const TypedImage& img, bool sampling_linear)
{
this->Load(img, sampling_linear);
}
inline GlTexture::GlTexture(GlTexture&& tex)
{
*this = std::move(tex);
}
inline GlTexture& GlTexture::operator=(GlTexture&& tex)
{
if (&tex != this) {
internal_format = tex.internal_format;
tid = tex.tid;
width = tex.width;
height = tex.height;
tex.internal_format = 0;
tex.tid = 0;
}
return *this;
}
inline bool GlTexture::IsValid() const
{
return tid != 0;
}
inline void GlTexture::Delete()
{
// We have no GL context whilst exiting.
if(internal_format!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1,&tid);
internal_format = 0;
tid = 0;
width = 0;
height = 0;
}
}
inline GlTexture::~GlTexture()
{
// We have no GL context whilst exiting.
if(internal_format!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1,&tid);
}
}
inline void GlTexture::Bind() const
{
glBindTexture(GL_TEXTURE_2D, tid);
}
inline void GlTexture::Unbind() const
{
glBindTexture(GL_TEXTURE_2D, 0);
}
inline void GlTexture::Reinitialise(GLsizei w, GLsizei h, GLint int_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data )
{
if(tid!=0) {
glDeleteTextures(1,&tid);
}
internal_format = int_format;
width = w;
height = h;
glGenTextures(1,&tid);
Bind();
// GL_LUMINANCE and GL_FLOAT don't seem to actually affect buffer, but some values are required
// for call to succeed.
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, border, glformat, gltype, data);
if(sampling_linear) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}else{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
CheckGlDieOnError();
}
inline void GlTexture::Upload(
const void* data,
GLenum data_format, GLenum data_type
) {
Bind();
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,data_format,data_type,data);
CheckGlDieOnError();
}
inline void GlTexture::Upload(
const void* data,
GLsizei tex_x_offset, GLsizei tex_y_offset,
GLsizei data_w, GLsizei data_h,
GLenum data_format, GLenum data_type )
{
Bind();
glTexSubImage2D(GL_TEXTURE_2D,0,tex_x_offset,tex_y_offset,data_w,data_h,data_format,data_type,data);
CheckGlDieOnError();
}
inline void GlTexture::Load(const TypedImage& image, bool sampling_linear)
{
GlPixFormat fmt(image.fmt);
Reinitialise((GLint)image.w, (GLint)image.h, GL_RGBA32F, sampling_linear, 0, fmt.glformat, fmt.gltype, image.ptr );
}
inline void GlTexture::LoadFromFile(const std::string& filename, bool sampling_linear)
{
TypedImage image = LoadImage(filename);
Load(image, sampling_linear);
}
#ifndef HAVE_GLES
inline void GlTexture::Download(void* image, GLenum data_layout, GLenum data_type) const
{
Bind();
glGetTexImage(GL_TEXTURE_2D, 0, data_layout, data_type, image);
Unbind();
}
inline void GlTexture::Download(TypedImage& image) const
{
switch (internal_format)
{
case GL_LUMINANCE8:
image.Reinitialise(width, height, PixelFormatFromString("GRAY8") );
Download(image.ptr, GL_LUMINANCE, GL_UNSIGNED_BYTE);
break;
case GL_LUMINANCE16:
image.Reinitialise(width, height, PixelFormatFromString("GRAY16LE") );
Download(image.ptr, GL_LUMINANCE, GL_UNSIGNED_SHORT);
break;
case GL_RGB8:
image.Reinitialise(width, height, PixelFormatFromString("RGB24"));
Download(image.ptr, GL_RGB, GL_UNSIGNED_BYTE);
break;
case GL_RGBA8:
image.Reinitialise(width, height, PixelFormatFromString("RGBA32"));
Download(image.ptr, GL_RGBA, GL_UNSIGNED_BYTE);
break;
case GL_RGB16:
image.Reinitialise(width, height, PixelFormatFromString("RGB48"));
Download(image.ptr, GL_RGB, GL_UNSIGNED_SHORT);
break;
case GL_RGBA16:
image.Reinitialise(width, height, PixelFormatFromString("RGBA64"));
Download(image.ptr, GL_RGBA, GL_UNSIGNED_SHORT);
break;
case GL_LUMINANCE:
case GL_LUMINANCE32F_ARB:
image.Reinitialise(width, height, PixelFormatFromString("GRAY32F"));
Download(image.ptr, GL_LUMINANCE, GL_FLOAT);
break;
case GL_RGB:
case GL_RGB32F:
image.Reinitialise(width, height, PixelFormatFromString("RGB96F"));
Download(image.ptr, GL_RGB, GL_FLOAT);
break;
case GL_RGBA:
case GL_RGBA32F:
image.Reinitialise(width, height, PixelFormatFromString("RGBA128F"));
Download(image.ptr, GL_RGBA, GL_FLOAT);
break;
default:
throw std::runtime_error(
"GlTexture::Download - Unknown internal format (" +
pangolin::Convert<std::string,GLint>::Do(internal_format) +
")"
);
}
}
inline void GlTexture::CopyFrom(const GlTexture& tex)
{
if(!tid || width != tex.width || height != tex.height ||
internal_format != tex.internal_format)
{
Reinitialise(tex.width, tex.height, tex.internal_format, true);
}
glCopyImageSubData(tex.tid, GL_TEXTURE_2D, 0, 0, 0, 0,
tid, GL_TEXTURE_2D, 0, 0, 0, 0,
width, height, 1);
CheckGlDieOnError();
}
inline void GlTexture::Save(const std::string& filename, bool top_line_first)
{
TypedImage image;
Download(image);
pangolin::SaveImage(image, filename, top_line_first);
}
#endif // HAVE_GLES
inline void GlTexture::SetLinear()
{
Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Unbind();
}
inline void GlTexture::SetNearestNeighbour()
{
Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Unbind();
}
inline void GlTexture::RenderToViewport(const bool flip) const
{
if(flip) {
RenderToViewportFlipY();
}else{
RenderToViewport();
}
}
inline void GlTexture::RenderToViewport() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewport(Viewport tex_vp, bool flipx, bool flipy) const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat l = tex_vp.l / (float)(width);
GLfloat b = tex_vp.b / (float)(height);
GLfloat r = (tex_vp.l+tex_vp.w) / (float)(width);
GLfloat t = (tex_vp.b+tex_vp.h) / (float)(height);
if(flipx) std::swap(l,r);
if(flipy) std::swap(b,t);
GLfloat sq_tex[] = { l,b, r,b, r,t, l,t };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewportFlipY() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,1, 1,1, 1,0, 0,0 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewportFlipXFlipY() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { 1,1, -1,1, -1,-1, 1,-1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
////////////////////////////////////////////////////////////////////////////
inline GlRenderBuffer::GlRenderBuffer()
: width(0), height(0), rbid(0)
{
}
inline GlRenderBuffer::GlRenderBuffer(GLint width, GLint height, GLint internal_format )
: width(0), height(0), rbid(0)
{
Reinitialise(width,height,internal_format);
}
#ifndef HAVE_GLES
inline void GlRenderBuffer::Reinitialise(GLint width, GLint height, GLint internal_format)
{
if( this->width != 0 ) {
glDeleteRenderbuffersEXT(1, &rbid);
}
this->width = width;
this->height = height;
glGenRenderbuffersEXT(1, &rbid);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbid);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internal_format, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
inline GlRenderBuffer::~GlRenderBuffer()
{
// We have no GL context whilst exiting.
if( width!=0 && !pangolin::ShouldQuit() ) {
glDeleteRenderbuffersEXT(1, &rbid);
}
}
#else
inline void GlRenderBuffer::Reinitialise(GLint width, GLint height, GLint internal_format)
{
if( width!=0 ) {
glDeleteTextures(1, &rbid);
}
// Use a texture instead...
glGenTextures(1, &rbid);
glBindTexture(GL_TEXTURE_2D, rbid);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
width, height,
0, internal_format, GL_UNSIGNED_SHORT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
inline GlRenderBuffer::~GlRenderBuffer()
{
// We have no GL context whilst exiting.
if( width!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1, &rbid);
}
}
#endif // HAVE_GLES
inline GlRenderBuffer::GlRenderBuffer(GlRenderBuffer&& tex)
: width(tex.width), height(tex.height), rbid(tex.rbid)
{
tex.rbid = tex.width = tex.height = 0;
}
////////////////////////////////////////////////////////////////////////////
inline GlFramebuffer::GlFramebuffer()
: fbid(0), attachments(0)
{
}
inline GlFramebuffer::~GlFramebuffer()
{
if(fbid) {
glDeleteFramebuffersEXT(1, &fbid);
}
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachColour(colour2);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlTexture& colour3, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachColour(colour2);
AttachColour(colour3);
AttachDepth(depth);
CheckGlDieOnError();
}
inline void GlFramebuffer::Bind() const
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
#ifndef HAVE_GLES
glDrawBuffers( attachments, attachment_buffers );
#endif
}
inline void GlFramebuffer::Reinitialise()
{
if(fbid) {
glDeleteFramebuffersEXT(1, &fbid);
}
glGenFramebuffersEXT(1, &fbid);
}
inline void GlFramebuffer::Unbind() const
{
#ifndef HAVE_GLES
glDrawBuffers( 1, attachment_buffers );
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
inline GLenum GlFramebuffer::AttachColour(GlTexture& tex )
{
if(!fbid) Reinitialise();
const GLenum color_attachment = GL_COLOR_ATTACHMENT0_EXT + attachments;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, color_attachment, GL_TEXTURE_2D, tex.tid, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
attachments++;
CheckGlDieOnError();
return color_attachment;
}
inline void GlFramebuffer::AttachDepth(GlRenderBuffer& rb )
{
if(!fbid) Reinitialise();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
#if !defined(HAVE_GLES)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb.rbid);
#elif defined(HAVE_GLES_2)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, rb.rbid, 0);
#else
throw std::exception();
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
CheckGlDieOnError();
}
////////////////////////////////////////////////////////////////////////////
inline GlBufferData::GlBufferData()
: bo(0)
{
}
inline GlBufferData::GlBufferData(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse, const unsigned char* data )
: bo(0)
{
Reinitialise(buffer_type, size_bytes, gluse, data );
}
//! Move Constructor
inline GlBufferData::GlBufferData(GlBufferData&& tex)
: bo(0)
{
*this = std::move(tex);
}
inline GlBufferData& GlBufferData::operator=(GlBufferData&& tex)
{
Free();
this->bo = tex.bo;
this->buffer_type = tex.buffer_type;
this->gluse = tex.gluse;
this->size_bytes = tex.size_bytes;
tex.bo = 0;
return *this;
}
inline GlBufferData::~GlBufferData()
{
Free();
}
inline void GlBufferData::Free()
{
if(bo!=0) {
glDeleteBuffers(1, &bo);
}
}
inline bool GlBufferData::IsValid() const
{
return bo != 0;
}
inline size_t GlBufferData::SizeBytes() const
{
return size_bytes;
}
inline void GlBufferData::Reinitialise(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse, const unsigned char* data )
{
if(!bo) {
glGenBuffers(1, &bo);
}
this->buffer_type = buffer_type;
this->gluse = gluse;
this->size_bytes = size_bytes;
Bind();
glBufferData(buffer_type, size_bytes, data, gluse);
Unbind();
}
inline void GlBufferData::Bind() const
{
glBindBuffer(buffer_type, bo);
}
inline void GlBufferData::Unbind() const
{
glBindBuffer(buffer_type, 0);
}
inline void GlBufferData::Upload(const GLvoid* data, GLsizeiptr size_bytes, GLintptr offset)
{
if(offset + size_bytes > this->size_bytes) {
throw std::runtime_error("GlBufferData: Trying to upload past capacity.");
}
Bind();
glBufferSubData(buffer_type,offset,size_bytes,data);
Unbind();
}
inline void GlBufferData::Download(GLvoid* data, GLsizeiptr size_bytes, GLintptr offset) const
{
Bind();
glGetBufferSubData(buffer_type, offset, size_bytes, data);
Unbind();
}
////////////////////////////////////////////////////////////////////////////
inline GlBuffer::GlBuffer()
: GlBufferData(), num_elements(0)
{
}
inline GlBuffer::GlBuffer(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse )
: GlBufferData(buffer_type, num_elements * count_per_element * GlDataTypeBytes(datatype), gluse),
datatype(datatype), num_elements(num_elements), count_per_element(count_per_element)
{
}
inline GlBuffer::GlBuffer(GlBuffer&& o)
: GlBufferData()
{
*this = std::move(o);
}
inline GlBuffer& GlBuffer::operator=(GlBuffer&& o)
{
datatype = o.datatype;
num_elements = o.num_elements;
count_per_element = o.count_per_element;
GlBufferData::operator =(std::move(o));
return *this;
}
inline void GlBuffer::Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse, const unsigned char* data )
{
this->datatype = datatype;
this->num_elements = num_elements;
this->count_per_element = count_per_element;
const GLuint size_bytes = num_elements * count_per_element * GlDataTypeBytes(datatype);
GlBufferData::Reinitialise(buffer_type, size_bytes, gluse, data);
}
inline void GlBuffer::Reinitialise(GlBuffer const& other )
{
Reinitialise(other.buffer_type, other.num_elements, other.datatype, other.count_per_element, other.gluse);
}
inline void GlBuffer::Resize(GLuint new_num_elements)
{
if(bo!=0) {
#ifndef HAVE_GLES
// Backup current data, reinit memory, restore old data
const size_t backup_elements = std::min(new_num_elements,num_elements);
const size_t backup_size_bytes = backup_elements*GlDataTypeBytes(datatype)*count_per_element;
unsigned char* backup = new unsigned char[backup_size_bytes];
Bind();
glGetBufferSubData(buffer_type, 0, backup_size_bytes, backup);
glBufferData(buffer_type, new_num_elements*GlDataTypeBytes(datatype)*count_per_element, 0, gluse);
glBufferSubData(buffer_type, 0, backup_size_bytes, backup);
Unbind();
delete[] backup;
#else
throw std::exception();
#endif
}else{
Reinitialise(buffer_type, new_num_elements, datatype, count_per_element, gluse);
}
num_elements = new_num_elements;
}
////////////////////////////////////////////////////////////////////////////
inline GlSizeableBuffer::GlSizeableBuffer(GlBufferType buffer_type, GLuint initial_num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse )
: GlBuffer(buffer_type, initial_num_elements, datatype, count_per_element, gluse), m_num_verts(0)
{
}
inline void GlSizeableBuffer::Clear()
{
m_num_verts = 0;
}
#ifdef USE_EIGEN
template<typename Derived> inline
void GlSizeableBuffer::Add(const Eigen::DenseBase<Derived>& vec)
{
typedef typename Eigen::DenseBase<Derived>::Scalar Scalar;
assert(vec.rows()==GlBuffer::count_per_element);
CheckResize(m_num_verts + 1);
// TODO: taking address of first element is really dodgey. Need to work out
// when this is okay!
Upload(&vec(0,0), sizeof(Scalar)*vec.rows()*vec.cols(), sizeof(Scalar)*vec.rows()*m_num_verts);
m_num_verts += vec.cols();
}
template<typename Derived> inline
void GlSizeableBuffer::Update(const Eigen::DenseBase<Derived>& vec, size_t position )
{
typedef typename Eigen::DenseBase<Derived>::Scalar Scalar;
assert(vec.rows()==GlBuffer::count_per_element);
CheckResize(position + vec.cols() );
// TODO: taking address of first element is really dodgey. Need to work out
// when this is okay!
Upload(&vec(0,0), sizeof(Scalar)*vec.rows()*vec.cols(), sizeof(Scalar)*vec.rows()*position );
m_num_verts = std::max(position+vec.cols(), m_num_verts);
}
#endif
inline size_t GlSizeableBuffer::start() const {
return 0;
}
inline size_t GlSizeableBuffer::size() const {
return m_num_verts;
}
inline void GlSizeableBuffer::CheckResize(size_t num_verts)
{
if( num_verts > GlBuffer::num_elements) {
const size_t new_size = NextSize(num_verts);
GlBuffer::Resize((GLuint)new_size);
}
}
inline size_t GlSizeableBuffer::NextSize(size_t min_size) const
{
size_t new_size = std::max(GlBuffer::num_elements, 1u);
while(new_size < min_size) {
new_size *= 2;
}
return new_size;
}
}

View File

@@ -0,0 +1,78 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <map>
namespace pangolin {
struct PANGOLIN_EXPORT XYUV
{
XYUV() {}
XYUV(GLfloat x, GLfloat y, GLfloat tu, GLfloat tv)
: x(x), y(y), tu(tu), tv(tv) {}
XYUV operator+(float dx) const {
return XYUV(x+dx,y,tu,tv);
}
GLfloat x, y, tu, tv;
};
class PANGOLIN_EXPORT GlChar
{
public:
GlChar();
GlChar(int tw, int th, int x, int y, int w, int h, GLfloat x_step, GLfloat ox, GLfloat oy);
inline const XYUV& GetVert(size_t i) const {
return vs[i];
}
inline GLfloat StepX() const {
return x_step;
}
inline GLfloat YMin() const {
return y_min;
}
inline GLfloat YMax() const {
return y_max;
}
void Draw() const;
protected:
XYUV vs[4];
GLfloat x_step;
GLfloat y_min, y_max;
};
}

View File

@@ -0,0 +1,258 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <algorithm>
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include "gl.h"
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
struct GlBufferCudaPtr : public GlBuffer
{
//! Default constructor represents 'no buffer'
GlBufferCudaPtr();
GlBufferCudaPtr(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
GlBufferCudaPtr(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
PANGOLIN_DEPRECATED
GlBufferCudaPtr(GlBufferType buffer_type, GLuint width, GLuint height, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
~GlBufferCudaPtr();
void Reinitialise(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
void Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
/**
* Use parameters from another @c GlBufferCudaPtr to initialize this buffer.
*/
void Reinitialise(const GlBufferCudaPtr& other);
unsigned int cuda_use;
cudaGraphicsResource* cuda_res;
};
struct GlTextureCudaArray : GlTexture
{
GlTextureCudaArray();
// Some internal_formats aren't accepted. I have trouble with GL_RGB8
GlTextureCudaArray(int width, int height, GLint internal_format, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL);
~GlTextureCudaArray();
void Reinitialise(int width, int height, GLint internal_format, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL) override;
cudaGraphicsResource* cuda_res;
};
struct CudaScopedMappedPtr
{
CudaScopedMappedPtr(const GlBufferCudaPtr& buffer);
~CudaScopedMappedPtr();
void* operator*();
cudaGraphicsResource* res;
private:
CudaScopedMappedPtr(const CudaScopedMappedPtr&) {}
};
struct CudaScopedMappedArray
{
CudaScopedMappedArray(const GlTextureCudaArray& tex);
~CudaScopedMappedArray();
cudaArray* operator*();
cudaGraphicsResource* res;
private:
CudaScopedMappedArray(const CudaScopedMappedArray&) {}
};
void CopyPboToTex(GlBufferCudaPtr& buffer, GlTexture& tex);
void swap(GlBufferCudaPtr& a, GlBufferCudaPtr& b);
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline GlBufferCudaPtr::GlBufferCudaPtr()
: cuda_res(0)
{
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
: cuda_res(0)
{
Reinitialise(buffer_type, size_bytes, cudause, gluse);
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause, GLenum gluse )
: cuda_res(0)
{
Reinitialise(buffer_type, num_elements, datatype, count_per_element, cudause, gluse);
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint width, GLuint height, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
: cuda_res(0)
{
Reinitialise(buffer_type, width*height, datatype, count_per_element, cudause, gluse);
}
inline GlBufferCudaPtr::~GlBufferCudaPtr()
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
}
inline void GlBufferCudaPtr::Reinitialise(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
{
GlBufferCudaPtr::Reinitialise(buffer_type, size_bytes, GL_BYTE, 1, cudause, gluse);
}
inline void GlBufferCudaPtr::Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
GlBuffer::Reinitialise(buffer_type, num_elements, datatype, count_per_element, gluse);
cuda_use = cudause;
cudaGraphicsGLRegisterBuffer( &cuda_res, bo, cudause );
}
inline void GlBufferCudaPtr::Reinitialise(const GlBufferCudaPtr& other)
{
Reinitialise(other.buffer_type, other.num_elements, other.datatype, other.count_per_element, other.cuda_use, other.gluse);
}
inline GlTextureCudaArray::GlTextureCudaArray()
: GlTexture(), cuda_res(0)
{
// Not a texture
}
inline GlTextureCudaArray::GlTextureCudaArray(int width, int height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid *data)
:GlTexture(width,height,internal_format, sampling_linear, border, glformat, gltype, data)
{
// TODO: specify flags too
const cudaError_t err = cudaGraphicsGLRegisterImage(&cuda_res, tid, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone);
if( err != cudaSuccess ) {
std::cout << "cudaGraphicsGLRegisterImage failed: " << err << std::endl;
}
}
inline GlTextureCudaArray::~GlTextureCudaArray()
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
}
inline void GlTextureCudaArray::Reinitialise(int width, int height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data)
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
GlTexture::Reinitialise(width, height, internal_format, sampling_linear, border, glformat, gltype, data);
const cudaError_t err = cudaGraphicsGLRegisterImage(&cuda_res, tid, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone);
if( err != cudaSuccess ) {
std::cout << "cudaGraphicsGLRegisterImage failed: " << err << std::endl;
}
}
inline CudaScopedMappedPtr::CudaScopedMappedPtr(const GlBufferCudaPtr& buffer)
: res(buffer.cuda_res)
{
cudaGraphicsMapResources(1, &res, 0);
}
inline CudaScopedMappedPtr::~CudaScopedMappedPtr()
{
cudaGraphicsUnmapResources(1, &res, 0);
}
inline void* CudaScopedMappedPtr::operator*()
{
size_t num_bytes;
void* d_ptr;
cudaGraphicsResourceGetMappedPointer(&d_ptr,&num_bytes,res);
return d_ptr;
}
inline CudaScopedMappedArray::CudaScopedMappedArray(const GlTextureCudaArray& tex)
: res(tex.cuda_res)
{
cudaGraphicsMapResources(1, &res);
}
inline CudaScopedMappedArray::~CudaScopedMappedArray()
{
cudaGraphicsUnmapResources(1, &res);
}
inline cudaArray* CudaScopedMappedArray::operator*()
{
cudaArray* array;
cudaGraphicsSubResourceGetMappedArray(&array, res, 0, 0);
return array;
}
inline void CopyPboToTex(const GlBufferCudaPtr& buffer, GlTexture& tex, GLenum buffer_layout, GLenum buffer_data_type )
{
buffer.Bind();
tex.Bind();
glTexImage2D(GL_TEXTURE_2D, 0, tex.internal_format, tex.width, tex.height, 0, buffer_layout, buffer_data_type, 0);
buffer.Unbind();
tex.Unbind();
}
template<typename T>
inline void CopyDevMemtoTex(T* d_img, size_t pitch, GlTextureCudaArray& tex )
{
CudaScopedMappedArray arr_tex(tex);
cudaMemcpy2DToArray(*arr_tex, 0, 0, d_img, pitch, tex.width*sizeof(T), tex.height, cudaMemcpyDeviceToDevice );
}
inline void swap(GlBufferCudaPtr& a, GlBufferCudaPtr& b)
{
std::swap(a.bo, b.bo);
std::swap(a.cuda_res, b.cuda_res);
std::swap(a.buffer_type, b.buffer_type);
}
}

View File

@@ -0,0 +1,518 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/display/opengl_render_state.h>
#include <vector>
#include <math.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#include <Eigen/src/Geometry/AlignedBox.h>
#endif // USE_EIGEN
namespace pangolin
{
// h [0,360)
// s [0,1]
// v [0,1]
inline void glColorHSV( GLfloat hue, GLfloat s=1.0f, GLfloat v=1.0f )
{
const GLfloat h = hue / 60.0f;
const int i = (int)floor(h);
const GLfloat f = (i%2 == 0) ? 1-(h-i) : h-i;
const GLfloat m = v * (1-s);
const GLfloat n = v * (1-s*f);
switch(i)
{
case 0: glColor4f(v,n,m,1); break;
case 1: glColor4f(n,v,m,1); break;
case 2: glColor4f(m,v,n,1); break;
case 3: glColor4f(m,n,v,1); break;
case 4: glColor4f(n,m,v,1); break;
case 5: glColor4f(v,m,n,1); break;
default:
break;
}
}
inline void glColorBin( int bin, int max_bins, GLfloat sat=1.0f, GLfloat val=1.0f )
{
if( bin >= 0 ) {
const GLfloat hue = (GLfloat)(bin%max_bins) * 360.0f / (GLfloat)max_bins;
glColorHSV(hue,sat,val);
}else{
glColor4f(1,1,1,1);
}
}
template<typename T>
inline void glDrawVertices(
size_t num_vertices, const T* const vertex_ptr, GLenum mode,
size_t elements_per_vertex = GlFormatTraits<T>::components,
size_t vertex_stride_bytes = 0 )
{
if(num_vertices > 0)
{
PANGO_ENSURE(vertex_ptr != nullptr);
PANGO_ENSURE(mode != GL_LINES || num_vertices % 2 == 0, "number of vertices (%) must be even in GL_LINES mode", num_vertices );
glVertexPointer(elements_per_vertex, GlFormatTraits<T>::gltype, vertex_stride_bytes, vertex_ptr);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(mode, 0, num_vertices);
glDisableClientState(GL_VERTEX_ARRAY);
}
}
template<typename TV, typename TC>
inline void glDrawColoredVertices(
size_t num_vertices, const TV* const vertex_ptr, const TC* const color_ptr, GLenum mode,
size_t elements_per_vertex = GlFormatTraits<TV>::components,
size_t elements_per_color = GlFormatTraits<TC>::components,
size_t vertex_stride_bytes = 0,
size_t color_stride_bytes = 0
) {
if(color_ptr) {
glColorPointer(elements_per_color, GlFormatTraits<TC>::gltype, color_stride_bytes, color_ptr);
glEnableClientState(GL_COLOR_ARRAY);
glDrawVertices<TV>(num_vertices, vertex_ptr, mode, elements_per_vertex, vertex_stride_bytes);
glDisableClientState(GL_COLOR_ARRAY);
}else{
glDrawVertices<TV>(num_vertices, vertex_ptr, mode, elements_per_vertex, vertex_stride_bytes);
}
}
inline void glDrawLine( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
const GLfloat verts[] = { x1,y1, x2,y2 };
glDrawVertices<float>(2, verts, GL_LINES, 2);
}
inline void glDrawLine( GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
const GLfloat verts[] = { x1,y1,z1, x2,y2,z2 };
glDrawVertices<float>(2, verts, GL_LINES, 3);
}
inline void glDrawCross( GLfloat x, GLfloat y, GLfloat rad )
{
const GLfloat verts[] = { x-rad,y, x+rad, y, x,y-rad, x, y+rad};
glDrawVertices<float>(4, verts, GL_LINES, 2);
}
inline void glDrawCross( GLfloat x, GLfloat y, GLfloat z, GLfloat rad )
{
const GLfloat verts[] = { x-rad,y,z, x+rad,y,z, x,y-rad,z, x,y+rad,z, x,y,z-rad, x,y,z+rad };
glDrawVertices<float>(6, verts, GL_LINES, 3);
}
inline void glDrawAxis(float s)
{
const GLfloat cols[] = { 1,0,0, 1,0,0, 0,1,0, 0,1,0, 0,0,1, 0,0,1 };
const GLfloat verts[] = { 0,0,0, s,0,0, 0,0,0, 0,s,0, 0,0,0, 0,0,s };
glDrawColoredVertices<float,float>(6, verts, cols, GL_LINES, 3, 3);
}
inline void glDrawRect( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLenum mode = GL_TRIANGLE_FAN )
{
const GLfloat verts[] = { x1,y1, x2,y1, x2,y2, x1,y2 };
glDrawVertices<float>(4, verts, mode, 2);
}
inline void glDrawRectPerimeter( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
glDrawRect(x1,y1, x2,y2, GL_LINE_LOOP);
}
inline void glDrawCirclePerimeter( float x, float y, float rad )
{
const int N = 50;
GLfloat verts[N*2];
const float TAU_DIV_N = 2*(float)M_PI/N;
for(int i = 0; i < N*2; i+=2) {
verts[i] = x + rad * cos(i*TAU_DIV_N);
verts[i+1] = y + rad * sin(i*TAU_DIV_N);
}
glDrawVertices<float>(N, verts, GL_LINES, 2);
}
inline void glDrawCircle( GLfloat x, GLfloat y, GLfloat rad )
{
const int N = 50;
GLfloat verts[N*2];
// Draw vertices anticlockwise for front face
const float TAU_DIV_N = 2*(float)M_PI/N;
for(int i = 0; i < N*2; i+=2) {
verts[i] = x + rad * cos(-i*TAU_DIV_N);
verts[i+1] = y + rad * sin(-i*TAU_DIV_N);
}
// Render filled shape and outline (to make it look smooth)
glVertexPointer(2, GL_FLOAT, 0, verts);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_FAN, 0, N);
glDrawArrays(GL_LINE_STRIP, 0, N);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glDrawColouredCube(GLfloat axis_min=-0.5f, GLfloat axis_max = +0.5f)
{
const GLfloat l = axis_min;
const GLfloat h = axis_max;
const GLfloat verts[] = {
l,l,h, h,l,h, l,h,h, h,h,h, // FRONT
l,l,l, l,h,l, h,l,l, h,h,l, // BACK
l,l,h, l,h,h, l,l,l, l,h,l, // LEFT
h,l,l, h,h,l, h,l,h, h,h,h, // RIGHT
l,h,h, h,h,h, l,h,l, h,h,l, // TOP
l,l,h, l,l,l, h,l,h, h,l,l // BOTTOM
};
glVertexPointer(3, GL_FLOAT, 0, verts);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glDraw_x0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for (int i = -grid; i <= grid; ++i) {
glDrawLine(0.0, i*scale, -maxord, 0.0, i*scale, +maxord);
glDrawLine(0.0, -maxord, i*scale, 0.0, +maxord, i*scale);
}
}
inline void glDraw_y0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for (int i = -grid; i <= grid; ++i) {
glDrawLine(i*scale, 0.0, -maxord, i*scale, 0.0, +maxord);
glDrawLine(-maxord, 0.0, i*scale, +maxord, 0.0, i*scale);
}
}
inline void glDraw_z0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for(int i=-grid; i<=grid; ++i ) {
glDrawLine(i*scale,-maxord, i*scale,+maxord);
glDrawLine(-maxord, i*scale, +maxord, i*scale);
}
}
inline void glDrawFrustum( GLfloat u0, GLfloat v0, GLfloat fu, GLfloat fv, int w, int h, GLfloat scale )
{
const GLfloat xl = scale * u0;
const GLfloat xh = scale * (w*fu + u0);
const GLfloat yl = scale * v0;
const GLfloat yh = scale * (h*fv + v0);
const GLfloat verts[] = {
xl,yl,scale, xh,yl,scale,
xh,yh,scale, xl,yh,scale,
xl,yl,scale, 0,0,0,
xh,yl,scale, 0,0,0,
xl,yh,scale, 0,0,0,
xh,yh,scale
};
glDrawVertices(11, verts, GL_LINE_STRIP, 3);
}
inline void glDrawTexture(GLenum target, GLuint texid)
{
glBindTexture(target, texid);
glEnable(target);
const GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(target);
}
inline void glDrawTextureFlipY(GLenum target, GLuint texid)
{
glBindTexture(target, texid);
glEnable(target);
const GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat sq_tex[] = { 0,1, 1,1, 1,0, 0,0 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(target);
}
#ifdef USE_EIGEN
#ifndef HAVE_GLES
inline void glVertex( const Eigen::Vector3d& p )
{
glVertex3dv(p.data());
}
#endif
inline void glDrawLine( const Eigen::Vector2d& p1, const Eigen::Vector2d& p2 )
{
glDrawLine((GLfloat)p1(0), (GLfloat)p1(1), (GLfloat)p2(0), (GLfloat)p2(1));
}
// Draws a vector of 2d or 3d vertices using provided ``mode``.
//
// Preconditions:
// - ``mode`` must be GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, etc
// - If ``mode == GL_LINES``, then ``vertices.size()`` must be a multiple of 2.
//
template<typename P, int N, class Allocator>
void glDrawVertices(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices, GLenum mode)
{
glDrawVertices(vertices.size(), vertices.data(), mode);
}
// Draws a vector of 2d or 3d points.
//
template<typename P, int N, class Allocator>
void glDrawPoints(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_POINTS);
}
// Draws a vector of 2d or 3d lines.
//
// Precondition: ``vertices.size()`` must be a multiple of 2.
//
template<typename P, int N, class Allocator>
void glDrawLines(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINES);
}
// Draws a 2d or 3d line strip.
//
template<typename P, int N, class Allocator>
void glDrawLineStrip(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINE_STRIP);
}
// Draws a 2d or 3d line loop.
//
template<typename P, int N, class Allocator>
void glDrawLineLoop(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINE_LOOP);
}
inline void glDrawCross( const Eigen::Vector2d& p, double r = 5.0 )
{
glDrawCross((GLfloat)p(0), (GLfloat)p(1), (GLfloat)r);
}
inline void glDrawCross( const Eigen::Vector3d& p, double r = 5.0 )
{
glDrawCross((GLfloat)p(0), (GLfloat)p(1), (GLfloat)p(2), (GLfloat)r);
}
inline void glDrawCircle( const Eigen::Vector2d& p, double radius = 5.0 )
{
glDrawCircle((GLfloat)p(0), (GLfloat)p(1), (GLfloat)radius);
}
inline void glDrawCirclePerimeter( const Eigen::Vector2d& p, double radius = 5.0 )
{
glDrawCirclePerimeter((GLfloat)p(0), (GLfloat)p(1), (GLfloat)radius);
}
inline void glSetFrameOfReference( const Eigen::Matrix4f& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf( T_wf.data() );
}
inline void glSetFrameOfReference( const Eigen::Matrix4d& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
#ifndef HAVE_GLES
glMultMatrixd( T_wf.data() );
#else
const Eigen::Matrix4f fT_wf = T_wf.cast<GLfloat>();
glMultMatrixf( fT_wf.data() );
#endif
}
inline void glSetFrameOfReference( const pangolin::OpenGlMatrix& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixd( T_wf.m );
}
inline void glUnsetFrameOfReference()
{
glPopMatrix();
}
template<typename T, typename S>
inline void glDrawAxis( const T& T_wf, S scale )
{
glSetFrameOfReference(T_wf);
glDrawAxis(scale);
glUnsetFrameOfReference();
}
template<typename T>
inline void glDrawFrustum( const Eigen::Matrix<T,3,3>& Kinv, int w, int h, GLfloat scale )
{
glDrawFrustum((GLfloat)Kinv(0,2), (GLfloat)Kinv(1,2), (GLfloat)Kinv(0,0), (GLfloat)Kinv(1,1), w, h, scale);
}
template<typename T>
inline void glDrawFrustum( const Eigen::Matrix<T,3,3>& Kinv, int w, int h, const Eigen::Matrix<T,4,4>& T_wf, T scale )
{
glSetFrameOfReference(T_wf);
glDrawFrustum(Kinv,w,h,scale);
glUnsetFrameOfReference();
}
template<typename T>
inline void glDrawAlignedBox( const Eigen::AlignedBox<T,2>& box, GLenum mode = GL_TRIANGLE_FAN )
{
const Eigen::Matrix<float,2,1> l = box.min().template cast<float>();
const Eigen::Matrix<float,2,1> h = box.max().template cast<float>();
GLfloat verts[] = {
l[0], l[1],
h[0], l[1],
h[0], h[1],
l[0], h[1]
};
glDrawVertices(4, verts, mode, 2);
}
template<typename T>
inline void glDrawAlignedBoxPerimeter( const Eigen::AlignedBox<T,2>& box)
{
glDrawAlignedBox<T>(box, GL_LINE_LOOP);
}
template<typename T>
inline void glDrawAlignedBox( const Eigen::AlignedBox<T,3>& box)
{
const Eigen::Matrix<float,3,1> l = box.min().template cast<float>();
const Eigen::Matrix<float,3,1> h = box.max().template cast<float>();
GLfloat verts[] = {
l[0], l[1], l[2],
l[0], l[1], h[2],
h[0], l[1], h[2],
h[0], l[1], l[2],
l[0], l[1], l[2],
l[0], h[1], l[2],
h[0], h[1], l[2],
h[0], l[1], l[2],
h[0], h[1], l[2],
h[0], h[1], h[2],
l[0], h[1], h[2],
l[0], h[1], l[2],
l[0], h[1], h[2],
l[0], l[1], h[2],
h[0], l[1], h[2],
h[0], h[1], h[2]
};
glDrawVertices(16, verts, GL_LINE_STRIP, 3);
}
#endif // USE_EIGEN
#ifndef HAVE_GLES
inline void glPixelTransferScale( float r, float g, float b )
{
glPixelTransferf(GL_RED_SCALE,r);
glPixelTransferf(GL_GREEN_SCALE,g);
glPixelTransferf(GL_BLUE_SCALE,b);
}
inline void glPixelTransferScale( float scale )
{
glPixelTransferScale(scale,scale,scale);
}
#endif
void glRecordGraphic(float x, float y, float radius);
}

View File

@@ -0,0 +1,78 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2015 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gltext.h>
#include <cstdio>
#include <cstdarg>
namespace pangolin {
class PANGOLIN_EXPORT GlFont
{
public:
// Singleton instance if requested.
static GlFont& I();
// Load GL Font data. Delay uploading as texture until first use.
GlFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w=512, int tex_h=512);
GlFont(const std::string& filename, float pixel_height, int tex_w=512, int tex_h=512);
virtual ~GlFont();
// Generate renderable GlText object from this font.
GlText Text( const char* fmt, ... );
GlText Text( const std::string& str );
inline float Height() const {
return font_height_px;
}
protected:
void InitialiseFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h);
// This can only be called once GL context is initialised
void InitialiseGlTexture();
const static int FIRST_CHAR = 32;
const static int NUM_CHARS = 96;
float font_height_px;
int tex_w;
int tex_h;
unsigned char* font_bitmap;
GlTexture mTex;
GlChar chardata[NUM_CHARS];
GLfloat kern_table[NUM_CHARS*NUM_CHARS];
};
}

View File

@@ -0,0 +1,214 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#ifdef HAVE_EIGEN
# include <Eigen/Core>
#endif
namespace pangolin
{
template<typename T>
struct GlFormatTraits;
//{
// static const GLint glinternalformat = 0;
// static const GLenum glformat = 0;
// static const GLenum gltype = 0;
// static const T glmin = 0;
// static const T glmax = 0;
//};
template<>
struct GlFormatTraits<unsigned char>
{
static const GLint glinternalformat = GL_LUMINANCE8;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<unsigned short>
{
static const GLint glinternalformat = GL_LUMINANCE16;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<unsigned int>
{
static const GLint glinternalformat = GL_LUMINANCE32I_EXT;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_INT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<int>
{
static const GLint glinternalformat = GL_LUMINANCE32I_EXT;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_INT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<float>
{
static const GLint glinternalformat = GL_LUMINANCE32F_ARB;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<double>
{
static const GLint glinternalformat = GL_LUMINANCE32F_ARB;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 1;
};
#ifdef HAVE_EIGEN
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Vector2i>
{
static const GLint glinternalformat = GL_RG32I;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_INT;
static const size_t components = 2;
};
template <>
struct GlFormatTraits<Eigen::Vector2f>
{
static const GLint glinternalformat = GL_RG32F;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 2;
};
template <>
struct GlFormatTraits<Eigen::Vector2d>
{
static const GLint glinternalformat = GL_RG32F;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 2;
};
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned char,3,1>>
{
static const GLint glinternalformat = GL_RGB8;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned short,3,1>>
{
static const GLint glinternalformat = GL_RGBA16;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Vector3f>
{
static const GLint glinternalformat = GL_RGB32F;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Vector3d>
{
static const GLint glinternalformat = GL_RGB32F;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 3;
};
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned char,4,1>>
{
static const GLint glinternalformat = GL_RGBA8;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned short,4,1>>
{
static const GLint glinternalformat = GL_RGBA16;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Vector4f>
{
static const GLint glinternalformat = GL_RGBA32F;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Vector4d>
{
static const GLint glinternalformat = GL_RGBA32F;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 4;
};
#endif // HAVE_EIGEN
}

View File

@@ -0,0 +1,46 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#ifdef HAVE_GLES
#include <pangolin/gl/compat/gl_es_compat.h>
#endif
#define CheckGlDieOnError() pangolin::_CheckGlDieOnError( __FILE__, __LINE__ );
namespace pangolin {
inline void _CheckGlDieOnError( const char *sFile, const int nLine )
{
const GLenum glError = glGetError();
if( glError != GL_NO_ERROR ) {
pango_print_error("OpenGL Error %x: %s\n", glError, glErrorString(glError));
pango_print_error("In: %s, line %d\n", sFile, nLine);
}
}
}

View File

@@ -0,0 +1,79 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
namespace pangolin {
PANGOLIN_EXPORT
const char* glErrorString(GLenum error);
/// Clone of gluProject
PANGOLIN_EXPORT
GLint glProject(
float objx, float objy, float objz,
const float modelMatrix[16],
const float projMatrix[16],
const GLint viewport[4],
float* winx, float* winy, float* winz
);
/// Clone of gluUnProject
PANGOLIN_EXPORT
GLint glUnProject(
float winx, float winy, float winz,
const float modelMatrix[16],
const float projMatrix[16],
const GLint viewport[4],
float* objx, float* objy, float* objz
);
/// Clone of gluProject
PANGOLIN_EXPORT
GLint glProject(
double objx, double objy, double objz,
const double modelMatrix[16],
const double projMatrix[16],
const GLint viewport[4],
double* winx, double* winy, double* winz
);
/// Clone of gluUnProject
PANGOLIN_EXPORT
GLint glUnProject(
double winx, double winy, double winz,
const double modelMatrix[16],
const double projMatrix[16],
const GLint viewport[4],
double* objx, double* objy, double* objz
);
}

View File

@@ -0,0 +1,95 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/image/pixel_format.h>
#include <stdexcept>
namespace pangolin {
// This class may dissapear in the future
struct GlPixFormat
{
GlPixFormat() {}
GlPixFormat(const PixelFormat& fmt)
{
switch( fmt.channels) {
case 1: glformat = GL_LUMINANCE; break;
case 3: glformat = (fmt.format == "BGR24" || fmt.format == "BGR48") ? GL_BGR : GL_RGB; break;
case 4: glformat = (fmt.format == "BGRA24" || fmt.format == "BGRA32" || fmt.format == "BGRA48") ? GL_BGRA : GL_RGBA; break;
default: throw std::runtime_error("Unable to form OpenGL format from video format: '" + fmt.format + "'.");
}
const bool is_integral = fmt.format.find('F') == std::string::npos;
switch (fmt.channel_bits[0]) {
case 8: gltype = GL_UNSIGNED_BYTE; break;
case 16: gltype = GL_UNSIGNED_SHORT; break;
case 32: gltype = (is_integral ? GL_UNSIGNED_INT : GL_FLOAT); break;
case 64: gltype = (is_integral ? GL_UNSIGNED_INT64_NV : GL_DOUBLE); break;
default: throw std::runtime_error("Unknown OpenGL data type for video format: '" + fmt.format + "'.");
}
if(glformat == GL_LUMINANCE) {
if(gltype == GL_UNSIGNED_BYTE) {
scalable_internal_format = GL_LUMINANCE8;
}else if(gltype == GL_UNSIGNED_SHORT){
scalable_internal_format = GL_LUMINANCE16;
}else{
scalable_internal_format = GL_LUMINANCE32F_ARB;
}
}else{
if(gltype == GL_UNSIGNED_BYTE) {
scalable_internal_format = GL_RGBA8;
}else if(gltype == GL_UNSIGNED_SHORT) {
scalable_internal_format = GL_RGBA16;
}else{
scalable_internal_format = GL_RGBA32F;
}
}
}
template<typename T>
static GlPixFormat FromType()
{
GlPixFormat fmt;
fmt.glformat = GlFormatTraits<T>::glformat;
fmt.gltype = GlFormatTraits<T>::gltype;
fmt.scalable_internal_format = GlFormatTraits<T>::glinternalformat;
return fmt;
}
GLint glformat;
GLenum gltype;
GLint scalable_internal_format;
};
}

View File

@@ -0,0 +1,83 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
//////////////////////////////////////////////////////////
// Attempt to portably include Necessary OpenGL headers
//////////////////////////////////////////////////////////
#include <pangolin/platform.h>
#ifdef _WIN_
// Define maths quantities when using <cmath> to match posix systems
#ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
#endif
// Don't define min / max macros in windows.h or other unnecessary macros
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
// Undef nuisance Windows.h macros which interfere with our methods
#undef LoadImage
#undef near
#undef far
#undef ERROR
#endif
#include <GL/glew.h>
#ifdef HAVE_GLES
#if defined(_ANDROID_)
#include <EGL/egl.h>
#ifdef HAVE_GLES_2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#include <GLES/gl.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES/glext.h>
#endif
#elif defined(_APPLE_IOS_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#endif
#else
#ifdef _OSX_
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#endif // HAVE_GLES
#include <pangolin/gl/glpangoglu.h>

View File

@@ -0,0 +1,738 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/colour.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/display/opengl_render_state.h>
#ifdef HAVE_GLES
#define GLhandleARB GLuint
#endif
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif // USE_EIGEN
namespace pangolin
{
////////////////////////////////////////////////
// Standard attribute locations
////////////////////////////////////////////////
const GLuint DEFAULT_LOCATION_POSITION = 0;
const GLuint DEFAULT_LOCATION_COLOUR = 1;
const GLuint DEFAULT_LOCATION_NORMAL = 2;
const GLuint DEFAULT_LOCATION_TEXCOORD = 3;
const char DEFAULT_NAME_POSITION[] = "a_position";
const char DEFAULT_NAME_COLOUR[] = "a_color";
const char DEFAULT_NAME_NORMAL[] = "a_normal";
const char DEFAULT_NAME_TEXCOORD[] = "a_texcoord";
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
enum GlSlShaderType
{
GlSlAnnotatedShader = 0,
GlSlFragmentShader = GL_FRAGMENT_SHADER,
GlSlVertexShader = GL_VERTEX_SHADER,
GlSlGeometryShader = 0x8DD9 /*GL_GEOMETRY_SHADER*/,
GlSlComputeShader = 0x91B9 /*GL_COMPUTE_SHADER*/
};
class GlSlProgram
{
public:
GlSlProgram();
//! Move Constructor
GlSlProgram(GlSlProgram&& tex);
~GlSlProgram();
bool AddShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
const std::vector<std::string>& search_path = std::vector<std::string>()
);
bool AddShaderFromFile(
GlSlShaderType shader_type,
const std::string& filename,
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
const std::vector<std::string>& search_path = std::vector<std::string>()
);
bool Link();
// Remove all shaders from this program, and reload from files.
bool ReloadShaderFiles();
GLint GetAttributeHandle(const std::string& name);
GLint GetUniformHandle(const std::string& name);
// Before setting uniforms, be sure to Bind() the GlSl program first.
void SetUniform(const std::string& name, int x);
void SetUniform(const std::string& name, int x1, int x2);
void SetUniform(const std::string& name, int x1, int x2, int x3);
void SetUniform(const std::string& name, int x1, int x2, int x3, int x4);
void SetUniform(const std::string& name, float f);
void SetUniform(const std::string& name, float f1, float f2);
void SetUniform(const std::string& name, float f1, float f2, float f3);
void SetUniform(const std::string& name, float f1, float f2, float f3, float f4);
void SetUniform(const std::string& name, Colour c);
void SetUniform(const std::string& name, const OpenGlMatrix& m);
#ifdef HAVE_EIGEN
void SetUniform(const std::string& name, const Eigen::Matrix3f& m);
void SetUniform(const std::string& name, const Eigen::Matrix4f& m);
void SetUniform(const std::string& name, const Eigen::Matrix3d& m);
void SetUniform(const std::string& name, const Eigen::Matrix4d& m);
#endif
#if GL_VERSION_4_3
GLint GetProgramResourceIndex(const std::string& name);
void SetShaderStorageBlock(const std::string& name, const int& bindingIndex);
#endif
void Bind();
void SaveBind();
void Unbind();
void BindPangolinDefaultAttribLocationsAndLink();
// Unlink all shaders from program
void ClearShaders();
GLint ProgramId() const {
return prog;
}
bool Valid() const {
return ProgramId() != 0;
}
protected:
struct ShaderFileOrCode
{
GlSlShaderType shader_type;
std::string filename;
std::string code;
std::map<std::string,std::string> program_defines;
std::vector<std::string> search_path;
};
// Convenience method to load shader description
bool AddShaderFile(const ShaderFileOrCode &shader_file);
std::string ParseIncludeFilename(
const std::string& location
);
std::string SearchIncludePath(
const std::string& filename,
const std::vector<std::string>& search_path,
const std::string& current_path
);
bool AddPreprocessedShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::string& name_for_errors
);
void PreprocessGLSL(
std::istream& input,
std::ostream& output,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path,
const std::string& current_path
);
// Split 'code' into several code blocks per shader type
// shader blocks in 'code' must be annotated with:
// @start vertex, @start fragment, @start geometry or @start compute
static std::map<GlSlShaderType,std::string>
SplitAnnotatedShaders(const std::string& code);
bool linked;
std::vector<GLhandleARB> shaders;
GLenum prog;
GLint prev_prog;
std::vector<ShaderFileOrCode> shader_files;
};
class GlSlUtilities
{
public:
inline static GlSlProgram& OffsetAndScale(float offset, float scale) {
GlSlProgram& prog = Instance().prog_offsetscale;
prog.Bind();
prog.SetUniform("offset", offset);
prog.SetUniform("scale", scale);
return prog;
}
inline static GlSlProgram& Scale(float scale, float bias = 0.0f) {
GlSlProgram& prog = Instance().prog_scale;
prog.Bind();
prog.SetUniform("scale", scale);
prog.SetUniform("bias", bias);
return prog;
}
inline static void UseNone()
{
glUseProgram(0);
}
protected:
static GlSlUtilities& Instance() {
// TODO: BUG: The GlSLUtilities instance needs to be tied
// to the OpenGL context, not the thread, or globally.
#ifndef PANGO_NO_THREADLOCAL
thread_local
#else
static
#endif
GlSlUtilities instance;
return instance;
}
// protected constructor
GlSlUtilities() {
const char* source_scale =
"uniform float scale;"
"uniform float bias;"
"uniform sampler2D tex;"
"void main() {"
" vec2 uv = gl_TexCoord[0].st;"
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
" gl_FragColor = texture2D(tex,uv);"
" gl_FragColor.xyz *= scale;"
" gl_FragColor.xyz += vec3(bias,bias,bias);"
" }else{"
" float v = 0.1;"
" gl_FragColor.xyz = vec3(v,v,v);"
" }"
"}";
prog_scale.AddShader(GlSlFragmentShader, source_scale);
prog_scale.Link();
const char* source_offsetscale =
"uniform float offset;"
"uniform float scale;"
"uniform sampler2D tex;"
"void main() {"
" vec2 uv = gl_TexCoord[0].st;"
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
" gl_FragColor = texture2D(tex,gl_TexCoord[0].st);"
" gl_FragColor.xyz += vec3(offset,offset,offset);"
" gl_FragColor.xyz *= scale;"
" }else{"
" float v = 0.1;"
" gl_FragColor.xyz = vec3(v,v,v);"
" }"
"}";
prog_offsetscale.AddShader(GlSlFragmentShader, source_offsetscale);
prog_offsetscale.Link();
}
GlSlProgram prog_scale;
GlSlProgram prog_offsetscale;
};
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline bool IsLinkSuccessPrintLog(GLhandleARB prog)
{
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if(status != GL_TRUE) {
pango_print_error("GLSL Program link failed: ");
const int PROGRAM_LOG_MAX_LEN = 10240;
char infolog[PROGRAM_LOG_MAX_LEN];
GLsizei len;
glGetProgramInfoLog(prog, PROGRAM_LOG_MAX_LEN, &len, infolog);
if(len) {
pango_print_error("%s\n",infolog);
}else{
pango_print_error("No details provided.\n");
}
return false;
}
return true;
}
inline bool IsCompileSuccessPrintLog(GLhandleARB shader, const std::string& name_for_errors)
{
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GL_TRUE) {
pango_print_error("GLSL Shader compilation failed: ");
const int SHADER_LOG_MAX_LEN = 10240;
char infolog[SHADER_LOG_MAX_LEN];
GLsizei len;
glGetShaderInfoLog(shader, SHADER_LOG_MAX_LEN, &len, infolog);
if(len) {
pango_print_error("%s:\n%s\n",name_for_errors.c_str(), infolog);
}else{
pango_print_error("%s:\nNo details provided.\n",name_for_errors.c_str());
}
return false;
}
return true;
}
inline GlSlProgram::GlSlProgram()
: linked(false), prog(0), prev_prog(0)
{
}
//! Move Constructor
inline GlSlProgram::GlSlProgram(GlSlProgram&& o)
: linked(o.linked), shaders(o.shaders), prog(o.prog), prev_prog(o.prev_prog)
{
o.prog = 0;
}
inline GlSlProgram::~GlSlProgram()
{
if(prog) {
ClearShaders();
glDeleteProgram(prog);
}
}
inline void PrintSourceCode(const std::string& src)
{
std::stringstream ss(src);
std::string line;
for(int linenum=1; std::getline(ss,line,'\n'); ++linenum) {
std::cout << linenum << ":\t" << line << std::endl;
}
}
inline bool GlSlProgram::AddPreprocessedShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::string& name_for_errors
) {
if(!prog) {
prog = glCreateProgram();
}
// PrintSourceCode(source_code);
GLhandleARB shader = glCreateShader(shader_type);
const char* source = source_code.c_str();
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
bool success = IsCompileSuccessPrintLog(shader, name_for_errors);
if(success) {
glAttachShader(prog, shader);
shaders.push_back(shader);
linked = false;
}
return success;
}
inline std::string GlSlProgram::ParseIncludeFilename(const std::string& location)
{
size_t start = location.find_first_of("\"<");
if(start != std::string::npos) {
size_t end = location.find_first_of("\">", start+1);
if(end != std::string::npos) {
return location.substr(start+1, end - start - 1);
}
}
throw std::runtime_error("GLSL Parser: Unable to parse include location " + location );
}
inline std::string GlSlProgram::SearchIncludePath(
const std::string& filename,
const std::vector<std::string>& search_path,
const std::string& current_path
) {
if(FileExists(current_path + "/" + filename)) {
return current_path + "/" + filename;
}else{
for(size_t i=0; i < search_path.size(); ++i) {
const std::string hypoth = search_path[i] + "/" + filename;
if( FileExists(hypoth) ) {
return hypoth;
}
}
}
return "";
}
inline void GlSlProgram::PreprocessGLSL(
std::istream& input, std::ostream& output,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string> &search_path,
const std::string &current_path
) {
const size_t MAXLINESIZE = 10240;
char line[MAXLINESIZE] = "";
while(!input.eof()) {
// Take like from source
input.getline(line,MAXLINESIZE);
// Transform
if( !strncmp(line, "#include", 8 ) ) {
// C++ / G3D style include directive
const std::string import_file = ParseIncludeFilename(line+8);
const std::string resolved_file = SearchIncludePath(import_file, search_path, current_path);
std::ifstream ifs(resolved_file.c_str());
if(ifs.good()) {
const std::string file_path = pangolin::PathParent(resolved_file);
PreprocessGLSL(ifs, output, program_defines, search_path, file_path);
}else{
throw std::runtime_error("GLSL Parser: Unable to open " + import_file );
}
}else if( !strncmp(line, "#expect", 7) ) {
// G3D style 'expect' directive, annotating expected preprocessor
// definition with document string
// Consume whitespace before token
size_t token_start = 7;
while( std::isspace(line[token_start]) ) ++token_start;
// Iterate over contigous charecters until \0 or whitespace
size_t token_end = token_start;
while( line[token_end] && !std::isspace(line[token_end]) ) ++token_end;
std::string token(line+token_start, line+token_end);
std::map<std::string,std::string>::const_iterator it = program_defines.find(token);
if( it == program_defines.end() ) {
pango_print_warn("Expected define missing (defaulting to 0): '%s'\n%s\n", token.c_str(), line + token_end );
output << "#define " << token << " 0" << std::endl;
}else{
output << "#define " << token << " " << it->second << std::endl;
}
}else{
// Output directly
output << line << std::endl;
}
}
}
inline void GlSlProgram::ClearShaders()
{
// Remove and delete each shader
for(size_t i=0; i<shaders.size(); ++i ) {
glDetachShader(prog, shaders[i]);
glDeleteShader(shaders[i]);
}
shaders.clear();
}
inline bool GlSlProgram::AddShaderFile(const ShaderFileOrCode& shader_file)
{
std::stringstream buffer;
if(shader_file.code.empty()) {
std::ifstream ifs(shader_file.filename.c_str());
if(ifs.is_open()) {
PreprocessGLSL(ifs, buffer, shader_file.program_defines, shader_file.search_path, ".");
}else{
throw std::runtime_error(FormatString("Unable to open shader file '%'", shader_file.filename));
}
}else{
std::istringstream iss(shader_file.code);
PreprocessGLSL(iss, buffer, shader_file.program_defines, shader_file.search_path, ".");
}
const std::string code = buffer.str();
const std::string input_name = !shader_file.filename.empty() ? shader_file.filename : "<string>";
if(shader_file.shader_type == GlSlAnnotatedShader) {
const std::map<GlSlShaderType,std::string> split_progs = SplitAnnotatedShaders(code);
for(const auto& type_code : split_progs) {
if(!AddPreprocessedShader(type_code.first, type_code.second, input_name )) {
return false;
}
}
return true;
}else{
return AddPreprocessedShader(shader_file.shader_type, code, input_name);
}
}
inline bool GlSlProgram::AddShaderFromFile(
GlSlShaderType shader_type,
const std::string& filename,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path
) {
ShaderFileOrCode shader_file = {
shader_type,
pangolin::PathExpand(filename),
std::string(),
program_defines,
search_path
};
shader_files.push_back(shader_file);
return AddShaderFile(shader_file);
}
inline bool GlSlProgram::AddShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path
) {
ShaderFileOrCode shader_file = {
shader_type,
std::string(),
source_code,
program_defines,
search_path
};
shader_files.push_back(shader_file);
return AddShaderFile(shader_file);
}
inline bool GlSlProgram::ReloadShaderFiles()
{
ClearShaders();
for(const auto& sf : shader_files) {
if(!AddShaderFile(sf)) {
return false;
}
}
Link();
return true;
}
inline std::map<GlSlShaderType,std::string>
GlSlProgram::SplitAnnotatedShaders(const std::string& code)
{
std::map<GlSlShaderType,std::string> ret;
std::stringstream input(code);
std::stringstream output;
const size_t MAXLINESIZE = 10240;
char line[MAXLINESIZE];
GlSlShaderType current_type = GlSlAnnotatedShader;
auto finish_block = [&](GlSlShaderType type){
if(current_type != GlSlAnnotatedShader) {
ret[current_type] = output.str();
}
output.str(std::string());
current_type = type;
};
while(!input.eof()) {
// Take like from source
input.getline(line,MAXLINESIZE);
// Transform
if( !strncmp(line, "@start", 6 ) ) {
const std::string str_shader_type = pangolin::Trim(std::string(line).substr(6));
if(str_shader_type == "vertex") {
finish_block(GlSlVertexShader);
}else if(str_shader_type == "fragment") {
finish_block(GlSlFragmentShader);
}else if(str_shader_type == "geometry") {
finish_block(GlSlGeometryShader);
}else if(str_shader_type == "compute") {
finish_block(GlSlComputeShader);
}
}else{
output << line << std::endl;
}
}
finish_block(GlSlAnnotatedShader);
return ret;
}
inline bool GlSlProgram::Link()
{
glLinkProgram(prog);
return IsLinkSuccessPrintLog(prog);
}
inline void GlSlProgram::Bind()
{
prev_prog = 0;
glUseProgram(prog);
}
inline void GlSlProgram::SaveBind()
{
glGetIntegerv(GL_CURRENT_PROGRAM, &prev_prog);
glUseProgram(prog);
}
inline void GlSlProgram::Unbind()
{
glUseProgram(prev_prog);
}
inline GLint GlSlProgram::GetAttributeHandle(const std::string& name)
{
return glGetAttribLocation(prog, name.c_str());
}
inline GLint GlSlProgram::GetUniformHandle(const std::string& name)
{
return glGetUniformLocation(prog, name.c_str());
}
inline void GlSlProgram::SetUniform(const std::string& name, int x)
{
glUniform1i( GetUniformHandle(name), x);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2)
{
glUniform2i( GetUniformHandle(name), x1, x2);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3)
{
glUniform3i( GetUniformHandle(name), x1, x2, x3);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3, int x4)
{
glUniform4i( GetUniformHandle(name), x1, x2, x3, x4);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f)
{
glUniform1f( GetUniformHandle(name), f);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2)
{
glUniform2f( GetUniformHandle(name), f1,f2);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3)
{
glUniform3f( GetUniformHandle(name), f1,f2,f3);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3, float f4)
{
glUniform4f( GetUniformHandle(name), f1,f2,f3,f4);
}
inline void GlSlProgram::SetUniform(const std::string& name, Colour c)
{
glUniform4f( GetUniformHandle(name), c.r, c.g, c.b, c.a);
}
inline void GlSlProgram::SetUniform(const std::string& name, const OpenGlMatrix& mat)
{
// glUniformMatrix4dv seems to be crashing...
float m[16];
for (int i = 0; i < 16; ++i) {
m[i] = (float)mat.m[i];
}
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m);
}
#ifdef HAVE_EIGEN
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3f& m)
{
glUniformMatrix3fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4f& m)
{
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3d& m)
{
glUniformMatrix3dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4d& m)
{
glUniformMatrix4dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
#endif
inline void GlSlProgram::BindPangolinDefaultAttribLocationsAndLink()
{
glBindAttribLocation(prog, DEFAULT_LOCATION_POSITION, DEFAULT_NAME_POSITION);
glBindAttribLocation(prog, DEFAULT_LOCATION_COLOUR, DEFAULT_NAME_COLOUR);
glBindAttribLocation(prog, DEFAULT_LOCATION_NORMAL, DEFAULT_NAME_NORMAL);
glBindAttribLocation(prog, DEFAULT_LOCATION_TEXCOORD, DEFAULT_NAME_TEXCOORD);
Link();
}
#if GL_VERSION_4_3
inline GLint GlSlProgram::GetProgramResourceIndex(const std::string& name)
{
return glGetProgramResourceIndex(prog, GL_SHADER_STORAGE_BLOCK, name.c_str());
}
inline void GlSlProgram::SetShaderStorageBlock(const std::string& name, const int& bindingIndex)
{
glShaderStorageBlockBinding(prog, GetProgramResourceIndex(name), bindingIndex);
}
#endif
}

View File

@@ -0,0 +1,220 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Vincent Mamo, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <stack>
namespace pangolin
{
class GlState {
class CapabilityState {
public:
CapabilityState(GLenum cap, GLboolean enable)
: m_cap(cap), m_enable(enable)
{
}
void Apply() {
if(m_enable) {
::glEnable(m_cap);
}else{
::glDisable(m_cap);
}
}
void UnApply() {
if(m_enable) {
::glDisable(m_cap);
}else{
::glEnable(m_cap);
}
}
protected:
GLenum m_cap;
GLboolean m_enable;
};
public:
GlState()
: m_DepthMaskCalled(false),
m_ShadeModelCalled(false),
m_CullFaceCalled(false),
m_PointSizeCalled(false),
m_LineWidthCalled(false),
m_ColorMaskCalled(false),
m_ViewportCalled(false)
{
}
~GlState() {
// Restore original state
while (!m_history.empty()) {
m_history.top().UnApply();
m_history.pop();
}
if (m_DepthMaskCalled) {
::glDepthMask(m_OriginalDepthMask);
}
if (m_ShadeModelCalled) {
::glShadeModel(m_OriginalShadeModel);
}
if (m_CullFaceCalled) {
::glCullFace(m_OriginalCullFace);
}
if(m_PointSizeCalled) {
::glPointSize(m_OriginalPointSize);
}
if(m_LineWidthCalled) {
::glLineWidth(m_OriginalLineWidth);
}
if (m_ColorMaskCalled) {
::glColorMask(m_OriginalColorMask[0], m_OriginalColorMask[1], m_OriginalColorMask[2], m_OriginalColorMask[3]);
}
if (m_ViewportCalled) {
::glViewport(m_OriginalViewport[0], m_OriginalViewport[1], m_OriginalViewport[2], m_OriginalViewport[3]);
}
}
static inline GLboolean IsEnabled(GLenum cap)
{
GLboolean curVal;
glGetBooleanv(cap, &curVal);
return curVal;
}
inline void glEnable(GLenum cap)
{
if(!IsEnabled(cap)) {
m_history.push(CapabilityState(cap,true));
::glEnable(cap);
}
}
inline void glDisable(GLenum cap)
{
if(IsEnabled(cap)) {
m_history.push(CapabilityState(cap,false));
::glDisable(cap);
}
}
bool m_DepthMaskCalled;
GLboolean m_OriginalDepthMask;
inline void glDepthMask(GLboolean flag)
{
if(!m_DepthMaskCalled) {
m_DepthMaskCalled = true;
glGetBooleanv(GL_DEPTH_WRITEMASK, &m_OriginalDepthMask);
}
::glDepthMask(flag);
}
bool m_ShadeModelCalled;
GLint m_OriginalShadeModel;
inline void glShadeModel(GLint mode)
{
if(!m_ShadeModelCalled) {
m_ShadeModelCalled = true;
glGetIntegerv(GL_SHADE_MODEL, &m_OriginalShadeModel);
}
::glShadeModel(mode);
}
bool m_CullFaceCalled;
GLint m_OriginalCullFace;
void glCullFace(GLenum mode)
{
if(!m_ShadeModelCalled) {
m_ShadeModelCalled = true;
glGetIntegerv(GL_CULL_FACE_MODE, &m_OriginalCullFace);
}
::glCullFace(mode);
}
bool m_PointSizeCalled;
GLfloat m_OriginalPointSize;
void glPointSize(GLfloat size)
{
if(!m_PointSizeCalled) {
m_PointSizeCalled = true;
glGetFloatv(GL_POINT_SIZE, &m_OriginalPointSize);
}
::glPointSize(size);
}
bool m_LineWidthCalled;
GLfloat m_OriginalLineWidth;
void glLineWidth(GLfloat width)
{
if(!m_LineWidthCalled) {
m_LineWidthCalled = true;
glGetFloatv(GL_LINE_WIDTH, &m_OriginalLineWidth);
}
::glLineWidth(width);
}
bool m_ColorMaskCalled;
GLboolean m_OriginalColorMask[4];
inline void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
if(!m_ColorMaskCalled) {
m_ColorMaskCalled = true;
glGetBooleanv(GL_COLOR_WRITEMASK, m_OriginalColorMask);
}
::glColorMask(red, green, blue, alpha);
}
bool m_ViewportCalled;
GLint m_OriginalViewport[4];
inline void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
if(!m_ViewportCalled) {
m_ViewportCalled = true;
glGetIntegerv(GL_VIEWPORT, m_OriginalViewport);
}
::glViewport(x, y, width, height);
}
std::stack<CapabilityState> m_history;
};
}

View File

@@ -0,0 +1,98 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glchar.h>
#include <vector>
#include <string>
namespace pangolin {
class PANGOLIN_EXPORT GlText
{
public:
GlText();
GlText(const GlText& txt);
GlText(const GlTexture& font_tex);
void AddSpace(GLfloat s);
// Add specified charector to this string.
void Add(unsigned char c, const GlChar& glc);
// Clear text
void Clear();
// Render without transform in text-centric pixel coordinates
void Draw() const;
void DrawGlSl() const;
#ifdef BUILD_PANGOLIN_GUI
// Render at (x,y,z)' in object coordinates,
// keeping text size and orientation constant
void Draw(GLfloat x, GLfloat y, GLfloat z = 0.0f) const;
// Render at (x,y,z)' in window coordinates.
void DrawWindow(GLfloat x, GLfloat y, GLfloat z = 0.0f) const;
#endif // BUILD_PANGOLIN_GUI
// Return text that this object signifies.
const std::string& Text() const {
return str;
}
// Return width in pixels of this text.
GLfloat Width() const {
return width;
}
// Return height in pixels of this text.
GLfloat Height() const {
return ymax;
}
// Return height in pixels of this text, including under baseline
GLfloat FullHeight() const {
return ymax - ymin;
}
//protected:
const GlTexture* tex;
std::string str;
GLfloat width;
GLfloat ymin;
GLfloat ymax;
std::vector<XYUV> vs;
};
}

View File

@@ -0,0 +1,116 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/image/image.h>
#include <memory>
#include <map>
namespace pangolin
{
class PANGOLIN_EXPORT TextureCache
{
public:
static TextureCache& I();
GlTexture& GlTex(GLsizei w, GLsizei h, GLint internal_format, GLint glformat, GLenum gltype)
{
const long key =
(((long)internal_format)<<20) ^
(((long)glformat)<<10) ^ gltype;
// Lookup texture
std::shared_ptr<GlTexture>& ptex = texture_map[key];
if(!ptex) {
ptex = std::shared_ptr<GlTexture>(new GlTexture());
}
GlTexture& tex = *ptex;
// Initialise if it didn't already exist or the size was too small
if(!tex.tid || tex.width < w || tex.height < h) {
tex.Reinitialise(
std::max(tex.width,w), std::max(tex.height,h),
internal_format, default_sampling_linear, 0,
glformat, gltype
);
}
return tex;
}
template<typename T>
GlTexture& GlTex(GLsizei w, GLsizei h)
{
return GlTex( w, h,
GlFormatTraits<T>::glinternalformat,
GlFormatTraits<T>::glformat,
GlFormatTraits<T>::gltype
);
}
protected:
bool default_sampling_linear;
std::map<long, std::shared_ptr<GlTexture> > texture_map;
// Protected constructor
TextureCache()
: default_sampling_linear(true)
{
}
};
template<typename T>
void RenderToViewport(Image<T>& image, bool flipx=false, bool flipy=false)
{
// Retrieve texture that is at least as large as image and of appropriate type.
GlTexture& tex = TextureCache::I().GlTex<T>(image.w, image.h);
tex.Upload(image.ptr,0,0, image.w, image.h, GlFormatTraits<T>::glformat, GlFormatTraits<T>::gltype);
tex.RenderToViewport(Viewport(0,0,image.w, image.h), flipx, flipy);
}
// This method may dissapear in the future
inline void RenderToViewport(
Image<unsigned char>& image,
const pangolin::GlPixFormat& fmt,
bool flipx=false, bool flipy=false,
bool linear_sampling = true
) {
pangolin::GlTexture& tex = pangolin::TextureCache::I().GlTex((GLsizei)image.w, (GLsizei)image.h, fmt.scalable_internal_format, fmt.glformat, fmt.gltype);
tex.Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_sampling ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_sampling ? GL_LINEAR : GL_NEAREST);
tex.Upload(image.ptr,0,0, (GLsizei)image.w, (GLsizei)image.h, fmt.glformat, fmt.gltype);
tex.RenderToViewport(pangolin::Viewport(0,0,(GLint)image.w, (GLint)image.h), flipx, flipy);
}
}

View File

@@ -0,0 +1,225 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
void MakeTriangleStripIboForVbo(GlBuffer& ibo, int w, int h);
GlBuffer MakeTriangleStripIboForVbo(int w, int h);
void RenderVbo(GlBuffer& vbo, GLenum mode = GL_POINTS);
void RenderVboCbo(GlBuffer& vbo, GlBuffer& cbo, bool draw_color = true, GLenum mode = GL_POINTS);
void RenderVboIbo(GlBuffer& vbo, GlBuffer& ibo, bool draw_mesh = true);
void RenderVboIboCbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, bool draw_mesh = true, bool draw_color = true);
void RenderVboIboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& nbo, bool draw_mesh = true, bool draw_normals = true);
void RenderVboIboCboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, GlBuffer& nbo, bool draw_mesh = true, bool draw_color = true, bool draw_normals = true);
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline void MakeTriangleStripIboForVbo(GlBuffer& ibo, int w, int h)
{
const int num_elements = w*(h-1)*2;
unsigned int* buffer = new unsigned int[num_elements];
unsigned int* ptr = buffer;
for(int y=0; y < (h-1);)
{
for(int x=0; x<w; ++x) {
(*ptr++) = y*w+x;
(*ptr++) = (y+1)*w+x;
}
++y;
if(y>=(h-1)) break;
for(int x=w-1; x>=0; --x) {
(*ptr++) = y*w+x;
(*ptr++) = (y+1)*w+x;
}
++y;
}
ibo.Reinitialise(GlElementArrayBuffer, num_elements, GL_UNSIGNED_INT, 1, GL_STATIC_DRAW );
ibo.Upload(buffer, sizeof(unsigned int)*num_elements );
delete[] buffer;
}
inline GlBuffer MakeTriangleStripIboForVbo(int w, int h)
{
GlBuffer ibo;
MakeTriangleStripIboForVbo(ibo,w,h);
return ibo;
}
inline void RenderVbo(GlBuffer& vbo, GLenum mode)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(mode, 0, vbo.num_elements);
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboCbo(GlBuffer& vbo, GlBuffer& cbo, bool draw_color, GLenum mode )
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
RenderVbo(vbo,mode);
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
}
inline void RenderVboIbo(GlBuffer& vbo, GlBuffer& ibo, bool draw_mesh)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboIboCbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, bool draw_mesh, bool draw_color )
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
RenderVboIbo(vbo,ibo,draw_mesh);
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
}
inline void RenderVboIboCboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, GlBuffer& nbo, bool draw_mesh, bool draw_color, bool draw_normals)
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
if(draw_normals) {
nbo.Bind();
glNormalPointer(nbo.datatype, (GLsizei)(nbo.count_per_element * GlDataTypeBytes(nbo.datatype)),0);
glEnableClientState(GL_NORMAL_ARRAY);
}
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
if(draw_normals) {
glDisableClientState(GL_NORMAL_ARRAY);
nbo.Unbind();
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboIboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& nbo, bool draw_mesh, bool draw_normals)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_normals) {
nbo.Bind();
glNormalPointer(nbo.datatype, (GLsizei)(nbo.count_per_element * GlDataTypeBytes(nbo.datatype)), 0);
glEnableClientState(GL_NORMAL_ARRAY);
}
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
if(draw_normals) {
glDisableClientState(GL_NORMAL_ARRAY);
nbo.Unbind();
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
}

View File

@@ -0,0 +1,116 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/handler/handler_enums.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
#ifdef _OSX_
#define PANGO_DFLT_HANDLER3D_ZF (1.0f/50.0f)
#else
#define PANGO_DFLT_HANDLER3D_ZF (1.0f/10.0f)
#endif
namespace pangolin
{
// Forward declarations
struct View;
/// Input Handler base class.
/// Virtual methods which recurse into sub-displays.
struct PANGOLIN_EXPORT Handler
{
virtual ~Handler() {}
virtual void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
virtual void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
virtual void MouseMotion(View&, int x, int y, int button_state);
virtual void PassiveMouseMotion(View&, int x, int y, int button_state);
virtual void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
};
struct PANGOLIN_EXPORT HandlerScroll : Handler
{
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
};
struct PANGOLIN_EXPORT Handler3D : Handler
{
Handler3D(OpenGlRenderState& cam_state, AxisDirection enforce_up=AxisNone, float trans_scale=0.01f, float zoom_fraction= PANGO_DFLT_HANDLER3D_ZF);
virtual bool ValidWinDepth(GLprecision depth);
virtual void PixelUnproject( View& view, GLprecision winx, GLprecision winy, GLprecision winz, GLprecision Pc[3]);
virtual void GetPosNormal(View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z = 1.0);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
void MouseMotion(View&, int x, int y, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
#ifdef USE_EIGEN
// Return selected point in world coordinates
inline Eigen::Vector3d Selected_P_w() const {
return Eigen::Map<const Eigen::Matrix<GLprecision,3,1>>(Pw).cast<double>();
}
#endif
inline int KeyState() const{
return funcKeyState;
}
protected:
OpenGlRenderState* cam_state;
const static int hwin = 8;
AxisDirection enforce_up;
float tf; // translation factor
float zf; // zoom fraction
CameraSpec cameraspec;
GLprecision last_z;
float last_pos[2];
GLprecision rot_center[3];
GLprecision p[3];
GLprecision Pw[3];
GLprecision Pc[3];
GLprecision n[3];
int funcKeyState;
};
static Handler StaticHandler;
static HandlerScroll StaticHandlerScroll;
}

View File

@@ -0,0 +1,94 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
namespace pangolin
{
// Supported Key modifiers for GlobalKeyPressCallback.
// e.g. PANGO_CTRL + 'r', PANGO_SPECIAL + PANGO_KEY_RIGHT, etc.
const int PANGO_SPECIAL = 128;
const int PANGO_CTRL = -96;
const int PANGO_OPTN = 132;
// Ordinary keys
const int PANGO_KEY_TAB = 9;
const int PANGO_KEY_ESCAPE = 27;
// Special Keys (same as GLUT_ defines)
const int PANGO_KEY_F1 = 1;
const int PANGO_KEY_F2 = 2;
const int PANGO_KEY_F3 = 3;
const int PANGO_KEY_F4 = 4;
const int PANGO_KEY_F5 = 5;
const int PANGO_KEY_F6 = 6;
const int PANGO_KEY_F7 = 7;
const int PANGO_KEY_F8 = 8;
const int PANGO_KEY_F9 = 9;
const int PANGO_KEY_F10 = 10;
const int PANGO_KEY_F11 = 11;
const int PANGO_KEY_F12 = 12;
const int PANGO_KEY_LEFT = 100;
const int PANGO_KEY_UP = 101;
const int PANGO_KEY_RIGHT = 102;
const int PANGO_KEY_DOWN = 103;
const int PANGO_KEY_PAGE_UP = 104;
const int PANGO_KEY_PAGE_DOWN = 105;
const int PANGO_KEY_HOME = 106;
const int PANGO_KEY_END = 107;
const int PANGO_KEY_INSERT = 108;
enum MouseButton
{
MouseButtonLeft = 1,
MouseButtonMiddle = 2,
MouseButtonRight = 4,
MouseWheelUp = 8,
MouseWheelDown = 16,
MouseWheelRight = 32,
MouseWheelLeft = 64,
};
enum KeyModifier
{
KeyModifierShift = 1<<16,
KeyModifierCtrl = 1<<17,
KeyModifierAlt = 1<<18,
KeyModifierCmd = 1<<19,
KeyModifierFnc = 1<<20
};
enum InputSpecial
{
InputSpecialScroll,
InputSpecialZoom,
InputSpecialRotate,
InputSpecialTablet
};
}

View File

@@ -0,0 +1,48 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef HANDLER_GLBUFFER_H
#define HANDLER_GLBUFFER_H
#include <pangolin/handler/handler.h>
#include <pangolin/gl/gl.h>
namespace pangolin
{
struct Handler3DFramebuffer : public pangolin::Handler3D
{
Handler3DFramebuffer(GlFramebuffer& fb, pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up=pangolin::AxisNone, float trans_scale=0.01f);
void GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision /*n*/[3], GLprecision default_z);
protected:
GlFramebuffer& fb;
};
}
#endif // HANDLER_GLBUFFER_H

View File

@@ -0,0 +1,162 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/image_utils.h>
#include <pangolin/display/viewport.h>
#include <pangolin/display/view.h>
#include <pangolin/handler/handler.h>
#include <pangolin/plot/range.h>
#include <pangolin/gl/gl.h>
#include <functional>
namespace pangolin
{
class ImageViewHandler : public Handler
{
public:
struct EventData {
EventData(View& v, ImageViewHandler& h) : view(v), handler(h) {}
View& view;
ImageViewHandler& handler;
};
struct OnSelectionEventData : public EventData {
OnSelectionEventData(View& v, ImageViewHandler& h, bool dragging)
: EventData(v,h), dragging(dragging) {}
bool dragging;
};
typedef std::function<void(OnSelectionEventData)> OnSelectionCallbackFn;
// Default constructor: User must call SetDimensions() once image dimensions are known.
// Default range is [0,1] in x and y.
ImageViewHandler();
// View ranges store extremes of image (boundary of pixels)
// in 'discrete' coords, where 0,0 is center of top-left pixel.
ImageViewHandler(size_t w, size_t h);
void SetDimensions(size_t w, size_t h);
void UpdateView();
void glSetViewOrtho();
void glRenderTexture(pangolin::GlTexture& tex);
void glRenderTexture(GLuint tex, GLint width, GLint height);
void glRenderOverlay();
void ScreenToImage(Viewport& v, float xpix, float ypix, float& ximg, float& yimg);
void ImageToScreen(Viewport& v, float ximg, float yimg, float& xpix, float& ypix);
bool UseNN() const;
bool& UseNN();
bool& FlipTextureX();
bool& FlipTextureY();
pangolin::XYRangef& GetViewToRender();
float GetViewScale();
pangolin::XYRangef& GetView();
pangolin::XYRangef& GetDefaultView();
pangolin::XYRangef& GetSelection();
void GetHover(float& x, float& y);
void SetView(const pangolin::XYRangef& range);
void SetViewSmooth(const pangolin::XYRangef& range);
void ScrollView(float x, float y);
void ScrollViewSmooth(float x, float y);
void ScaleView(float x, float y, float cx, float cy);
void ScaleViewSmooth(float x, float y, float cx, float cy);
void ResetView();
///////////////////////////////////////////////////////
/// pangolin::Handler
///////////////////////////////////////////////////////
void Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed) override;
void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
void MouseMotion(View& view, int x, int y, int button_state) override;
void PassiveMouseMotion(View&, int /*x*/, int /*y*/, int /*button_state*/) override;
void Special(View& view, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int /*button_state*/) override;
///////////////////////////////////////////////////////
/// Callbacks
///////////////////////////////////////////////////////
OnSelectionCallbackFn OnSelectionCallback;
protected:
void FixSelection(XYRangef& sel);
void AdjustScale();
void AdjustTranslation();
static ImageViewHandler* to_link;
static float animate_factor;
ImageViewHandler* linked_view_handler;
pangolin::XYRangef rview_default;
pangolin::XYRangef rview_max;
pangolin::XYRangef rview;
pangolin::XYRangef target;
pangolin::XYRangef selection;
float hover_img[2];
int last_mouse_pos[2];
bool use_nn;
bool flipTextureX;
bool flipTextureY;
};
}

View File

@@ -0,0 +1,45 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
namespace pangolin {
// Hold a reference to an object to be copied
template<typename T>
struct CopyObject {
CopyObject(const T& obj) : obj(obj) { }
const T& obj;
};
// Return copy wrapper for assignment to another object.
template<typename T>
typename pangolin::CopyObject<T> Copy(const T& obj) {
return typename pangolin::CopyObject<T>(obj);
}
}

View File

@@ -0,0 +1,428 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/image/memcpy.h>
#include <cstddef>
#include <functional>
#include <limits>
#include <cstring>
#ifdef PANGO_ENABLE_BOUNDS_CHECKS
# define PANGO_BOUNDS_ASSERT(...) PANGO_ENSURE(##__VA_ARGS__)
#else
# define PANGO_BOUNDS_ASSERT(...) ((void)0)
#endif
// Allow user defined macro to be inserted into Image class.
#ifndef PANGO_EXTENSION_IMAGE
# define PANGO_EXTENSION_IMAGE
#endif
namespace pangolin
{
// Simple image wrapper
template<typename T>
struct Image
{
using PixelType = T;
inline Image()
: pitch(0), ptr(0), w(0), h(0)
{
}
inline Image(T* ptr, size_t w, size_t h, size_t pitch)
: pitch(pitch), ptr(ptr), w(w), h(h)
{
}
PANGO_HOST_DEVICE inline
size_t SizeBytes() const
{
return pitch * h;
}
PANGO_HOST_DEVICE inline
size_t Area() const
{
return w * h;
}
PANGO_HOST_DEVICE inline
bool IsValid() const
{
return ptr != 0;
}
PANGO_HOST_DEVICE inline
bool IsContiguous() const
{
return w*sizeof(T) == pitch;
}
//////////////////////////////////////////////////////
// Iterators
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
T* begin()
{
return ptr;
}
PANGO_HOST_DEVICE inline
T* end()
{
return RowPtr(h-1) + w;
}
PANGO_HOST_DEVICE inline
const T* begin() const
{
return ptr;
}
PANGO_HOST_DEVICE inline
const T* end() const
{
return RowPtr(h-1) + w;
}
PANGO_HOST_DEVICE inline
size_t size() const
{
return w*h;
}
//////////////////////////////////////////////////////
// Image transforms
//////////////////////////////////////////////////////
template<typename UnaryOperation>
PANGO_HOST_DEVICE inline
void Transform(UnaryOperation unary_op)
{
PANGO_ASSERT(IsValid());
for(size_t y=0; y < h; ++y) {
T* el = RowPtr(y);
const T* el_end = el+w;
for( ; el != el_end; ++el) {
*el = unary_op(*el);
}
}
}
PANGO_HOST_DEVICE inline
void Fill(const T& val)
{
Transform( [&](const T&) {return val;} );
}
PANGO_HOST_DEVICE inline
void Replace(const T& oldval, const T& newval)
{
Transform( [&](const T& val) {
return (val == oldval) ? newval : val;
});
}
inline
void Memset(unsigned char v = 0)
{
PANGO_ASSERT(IsValid());
if(IsContiguous()) {
::pangolin::Memset((char*)ptr, v, pitch*h);
}else{
for(size_t y=0; y < h; ++y) {
::pangolin::Memset((char*)RowPtr(y), v, pitch);
}
}
}
inline
void CopyFrom(const Image<T>& img)
{
if(IsValid() && img.IsValid()) {
PANGO_ASSERT(w >= img.w && h >= img.h);
PitchedCopy((char*)ptr,pitch,(char*)img.ptr,img.pitch, std::min(img.w,w)*sizeof(T), std::min(img.h,h) );
}else if( img.IsValid() != IsValid() ){
PANGO_ASSERT(false && "Cannot copy from / to an unasigned image." );
}
}
//////////////////////////////////////////////////////
// Reductions
//////////////////////////////////////////////////////
template<typename BinaryOperation>
PANGO_HOST_DEVICE inline
T Accumulate(const T init, BinaryOperation binary_op)
{
PANGO_ASSERT(IsValid());
T val = init;
for(size_t y=0; y < h; ++y) {
T* el = RowPtr(y);
const T* el_end = el+w;
for(; el != el_end; ++el) {
val = binary_op(val, *el);
}
}
return val;
}
std::pair<T,T> MinMax() const
{
PANGO_ASSERT(IsValid());
std::pair<T,T> minmax(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest());
for(size_t r=0; r < h; ++r) {
const T* ptr = RowPtr(r);
const T* end = ptr + w;
while( ptr != end) {
minmax.first = std::min(*ptr, minmax.first);
minmax.second = std::max(*ptr, minmax.second);
++ptr;
}
}
return minmax;
}
template<typename Tout=T>
Tout Sum() const
{
return Accumulate((T)0, [](const T& lhs, const T& rhs){ return lhs + rhs; });
}
template<typename Tout=T>
Tout Mean() const
{
return Sum<Tout>() / Area();
}
//////////////////////////////////////////////////////
// Direct Pixel Access
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
T* RowPtr(size_t y)
{
return (T*)((unsigned char*)(ptr) + y*pitch);
}
PANGO_HOST_DEVICE inline
const T* RowPtr(size_t y) const
{
return (T*)((unsigned char*)(ptr) + y*pitch);
}
PANGO_HOST_DEVICE inline
T& operator()(size_t x, size_t y)
{
PANGO_BOUNDS_ASSERT( InBounds(x,y) );
return RowPtr(y)[x];
}
PANGO_HOST_DEVICE inline
const T& operator()(size_t x, size_t y) const
{
PANGO_BOUNDS_ASSERT( InBounds(x,y) );
return RowPtr(y)[x];
}
template<typename TVec>
PANGO_HOST_DEVICE inline
T& operator()(const TVec& p)
{
PANGO_BOUNDS_ASSERT( InBounds(p[0],p[1]) );
return RowPtr(p[1])[p[0]];
}
template<typename TVec>
PANGO_HOST_DEVICE inline
const T& operator()(const TVec& p) const
{
PANGO_BOUNDS_ASSERT( InBounds(p[0],p[1]) );
return RowPtr(p[1])[p[0]];
}
PANGO_HOST_DEVICE inline
T& operator[](size_t ix)
{
PANGO_BOUNDS_ASSERT( InImage(ptr+ix) );
return ptr[ix];
}
PANGO_HOST_DEVICE inline
const T& operator[](size_t ix) const
{
PANGO_BOUNDS_ASSERT( InImage(ptr+ix) );
return ptr[ix];
}
//////////////////////////////////////////////////////
// Bounds Checking
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE
bool InImage(const T* ptest) const
{
return ptr <= ptest && ptest < RowPtr(h);
}
PANGO_HOST_DEVICE inline
bool InBounds(int x, int y) const
{
return 0 <= x && x < (int)w && 0 <= y && y < (int)h;
}
PANGO_HOST_DEVICE inline
bool InBounds(float x, float y, float border) const
{
return border <= x && x < (w-border) && border <= y && y < (h-border);
}
template<typename TVec, typename TBorder>
PANGO_HOST_DEVICE inline
bool InBounds( const TVec& p, const TBorder border = (TBorder)0 ) const
{
return border <= p[0] && p[0] < ((int)w - border) && border <= p[1] && p[1] < ((int)h - border);
}
//////////////////////////////////////////////////////
// Obtain slices / subimages
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
const Image<const T> SubImage(size_t x, size_t y, size_t width, size_t height) const
{
PANGO_ASSERT( (x+width) <= w && (y+height) <= h);
return Image<const T>( RowPtr(y)+x, width, height, pitch);
}
PANGO_HOST_DEVICE inline
Image<T> SubImage(size_t x, size_t y, size_t width, size_t height)
{
PANGO_ASSERT( (x+width) <= w && (y+height) <= h);
return Image<T>( RowPtr(y)+x, width, height, pitch);
}
PANGO_HOST_DEVICE inline
const Image<T> Row(int y) const
{
return SubImage(0,y,w,1);
}
PANGO_HOST_DEVICE inline
Image<T> Row(int y)
{
return SubImage(0,y,w,1);
}
PANGO_HOST_DEVICE inline
const Image<T> Col(int x) const
{
return SubImage(x,0,1,h);
}
PANGO_HOST_DEVICE inline
Image<T> Col(int x)
{
return SubImage(x,0,1,h);
}
//////////////////////////////////////////////////////
// Data mangling
//////////////////////////////////////////////////////
template<typename TRecast>
PANGO_HOST_DEVICE inline
Image<TRecast> Reinterpret() const
{
PANGO_ASSERT(sizeof(TRecast) == sizeof(T), "sizeof(TRecast) must match sizeof(T): % != %", sizeof(TRecast), sizeof(T) );
return UnsafeReinterpret<TRecast>();
}
template<typename TRecast>
PANGO_HOST_DEVICE inline
Image<TRecast> UnsafeReinterpret() const
{
return Image<TRecast>((TRecast*)ptr,w,h,pitch);
}
//////////////////////////////////////////////////////
// Deprecated methods
//////////////////////////////////////////////////////
// PANGOLIN_DEPRECATED inline
Image(size_t w, size_t h, size_t pitch, T* ptr)
: pitch(pitch), ptr(ptr), w(w), h(h)
{
}
// Use RAII/move aware pangolin::ManagedImage instead
// PANGOLIN_DEPRECATED inline
void Dealloc()
{
if(ptr) {
::operator delete(ptr);
ptr = nullptr;
}
}
// Use RAII/move aware pangolin::ManagedImage instead
// PANGOLIN_DEPRECATED inline
void Alloc(size_t w, size_t h, size_t pitch)
{
Dealloc();
this->w = w;
this->h = h;
this->pitch = pitch;
this->ptr = (T*)::operator new(h*pitch);
}
//////////////////////////////////////////////////////
// Data members
//////////////////////////////////////////////////////
size_t pitch;
T* ptr;
size_t w;
size_t h;
PANGO_EXTENSION_IMAGE
};
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <pangolin/image/managed_image.h>
#include <pangolin/utils/compontent_cast.h>
namespace pangolin
{
template <typename To, typename T>
void ImageConvert(Image<To>& dst, const Image<T>& src, To scale = 1.0)
{
for(unsigned int y = 0; y < dst.h; ++y)
{
const T* prs = src.RowPtr(y);
To* prd = dst.RowPtr(y);
for(unsigned int x = 0; x < dst.w; ++x)
{
*(prd++) = scale * ComponentCast<To, T>::cast(*(prs++));
}
}
}
template <typename To, typename T>
ManagedImage<To> ImageConvert(const Image<T>& src, To scale = 1.0)
{
ManagedImage<To> dst(src.w, src.h);
ImageConvert<To,T>(dst,src,scale);
return dst;
}
}

View File

@@ -0,0 +1,65 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/image/typed_image.h>
#include <pangolin/utils/file_extension.h>
namespace pangolin {
PANGOLIN_EXPORT
TypedImage LoadImage(std::istream& in, ImageFileType file_type);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename, ImageFileType file_type);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename, const PixelFormat& raw_fmt, size_t raw_width, size_t raw_height, size_t raw_pitch);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, ImageFileType file_type, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, ImageFileType file_type, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const TypedImage& image, const std::string& filename, bool top_line_first = true, float quality = 100.0f);
}

View File

@@ -0,0 +1,185 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <limits>
#include <utility>
#include <pangolin/image/image.h>
#include <pangolin/plot/range.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glpixformat.h>
namespace pangolin
{
namespace internal
{
template <typename T>
std::pair<float, float> GetMinMax(const Image<T>& img, size_t channels)
{
const size_t max_channels = 3;
const size_t colour_channels = std::min(channels, max_channels);
std::pair<float, float> chan_mm[max_channels];
for(size_t c = 0; c < max_channels; ++c)
{
chan_mm[c].first = +std::numeric_limits<float>::max();
chan_mm[c].second = -std::numeric_limits<float>::max();
}
for(size_t y = 0; y < img.h; ++y)
{
T* pix = (T*)((char*)img.ptr + y * img.pitch);
for(size_t x = 0; x < img.w; ++x)
{
for(size_t c = 0; c < colour_channels; ++c)
{
if(pix[c] < chan_mm[c].first)
chan_mm[c].first = (float)pix[c];
if(pix[c] > chan_mm[c].second)
chan_mm[c].second = (float)pix[c];
}
pix += channels;
}
}
// Find min / max of all channels, ignoring 4th alpha channel
std::pair<float, float> mm = chan_mm[0];
for(size_t c = 1; c < colour_channels; ++c)
{
mm.first = std::min(mm.first, chan_mm[c].first);
mm.second = std::max(mm.second, chan_mm[c].second);
}
return mm;
}
template<typename T>
pangolin::Image<T> GetImageRoi( pangolin::Image<T> img, size_t channels, const pangolin::XYRangei& roi )
{
return pangolin::Image<T>(
img.RowPtr(std::min(roi.y.min,roi.y.max)) + channels*std::min(roi.x.min,roi.x.max),
roi.x.AbsSize(), roi.y.AbsSize(),
img.pitch
);
}
template<typename T>
std::pair<float,float> GetOffsetScale(const pangolin::Image<T>& img, size_t channels, float type_max, float format_max)
{
// Find min / max of all channels, ignoring 4th alpha channel
const std::pair<float,float> mm = internal::GetMinMax<T>(img,channels);
const float type_scale = format_max / type_max;
const float offset = -type_scale* mm.first;
const float scale = type_max / (mm.second - mm.first);
return std::pair<float,float>(offset, scale);
}
template<typename T>
float GetScaleOnly(const pangolin::Image<T>& img, size_t channels, float type_max, float /*format_max*/)
{
// Find min / max of all channels, ignoring 4th alpha channel
const std::pair<float,float> mm = internal::GetMinMax<T>(img,channels);
const float scale = type_max / mm.second;
return scale;
}
} // internal
inline std::pair<float, float> GetMinMax(
const Image<unsigned char>& img,
XYRangei iroi, const GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w - 1, 0, (int)img.h - 1);
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_FLOAT) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_DOUBLE) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels);
} else {
return std::pair<float, float>(std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest());
}
}
inline std::pair<float,float> GetOffsetScale(
const pangolin::Image<unsigned char>& img,
pangolin::XYRangei iroi, const pangolin::GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w-1, 0, (int)img.h-1 );
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels, 255.0f, 1.0f);
}else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels, 65535.0f, 1.0f);
}else if(glfmt.gltype == GL_FLOAT) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else if(glfmt.gltype == GL_DOUBLE) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else{
return std::pair<float,float>(0.0f, 1.0f);
}
}
inline float GetScaleOnly(
const pangolin::Image<unsigned char>& img,
pangolin::XYRangei iroi, const pangolin::GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w-1, 0, (int)img.h-1 );
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels, 255.0f, 1.0f);
}else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels, 65535.0f, 1.0f);
}else if(glfmt.gltype == GL_FLOAT) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else if(glfmt.gltype == GL_DOUBLE) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else{
return 1.0f;
}
}
}

View File

@@ -0,0 +1,175 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/image.h>
#include <pangolin/image/copy.h>
namespace pangolin {
template<class T> using DefaultImageAllocator = std::allocator<T>;
// Image that manages it's own memory, storing a strong pointer to it's memory
template<typename T, class Allocator = DefaultImageAllocator<T> >
class ManagedImage : public Image<T>
{
public:
// Destructor
inline
~ManagedImage()
{
Deallocate();
}
// Null image
inline
ManagedImage()
{
}
// Row image
inline
ManagedImage(size_t w)
: Image<T>(
Allocator().allocate(w),
w, 1, w*sizeof(T)
)
{
}
inline
ManagedImage(size_t w, size_t h)
: Image<T>(
Allocator().allocate(w*h),
w, h, w*sizeof(T)
)
{
}
inline
ManagedImage(size_t w, size_t h, size_t pitch_bytes)
: Image<T>(
Allocator().allocate( (h*pitch_bytes) / sizeof(T) + 1),
w, h, pitch_bytes
)
{
}
// Not copy constructable
inline
ManagedImage( const ManagedImage<T>& other ) = delete;
// Move constructor
inline
ManagedImage(ManagedImage<T,Allocator>&& img)
{
*this = std::move(img);
}
// Move asignment
inline
void operator=(ManagedImage<T,Allocator>&& img)
{
Deallocate();
Image<T>::pitch = img.pitch;
Image<T>::ptr = img.ptr;
Image<T>::w = img.w;
Image<T>::h = img.h;
img.ptr = nullptr;
}
// Explicit copy constructor
template<typename TOther>
ManagedImage( const CopyObject<TOther>& other )
{
CopyFrom(other.obj);
}
// Explicit copy assignment
template<typename TOther>
void operator=(const CopyObject<TOther>& other)
{
CopyFrom(other.obj);
}
inline
void Swap(ManagedImage<T>& img)
{
std::swap(img.pitch, Image<T>::pitch);
std::swap(img.ptr, Image<T>::ptr);
std::swap(img.w, Image<T>::w);
std::swap(img.h, Image<T>::h);
}
inline
void CopyFrom(const Image<T>& img)
{
if(!Image<T>::IsValid() || Image<T>::w != img.w || Image<T>::h != img.h) {
Reinitialise(img.w,img.h);
}
Image<T>::CopyFrom(img);
}
inline
void Reinitialise(size_t w, size_t h)
{
if(!Image<T>::ptr || Image<T>::w != w || Image<T>::h != h) {
*this = ManagedImage<T,Allocator>(w,h);
}
}
inline
void Reinitialise(size_t w, size_t h, size_t pitch)
{
if(!Image<T>::ptr || Image<T>::w != w || Image<T>::h != h || Image<T>::pitch != pitch) {
*this = ManagedImage<T,Allocator>(w,h,pitch);
}
}
inline void Deallocate()
{
if (Image<T>::ptr) {
Allocator().deallocate(Image<T>::ptr, (Image<T>::h * Image<T>::pitch) / sizeof(T) );
Image<T>::ptr = nullptr;
}
}
// Move asignment
template<typename TOther, typename AllocOther> inline
void OwnAndReinterpret(ManagedImage<TOther,AllocOther>&& img)
{
Deallocate();
Image<T>::pitch = img.pitch;
Image<T>::ptr = (T*)img.ptr;
Image<T>::w = img.w;
Image<T>::h = img.h;
img.ptr = nullptr;
}
};
}

View File

@@ -0,0 +1,110 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <cstring>
#ifdef HAVE_CUDA
# include <cuda_runtime.h>
#endif
namespace pangolin {
template<typename T>
PANGO_HOST_DEVICE inline
bool IsDevicePtr(T* ptr)
{
#ifdef HAVE_CUDA
cudaPointerAttributes attributes;
cudaError_t res = cudaPointerGetAttributes(&attributes,ptr);
//Flushing the error flag for future CUDA error checks
if(res != cudaSuccess)
{
cudaGetLastError();
return false;
}
return attributes.memoryType == cudaMemoryTypeDevice;
#else
PANGOLIN_UNUSED(ptr);
return false;
#endif
}
PANGO_HOST_DEVICE inline
void MemCopy(void *dst, const void *src, size_t size_bytes)
{
#ifdef HAVE_CUDA
cudaMemcpy(dst,src, size_bytes, cudaMemcpyDefault);
#else
std::memcpy(dst, src, size_bytes);
#endif
}
inline
void PitchedCopy(char* dst, unsigned int dst_pitch_bytes, const char* src, unsigned int src_pitch_bytes, unsigned int width_bytes, unsigned int height)
{
#ifdef HAVE_CUDA
cudaMemcpy2D(dst, dst_pitch_bytes, src, src_pitch_bytes, width_bytes, height, cudaMemcpyDefault);
#else
if(dst_pitch_bytes == width_bytes && src_pitch_bytes == width_bytes ) {
std::memcpy(dst, src, height * width_bytes);
}else{
for(unsigned int row=0; row < height; ++row) {
std::memcpy(dst, src, width_bytes);
dst += dst_pitch_bytes;
src += src_pitch_bytes;
}
}
#endif
}
PANGO_HOST_DEVICE inline
void Memset(char* ptr, unsigned char v, size_t size_bytes)
{
#ifdef __CUDA_ARCH__
// Called in kernel
char* end = ptr + size_bytes;
for(char* p=ptr; p != end; ++p) *p = v;
#else
# ifdef HAVE_CUDA
if(IsDevicePtr(ptr))
{
cudaMemset(ptr, v, size_bytes);
}else
# endif // HAVE_CUDA
{
std::memset(ptr, v, size_bytes);
}
#endif // __CUDA_ARCH__
}
}

View File

@@ -0,0 +1,66 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011-2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
struct PANGOLIN_EXPORT PixelFormat
{
// Previously, VideoInterface::PixFormat returned a string.
// For compatibility, make this string convertable
inline operator std::string() const { return format; }
std::string format;
unsigned int channels;
unsigned int channel_bits[4]; //Of the data type
unsigned int bpp; //Of the data type
unsigned int channel_bit_depth; //Of the data
bool planar;
};
//! Return Pixel Format properties given string specification in
//! FFMPEG notation.
PANGOLIN_EXPORT
PixelFormat PixelFormatFromString(const std::string& format);
////////////////////////////////////////////////////////////////////
/// Deprecated aliases for above
PANGOLIN_DEPRECATED
typedef PixelFormat VideoPixelFormat;
PANGOLIN_DEPRECATED
inline PixelFormat VideoFormatFromString(const std::string& format) {
return PixelFormatFromString(format);
}
}

View File

@@ -0,0 +1,91 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/managed_image.h>
#include <pangolin/image/pixel_format.h>
namespace pangolin {
struct TypedImage : public ManagedImage<unsigned char>
{
typedef ManagedImage<unsigned char> Base;
inline TypedImage()
: Base()
{
}
inline TypedImage(size_t w, size_t h, const PixelFormat& fmt)
: Base(w,h,w*fmt.bpp/8), fmt(fmt)
{
}
inline TypedImage(size_t w, size_t h, const PixelFormat& fmt, size_t pitch )
: Base(w,h, pitch), fmt(fmt)
{
}
inline
void Reinitialise(size_t w, size_t h, const PixelFormat& fmt)
{
Base::Reinitialise(w, h, w*fmt.bpp/8);
this->fmt = fmt;
}
inline
void Reinitialise(size_t w, size_t h, const PixelFormat& fmt, size_t pitch)
{
Base::Reinitialise(w, h, pitch);
this->fmt = fmt;
}
// Not copy constructable
inline
TypedImage( const TypedImage& other ) = delete;
// Move constructor
inline
TypedImage(TypedImage&& img)
{
*this = std::move(img);
}
// Move asignment
inline
void operator=(TypedImage&& img)
{
fmt = img.fmt;
Base::operator =( std::move(img));
}
PixelFormat fmt;
};
}

View File

@@ -0,0 +1,36 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <UIKit/UIKit.h>
#import "PangolinUIView.h"
@interface PangolinAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -0,0 +1,22 @@
//
// GlTestViewController.h
// gltest
//
// Created by Steven Lovegrove on 30/01/2014.
// Copyright (c) 2014 Steven Lovegrove. All rights reserved.
//
#import <UIKit/UIKit.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@interface PangolinUIView : UIView {
CAEAGLLayer* _eaglLayer;
EAGLContext* _context;
GLuint _colorRenderBuffer;
GLuint _depthRenderBuffer;
}
@end

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <mutex>
#include <pangolin/log/packetstream.h>
#include <pangolin/log/packetstream_source.h>
namespace pangolin {
// Encapsulate serialized reading of Packet from stream.
struct Packet
{
Packet(PacketStream& s, std::unique_lock<std::recursive_mutex>&& mutex, std::vector<PacketStreamSource>& srcs);
Packet(const Packet&) = delete;
Packet(Packet&& o);
~Packet();
size_t BytesRead() const;
int BytesRemaining() const;
PacketStream& Stream()
{
return _stream;
}
PacketStreamSourceId src;
int64_t time;
size_t size;
size_t sequence_num;
picojson::value meta;
std::streampos frame_streampos;
private:
void ParsePacketHeader(PacketStream& s, std::vector<PacketStreamSource>& srcs);
void ReadRemaining();
PacketStream& _stream;
std::unique_lock<std::recursive_mutex> lock;
std::streampos data_streampos;
size_t _data_len;
};
}

View File

@@ -0,0 +1,111 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <fstream>
#include <pangolin/platform.h>
#include <pangolin/log/packetstream_tags.h>
#include <pangolin/utils/file_utils.h>
namespace pangolin
{
class PacketStream: public std::ifstream
{
public:
PacketStream()
: _is_pipe(false)
{
cclear();
}
PacketStream(const std::string& filename)
: Base(filename.c_str(), std::ios::in | std::ios::binary),
_is_pipe(IsPipe(filename))
{
cclear();
}
bool seekable() const
{
return is_open() && !_is_pipe;
}
void open(const std::string& filename)
{
close();
_is_pipe = IsPipe(filename);
Base::open(filename.c_str(), std::ios::in | std::ios::binary);
}
void close()
{
cclear();
if (Base::is_open()) Base::close();
}
void seekg(std::streampos target);
void seekg(std::streamoff off, std::ios_base::seekdir way);
std::streampos tellg();
size_t read(char* target, size_t len);
char get();
size_t skip(size_t len);
size_t readUINT();
int64_t readTimestamp();
pangoTagType peekTag();
pangoTagType readTag();
pangoTagType readTag(pangoTagType);
pangoTagType syncToTag();
private:
using Base = std::ifstream;
bool _is_pipe;
pangoTagType _tag;
// Amount of frame data left to read. Tracks our position within a data block.
void cclear() {
_tag = 0;
}
};
}

View File

@@ -0,0 +1,120 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <fstream>
#include <mutex>
#include <thread>
#include <pangolin/log/packet.h>
#include <pangolin/log/sync_time.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/timer.h>
namespace pangolin
{
class PANGOLIN_EXPORT PacketStreamReader
{
public:
PacketStreamReader();
PacketStreamReader(const std::string& filename);
~PacketStreamReader();
void Open(const std::string& filename);
void Close();
const std::vector<PacketStreamSource>&
Sources() const
{
return _sources;
}
// Grab Next available frame packetstream
Packet NextFrame();
// Grab Next available frame in packetstream from src, discarding other frames.
Packet NextFrame(PacketStreamSourceId src);
bool Good() const
{
return _stream.good();
}
// Jumps to a particular packet.
size_t Seek(PacketStreamSourceId src, size_t framenum);
// Jumps to the first packet with time >= time
size_t Seek(PacketStreamSourceId src, SyncTime::TimePoint time);
void FixFileIndex();
private:
bool GoodToRead();
bool SetupIndex();
void ParseHeader();
void ParseNewSource();
bool ParseIndex();
void RebuildIndex();
void AppendIndex();
std::streampos ParseFooter();
void SkipSync();
void ReSync() {
_stream.syncToTag();
}
std::string _filename;
std::vector<PacketStreamSource> _sources;
SyncTime::TimePoint packet_stream_start;
PacketStream _stream;
std::recursive_mutex _mutex;
bool _is_pipe;
int _pipe_fd;
};
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <iostream>
#include <pangolin/platform.h>
#include <pangolin/utils/picojson.h>
namespace pangolin {
using PacketStreamSourceId = size_t;
struct PANGOLIN_EXPORT PacketStreamSource
{
struct PacketInfo
{
std::streampos pos;
int64_t capture_time;
};
PacketStreamSource()
: id(static_cast<PacketStreamSourceId>(-1)),
version(0),
data_alignment_bytes(1),
data_size_bytes(0),
next_packet_id(0)
{
}
std::streampos FindSeekLocation(size_t packet_id)
{
if(packet_id < index.size()) {
return index[packet_id].pos;
}else{
return std::streampos(-1);
}
}
int64_t NextPacketTime() const
{
if(next_packet_id < index.size()) {
return index[next_packet_id].capture_time;
}else{
return 0;
}
}
std::string driver;
size_t id;
std::string uri;
picojson::value info;
int64_t version;
int64_t data_alignment_bytes;
std::string data_definitions;
int64_t data_size_bytes;
// Index keyed by packet_id
std::vector<PacketInfo> index;
// Based on current position in stream
size_t next_packet_id;
};
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <string>
namespace pangolin {
using pangoTagType = uint32_t;
const static std::string PANGO_MAGIC = "PANGO";
const static std::string pss_src_driver = "driver";
const static std::string pss_src_id = "id";
const static std::string pss_src_info = "info";
const static std::string pss_src_uri = "uri";
const static std::string pss_src_packet = "packet";
const static std::string pss_src_version = "version";
const static std::string pss_pkt_alignment_bytes = "alignment_bytes";
const static std::string pss_pkt_definitions = "definitions";
const static std::string pss_pkt_size_bytes = "size_bytes";
const static std::string pss_pkt_format_written = "format_written";
const unsigned int TAG_LENGTH = 3;
#define PANGO_TAG(a,b,c) ( (c<<16) | (b<<8) | a)
const uint32_t TAG_PANGO_HDR = PANGO_TAG('L', 'I', 'N');
const uint32_t TAG_PANGO_MAGIC = PANGO_TAG('P', 'A', 'N');
const uint32_t TAG_PANGO_SYNC = PANGO_TAG('S', 'Y', 'N');
const uint32_t TAG_PANGO_STATS = PANGO_TAG('S', 'T', 'A');
const uint32_t TAG_PANGO_FOOTER = PANGO_TAG('F', 'T', 'R');
const uint32_t TAG_ADD_SOURCE = PANGO_TAG('S', 'R', 'C');
const uint32_t TAG_SRC_JSON = PANGO_TAG('J', 'S', 'N');
const uint32_t TAG_SRC_PACKET = PANGO_TAG('P', 'K', 'T');
const uint32_t TAG_END = PANGO_TAG('E', 'N', 'D');
#undef PANGO_TAG
inline std::string tagName(int v)
{
char b[4];
b[0] = v&0xff;
b[1] = (v>>8)&0xff;
b[2] = (v>>16)&0xff;
b[3] = 0x00;
return std::string(b);
}
}

View File

@@ -0,0 +1,173 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <ostream>
#include <pangolin/log/packetstream.h>
#include <pangolin/log/packetstream_source.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/threadedfilebuf.h>
namespace pangolin
{
class PANGOLIN_EXPORT PacketStreamWriter
{
public:
PacketStreamWriter()
: _stream(&_buffer), _indexable(false), _open(false), _bytes_written(0)
{
_stream.exceptions(std::ostream::badbit);
}
PacketStreamWriter(const std::string& filename, size_t buffer_size = 100*1024*1024)
: _buffer(pangolin::PathExpand(filename), buffer_size), _stream(&_buffer),
_indexable(!IsPipe(filename)), _open(_stream.good()), _bytes_written(0)
{
_stream.exceptions(std::ostream::badbit);
WriteHeader();
}
~PacketStreamWriter() {
Close();
}
void Open(const std::string& filename, size_t buffer_size = 100 * 1024 * 1024)
{
Close();
_buffer.open(filename, buffer_size);
_open = _stream.good();
_bytes_written = 0;
_indexable = !IsPipe(filename);
WriteHeader();
}
void Close()
{
if (_open)
{
if (_indexable) {
WriteEnd();
}
_buffer.close();
_open = false;
}
}
// Does not write footer or index.
void ForceClose()
{
if (_open)
{
_buffer.force_close();
Close();
}
}
// Writes to the stream immediately upon add. Return source id # and writes
// source id # to argument struct
PacketStreamSourceId AddSource(PacketStreamSource& source);
// If constructor is called inline
PacketStreamSourceId AddSource(const PacketStreamSource& source);
void WriteSourcePacket(
PacketStreamSourceId src, const char* source,const int64_t receive_time_us,
size_t sourcelen, const picojson::value& meta = picojson::value()
);
// For stream read/write synchronization. Note that this is NOT the same as
// time synchronization on playback of iPacketStreams.
void WriteSync();
// Writes the end of the stream data, including the index. Does NOT close
// the underlying ostream.
void WriteEnd();
const std::vector<PacketStreamSource>& Sources() const {
return _sources;
}
bool IsOpen() const {
return _open;
}
private:
void WriteHeader();
void Write(const PacketStreamSource&);
void WriteMeta(PacketStreamSourceId src, const picojson::value& data);
threadedfilebuf _buffer;
std::ostream _stream;
bool _indexable, _open;
std::vector<PacketStreamSource> _sources;
size_t _bytes_written;
std::recursive_mutex _lock;
};
inline void writeCompressedUnsignedInt(std::ostream& writer, size_t n)
{
while (n >= 0x80)
{
writer.put(0x80 | (n & 0x7F));
n >>= 7;
}
writer.put(static_cast<unsigned char>(n));
}
inline void writeTimestamp(std::ostream& writer, int64_t time_us)
{
writer.write(reinterpret_cast<const char*>(&time_us), sizeof(decltype(time_us)));
}
inline void writeTag(std::ostream& writer, const pangoTagType tag)
{
writer.write(reinterpret_cast<const char*>(&tag), TAG_LENGTH);
}
inline picojson::value SourceStats(const std::vector<PacketStreamSource>& srcs)
{
picojson::value stat;
stat["num_sources"] = srcs.size();
stat["src_packet_index"] = picojson::array();
stat["src_packet_times"] = picojson::array();
for(auto& src : srcs) {
picojson::array pkt_index, pkt_times;
for (const PacketStreamSource::PacketInfo& frame : src.index) {
pkt_index.emplace_back(frame.pos);
pkt_times.emplace_back(frame.capture_time);
}
stat["src_packet_index"].push_back(std::move(pkt_index));
stat["src_packet_times"].push_back(std::move(pkt_times));
}
return stat;
}
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <memory>
#include <vector>
#include <pangolin/log/packetstream_reader.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/registration.h>
namespace pangolin {
class Params;
class PlaybackSession
{
public:
// Singleton Instance
static std::shared_ptr<PlaybackSession> Default();
// Return thread-safe, shared instance of PacketStreamReader, providing
// serialised read for PacketStreamReader
std::shared_ptr<PacketStreamReader> Open(const std::string& filename)
{
const std::string path = SanitizePath(PathExpand(filename));
auto i = readers.find(path);
if(i == readers.end()) {
auto psr = std::make_shared<PacketStreamReader>(path);
readers[path] = psr;
return psr;
}else{
return i->second;
}
}
SyncTime& Time()
{
return time;
}
static std::shared_ptr<PlaybackSession> ChooseFromParams(const Params& params);
private:
std::map<std::string,std::shared_ptr<PacketStreamReader>> readers;
SyncTime time;
};
}

View File

@@ -0,0 +1,230 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/signal_slot.h>
#include <pangolin/utils/timer.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
namespace pangolin
{
// Lightweight timestamp class to allow synchronized playback from the same (or a different) stream.
// All playback functions called with the same SyncTime will be time-synchronized, and will remain synchronized on seek() if the SyncTime is passed in when seeking.
// Playback with multiple SyncTimes (on the same or different streams) should also be synced, even in different processes or systems (underlying clock sync is not required).
// However, playback with multiple SyncTimes will break on seek().
class PANGOLIN_EXPORT SyncTime
{
public:
using Clock = baseclock;
using Duration = Clock::duration;
using TimePoint = Clock::time_point;
struct SeekInterruption: std::runtime_error
{
SeekInterruption() : std::runtime_error("Time queue invalidated by seek"){}
};
SyncTime(Duration virtual_clock_offset = std::chrono::milliseconds(0))
: seeking(false)
{
SetOffset(virtual_clock_offset);
}
// No copy constructor
SyncTime(const SyncTime&) = delete;
void SetOffset(Duration virtual_clock_offset)
{
virtual_offset = virtual_clock_offset;
}
void SetClock(TimePoint virtual_now)
{
virtual_offset = virtual_now - Clock::now();
}
TimePoint TimeNow() const
{
return Clock::now() + virtual_offset;
}
TimePoint ToVirtual(TimePoint real) const
{
return real + virtual_offset;
}
TimePoint ToReal(TimePoint virt) const
{
return virt - virtual_offset;
}
void WaitUntil(TimePoint virtual_time) const
{
std::this_thread::sleep_until( ToReal(virtual_time) );
}
int64_t QueueEvent(int64_t new_event_time_us)
{
return WaitDequeueAndQueueEvent(0, new_event_time_us);
}
void DequeueEvent(int64_t event_time_us)
{
std::unique_lock<std::mutex> l(time_mutex);
auto i = std::find(time_queue_us.begin(), time_queue_us.end(), event_time_us);
PANGO_ENSURE(i != time_queue_us.end());
time_queue_us.erase(i);
queue_changed.notify_all();
}
int64_t WaitDequeueAndQueueEvent(int64_t event_time_us, int64_t new_event_time_us =0 )
{
std::unique_lock<std::mutex> l(time_mutex);
if(event_time_us) {
PANGO_ENSURE(time_queue_us.size());
// Wait until we're top the priority-queue
queue_changed.wait(l, [&](){
if(seeking) {
// Time queue will be invalidated on seek.
// Unblock without action
throw SeekInterruption();
}
return time_queue_us.back() == event_time_us;
});
// Dequeue
time_queue_us.pop_back();
}
if(new_event_time_us) {
// Add the new event whilst we still hold the lock, so that our
// event can't be missed
insert_sorted(time_queue_us, new_event_time_us, std::greater<int64_t>());
if(time_queue_us.back() == new_event_time_us) {
// Return to avoid yielding when we're next.
return new_event_time_us;
}
}
// Only yield if another device is next
queue_changed.notify_all();
return new_event_time_us;
}
void NotifyAll()
{
queue_changed.notify_all();
}
std::mutex& TimeMutex()
{
return time_mutex;
}
void Stop()
{
seeking = true;
OnTimeStop();
queue_changed.notify_all();
}
void Start()
{
OnTimeStart();
seeking=false;
}
void Seek(TimePoint t)
{
Stop();
OnSeek(t);
Start();
}
Signal<> OnTimeStart;
Signal<> OnTimeStop;
Signal<TimePoint> OnSeek;
private:
template< typename T, typename Pred >
static typename std::vector<T>::iterator
insert_sorted( std::vector<T> & vec, T const& item, Pred pred )
{
return vec.insert (
std::upper_bound( vec.begin(), vec.end(), item, pred ), item
);
}
std::vector<int64_t> time_queue_us;
Duration virtual_offset;
std::mutex time_mutex;
std::condition_variable queue_changed;
bool seeking;
};
struct SyncTimeEventPromise
{
SyncTimeEventPromise(SyncTime& sync, int64_t time_us = 0)
: sync(sync), time_us(time_us)
{
sync.QueueEvent(time_us);
}
~SyncTimeEventPromise()
{
Cancel();
}
void Cancel()
{
if(time_us) {
sync.DequeueEvent(time_us);
time_us = 0;
}
}
void WaitAndRenew(int64_t new_time_us)
{
time_us = sync.WaitDequeueAndQueueEvent(time_us, new_time_us);
}
private:
SyncTime& sync;
int64_t time_us;
};
}

View File

@@ -0,0 +1,64 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#ifdef BUILD_PANGOLIN_GUI
#include <pangolin/gl/gl.h>
#include <pangolin/gl/gldraw.h>
#include <pangolin/gl/glvbo.h>
#include <pangolin/gl/glstate.h>
#include <pangolin/gl/colour.h>
#include <pangolin/display/display.h>
#include <pangolin/display/view.h>
#ifdef _ANDROID_
#include <pangolin/display/device/display_android.h>
#endif
#if !defined(HAVE_GLES) || defined(HAVE_GLES_2)
#include <pangolin/plot/plotter.h>
#endif
#endif // BUILD_PANGOLIN_GUI
#ifdef BUILD_PANGOLIN_VARS
#include <pangolin/var/varextra.h>
#ifdef BUILD_PANGOLIN_GUI
#include <pangolin/display/widgets/widgets.h>
#endif // BUILD_PANGOLIN_GUI
#endif // BUILD_PANGOLIN_VARS
#ifdef BUILD_PANGOLIN_VIDEO
#include <pangolin/video/video.h>
#include <pangolin/video/video_input.h>
#include <pangolin/video/video_output.h>
#endif // BUILD_PANGOLIN_VIDEO
#include <pangolin/image/image_io.h>
// Let other libraries headers know about Pangolin
#define HAVE_PANGOLIN

View File

@@ -0,0 +1,81 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/config.h>
// Include portable printf-style format macros
#define __STDC_FORMAT_MACROS
#ifdef _GCC_
# define PANGOLIN_DEPRECATED __attribute__((deprecated))
#elif defined _MSVC_
# define PANGOLIN_DEPRECATED __declspec(deprecated)
#else
# define PANGOLIN_DEPRECATED
#endif
#ifdef _MSVC_
# define __thread __declspec(thread)
# include <pangolin/pangolin_export.h>
#else
# define PANGOLIN_EXPORT
#endif //_MSVC_
#define PANGOLIN_UNUSED(x) (void)(x)
#ifdef _APPLE_IOS_
// Not supported on this platform.
#define __thread
#endif // _APPLE_IOS_
// HOST / DEVICE Annotations
#ifdef __CUDACC__
# include <cuda_runtime.h>
# define PANGO_HOST_DEVICE __host__ __device__
#else
# define PANGO_HOST_DEVICE
#endif
// Non-standard check that header exists (Clang, GCC 5.X)
// Useful for
#if defined(__has_include)
# define PANGO_HEADER_EXISTS(x) __has_include(x)
#else
# define PANGO_HEADER_EXISTS(x) 0
#endif
// Workaround for Apple-Clangs lack of thread_local support
#if defined(_CLANG_) && defined(_OSX_)
# if !__has_feature(cxx_thread_local)
# define PANGO_NO_THREADLOCAL
# endif
#endif
#include <pangolin/utils/assert.h>
#include <pangolin/utils/log.h>

View File

@@ -0,0 +1,243 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <algorithm> // std::min, std::max
#include <limits>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <vector>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
namespace pangolin
{
/// Simple statistics recorded for a logged input dimension.
struct DimensionStats
{
DimensionStats()
{
Reset();
}
void Reset()
{
isMonotonic = true;
sum = 0.0f;
sum_sq = 0.0f;
min = std::numeric_limits<float>::max();
max = std::numeric_limits<float>::lowest();
}
void Add(const float v)
{
isMonotonic = isMonotonic && (v >= max);
sum += v;
sum_sq += v*v;
min = std::min(min, v);
max = std::max(max, v);
}
bool isMonotonic;
float sum;
float sum_sq;
float min;
float max;
};
class DataLogBlock
{
public:
/// @param dim: dimension of sample
/// @param max_samples: maximum number of samples this block can hold
/// @param start_id: index of first sample (from entire dataset) in this buffer
DataLogBlock(size_t dim, size_t max_samples, size_t start_id)
: dim(dim), max_samples(max_samples), samples(0),
start_id(start_id)
{
sample_buffer = std::unique_ptr<float[]>(new float[dim*max_samples]);
// stats = std::unique_ptr<DimensionStats[]>(new DimensionStats[dim]);
}
~DataLogBlock()
{
}
size_t Samples() const
{
return samples;
}
size_t MaxSamples() const
{
return max_samples;
}
/// Return how many more samples can fit in this block
size_t SampleSpaceLeft() const
{
return MaxSamples()- Samples();
}
bool IsFull() const
{
return Samples() >= MaxSamples();
}
/// Add data to block
void AddSamples(size_t num_samples, size_t dimensions, const float* data_dim_major );
/// Delete all samples
void ClearLinked()
{
samples = 0;
nextBlock.reset();
}
DataLogBlock* NextBlock() const
{
return nextBlock.get();
}
size_t StartId() const
{
return start_id;
}
float* DimData(size_t d) const
{
return sample_buffer.get() + d;
}
size_t Dimensions() const
{
return dim;
}
const float* Sample(size_t n) const
{
const int id = (int)n - (int)start_id;
if( 0 <= id && id < (int)samples ) {
return sample_buffer.get() + dim*id;
}else{
if(nextBlock) {
return nextBlock->Sample(n);
}else{
throw std::out_of_range("Index out of range.");
}
}
}
protected:
size_t dim;
size_t max_samples;
size_t samples;
size_t start_id;
std::unique_ptr<float[]> sample_buffer;
// std::unique_ptr<DimensionStats[]> stats;
std::unique_ptr<DataLogBlock> nextBlock;
};
/// A DataLog can efficiently record floating point sample data of any size.
/// Memory is allocated in blocks is transparent to the user.
class PANGOLIN_EXPORT DataLog
{
public:
/// @param block_samples_alloc number of samples each memory block can hold.
DataLog(unsigned int block_samples_alloc = 10000 );
~DataLog();
/// Provide textual labels corresponding to each dimension logged.
/// This information may be used by graphical interfaces to DataLog.
void SetLabels(const std::vector<std::string> & labels);
const std::vector<std::string>& Labels() const;
void Log(size_t dimension, const float * vals, unsigned int samples = 1);
void Log(float v);
void Log(float v1, float v2);
void Log(float v1, float v2, float v3);
void Log(float v1, float v2, float v3, float v4);
void Log(float v1, float v2, float v3, float v4, float v5);
void Log(float v1, float v2, float v3, float v4, float v5, float v6);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9, float v10);
void Log(const std::vector<float> & vals);
#ifdef USE_EIGEN
template<typename Derived>
void Log(const Eigen::MatrixBase<Derived>& M)
{
Log( M.rows() * M.cols(), M.template cast<float>().eval().data() );
}
#endif
void Clear();
void Save(std::string filename);
// Return first block of stored data
const DataLogBlock* FirstBlock() const;
// Return last block of stored data
const DataLogBlock* LastBlock() const;
// Return number of samples stored in this DataLog
size_t Samples() const;
// Return pointer to stored sample n
const float* Sample(int n) const;
// Return stats computed for each dimension if enabled.
const DimensionStats& Stats(size_t dim) const;
std::mutex access_mutex;
protected:
unsigned int block_samples_alloc;
std::vector<std::string> labels;
std::unique_ptr<DataLogBlock> block0;
DataLogBlock* blockn;
std::vector<DimensionStats> stats;
bool record_stats;
};
}

View File

@@ -0,0 +1,282 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLOTTER_H
#define PLOTTER_H
#include <limits>
#include <pangolin/display/view.h>
#include <pangolin/gl/colour.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glfont.h>
#include <pangolin/gl/glsl.h>
#include <pangolin/handler/handler.h>
#include <pangolin/plot/datalog.h>
#include <pangolin/plot/range.h>
#include <set>
namespace pangolin
{
enum DrawingMode
{
DrawingModePoints = GL_POINTS,
DrawingModeDashed = GL_LINES,
DrawingModeLine = GL_LINE_STRIP,
DrawingModeNone,
};
struct Marker
{
enum Direction
{
Horizontal,
Vertical
};
enum Equality
{
LessThan = -1,
Equal = 0,
GreaterThan = 1
};
Marker(Direction d, float value, Equality leg = Equal, Colour c = Colour() )
: colour(c)
{
if(d == Horizontal) {
range.x = Rangef::Open();
range.y = Rangef::Containing(value);
if(leg == LessThan) {
range.y.Insert(std::numeric_limits<float>::lowest() );
}else if(leg == GreaterThan) {
range.y.Insert(std::numeric_limits<float>::max() );
}
}else if(d == Vertical) {
range.x = Rangef::Containing(value);
range.y = Rangef::Open();
if(leg == LessThan) {
range.x.Insert(std::numeric_limits<float>::lowest() );
}else if(leg == GreaterThan) {
range.x.Insert(std::numeric_limits<float>::max() );
}
}
}
Marker(const XYRangef& range, const Colour& c = Colour() )
: range(range), colour(c)
{
}
XYRangef range;
Colour colour;
};
class PANGOLIN_EXPORT Plotter : public View, Handler
{
public:
Plotter(
DataLog* default_log,
float left=0, float right=600, float bottom=-1, float top=1,
float tickx=30, float ticky=0.5,
Plotter* linked_plotter_x = 0,
Plotter* linked_plotter_y = 0
);
virtual ~Plotter();
void Render();
XYRangef& GetSelection();
XYRangef& GetDefaultView();
void SetDefaultView(const XYRangef& range);
XYRangef& GetView();
void SetView(const XYRangef& range);
void SetViewSmooth(const XYRangef& range);
void ScrollView(float x, float y);
void ScrollViewSmooth(float x, float y);
void ScaleView(float x, float y, float cx, float cy);
void ScaleViewSmooth(float x, float y, float cx, float cy);
void ResetView();
void SetTicks(float tickx, float ticky);
void Track(const std::string& x="$i", const std::string& y = "");
void ToggleTracking();
void Trigger(const std::string& x="$0", int edge = -1, float value = 0.0f);
void ToggleTrigger();
void SetBackgroundColour(const Colour& col);
void SetAxisColour(const Colour& col);
void SetTickColour(const Colour& col);
void ScreenToPlot(int xpix, int ypix, float &xplot, float &yplot);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void PassiveMouseMotion(View&, int x, int y, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
/// Remove all current series plots
void ClearSeries();
/// Add series X,Y plot from glsl compatible expressions x_expr, y_expr
/// $i refers to integral index of datum in log.
/// $0, $1, $2, ... refers to nth series in log.
/// e.g. x_expr = "$i", y_expr = "$0" // index - data[0] plot
/// e.g. x_expr = "$0", y_expr = "$1" // data[0], data[1] X-Y plot
/// e.g. x_exptr ="$i", y_expr = "sqrt($1)} // index - sqrt(data[0]) plot
void AddSeries(const std::string& x_expr, const std::string& y_expr,
DrawingMode drawing_mode = DrawingModeLine, Colour colour = Colour::Unspecified(),
const std::string &title = "$y", DataLog* log = nullptr
);
std::string PlotTitleFromExpr(const std::string& expr) const;
/// Remove all current markers
void ClearMarkers();
/// Add horizontal or vertical inequality marker; equal-to, less-than, or greater than.
/// This is useful for annotating a critical point or valid region.
Marker& AddMarker(
Marker::Direction d, float value,
Marker::Equality leg = Marker::Equal, Colour c = Colour()
);
Marker& AddMarker( const Marker& marker );
void ClearImplicitPlots();
void AddImplicitPlot();
/// Reset colour wheel to initial state. May be useful together with ClearSeries() / ClearMarkers()
void ResetColourWheel();
protected:
struct PANGOLIN_EXPORT Tick
{
float val;
float factor;
std::string symbol;
};
struct PANGOLIN_EXPORT PlotAttrib
{
PlotAttrib(std::string name, int plot_id, int location = -1)
: name(name), plot_id(plot_id), location(location) { }
std::string name;
int plot_id;
int location;
};
struct PANGOLIN_EXPORT PlotSeries
{
PlotSeries();
void CreatePlot(const std::string& x, const std::string& y, Colour c, std::string title);
GlSlProgram prog;
GlText title;
bool contains_id;
std::vector<PlotAttrib> attribs;
DataLog* log;
GLenum drawing_mode;
Colour colour;
bool used;
};
struct PANGOLIN_EXPORT PlotImplicit
{
// Assign to gl_FragColor
void CreatePlot(const std::string& code);
// Expression uses x,y and assignes colours [0,1] to r,g,b,a
void CreateColouredPlot(const std::string& code);
// Expression uses x,y and evaluates to true/false;
void CreateInequality(const std::string& ie, Colour c);
// Expression uses x,y and evaluates to a number
void CreateDistancePlot(const std::string& dist);
GlSlProgram prog;
};
void FixSelection();
void UpdateView();
Tick FindTickFactor(float tick);
DataLog* default_log;
ColourWheel colour_wheel;
Colour colour_bg;
Colour colour_tk;
Colour colour_ax;
GlSlProgram prog_lines;
GlSlProgram prog_text;
std::vector<PlotSeries> plotseries;
std::vector<Marker> plotmarkers;
std::vector<PlotImplicit> plotimplicits;
Tick tick[2];
XYRangef rview_default;
XYRangef rview;
XYRangef target;
XYRangef selection;
void ComputeTrackValue( float track_val[2] );
XYRangef ComputeAutoSelection();
bool track;
std::string track_x;
std::string track_y;
float last_track_val[2];
// -1: falling, -0:disable, 1: rising
int trigger_edge;
float trigger_value;
std::string trigger;
float hover[2];
int last_mouse_pos[2];
Plotter* linked_plotter_x;
Plotter* linked_plotter_y;
};
} // namespace pangolin
#endif // PLOTTER_H

View File

@@ -0,0 +1,372 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <limits>
#include <algorithm>
#include <cmath>
//prevent including Eigen in cuda files
#if defined(HAVE_EIGEN) && !defined(__CUDACC__)
# define USE_EIGEN
#endif
#ifdef USE_EIGEN
# include <Eigen/Core>
# include <Eigen/src/Geometry/AlignedBox.h>
#endif // USE_EIGEN
namespace pangolin
{
template<typename T>
struct Range
{
static Range<T> Open()
{
return Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
}
static Range<T> Empty()
{
return Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest());
}
static Range<T> Containing(T val)
{
return Range<T>(val, val);
}
Range()
: min(+std::numeric_limits<T>::max()),
max(-std::numeric_limits<T>::max())
{
}
Range(T rmin, T rmax)
: min(rmin), max(rmax)
{
}
Range operator+(T v)
{
return Range(min+v, max+v);
}
Range operator-(T v)
{
return Range(min-v, max-v);
}
Range& operator+=(T v)
{
min += v;
max += v;
return *this;
}
Range& operator-=(T v)
{
min -= v;
max -= v;
return *this;
}
Range& operator*=(T v)
{
min *= v;
max *= v;
return *this;
}
Range& operator/=(T v)
{
min /= v;
max /= v;
return *this;
}
Range& operator+=(const Range& o)
{
min += o.min;
max += o.max;
return *this;
}
Range& operator-=(const Range& o)
{
min -= o.min;
max -= o.max;
return *this;
}
Range operator+(const Range& o) const
{
return Range(min + o.min, max + o.max);
}
Range operator-(const Range& o) const
{
return Range(min - o.min, max - o.max);
}
Range operator*(float s) const
{
return Range(T(s*min), T(s*max));
}
T Size() const
{
return max - min;
}
T AbsSize() const
{
return std::abs(Size());
}
T Mid() const
{
return (min + max) / (T)2.0f;
}
void Scale(float s, float center = 0.0f)
{
min = T(s*(min-center) + center);
max = T(s*(max-center) + center);
}
void Insert(T v)
{
min = std::min(min,v);
max = std::max(max,v);
}
void Insert(const Range<T>& r)
{
Insert(r.min);
Insert(r.max);
}
void Clamp(T vmin, T vmax)
{
min = std::min(std::max(vmin, min), vmax);
max = std::min(std::max(vmin, max), vmax);
}
void Clamp(const Range& o)
{
Clamp(o.min, o.max);
}
void Clear()
{
min = std::numeric_limits<T>::max();
max = std::numeric_limits<T>::lowest();
}
bool Contains(T v) const
{
return min <= v && v <= max;
}
bool ContainsWeak(T v) const
{
return (min <= v && v <= max)
|| (max <= v && v <= min);
}
template<typename To>
Range<To> Cast() const
{
return Range<To>(To(min), To(max));
}
T min;
T max;
};
template<typename T>
struct XYRange
{
static XYRange<T> Open()
{
return XYRange<T>(
Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()),
Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max())
);
}
static XYRange<T> Empty()
{
return XYRange<T>(
Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()),
Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest())
);
}
static XYRange<T> Containing(T x, T y)
{
return XYRange<T>(
Range<T>(x, x),
Range<T>(y, y)
);
}
XYRange()
{
}
XYRange(const Range<T>& xrange, const Range<T>& yrange)
: x(xrange), y(yrange)
{
}
XYRange(T xmin, T xmax, T ymin, T ymax)
: x(xmin,xmax), y(ymin,ymax)
{
}
XYRange operator-(const XYRange& o) const
{
return XYRange(x - o.x, y - o.y);
}
XYRange operator*(float s) const
{
return XYRange(x*s, y*s);
}
XYRange& operator+=(const XYRange& o)
{
x += o.x;
y += o.y;
return *this;
}
void Scale(float sx, float sy, float centerx, float centery)
{
x.Scale(sx, centerx);
y.Scale(sy, centery);
}
void Clear()
{
x.Clear();
y.Clear();
}
void Clamp(T xmin, T xmax, T ymin, T ymax)
{
x.Clamp(xmin,xmax);
y.Clamp(ymin,ymax);
}
void Clamp(const XYRange& o)
{
x.Clamp(o.x);
y.Clamp(o.y);
}
void Insert(T xval, T yval)
{
x.Insert(xval);
y.Insert(yval);
}
void Insert(XYRange<T> r)
{
x.Insert(r.x);
y.Insert(r.y);
}
float Area() const
{
return x.Size() * y.Size();
}
bool Contains(float px, float py) const
{
return x.Contains(px) && y.Contains(py);
}
bool ContainsWeak(float px, float py) const
{
return x.ContainsWeak(px) && y.ContainsWeak(py);
}
template<typename To>
XYRange<To> Cast() const
{
return XYRange<To>(
x.template Cast<To>(),
y.template Cast<To>()
);
}
#ifdef USE_EIGEN
operator Eigen::AlignedBox<T,2>() const {
return Eigen::AlignedBox<T,2>(
Eigen::Matrix<T,2,1>(x.min, y.min),
Eigen::Matrix<T,2,1>(x.max, y.max)
);
}
Eigen::Matrix<T,2,1> Center() const {
return Eigen::Matrix<T,2,1>(x.Mid(), y.Mid());
}
#endif
Range<T> x;
Range<T> y;
};
typedef Range<int> Rangei;
typedef Range<float> Rangef;
typedef Range<double> Ranged;
typedef XYRange<int> XYRangei;
typedef XYRange<float> XYRangef;
typedef XYRange<double> XYRanged;
template<typename T> inline
Rangei Round(const Range<T>& r)
{
return Rangei( int(r.min+0.5), int(r.max+0.5) );
}
template<typename T> inline
XYRangei Round(const XYRange<T>& r)
{
return XYRangei( Round(r.x), Round(r.y) );
}
}

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/var/varextra.h>
#include <pangolin/python/pyuniqueobj.h>
#include <pangolin/console/ConsoleInterpreter.h>
#include <queue>
#include <set>
#include <thread>
namespace pangolin
{
class PyInterpreter : public ConsoleInterpreter
{
public:
PyInterpreter();
~PyInterpreter() override;
void PushCommand(const std::string &cmd) override;
bool PullLine(ConsoleLine& line) override;
std::vector<std::string> Complete(
const std::string& cmd, int max_options
) override;
static void AttachPrefix(void* data, const std::string& name, VarValueGeneric& var, bool brand_new );
private:
PyObject* pycompleter;
PyObject* pycomplete;
std::string ToString(PyObject* py);
void CheckPrintClearError();
PyUniqueObj EvalExec(const std::string& cmd);
std::queue<ConsoleLine> line_queue;
std::set<std::string> base_prefixes;
};
}

View File

@@ -0,0 +1,178 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <iomanip>
#include <queue>
#include <structmember.h>
#include <pangolin/var/var.h>
#include <pangolin/console/ConsoleInterpreter.h>
namespace pangolin
{
struct PyPangoIO {
PyObject_HEAD
static PyTypeObject Py_type;
static PyMethodDef Py_methods[];
PyPangoIO(PyTypeObject *type, std::queue<ConsoleLine>& line_queue, ConsoleLineType line_type)
: line_queue(line_queue), line_type(line_type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyPangoIO* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject */*type*/, PyObject */*args*/, PyObject */*kwds*/)
{
// Failure. Can only new in c++
return 0;
}
static int Py_init(PyPangoIO* /*self*/, PyObject* /*args*/, PyObject* /*kwds*/)
{
return 0;
}
static PyObject* Py_getattr(PyPangoIO *self, char* name)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericGetAttr((PyObject*)self, pystr );
}
static int Py_setattr(PyPangoIO *self, char* name, PyObject* val)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericSetAttr((PyObject*)self, pystr, val);
}
static PyObject* Py_write(PyPangoIO* self, PyObject *args)
{
const char *text = 0;
if (PyArg_ParseTuple(args, "s", &text)) {
self->buffer += std::string(text);
size_t nl = self->buffer.find_first_of('\n');
while(nl != std::string::npos) {
const std::string line = self->buffer.substr(0,nl);
self->line_queue.push(ConsoleLine(line,self->line_type));
self->buffer = self->buffer.substr(nl+1);
nl = self->buffer.find_first_of('\n');
}
}
Py_RETURN_NONE;
}
std::string buffer;
std::queue<ConsoleLine>& line_queue;
ConsoleLineType line_type;
};
PyMethodDef PyPangoIO::Py_methods[] = {
{"write", (PyCFunction)PyPangoIO::Py_write, METH_VARARGS, "Write to console" },
{NULL, NULL, 0, NULL}
};
#pragma GCC diagnostic push // Ignore python missing initializer warning.
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyPangoIO::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pangolin.PangoIO", /* tp_name*/
sizeof(PyPangoIO), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyPangoIO::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyPangoIO::Py_getattr, /* tp_getattr*/
(setattrfunc)PyPangoIO::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyPangoIO object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PyPangoIO::Py_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyPangoIO::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyPangoIO::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop // Return to normal
}

View File

@@ -0,0 +1,40 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
PANGOLIN_EXPORT
PyMODINIT_FUNC InitPyPangolinModule();
}

View File

@@ -0,0 +1,111 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
/// Class represents a reference counted PythonObject.
/// PythonObject is appropriately Py_INCREF'd and Py_DECREF'd
class PyUniqueObj
{
public:
inline
PyUniqueObj()
: obj(0)
{
}
/// Assumption: PythonObject has already been appropriately INCREF'd.
inline
PyUniqueObj(PyObject* obj)
: obj(obj)
{
}
inline
PyUniqueObj(const PyUniqueObj& other)
:obj(other.obj)
{
if(obj) Py_INCREF(obj);
}
inline
~PyUniqueObj()
{
if(obj) Py_DECREF(obj);
}
inline
PyUniqueObj(PyUniqueObj&& other)
: obj(other.obj)
{
other.obj = 0;
}
inline
void operator=(PyUniqueObj&& other)
{
Release();
obj = other.obj;
other.obj = 0;
}
inline
void operator=(PyObject* obj)
{
Release();
this->obj = obj;
}
inline
void Release() {
if(obj) {
Py_DECREF(obj);
obj = 0;
}
}
inline
PyObject* operator*() {
return obj;
}
inline
operator PyObject*() {
return obj;
}
private:
PyObject* obj;
};
}

View File

@@ -0,0 +1,271 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <structmember.h>
#include <iomanip>
#include <pangolin/var/var.h>
#include <pangolin/python/pyuniqueobj.h>
namespace pangolin
{
PyObject* GetPangoVarAsPython(const std::string& name)
{
VarState::VarStoreContainer::iterator i = VarState::I().vars.find(name);
if(i != VarState::I().vars.end()) {
VarValueGeneric* var = i->second;
try{
if( !strcmp(var->TypeId(), typeid(bool).name() ) ) {
const bool val = Var<bool>(*var).Get();
return PyBool_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(short).name() ) ||
!strcmp(var->TypeId(), typeid(int).name() ) ||
!strcmp(var->TypeId(), typeid(long).name() ) ) {
const long val = Var<long>(*var).Get();
return PyLong_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(double).name() ) ||
!strcmp(var->TypeId(), typeid(float).name() ) ) {
const double val = Var<double>(*var).Get();
return PyFloat_FromDouble(val);
}else{
const std::string val = var->str->Get();
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(val.c_str());
#else
return PyString_FromString(val.c_str());
#endif
}
}catch(const std::exception&) {
}
}
Py_RETURN_NONE;
}
void SetPangoVarFromPython(const std::string& name, PyObject* val)
{
try{
if (PyFloat_Check(val)) {
pangolin::Var<double> pango_var(name);
pango_var = PyFloat_AsDouble(val);
pango_var.Meta().gui_changed = true;
}else if (PyLong_Check(val)) {
pangolin::Var<long> pango_var(name);
pango_var = PyLong_AsLong(val);
pango_var.Meta().gui_changed = true;
}else if (PyBool_Check(val)) {
pangolin::Var<bool> pango_var(name);
pango_var = (val == Py_True) ? true : false;
pango_var.Meta().gui_changed = true;
}
#if PY_MAJOR_VERSION >= 3
else if (PyUnicode_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyUnicode_AsUTF8(val);
pango_var.Meta().gui_changed = true;
}
#else
else if (PyString_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyString_AsString(val);
pango_var.Meta().gui_changed = true;
} else if (PyInt_Check(val)) {
pangolin::Var<int> pango_var(name);
pango_var = PyInt_AsLong(val);
pango_var.Meta().gui_changed = true;
}
#endif
else {
PyUniqueObj pystr = PyObject_Repr(val);
#if PY_MAJOR_VERSION >= 3
const std::string str = PyUnicode_AsUTF8(pystr);
#else
const std::string str = PyString_AsString(pystr);
#endif
pangolin::Var<std::string> pango_var(name);
pango_var = str;
pango_var.Meta().gui_changed = true;
}
FlagVarChanged();
}catch(const std::exception& e) {
pango_print_error("%s\n", e.what());
}
}
struct PyVar {
static PyTypeObject Py_type;
PyObject_HEAD
PyVar(PyTypeObject *type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyVar* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
{
PyVar* self = new PyVar(type);
return (PyObject *)self;
}
static int Py_init(PyVar *self, PyObject *args, PyObject * /*kwds*/)
{
char* cNamespace = 0;
if (!PyArg_ParseTuple(args, "s", &cNamespace))
return -1;
self->ns = std::string(cNamespace);
return 0;
}
static PyObject* Py_getattr(PyVar *self, char* name)
{
const std::string prefix = self->ns + ".";
const std::string full_name = self->ns.empty() ? name : prefix + std::string(name);
if( !strcmp(name, "__call__") ||
!strcmp(name, "__dict__") ||
!strcmp(name, "__methods__") ||
!strcmp(name, "__class__") )
{
// Default behaviour
#if PY_MAJOR_VERSION >= 3
return PyObject_GenericGetAttr((PyObject*)self, PyUnicode_FromString(name));
#else
return PyObject_GenericGetAttr((PyObject*)self, PyString_FromString(name));
#endif
} else if( !strcmp(name, "__members__") ) {
const int nss = prefix.size();
PyObject* l = PyList_New(0);
for(const std::string& s : VarState::I().var_adds) {
if(!s.compare(0, nss, prefix)) {
size_t dot = s.find_first_of('.', nss);
std::string val = (dot != std::string::npos) ? s.substr(nss, dot - nss) : s.substr(nss);
#if PY_MAJOR_VERSION >= 3
PyList_Append(l, PyUnicode_FromString(val.c_str()));
#else
PyList_Append(l, PyString_FromString(val.c_str()));
#endif
}
}
return l;
}else if( pangolin::VarState::I().Exists(full_name) ) {
return GetPangoVarAsPython(full_name);
}else{
PyVar* obj = (PyVar*)PyVar::Py_new(&PyVar::Py_type,NULL,NULL);
if(obj) {
obj->ns = full_name;
return PyObject_Init((PyObject *)obj,&PyVar::Py_type);
}
return (PyObject *)obj;
}
Py_RETURN_NONE;
}
static int Py_setattr(PyVar *self, char* name, PyObject* val)
{
const std::string full_name = self->ns.empty() ? name : self->ns + "." + std::string(name);
SetPangoVarFromPython(full_name, val);
return 0;
}
std::string ns;
};
// The uninitialized variable can be ignored.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyVar::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pypangolin.Var", /* tp_name*/
sizeof(PyVar), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyVar::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyVar::Py_getattr, /* tp_getattr*/
(setattrfunc)PyVar::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyVar object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyVar::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyVar::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop
}

View File

@@ -0,0 +1,117 @@
#pragma once
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/display/viewport.h>
#include <pangolin/gl/gldraw.h>
#include <pangolin/scene/renderable.h>
#include <pangolin/scene/interactive_index.h>
#ifdef HAVE_EIGEN
# include <Eigen/Geometry>
#endif
namespace pangolin {
struct Axis : public Renderable, public Interactive
{
Axis()
: axis_length(1.0),
label_x(InteractiveIndex::I().Store(this)),
label_y(InteractiveIndex::I().Store(this)),
label_z(InteractiveIndex::I().Store(this))
{
}
void Render(const RenderParams&) override {
glColor4f(1,0,0,1);
glPushName(label_x.Id());
glDrawLine(0,0,0, axis_length,0,0);
glPopName();
glColor4f(0,1,0,1);
glPushName(label_y.Id());
glDrawLine(0,0,0, 0,axis_length,0);
glPopName();
glColor4f(0,0,1,1);
glPushName(label_z.Id());
glDrawLine(0,0,0, 0,0,axis_length);
glPopName();
}
bool Mouse(
int button,
const GLprecision /*win*/[3], const GLprecision /*obj*/[3], const GLprecision /*normal*/[3],
bool /*pressed*/, int button_state, int pickId
) override
{
PANGOLIN_UNUSED(button);
PANGOLIN_UNUSED(button_state);
PANGOLIN_UNUSED(pickId);
#ifdef HAVE_EIGEN
if((button == MouseWheelUp || button == MouseWheelDown) ) {
float scale = (button == MouseWheelUp) ? 0.01f : -0.01f;
if(button_state & KeyModifierShift) scale /= 10;
Eigen::Vector3d rot = Eigen::Vector3d::Zero();
Eigen::Vector3d xyz = Eigen::Vector3d::Zero();
if(button_state & KeyModifierCtrl) {
// rotate
if(pickId == label_x.Id()) {
rot << 1,0,0;
}else if(pickId == label_y.Id()) {
rot << 0,1,0;
}else if(pickId == label_z.Id()) {
rot << 0,0,1;
}else{
return false;
}
}else if(button_state & KeyModifierShift){
// translate
if(pickId == label_x.Id()) {
xyz << 1,0,0;
}else if(pickId == label_y.Id()) {
xyz << 0,1,0;
}else if(pickId == label_z.Id()) {
xyz << 0,0,1;
}else{
return false;
}
}else{
return false;
}
// old from new
Eigen::Matrix<double,4,4> T_on = Eigen::Matrix<double,4,4>::Identity();
T_on.block<3,3>(0,0) = Eigen::AngleAxis<double>(scale,rot).toRotationMatrix();
T_on.block<3,1>(0,3) = scale*xyz;
// Update
T_pc = (ToEigen<double>(T_pc) * T_on.inverse()).eval();
return true;
}
#endif // HAVE_EIGEN
return false;
}
virtual bool MouseMotion(
const GLprecision /*win*/[3], const GLprecision /*obj*/[3], const GLprecision /*normal*/[3],
int /*button_state*/, int /*pickId*/
) override
{
return false;
}
float axis_length;
const InteractiveIndex::Token label_x;
const InteractiveIndex::Token label_y;
const InteractiveIndex::Token label_z;
};
}

View File

@@ -0,0 +1,69 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin {
struct Interactive
{
static __thread GLuint current_id;
virtual ~Interactive() {}
virtual bool Mouse(
int button,
const GLprecision win[3], const GLprecision obj[3], const GLprecision normal[3],
bool pressed, int button_state, int pickId
) = 0;
virtual bool MouseMotion(
const GLprecision win[3], const GLprecision obj[3], const GLprecision normal[3],
int button_state, int pickId
) = 0;
};
struct RenderParams
{
RenderParams()
: render_mode(GL_RENDER)
{
}
GLint render_mode;
};
struct Manipulator : public Interactive
{
virtual void Render(const RenderParams& params) = 0;
};
}

View File

@@ -0,0 +1,115 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <map>
#include <pangolin/scene/interactive.h>
namespace pangolin {
class InteractiveIndex
{
public:
class Token
{
public:
friend class InteractiveIndex;
Token()
: id(0)
{
}
Token(Token&& o)
: id(o.id)
{
o.id = 0;
}
GLint Id() const
{
return id;
}
~Token()
{
if(id) {
InteractiveIndex::I().Unstore(*this);
}
}
private:
Token(GLint id)
: id(id)
{
}
GLint id;
};
static InteractiveIndex& I()
{
static InteractiveIndex instance;
return instance;
}
Interactive* Find(GLuint id)
{
auto kv = index.find(id);
if(kv != index.end()) {
return kv->second;
}
return nullptr;
}
Token Store(Interactive* r)
{
index[next_id] = r;
return Token(next_id++);
}
void Unstore(Token& t)
{
index.erase(t.id);
t.id = 0;
}
private:
// Private constructor.
InteractiveIndex()
: next_id(1)
{
}
GLint next_id;
std::map<GLint, Interactive*> index;
};
}

View File

@@ -0,0 +1,117 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <memory>
#include <map>
#include <random>
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/scene/interactive.h>
namespace pangolin {
class Renderable
{
public:
using guid_t = GLuint;
static guid_t UniqueGuid()
{
static std::random_device rd;
static std::mt19937 gen(rd());
return (guid_t)gen();
}
Renderable(const std::weak_ptr<Renderable>& parent = std::weak_ptr<Renderable>())
: guid(UniqueGuid()), parent(parent), T_pc(IdentityMatrix()), should_show(true)
{
}
virtual ~Renderable()
{
}
// Default implementation simply renders children.
virtual void Render(const RenderParams& params = RenderParams()) {
RenderChildren(params);
}
void RenderChildren(const RenderParams& params)
{
for(auto& p : children) {
Renderable& r = *p.second;
if(r.should_show) {
glPushMatrix();
r.T_pc.Multiply();
r.Render(params);
if(r.manipulator) {
r.manipulator->Render(params);
}
glPopMatrix();
}
}
}
std::shared_ptr<Renderable> FindChild(guid_t guid)
{
auto o = children.find(guid);
if(o != children.end()) {
return o->second;
}
for(auto& kv : children ) {
std::shared_ptr<Renderable> c = kv.second->FindChild(guid);
if(c) return c;
}
return std::shared_ptr<Renderable>();
}
Renderable& Add(const std::shared_ptr<Renderable>& child)
{
if(child) {
children[child->guid] = child;
};
return *this;
}
// Renderable properties
const guid_t guid;
std::weak_ptr<Renderable> parent;
pangolin::OpenGlMatrix T_pc;
bool should_show;
// Children
std::map<guid_t, std::shared_ptr<Renderable>> children;
// Manipulator (handler, thing)
std::shared_ptr<Manipulator> manipulator;
};
}

View File

@@ -0,0 +1,182 @@
#pragma once
#include <pangolin/handler/handler.h>
#include <pangolin/scene/renderable.h>
#include <pangolin/scene/interactive_index.h>
namespace pangolin {
inline void gluPickMatrix(
GLdouble x, GLdouble y,
GLdouble width, GLdouble height,
GLint viewport[4]
) {
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / (GLfloat)width;
sy = viewport[3] / (GLfloat)height;
tx = (viewport[2] + 2.0f * (viewport[0] - (GLfloat)x)) / (GLfloat)width;
ty = (viewport[3] + 2.0f * (viewport[1] - (GLfloat)y)) / (GLfloat)height;
#define M(row, col) m[col*4+row]
M(0, 0) = sx;
M(0, 1) = 0.0f;
M(0, 2) = 0.0f;
M(0, 3) = tx;
M(1, 0) = 0.0f;
M(1, 1) = sy;
M(1, 2) = 0.0f;
M(1, 3) = ty;
M(2, 0) = 0.0f;
M(2, 1) = 0.0f;
M(2, 2) = 1.0f;
M(2, 3) = 0.0f;
M(3, 0) = 0.0f;
M(3, 1) = 0.0f;
M(3, 2) = 0.0f;
M(3, 3) = 1.0f;
#undef M
glMultMatrixf(m);
}
struct SceneHandler : public Handler3D
{
SceneHandler(
Renderable& scene,
OpenGlRenderState& cam_state
) : Handler3D(cam_state), scene(scene)
{
}
void ProcessHitBuffer(GLint hits, GLuint* buf, std::map<GLuint, Interactive*>& hit_map )
{
GLuint* closestNames = 0;
GLuint closestNumNames = 0;
GLuint closestZ = std::numeric_limits<GLuint>::max();
for (int i = 0; i < hits; i++) {
if (buf[1] < closestZ) {
closestNames = buf + 3;
closestNumNames = buf[0];
closestZ = buf[1];
}
buf += buf[0] + 3;
}
for (unsigned int i = 0; i < closestNumNames; i++) {
const int pickId = closestNames[i];
hit_map[pickId] = InteractiveIndex::I().Find(pickId);
}
}
void ComputeHits(pangolin::View& view,
const pangolin::OpenGlRenderState& cam_state,
int x, int y, int grab_width,
std::map<GLuint, Interactive*>& hit_objects )
{
// Get views viewport / modelview /projection
GLint viewport[4] = {view.v.l, view.v.b, view.v.w, view.v.h};
pangolin::OpenGlMatrix mv = cam_state.GetModelViewMatrix();
pangolin::OpenGlMatrix proj = cam_state.GetProjectionMatrix();
// Prepare hit buffer object
const unsigned int MAX_SEL_SIZE = 64;
GLuint vSelectBuf[MAX_SEL_SIZE];
glSelectBuffer(MAX_SEL_SIZE, vSelectBuf);
// Load and adjust modelview projection matrices
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(x, y, grab_width, grab_width, viewport);
proj.Multiply();
glMatrixMode(GL_MODELVIEW);
mv.Load();
// Render scenegraph in 'select' mode
glRenderMode(GL_SELECT);
glInitNames();
RenderParams select;
select.render_mode = GL_SELECT;
scene.Render(select);
glFlush();
GLint nHits = glRenderMode(GL_RENDER);
// std::cout << " -- Number of Hits are: " << nHits << std::endl;
// std::cout << " -- size of hitobjects: " << hit_objects.size() << std::endl;
if (nHits > 0) {
ProcessHitBuffer(nHits, vSelectBuf, hit_objects);
}
}
void Mouse(pangolin::View& view, pangolin::MouseButton button,
int x, int y, bool pressed, int button_state)
{
GetPosNormal(view, x, y, p, Pw, Pc, n);
bool handled = false;
if (pressed) {
m_selected_objects.clear();
ComputeHits(view, *cam_state, x, y, 2*hwin+1, m_selected_objects);
}
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->Mouse( button, p, Pw, n, pressed, button_state, kv.first);
}
if (!handled) {
Handler3D::Mouse(view, button, x, y, pressed, button_state);
}
}
void MouseMotion(pangolin::View& view, int x, int y, int button_state)
{
GetPosNormal(view, x, y, p, Pw, Pc, n);
bool handled = false;
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->MouseMotion( p, Pw, n, button_state, kv.first);
}
if (!handled) {
pangolin::Handler3D::MouseMotion(view, x, y, button_state);
}
}
void Special(pangolin::View& view, pangolin::InputSpecial inType,
float x, float y, float p1, float p2, float p3, float p4,
int button_state)
{
GetPosNormal(view, (int)x, (int)y, p, Pw, Pc, n);
bool handled = false;
if (inType == pangolin::InputSpecialScroll)
{
m_selected_objects.clear();
ComputeHits(view, *cam_state, (int)x, (int)y, 2*hwin+1, m_selected_objects);
const MouseButton button = p2 > 0 ? MouseWheelUp : MouseWheelDown;
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->Mouse( button, p, Pw, n, true, button_state, kv.first);
}
}
if (!handled) {
pangolin::Handler3D::Special(view, inType, x, y,
p1, p2, p3, p4, button_state);
}
}
std::map<GLuint, Interactive*> m_selected_objects;
Renderable& scene;
unsigned int grab_width;
};
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <map>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin {
template<typename T, typename TEdge>
struct TreeNode
{
struct Edge
{
TEdge parent_child;
TreeNode node;
};
T item;
std::vector<Edge> edges;
};
template<typename T, typename TEdge>
using NodeFunction = std::function<void(TreeNode<T,TEdge>&,const TEdge&)>;
//template<typename T, typename TEdge>
//void VisitDepthFirst(TreeNode<T,TEdge>& node, const NodeFunction<T,TEdge>& func, const TEdge& T_root_node = TEdge())
//{
// func(node, T_root_node);
// for(auto& e : node.edges) {
// const TEdge T_root_child = T_root_node * e.parent_child;
// VisitDepthFirst(e.node, func, T_root_child);
// }
//}
//void Eg()
//{
// using RenderNode = TreeNode<std::shared_ptr<Renderable>,OpenGlMatrix>;
// RenderNode root;
// VisitDepthFirst<std::shared_ptr<Renderable>,OpenGlMatrix>(
// root, [](RenderNode& node, const OpenGlMatrix& T_root_node) {
// if(node.item) {
// node.item->DoRender();
// }
// }, IdentityMatrix());
//}
}

View File

@@ -0,0 +1,106 @@
#pragma once
#include <pangolin/display/window.h>
#include <pangolin/platform.h>
#include <pangolin/video/video_input.h>
#include <functional>
#include <mutex>
#include <string>
#include <thread>
namespace pangolin
{
PANGOLIN_EXPORT
class VideoViewer
{
public:
typedef std::function<void(const unsigned char* data,
const std::vector<Image<unsigned char> >& images,
const picojson::value& properties)> FrameChangedCallbackFn;
static constexpr int FRAME_SKIP = 30;
VideoViewer(const std::string& window_name, const std::string& input_uri, const std::string& output_uri = "video.pango" );
VideoViewer(const VideoViewer&) = delete;
virtual ~VideoViewer();
void Run();
void RunAsync();
void Quit();
void QuitAndWait();
inline int TotalFrames() const
{
return video_playback ? video_playback->GetTotalFrames() : std::numeric_limits<int>::max();
}
// Control playback
void OpenInput(const std::string& input_uri);
void CloseInput();
// Control recording
void Record();
void RecordOneFrame();
void StopRecording();
// Useful for user-control
void TogglePlay();
void ToggleRecord();
void ToggleDiscardBufferedFrames();
void ToggleWaitForFrames();
void SetDiscardBufferedFrames(bool new_state);
void SetWaitForFrames(bool new_state);
void Skip(int frames);
bool ChangeExposure(int delta_us);
bool ChangeGain(float delta);
void SetActiveCamera(int delta);
void DrawEveryNFrames(int n);
// Register to be notified of new image data
void SetFrameChangedCallback(FrameChangedCallbackFn cb);
void WaitUntilExit();
VideoInput& Video() {return video;}
const VideoInput& Video() const {return video;}
void SetRecordNthFrame(int record_nth_frame_) {
record_nth_frame = record_nth_frame_;
}
protected:
void RegisterDefaultKeyShortcutsAndPangoVariables();
std::mutex control_mutex;
std::string window_name;
std::thread vv_thread;
VideoInput video;
VideoPlaybackInterface* video_playback;
VideoInterface* video_interface;
std::string output_uri;
int current_frame;
int grab_until;
int record_nth_frame;
int draw_nth_frame;
bool video_grab_wait;
bool video_grab_newest;
bool should_run;
uint16_t active_cam;
FrameChangedCallbackFn frame_changed_callback;
};
void PANGOLIN_EXPORT RunVideoViewerUI(const std::string& input_uri, const std::string& output_uri);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Hauke Strasdat, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/format_string.h>
#include <iostream>
#ifdef __GNUC__
# define PANGO_FUNCTION __PRETTY_FUNCTION__
#elif (_MSC_VER >= 1310)
# define PANGO_FUNCTION __FUNCTION__
#else
# define PANGO_FUNCTION "unknown"
#endif
namespace pangolin {
template <typename... Args> PANGO_HOST_DEVICE
void abort(const char* function, const char* file, int line, Args&&... args)
{
std::printf("pangolin::abort() in function '%s', file '%s', line %d.\n", function, file, line);
#ifndef __CUDACC__
std::cout << FormatString(std::forward<Args>(args)...) << std::endl;
std::abort();
#endif
}
}
// Always check, even in debug
#define PANGO_ENSURE(expr, ...) ((expr) ? ((void)0) : pangolin::abort(PANGO_FUNCTION, __FILE__, __LINE__, ##__VA_ARGS__))
// May be disabled for optimisation
#define PANGO_ASSERT(expr, ...) ((expr) ? ((void)0) : pangolin::abort(PANGO_FUNCTION, __FILE__, __LINE__, ##__VA_ARGS__))

View File

@@ -0,0 +1,42 @@
#pragma once
#include <pangolin/platform.h>
#ifdef HAVE_EIGEN
# include <Eigen/Core>
#endif
namespace pangolin
{
// Scalar / Vector agnostic static_cast-like thing
//
// e.g. Promote float to double:
// ComponentCast<double,float>::cast(0.14f);
//
// e.g. Promote Eigen::Vector2f to Eigen::Vector2d:
// ComponentCast<Eigen::Vector2d,Eigen::Vector2f>::cast(Eigen::Vector2f(0.1,0.2);
template <typename To, typename From>
struct ComponentCast
{
PANGO_HOST_DEVICE
static To cast(const From& val)
{
return static_cast<To>(val);
}
};
#ifdef HAVE_EIGEN
template <typename To, typename FromDerived>
struct ComponentCast<To, Eigen::MatrixBase<FromDerived> >
{
PANGO_HOST_DEVICE
static To cast(const Eigen::MatrixBase<FromDerived>& val)
{
return val.template cast<typename To::Scalar>();
}
};
#endif
}

View File

@@ -0,0 +1,74 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
enum ImageFileType
{
ImageFileTypePpm,
ImageFileTypeTga,
ImageFileTypePng,
ImageFileTypeJpg,
ImageFileTypeTiff,
ImageFileTypeGif,
ImageFileTypeExr,
ImageFileTypePango,
ImageFileTypePvn,
ImageFileTypeZstd,
ImageFileTypeLz4,
ImageFileTypeP12b,
ImageFileTypePly,
ImageFileTypeObj,
ImageFileTypeUnknown
};
PANGOLIN_EXPORT
std::string ImageFileTypeToName(ImageFileType);
PANGOLIN_EXPORT
ImageFileType NameToImageFileType(const std::string&);
PANGOLIN_EXPORT
std::string FileLowercaseExtention(const std::string& filename);
PANGOLIN_EXPORT
ImageFileType FileTypeMagic(const unsigned char data[], size_t bytes);
PANGOLIN_EXPORT
ImageFileType FileTypeExtension(const std::string& ext);
PANGOLIN_EXPORT
ImageFileType FileType(const std::string& filename);
}

View File

@@ -0,0 +1,151 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
#include <vector>
#include <algorithm>
namespace pangolin
{
PANGOLIN_EXPORT
std::vector<std::string>& Split(const std::string& s, char delim, std::vector<std::string>& elements);
PANGOLIN_EXPORT
std::vector<std::string> Split(const std::string &s, char delim);
PANGOLIN_EXPORT
std::vector<std::string> Expand(const std::string &s, char open='[', char close=']', char delim=',');
PANGOLIN_EXPORT
std::string SanitizePath(const std::string& path);
PANGOLIN_EXPORT
std::string PathParent(const std::string& path, int levels = 1);
PANGOLIN_EXPORT
bool FileExists(const std::string& filename);
PANGOLIN_EXPORT
std::string FindPath(const std::string& child_path, const std::string& signature_path);
PANGOLIN_EXPORT
std::string PathExpand(const std::string& sPath);
PANGOLIN_EXPORT
bool MatchesWildcard(const std::string& str, const std::string& wildcard);
// Fill 'file_vec' with the files that match the glob-like 'wildcard_file_path'
// ? can be used to match any single charector
// * can be used to match any sequence of charectors in a directory
// ** can be used to match any directories across any number of levels
// e.g. FilesMatchingWildcard("~/*/code/*.h", vec);
// e.g. FilesMatchingWildcard("~/**/*.png", vec);
PANGOLIN_EXPORT
bool FilesMatchingWildcard(const std::string& wildcard_file_path, std::vector<std::string>& file_vec);
PANGOLIN_EXPORT
std::string MakeUniqueFilename(const std::string& filename);
PANGOLIN_EXPORT
bool IsPipe(const std::string& file);
PANGOLIN_EXPORT
bool IsPipe(int fd);
PANGOLIN_EXPORT
int WritablePipeFileDescriptor(const std::string& file);
/**
* Open the file for reading. Note that it is opened with O_NONBLOCK. The pipe
* open is done in two stages so that the producer knows a reader is waiting
* (but not blocked). The reader then checks PipeHasDataToRead() until it
* returns true. The file can then be opened. Note that the file descriptor
* should be closed after the read stream has been created so that the write
* side of the pipe does not get signaled.
*/
PANGOLIN_EXPORT
int ReadablePipeFileDescriptor(const std::string& file);
PANGOLIN_EXPORT
bool PipeHasDataToRead(int fd);
PANGOLIN_EXPORT
void FlushPipe(const std::string& file);
// TODO: Tidy these inlines up / move them
inline bool StartsWith(const std::string& str, const std::string& prefix)
{
return !str.compare(0, prefix.size(), prefix);
}
inline bool EndsWith(const std::string& str, const std::string& prefix)
{
return !str.compare(str.size() - prefix.size(), prefix.size(), prefix);
}
inline std::string Trim(const std::string& str, const std::string& delimiters = " \f\n\r\t\v" )
{
const size_t f = str.find_first_not_of( delimiters );
return f == std::string::npos ?
"" :
str.substr( f, str.find_last_not_of( delimiters ) + 1 );
}
inline void ToUpper( std::string& str )
{
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
inline void ToLower( std::string& str )
{
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
inline std::string ToUpperCopy( const std::string& str )
{
std::string out;
out.resize(str.size());
std::transform(str.begin(), str.end(), out.begin(), ::toupper);
return out;
}
inline std::string ToLowerCopy( const std::string& str )
{
std::string out;
out.resize(str.size());
std::transform(str.begin(), str.end(), out.begin(), ::tolower);
return out;
}
}

View File

@@ -0,0 +1,153 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <condition_variable>
#include <list>
#include <mutex>
#include <mutex>
#include <thread>
namespace pangolin
{
template<typename BufPType>
class FixSizeBuffersQueue
{
public:
FixSizeBuffersQueue() {}
~FixSizeBuffersQueue() {
}
BufPType getNewest() {
std::lock_guard<std::mutex> vlock(vMtx);
std::lock_guard<std::mutex> elock(eMtx);
if(validBuffers.size() == 0) {
// Empty queue.
return 0;
} else {
// Requeue all but newest buffers.
while(validBuffers.size() > 1) {
emptyBuffers.push_back(std::move(validBuffers.front()));
validBuffers.pop_front();
}
// Return newest buffer.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
BufPType getNext() {
std::lock_guard<std::mutex> vlock(vMtx);
if(validBuffers.size() == 0) {
// Empty queue.
return 0;
} else {
// Return oldest buffer.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
BufPType getFreeBuffer() {
std::lock_guard<std::mutex> vlock(vMtx);
std::lock_guard<std::mutex> elock(eMtx);
if(emptyBuffers.size() > 0) {
// Simply get a free buffer from the free buffers list.
BufPType bp = std::move(emptyBuffers.front());
emptyBuffers.pop_front();
return bp;
} else {
if(validBuffers.size() == 0) {
// Queue not yet initialized.
throw std::runtime_error("Queue not yet initialised.");
} else {
std::cerr << "Out of free buffers." << std::endl;
// No free buffers return oldest among the valid buffers.
BufPType bp = std::move(validBuffers.front());
validBuffers.pop_front();
return bp;
}
}
}
void addValidBuffer(BufPType bp) {
// Add buffer to valid buffers queue.
std::lock_guard<std::mutex> vlock(vMtx);
validBuffers.push_back(std::move(bp));
}
void returnOrAddUsedBuffer(BufPType bp) {
// Add buffer back to empty buffers queue.
std::lock_guard<std::mutex> elock(eMtx);
emptyBuffers.push_back(std::move(bp));
}
size_t AvailableFrames() const {
std::lock_guard<std::mutex> vlock(vMtx);
return validBuffers.size();
}
size_t EmptyBuffers() const {
std::lock_guard<std::mutex> elock(eMtx);
return emptyBuffers.size();
}
bool DropNFrames(size_t n) {
std::lock_guard<std::mutex> vlock(vMtx);
if(validBuffers.size() < n) {
return false;
} else {
std::lock_guard<std::mutex> elock(eMtx);
// Requeue all but newest buffers.
for(unsigned int i=0; i<n; ++i) {
emptyBuffers.push_back(std::move(validBuffers.front()));
validBuffers.pop_front();
}
return true;
}
}
// unsigned int BufferSizeBytes(){
// return bufferSizeBytes;
// }
private:
std::list<BufPType> validBuffers;
std::list<BufPType> emptyBuffers;
mutable std::mutex vMtx;
mutable std::mutex eMtx;
// unsigned int maxNumBuffers;
// unsigned int bufferSizeBytes;
};
}

View File

@@ -0,0 +1,87 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Hauke Strasdat, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
namespace pangolin {
namespace details {
// Following: http://stackoverflow.com/a/22759544
template <typename T>
class IsStreamable {
private:
template <typename TT>
static auto test(int) -> decltype( (std::declval<std::stringstream&>() << std::declval<TT>(), std::true_type()) );
template <typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<T>(0))::value;
};
inline void FormatStream(std::stringstream& stream, const char* text)
{
stream << text;
}
// Following: http://en.cppreference.com/w/cpp/language/parameter_pack
template <typename T, typename... Args>
void FormatStream(std::stringstream& stream, const char* text, T arg, Args... args)
{
static_assert(IsStreamable<T>::value,
"One of the args has not an ostream overload!");
for (; *text != '\0'; ++text) {
if (*text == '%') {
stream << arg;
FormatStream(stream, text + 1, args...);
return;
}
stream << *text;
}
stream << "\nFormat-Warning: There are " << sizeof...(Args) + 1
<< " args unused.";
}
} // namespace details
template <typename... Args>
std::string FormatString(const char* text, Args... args)
{
std::stringstream stream;
details::FormatStream(stream, text, args...);
return stream.str();
}
inline std::string FormatString()
{
return std::string();
}
}

View File

@@ -0,0 +1,44 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
// TODO: Something a bit more useful here, probably using format_string.h
#pragma once
#ifndef _ANDROID_
# include <cstdio>
# define pango_print_debug(...) printf(__VA_ARGS__)
# define pango_print_info(...) printf(__VA_ARGS__)
# define pango_print_error(...) fprintf(stderr, __VA_ARGS__)
# define pango_print_warn(...) fprintf(stderr, __VA_ARGS__)
#else
# include <android/log.h>
# define pango_print_debug(...) __android_log_print(ANDROID_LOG_DEBUG, "pango", __VA_ARGS__ );
# define pango_print_info(...) __android_log_print(ANDROID_LOG_INFO, "pango", __VA_ARGS__ );
# define pango_print_error(...) __android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__ );
# define pango_print_warn(...) __android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__ );
#endif

View File

@@ -0,0 +1,55 @@
#pragma once
#include <streambuf>
#include <vector>
namespace pangolin {
// A simple streambuf wrapper around std::vector for memory buffer use
struct memstreambuf : public std::streambuf
{
public:
memstreambuf(size_t initial_buffer_size)
{
buffer.reserve(initial_buffer_size);
}
// Avoiding use of std::streambuf's move constructor, since it is missing for old GCC
memstreambuf(memstreambuf&& o)
: buffer(std::move(o.buffer))
{
pubseekpos(o.pubseekoff(0, std::ios_base::cur));
}
size_t size() const
{
return buffer.size();
}
const unsigned char* data() const
{
return buffer.data();
}
void clear()
{
buffer.clear();
}
std::vector<unsigned char> buffer;
protected:
std::streamsize xsputn(const char_type* __s, std::streamsize __n) override
{
buffer.insert(buffer.end(), __s, __s + __n);
return __n;
}
int_type overflow(int_type __c) override
{
buffer.push_back( static_cast<unsigned char>(__c) );
return __c;
}
};
}

View File

@@ -0,0 +1,80 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/type_convert.h>
#include <string>
#include <vector>
namespace pangolin
{
class PANGOLIN_EXPORT Params
{
public:
typedef std::vector<std::pair<std::string,std::string>> ParamMap;
Params()
{
}
Params(std::initializer_list<std::pair<std::string,std::string>> l)
: params(l)
{
}
bool Contains(const std::string& key) const
{
for(ParamMap::const_iterator it = params.begin(); it!=params.end(); ++it) {
if(it->first == key) return true;
}
return false;
}
template<typename T>
T Get(const std::string& key, T default_val) const
{
// Return last value passed to the key.
for(ParamMap::const_reverse_iterator it = params.rbegin(); it!=params.rend(); ++it) {
if(it->first == key) return Convert<T, std::string>::Do(it->second);
}
return default_val;
}
template<typename T>
void Set(const std::string& key, const T& val)
{
params.push_back(std::pair<std::string,std::string>(key,Convert<std::string,T>::Do(val)));
}
ParamMap params;
};
}

Some files were not shown because too many files have changed in this diff Show More