]> git.tdb.fi Git - libs/gl.git/commitdiff
Add files
authorMikko Rasa <tdb@tdb.fi>
Mon, 27 Nov 2006 23:59:37 +0000 (23:59 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 27 Nov 2006 23:59:37 +0000 (23:59 +0000)
15 files changed:
Build [new file with mode: 0644]
source/font.cpp [new file with mode: 0644]
source/font.h [new file with mode: 0644]
source/misc.cpp [new file with mode: 0644]
source/misc.h [new file with mode: 0644]
source/rendermode.cpp [new file with mode: 0644]
source/rendermode.h [new file with mode: 0644]
source/select.cpp [new file with mode: 0644]
source/select.h [new file with mode: 0644]
source/texenv.h [new file with mode: 0644]
source/texture.cpp [new file with mode: 0644]
source/texture.h [new file with mode: 0644]
source/texture2d.cpp [new file with mode: 0644]
source/texture2d.h [new file with mode: 0644]
source/types.h [new file with mode: 0644]

diff --git a/Build b/Build
new file mode 100644 (file)
index 0000000..e8c0420
--- /dev/null
+++ b/Build
@@ -0,0 +1,16 @@
+package "mspgl"
+{
+       description "C++ wrappers for OpenGL";
+       version "0.1";
+
+       require "opengl";
+       require "mspparser";
+       require "libpng";
+
+       library "mspgl"
+       {
+               source "source";
+               install true;
+               install_headers "msp/gl";
+       };
+};
diff --git a/source/font.cpp b/source/font.cpp
new file mode 100644 (file)
index 0000000..31f43f7
--- /dev/null
@@ -0,0 +1,152 @@
+#include <GL/gl.h>
+#include "font.h"
+#include "texture2d.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Font::Font():
+       tex(0),
+       own_tex(false)
+{ }
+
+void Font::set_texture(const Texture2D &t)
+{
+       tex=&t;
+}
+
+void Font::add_glyph(wchar_t code, float x1, float y1, float x2, float y2, float w, float h, float desc, float adv)
+{
+       Glyph glyph;
+       glyph.code=code;
+       glyph.x1=x1;
+       glyph.y1=y1;
+       glyph.x2=x2;
+       glyph.y2=y2;
+       glyph.w=w;
+       glyph.h=h;
+       glyph.descent=desc;
+       glyph.advance=adv;
+}
+
+float Font::get_string_width(const string &str) const
+{
+       float x=0;
+
+       for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
+       {
+               GlyphMap::const_iterator j=glyphs.find((unsigned char)*i);
+               if(j==glyphs.end())
+                       continue;
+
+               const Glyph &glyph=j->second;
+
+               x+=glyph.advance;
+       }
+
+       return x;
+}
+
+void Font::draw_string(const string &str) const
+{
+       float x=0;
+       float data[16];
+
+       prepare(data);
+
+       for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
+               draw_glyph((unsigned char)*i, data, x);
+
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+Font::~Font()
+{
+       if(own_tex)
+               delete tex;
+}
+
+void Font::prepare(float *data) const
+{
+       tex->bind();
+
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glTexCoordPointer(2, GL_FLOAT, 4*sizeof(float), data);
+       glVertexPointer(2, GL_FLOAT, 4*sizeof(float), data+2);
+}
+
+void Font::draw_glyph(wchar_t code, float *data, float &x) const
+{
+       GlyphMap::const_iterator i=glyphs.find(code);
+       if(i==glyphs.end())
+               return;
+
+       const Glyph &glyph=i->second;
+
+       data[0]=data[12]=glyph.x1;
+       data[1]=data[5]=glyph.y1;
+       data[4]=data[8]=glyph.x2;
+       data[9]=data[13]=glyph.y2;
+
+       data[2]=data[14]=x;
+       data[3]=data[7]=glyph.descent;
+       data[6]=data[10]=x+glyph.w;
+       data[11]=data[15]=glyph.h+glyph.descent;
+
+       glDrawArrays(GL_QUADS, 0, 4);
+
+       x+=glyph.advance;
+}
+
+Font::Loader::Loader(Font &f):
+       font(f)
+{
+       add("texture", &Loader::texture);
+       add("glyph",   &Loader::glyph);
+}
+
+void Font::Loader::texture(const string &t)
+{
+       Texture2D *tex=new Texture2D;
+       tex->parameter(GL_GENERATE_MIPMAP, 1);
+       font.tex=tex;
+       tex->image(t);
+       font.own_tex=true;
+}
+
+void Font::Loader::glyph(unsigned c)
+{
+       Glyph gl;
+       gl.code=c;
+       load_sub(gl);
+       font.glyphs.insert(GlyphMap::value_type(c, gl));
+}
+
+Font::Glyph::Loader::Loader(Glyph &g):
+       glyph(g)
+{
+       add("texcoords", &Loader::texcoords);
+       add("size",      &Loader::size);
+       add("descent",   &Glyph::descent);
+       add("advance",   &Glyph::advance);
+}
+
+void Font::Glyph::Loader::texcoords(float x1, float y1, float x2, float y2)
+{
+       glyph.x1=x1;
+       glyph.y1=y1;
+       glyph.x2=x2;
+       glyph.y2=y2;
+}
+
+void Font::Glyph::Loader::size(float w, float h)
+{
+       glyph.w=w;
+       glyph.h=h;
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/font.h b/source/font.h
new file mode 100644 (file)
index 0000000..a4600fc
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef FONT_H_
+#define FONT_H_
+
+#include <map>
+#include <string>
+#include <msp/parser/loader.h>
+
+namespace Msp {
+namespace GL {
+
+class Texture2D;
+
+class Font
+{
+public:
+       class Loader: public Msp::Parser::Loader
+       {
+       public:
+               Loader(Font &);
+       private:
+               Font &font;
+
+               void texture(const std::string &);
+               void glyph(unsigned);
+       };
+
+       Font();
+       void  set_texture(const Texture2D &);
+       void  add_glyph(wchar_t, float, float, float, float, float, float, float, float);
+       float get_string_width(const std::string &) const;
+       void  draw_glyph(wchar_t);
+       void  draw_string(const std::string &) const;
+       void  draw_multiline(const std::string &) const;
+       ~Font();
+private:
+       struct Glyph
+       {
+               class Loader: public Msp::Parser::Loader
+               {
+               public:
+                       Loader(Glyph &);
+                       Glyph &get_object() { return glyph; }
+               private:
+                       Glyph &glyph;
+
+                       void texcoords(float, float, float, float);
+                       void size(float, float);
+               };
+
+               wchar_t code;
+               float x1,y1;
+               float x2,y2;
+               float w,h;
+               float descent;
+               float advance;
+       };
+       typedef std::map<wchar_t, Glyph> GlyphMap;
+
+       const Texture2D *tex;
+       bool     own_tex;
+       GlyphMap glyphs;
+
+       void prepare(float *) const;
+       void draw_glyph(wchar_t, float *, float &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/misc.cpp b/source/misc.cpp
new file mode 100644 (file)
index 0000000..b99310a
--- /dev/null
@@ -0,0 +1,15 @@
+#include "misc.h"
+
+namespace Msp {
+namespace GL {
+
+void set(GLenum state, bool value)
+{
+       if(value)
+               glEnable(state);
+       else
+               glDisable(state);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/misc.h b/source/misc.h
new file mode 100644 (file)
index 0000000..49c6cf5
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef MSP_GL_MISC_H_
+#define MSP_GL_MISC_H_
+
+#include <GL/gl.h>
+
+namespace Msp {
+namespace GL {
+
+void set(GLenum, bool);
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/rendermode.cpp b/source/rendermode.cpp
new file mode 100644 (file)
index 0000000..cef0b37
--- /dev/null
@@ -0,0 +1,21 @@
+#include "rendermode.h"
+#include "select.h"
+
+namespace Msp {
+namespace GL {
+
+int render_mode(RenderMode rm)
+{
+       int old_rm;
+       glGetIntegerv(GL_RENDER_MODE, &old_rm);
+       
+       int result=glRenderMode(rm);
+       
+       if(old_rm==SELECT)
+               _parse_internal_select_records(result);
+       
+       return result;
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/rendermode.h b/source/rendermode.h
new file mode 100644 (file)
index 0000000..cb8670c
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef MSP_GL_RENDERMODE_H_
+#define MSP_GL_RENDERMODE_H_
+
+#include <GL/gl.h>
+
+namespace Msp {
+namespace GL {
+
+enum RenderMode
+{
+       RENDER   = GL_RENDER,
+       SELECT   = GL_SELECT,
+       FEEDBACK = GL_FEEDBACK
+};
+
+int render_mode(RenderMode);
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/select.cpp b/source/select.cpp
new file mode 100644 (file)
index 0000000..e989de4
--- /dev/null
@@ -0,0 +1,47 @@
+#include <GL/gl.h>
+#include "select.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+vector<SelectRecord> *select_buf=0;
+vector<uint> select_buf_int;
+
+void select_buffer(vector<SelectRecord> &buf)
+{
+       select_buf_int.resize(1024);
+       glSelectBuffer(select_buf_int.size(), &select_buf_int[0]);
+       select_buf=&buf;
+}
+
+void parse_select_records(const uint *buf, uint count, vector<SelectRecord> &tbuf)
+{
+       uint i=0;
+       while(count--)
+       {
+               SelectRecord record;
+
+               uint n_names=buf[i++];
+               record.min_depth=buf[i++];
+               record.max_depth=buf[i++];
+
+               record.names.reserve(n_names);
+               while(n_names--)
+                       record.names.push_back(buf[i++]);
+               
+               tbuf.push_back(record);
+       }
+}
+
+void _parse_internal_select_records(uint count)
+{
+       if(!select_buf)
+               //XXX throw InvalidOperation();
+               return;
+       parse_select_records(&select_buf_int[0], count, *select_buf);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/select.h b/source/select.h
new file mode 100644 (file)
index 0000000..e862fe5
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef MSP_GL_SELECT_H_
+#define MSP_GL_SELECT_H_
+
+#include <vector>
+
+namespace Msp {
+namespace GL {
+               
+struct SelectRecord
+{
+       uint min_depth;
+       uint max_depth;
+       std::vector<uint> names;
+};
+
+void select_buffer(std::vector<SelectRecord> &);
+void parse_select_records(const uint *buf, uint, std::vector<SelectRecord> &);
+
+void _parse_internal_select_records(uint);
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/texenv.h b/source/texenv.h
new file mode 100644 (file)
index 0000000..8a341db
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef MSP_GL_TEXENV_H_
+#define MSP_GL_TEXENV_H_
+
+namespace Msp {
+namespace GL {
+
+class TexEnv
+{
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/texture.cpp b/source/texture.cpp
new file mode 100644 (file)
index 0000000..d12e18e
--- /dev/null
@@ -0,0 +1,70 @@
+#include "texture.h"
+
+namespace Msp {
+namespace GL {
+
+void Texture::bind() const
+{
+       if(!target) return;
+
+       glEnable(target);
+       glBindTexture(target, id);
+       bound=this;
+}
+
+void Texture::parameter(GLenum param, int value)
+{
+       if(bound!=this) bind();
+
+       glTexParameteri(target, param, value);
+}
+
+void Texture::parameter(GLenum param, float value)
+{
+       if(bound!=this) bind();
+
+       glTexParameterf(target, param, value);
+}
+
+sizei Texture::get_width(int level) const
+{
+       if(bound!=this) bind();
+
+       int width;
+       glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
+       return width;
+}
+
+sizei Texture::get_height(int level) const
+{
+       if(bound!=this) bind();
+
+       int height;
+       glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
+       return height;
+}
+
+sizei Texture::get_depth(int level) const
+{
+       if(bound!=this) bind();
+
+       int depth;
+       glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
+       return depth;
+}
+
+Texture::~Texture()
+{
+       glDeleteTextures(1, &id);
+}
+
+Texture::Texture():
+       target(0)
+{
+       glGenTextures(1, &id);
+}
+
+const Texture *Texture::bound=0;
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/texture.h b/source/texture.h
new file mode 100644 (file)
index 0000000..7c29865
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef MSP_GL_TEXTURE_H_
+#define MSP_GL_TEXTURE_H_
+
+#include <GL/gl.h>
+#include "types.h"
+
+namespace Msp {
+namespace GL {
+
+enum TextureFilter
+{
+       NEAREST                = GL_NEAREST,
+       LINEAR                 = GL_LINEAR,
+       NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST,
+       NEAREST_MIPMAP_LINEAR  = GL_NEAREST_MIPMAP_LINEAR,
+       LINEAR_MIPMAP_NEAREST  = GL_LINEAR_MIPMAP_NEAREST,
+       LINEAR_MIPMAP_LINEAR   = GL_LINEAR_MIPMAP_LINEAR
+};
+
+enum TextureFormat
+{
+       LUMINANCE8,
+       LUMINANCE8_ALPHA8,
+       RGB8,
+       RGBA8,
+       BGR8,
+       BGRA8
+};
+
+class Texture
+{
+public:
+       void bind() const;
+       void parameter(GLenum, int);
+       void parameter(GLenum, float);
+       void set_min_filter(TextureFilter f) { parameter(GL_TEXTURE_MIN_FILTER, f); }
+       void set_mag_filter(TextureFilter f) { parameter(GL_TEXTURE_MAG_FILTER, f); }
+       uint  get_id() const                 { return id; }
+       sizei get_width(int =0) const;
+       sizei get_height(int =0) const;
+       sizei get_depth(int =0) const;
+       ~Texture();
+protected:
+       uint   id;
+       GLenum target;
+
+       Texture();
+
+       static const Texture *bound;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/texture2d.cpp b/source/texture2d.cpp
new file mode 100644 (file)
index 0000000..e8e9759
--- /dev/null
@@ -0,0 +1,116 @@
+#include <png.h>
+#include <msp/error.h>
+#include "texture2d.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Texture2D::Texture2D()
+{
+       target=GL_TEXTURE_2D;
+}
+
+/**
+Uploads an image into the texture.  Direct wrapper for glTexImage2D.
+*/
+void Texture2D::image(int level, int ifmt, sizei width, sizei height, int border, GLenum fmt, GLenum type, void *data)
+{
+       if(bound!=this) bind();
+       glTexImage2D(target, level, ifmt, width, height, border, fmt, type, data);
+}
+
+/**
+Uploads an image into the texture.
+*/
+void Texture2D::image(int level, sizei width, sizei height, TextureFormat tfmt, void *data)
+{
+       int ifmt;
+       int fmt;
+       int type;
+
+       switch(tfmt)
+       {
+       case LUMINANCE8:        ifmt=GL_LUMINANCE;       fmt=GL_LUMINANCE;       type=GL_UNSIGNED_BYTE; break;
+       case LUMINANCE8_ALPHA8: ifmt=GL_LUMINANCE_ALPHA; fmt=GL_LUMINANCE_ALPHA; type=GL_UNSIGNED_BYTE; break;
+       case RGB8:  ifmt=GL_RGB;  fmt=GL_RGB;  type=GL_UNSIGNED_BYTE;        break;
+       case RGBA8: ifmt=GL_RGBA; fmt=GL_RGBA; type=GL_UNSIGNED_INT_8_8_8_8; break;
+       case BGR8:  ifmt=GL_RGB;  fmt=GL_BGR;  type=GL_UNSIGNED_BYTE;        break;
+       case BGRA8: ifmt=GL_RGBA; fmt=GL_BGRA; type=GL_UNSIGNED_INT_8_8_8_8; break;
+       default: return;
+       }
+
+       image(level, ifmt, width, height, 0, fmt, type, data);
+}
+
+/**
+Loads an image from a file and uploads it into the texture.  Currently assumes
+the file to be a PNG image.
+*/
+void Texture2D::image(const string &fn)
+{
+       FILE *file=fopen(fn.c_str(), "r");
+       if(!file) throw Exception("Couldn't open "+fn);
+
+       char sig[8];
+       fread(sig, 8, 1, file);
+       if(png_sig_cmp((png_byte *)sig, 0, 8))
+                throw Exception("Not a PNG image");
+
+       png_struct *pngs=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+       png_info   *pngi=png_create_info_struct(pngs);
+
+       if(setjmp(png_jmpbuf(pngs)))
+       {
+               png_destroy_read_struct(&pngs, &pngi, 0);
+               fclose(file);
+               throw Exception("PNG error");
+       }
+       png_init_io(pngs, file);
+       png_set_sig_bytes(pngs, 8);
+
+       png_read_info(pngs, pngi);
+
+       unsigned width=png_get_image_width(pngs, pngi);
+       unsigned height=png_get_image_height(pngs, pngi);
+       unsigned depth=png_get_bit_depth(pngs, pngi);
+       unsigned ctype=png_get_color_type(pngs, pngi);
+
+       if(ctype==PNG_COLOR_TYPE_PALETTE || depth<8)
+       {
+               png_destroy_read_struct(&pngs, &pngi, 0);
+               fclose(file);
+               throw Exception("Invalid color type or bit depth");
+       }
+
+       if(depth==16)
+               png_set_strip_16(pngs);
+
+       TextureFormat fmt;
+       unsigned planes;
+
+       switch(ctype)
+       {
+       case PNG_COLOR_TYPE_GRAY: fmt=LUMINANCE8; planes=1; break;
+       case PNG_COLOR_TYPE_GRAY_ALPHA: fmt=LUMINANCE8_ALPHA8; planes=2; break;
+       case PNG_COLOR_TYPE_RGB: fmt=RGB8; planes=3; break;
+       case PNG_COLOR_TYPE_RGB_ALPHA: fmt=RGBA8; planes=4; break;
+       }
+
+       png_byte *data=(png_byte *)malloc(width*height*planes);
+       png_byte *row_ptrs[height];
+       for(unsigned i=0; i<height; ++i)
+               row_ptrs[i]=data+(height-1-i)*width*planes;
+
+       png_read_image(pngs, row_ptrs);
+
+       image(0, width, height, fmt, data);
+       free(data);
+
+       png_destroy_read_struct(&pngs, &pngi, 0);
+       fclose(file);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/texture2d.h b/source/texture2d.h
new file mode 100644 (file)
index 0000000..86c2a89
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef MSP_GL_TEXTURE2D_H_
+#define MSP_GL_TEXTURE2D_H_
+
+#include <string>
+#include "texture.h"
+
+namespace Msp {
+namespace GL {
+
+class Texture2D: public Texture
+{
+public:
+       Texture2D();
+       void image(int, int, sizei, sizei, int, GLenum, GLenum, void *);
+       void image(int, sizei, sizei, TextureFormat, void *);
+       void image(const std::string &);
+private:
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
diff --git a/source/types.h b/source/types.h
new file mode 100644 (file)
index 0000000..adfd7de
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef MSP_GL_TYPES_H_
+#define MSP_GL_TYPES_H_
+
+namespace Msp {
+namespace GL {
+
+typedef signed char byte;
+typedef unsigned char ubyte;
+typedef unsigned sizei;
+typedef unsigned uint;
+
+} // namespace GL
+} // namespace Msp
+
+#endif