--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "immediate.h"
+
+namespace Msp {
+namespace GL {
+
+Immediate::Immediate(VertexFormat f):
+ array(f),
+ in_batch(false),
+ n_vertices(0)
+{ }
+
+void Immediate::begin(PrimitiveType t)
+{
+ type=t;
+ in_batch=true;
+ n_vertices=0;
+ builder=array.modify();
+}
+
+void Immediate::end()
+{
+ builder=0;
+
+ array.apply();
+ glDrawArrays(type, 0, n_vertices);
+
+ array.clear();
+ in_batch=false;
+}
+
+void Immediate::vertex_(float x, float y, float z, float w)
+{
+ if(!in_batch)
+ throw InvalidState("Vertex specification not between begin and end");
+
+ builder->texcoord(ts, tt, tr,tq);
+ builder->color(cr, cg, cb, ca);
+ builder->normal(nx, ny, nz);
+ builder->vertex(x, y, z, w);
+
+ ++n_vertices;
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_IMMEDIATE_H_
+#define MSP_GL_IMMEDIATE_H_
+
+#include "primitivetype.h"
+#include "vertexarray.h"
+#include "vertexbuilder.h"
+
+namespace Msp {
+namespace GL {
+
+/**
+Draws primitives on the screen. This works similarly to the OpenGL immediate
+mode: call begin() to start a batch of primitives, specify vertices, and call
+end() to terminate the batch. However, unlike OpenGL immediate mode, vertices
+are not drawn as they are specified. Instead, they are accumulated in a
+VertexArray and drawn when end() is called.
+*/
+class Immediate: public VertexBuilder
+{
+public:
+ Immediate(VertexFormat);
+ void begin(PrimitiveType);
+ void end();
+private:
+ VertexArray array;
+ RefPtr<VertexArrayBuilder> builder;
+ PrimitiveType type;
+ bool in_batch;
+ unsigned n_vertices;
+
+ virtual void vertex_(float, float, float, float);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_PRIMITIVETYPE_H_
+#define MSP_GL_PRIMITIVETYPE_H_
+
+#include <GL/gl.h>
+
+namespace Msp {
+namespace GL {
+
+enum PrimitiveType
+{
+ POINTS = GL_POINTS,
+ LINES = GL_LINES,
+ LINE_STRIP = GL_LINE_STRIP,
+ LINE_LOOP = GL_LINE_LOOP,
+ TRIANGLES = GL_TRIANGLES,
+ TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
+ TRIANGLE_FAN = GL_TRIANGLE_FAN,
+ QUADS = GL_QUADS,
+ QUAD = GL_QUAD_STRIP,
+ POLYGON = GL_POLYGON
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
}
}
+void Program::bind_attribute(int index, const string &name)
+{
+ glBindAttribLocation(id, index, name.c_str());
+}
+
bool Program::link()
{
for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
void attach_shader(Shader &shader);
void detach_shader(Shader &shader);
+ void bind_attribute(int, const std::string &);
bool link();
int get_param(GLenum param) const;
std::string get_info_log() const;
namespace Msp {
namespace GL {
-uint get_stride(VertexFormat f)
-{
- uint stride=0;
- for(uint fmt=f; fmt; fmt>>=4)
- stride+=(fmt&3)+1;
- return stride*sizeof(float);
-}
-
-
-VertexArrayBuilder::VertexArrayBuilder(VertexArray &a, vector<float> &d):
- data(d),
- array(a),
- format(array.get_format()),
- stride(get_stride(format)),
- cr(1), cg(1), cb(1), ca(1),
- ts(0), tt(0), tr(0), tq(0),
- nx(0), ny(0), nz(1)
-{ }
-
-void VertexArrayBuilder::vertex(float x, float y, float z, float w)
-{
- for(uint fmt=format; fmt; fmt>>=4)
- {
- uint size=(fmt&3)+1;
- switch(fmt&12)
- {
- case 0:
- data.push_back(x);
- data.push_back(y);
- if(size>=3) data.push_back(z);
- if(size>=4) data.push_back(w);
- break;
- case 4:
- data.push_back(nx);
- data.push_back(ny);
- data.push_back(nz);
- break;
- case 8:
- data.push_back(ts);
- if(size>=2) data.push_back(tt);
- if(size>=3) data.push_back(tr);
- if(size>=4) data.push_back(tq);
- break;
- case 12:
- if(size==1)
- {
- union { ubyte c[4]; float f; } u;
- u.c[0]=(ubyte)(cr*255);
- u.c[1]=(ubyte)(cg*255);
- u.c[2]=(ubyte)(cb*255);
- u.c[3]=(ubyte)(ca*255);
- data.push_back(u.f);
- }
- else
- {
- data.push_back(cr);
- data.push_back(cg);
- data.push_back(cb);
- if(size>=4) data.push_back(ca);
- }
- break;
- }
- }
- //cout<<"Added vertex with "<<data.size()-old_size<<" floats\n";
-}
-
-VertexArrayBuilder::~VertexArrayBuilder()
-{
- array.update_data();
-}
-
-
VertexArray::VertexArray(VertexFormat f):
format(NODATA),
stride(get_stride(f)),
vbuf(0),
own_vbuf(false)
{
- // Reverse the format so the first item is in lowest bits
+ // Reverse the format so the first item is in lowest bits. This makes handling in bind() easier.
for(uint fmt=f; fmt; fmt>>=4)
format=(format, static_cast<VertexFormat>(fmt&15));
}
data.clear();
}
+void VertexArray::reset(VertexFormat f)
+{
+ clear();
+ format=NODATA;
+ for(uint fmt=f; fmt; fmt>>=4)
+ format=(format, static_cast<VertexFormat>(fmt&15));
+ stride=get_stride(format);
+}
+
+RefPtr<VertexArrayBuilder> VertexArray::modify()
+{
+ return new VertexArrayBuilder(*this, data);
+}
+
void VertexArray::apply() const
{
if(vbuf) vbuf->bind();
unsigned VertexArray::enabled_arrays=0;
+VertexArray::Loader::Loader(VertexArray &a):
+ VertexArrayBuilder(a, a.data)
+{
+ add("vertex2", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
+ add("vertex3", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
+ add("vertex4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
+ add("normal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
+ add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
+ add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
+ add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
+ add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
+ add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
+ add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
+}
+
} // namespace GL
} // namespace Msp
#include <vector>
#include <msp/core/refptr.h>
+#include <msp/datafile/loader.h>
#include "types.h"
+#include "vertexarraybuilder.h"
+#include "vertexformat.h"
namespace Msp {
namespace GL {
-class VertexArray;
class VertexBuffer;
-enum VertexFormat
-{
- NODATA=0,
- VERTEX2=1,
- VERTEX3,
- VERTEX4,
- NORMAL3=6,
- TEXCOORD1=8,
- TEXCOORD2,
- TEXCOORD3,
- TEXCOORD4,
- COLOR4_UBYTE=12,
- COLOR3_FLOAT=14,
- COLOR4_FLOAT,
-};
-
-inline VertexFormat operator,(VertexFormat a, VertexFormat b) { return VertexFormat((a<<4)|b); }
-uint get_stride(VertexFormat);
-
-class VertexArrayBuilder
-{
-public:
- std::vector<float> &data;
-
- VertexArrayBuilder(VertexArray &, std::vector<float> &);
- void vertex(float x, float y) { vertex(x, y, 0, 1); }
- void vertex(float x, float y, float z) { vertex(x, y, z, 1); }
- void vertex(float, float, float, float);
- void normal(float x, float y, float z) { nx=x; ny=y; nz=z; }
- void texcoord(float s) { texcoord(s, 0, 0, 1); }
- void texcoord(float s, float t) { texcoord(s, t, 0, 1); }
- void texcoord(float s, float t, float r) { texcoord(s, t, r, 1); }
- void texcoord(float s, float t, float r, float q) { ts=s; tt=t; tr=r; tq=q; }
- void color(ubyte r, ubyte g, ubyte b) { color(r, g, b, 255); }
- void color(ubyte r, ubyte g, ubyte b, ubyte a) { color(r/255.f, g/255.f, b/255.f, a/255.f); }
- void color(float r, float g, float b) { color(r, g, b, 1); }
- void color(float r, float g, float b, float a) { cr=r; cg=g; cb=b; ca=a; }
- ~VertexArrayBuilder();
-private:
- VertexArray &array;
- VertexFormat format;
- uint stride;
-
- float cr, cg, cb, ca; // Color
- float ts, tt, tr, tq; // TexCoord
- float nx, ny, nz; // Normal
-};
-
class VertexArray
{
public:
+ class Loader: public DataFile::Loader, public VertexArrayBuilder
+ {
+ public:
+ Loader(VertexArray &);
+ };
+
VertexArray(VertexFormat);
~VertexArray();
void use_vertex_buffer();
void use_vertex_buffer(VertexBuffer *);
void clear();
- RefPtr<VertexArrayBuilder> modify() { return new VertexArrayBuilder(*this, data); }
+ void reset(VertexFormat);
+ RefPtr<VertexArrayBuilder> modify();
void apply() const;
void update_data();
private:
VertexBuffer *vbuf;
bool own_vbuf;
+ VertexArray(const VertexArray &);
+ VertexArray &operator=(const VertexArray &);
void set_array(unsigned, unsigned, unsigned) const;
static unsigned enabled_arrays;
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "vertexarray.h"
+#include "vertexarraybuilder.h"
+
+namespace Msp {
+namespace GL {
+
+VertexArrayBuilder::VertexArrayBuilder(VertexArray &a, std::vector<float> &d):
+ data(d),
+ array(a)
+{ }
+
+VertexArrayBuilder::~VertexArrayBuilder()
+{
+ array.update_data();
+}
+
+void VertexArrayBuilder::vertex_(float x, float y, float z, float w)
+{
+ for(uint fmt=array.get_format(); fmt; fmt>>=4)
+ {
+ uint size=(fmt&3)+1;
+ switch(fmt&12)
+ {
+ case 0:
+ data.push_back(x);
+ data.push_back(y);
+ if(size>=3) data.push_back(z);
+ if(size>=4) data.push_back(w);
+ break;
+ case 4:
+ data.push_back(nx);
+ data.push_back(ny);
+ data.push_back(nz);
+ break;
+ case 8:
+ data.push_back(ts);
+ if(size>=2) data.push_back(tt);
+ if(size>=3) data.push_back(tr);
+ if(size>=4) data.push_back(tq);
+ break;
+ case 12:
+ if(size==1)
+ {
+ union { ubyte c[4]; float f; } u;
+ u.c[0]=(ubyte)(cr*255);
+ u.c[1]=(ubyte)(cg*255);
+ u.c[2]=(ubyte)(cb*255);
+ u.c[3]=(ubyte)(ca*255);
+ data.push_back(u.f);
+ }
+ else
+ {
+ data.push_back(cr);
+ data.push_back(cg);
+ data.push_back(cb);
+ if(size>=4) data.push_back(ca);
+ }
+ break;
+ }
+ }
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_VERTEXARRAYBUIDER_H_
+#define MSP_GL_VERTEXARRAYBUIDER_H_
+
+#include <vector>
+#include "vertexbuilder.h"
+#include "vertexformat.h"
+
+namespace Msp {
+namespace GL {
+
+class VertexArray;
+
+class VertexArrayBuilder: public VertexBuilder
+{
+public:
+ std::vector<float> &data;
+
+ VertexArrayBuilder(VertexArray &, std::vector<float> &);
+ ~VertexArrayBuilder();
+
+private:
+ VertexArray &array;
+
+ VertexArrayBuilder(const VertexArrayBuilder &);
+ virtual void vertex_(float, float, float, float);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "vertexbuilder.h"
+
+namespace Msp {
+namespace GL {
+
+VertexBuilder::VertexBuilder():
+ cr(1), cg(1), cb(1), ca(1),
+ ts(0), tt(0), tr(0), tq(0),
+ nx(0), ny(0), nz(1)
+{ }
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_VERTEXBUILDER_H_
+#define MSP_GL_VERTEXBUILDER_H_
+
+#include "types.h"
+
+namespace Msp {
+namespace GL {
+
+/**
+Base class for classes that build vertices from a series of function calls.
+The operating model closely follows that of OpenGL immediate mode: vertex
+attributes can be specified at any time, and when a vertex() function is
+called, a vertex is created with the active attribute values.
+
+A derived class must overload the 4-argument vertex_() function to process the
+data. Attributes can be read from protected member variables.
+*/
+class VertexBuilder
+{
+public:
+ VertexBuilder();
+ virtual ~VertexBuilder() { }
+
+ void vertex(float x, float y) { vertex(x, y, 0, 1); }
+ void vertex(float x, float y, float z) { vertex(x, y, z, 1); }
+ void vertex(float x, float y, float z, float w) { vertex_(x, y, z, w); }
+ void normal(float x, float y, float z) { nx=x; ny=y; nz=z; }
+ void texcoord(float s) { texcoord(s, 0, 0, 1); }
+ void texcoord(float s, float t) { texcoord(s, t, 0, 1); }
+ void texcoord(float s, float t, float r) { texcoord(s, t, r, 1); }
+ void texcoord(float s, float t, float r, float q) { ts=s; tt=t; tr=r; tq=q; }
+ void color(ubyte r, ubyte g, ubyte b) { color(r, g, b, 255); }
+ void color(ubyte r, ubyte g, ubyte b, ubyte a) { color(r/255.f, g/255.f, b/255.f, a/255.f); }
+ void color(float r, float g, float b) { color(r, g, b, 1); }
+ void color(float r, float g, float b, float a) { cr=r; cg=g; cb=b; ca=a; }
+protected:
+ float cr, cg, cb, ca; // Color
+ float ts, tt, tr, tq; // TexCoord
+ float nx, ny, nz; // Normal
+
+ virtual void vertex_(float, float, float, float) =0;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "vertexformat.h"
+
+namespace Msp {
+namespace GL {
+
+uint get_stride(VertexFormat f)
+{
+ uint stride=0;
+ for(uint fmt=f; fmt; fmt>>=4)
+ stride+=(fmt&3)+1;
+ return stride*sizeof(float);
+}
+
+std::istream &operator>>(std::istream &in, VertexFormat &f)
+{
+ std::string str;
+ in>>str;
+
+ unsigned start=0;
+ unsigned comma;
+ f=NODATA;
+
+ while(1)
+ {
+ comma=str.find(',', start);
+ if(str.compare(start, comma-start, "VERTEX2"))
+ f=f,VERTEX2;
+ else if(str.compare(start, comma-start, "VERTEX3"))
+ f=f,VERTEX3;
+ else if(str.compare(start, comma-start, "VERTEX4"))
+ f=f,VERTEX4;
+ else if(str.compare(start, comma-start, "NORMAL3"))
+ f=f,NORMAL3;
+ else if(str.compare(start, comma-start, "TEXCOORD1"))
+ f=f,TEXCOORD1;
+ else if(str.compare(start, comma-start, "TEXCOORD2"))
+ f=f,TEXCOORD2;
+ else if(str.compare(start, comma-start, "TEXCOORD3"))
+ f=f,TEXCOORD3;
+ else if(str.compare(start, comma-start, "TEXCOORD4"))
+ f=f,TEXCOORD4;
+ else if(str.compare(start, comma-start, "COLOR4_UBYTE"))
+ f=f,COLOR4_UBYTE;
+ else if(str.compare(start, comma-start, "COLOR3_FLOAT"))
+ f=f,COLOR3_FLOAT;
+ else if(str.compare(start, comma-start, "COLOR4_FLOAT"))
+ f=f,COLOR4_FLOAT;
+ else
+ {
+ in.setstate(std::ios_base::failbit);
+ break;
+ }
+ start=comma+1;
+ if(comma==std::string::npos)
+ break;
+ }
+
+ return in;
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_VERTEXFORMAT_H_
+#define MSP_GL_VERTEXFORMAT_H_
+
+#include <istream>
+#include "types.h"
+
+namespace Msp {
+namespace GL {
+
+enum VertexFormat
+{
+ NODATA=0,
+ VERTEX2=1,
+ VERTEX3,
+ VERTEX4,
+ NORMAL3=6,
+ TEXCOORD1=8,
+ TEXCOORD2,
+ TEXCOORD3,
+ TEXCOORD4,
+ COLOR4_UBYTE=12,
+ COLOR3_FLOAT=14,
+ COLOR4_FLOAT,
+};
+
+inline VertexFormat operator,(VertexFormat a, VertexFormat b) { return VertexFormat(a<<4 | b); }
+uint get_stride(VertexFormat);
+std::istream &operator>>(std::istream &, VertexFormat &);
+
+} // namespace GL
+} // namespace Msp
+
+#endif