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

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();
}
}