From 7adcad3b40a03000a82e32db4523761c218309b8 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 27 Nov 2006 23:59:37 +0000 Subject: [PATCH] Add files --- Build | 16 +++++ source/font.cpp | 152 ++++++++++++++++++++++++++++++++++++++++++ source/font.h | 70 +++++++++++++++++++ source/misc.cpp | 15 +++++ source/misc.h | 14 ++++ source/rendermode.cpp | 21 ++++++ source/rendermode.h | 21 ++++++ source/select.cpp | 47 +++++++++++++ source/select.h | 24 +++++++ source/texenv.h | 14 ++++ source/texture.cpp | 70 +++++++++++++++++++ source/texture.h | 55 +++++++++++++++ source/texture2d.cpp | 116 ++++++++++++++++++++++++++++++++ source/texture2d.h | 23 +++++++ source/types.h | 15 +++++ 15 files changed, 673 insertions(+) create mode 100644 Build create mode 100644 source/font.cpp create mode 100644 source/font.h create mode 100644 source/misc.cpp create mode 100644 source/misc.h create mode 100644 source/rendermode.cpp create mode 100644 source/rendermode.h create mode 100644 source/select.cpp create mode 100644 source/select.h create mode 100644 source/texenv.h create mode 100644 source/texture.cpp create mode 100644 source/texture.h create mode 100644 source/texture2d.cpp create mode 100644 source/texture2d.h create mode 100644 source/types.h diff --git a/Build b/Build new file mode 100644 index 00000000..e8c0420f --- /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 index 00000000..31f43f73 --- /dev/null +++ b/source/font.cpp @@ -0,0 +1,152 @@ +#include +#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 index 00000000..a4600fc2 --- /dev/null +++ b/source/font.h @@ -0,0 +1,70 @@ +#ifndef FONT_H_ +#define FONT_H_ + +#include +#include +#include + +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 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 index 00000000..b99310a9 --- /dev/null +++ b/source/misc.cpp @@ -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 index 00000000..49c6cf5b --- /dev/null +++ b/source/misc.h @@ -0,0 +1,14 @@ +#ifndef MSP_GL_MISC_H_ +#define MSP_GL_MISC_H_ + +#include + +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 index 00000000..cef0b376 --- /dev/null +++ b/source/rendermode.cpp @@ -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 index 00000000..cb8670c8 --- /dev/null +++ b/source/rendermode.h @@ -0,0 +1,21 @@ +#ifndef MSP_GL_RENDERMODE_H_ +#define MSP_GL_RENDERMODE_H_ + +#include + +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 index 00000000..e989de4e --- /dev/null +++ b/source/select.cpp @@ -0,0 +1,47 @@ +#include +#include "select.h" + +using namespace std; + +namespace Msp { +namespace GL { + +vector *select_buf=0; +vector select_buf_int; + +void select_buffer(vector &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 &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 index 00000000..e862fe5c --- /dev/null +++ b/source/select.h @@ -0,0 +1,24 @@ +#ifndef MSP_GL_SELECT_H_ +#define MSP_GL_SELECT_H_ + +#include + +namespace Msp { +namespace GL { + +struct SelectRecord +{ + uint min_depth; + uint max_depth; + std::vector names; +}; + +void select_buffer(std::vector &); +void parse_select_records(const uint *buf, uint, std::vector &); + +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 index 00000000..8a341db3 --- /dev/null +++ b/source/texenv.h @@ -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 index 00000000..d12e18e0 --- /dev/null +++ b/source/texture.cpp @@ -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 index 00000000..7c298657 --- /dev/null +++ b/source/texture.h @@ -0,0 +1,55 @@ +#ifndef MSP_GL_TEXTURE_H_ +#define MSP_GL_TEXTURE_H_ + +#include +#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 index 00000000..e8e97592 --- /dev/null +++ b/source/texture2d.cpp @@ -0,0 +1,116 @@ +#include +#include +#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 +#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 index 00000000..adfd7deb --- /dev/null +++ b/source/types.h @@ -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 -- 2.43.0