From 85facfb688035b5bbc9a3a87d080582fbf34930b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 3 Sep 2007 11:39:58 +0000 Subject: [PATCH] Move VertexFormat and VertexArrayBuilder to their own files Create a generix VertexBuilder class for building vertices Add attribute binding to Program Add primitive types Add VertexArray loader Add Immediate --- source/immediate.cpp | 52 +++++++++++++++++ source/immediate.h | 44 +++++++++++++++ source/primitivetype.h | 33 +++++++++++ source/program.cpp | 5 ++ source/program.h | 1 + source/vertexarray.cpp | 103 ++++++++++------------------------ source/vertexarray.h | 63 +++++---------------- source/vertexarraybuilder.cpp | 71 +++++++++++++++++++++++ source/vertexarraybuilder.h | 38 +++++++++++++ source/vertexbuilder.cpp | 20 +++++++ source/vertexbuilder.h | 54 ++++++++++++++++++ source/vertexformat.cpp | 69 +++++++++++++++++++++++ source/vertexformat.h | 40 +++++++++++++ 13 files changed, 470 insertions(+), 123 deletions(-) create mode 100644 source/immediate.cpp create mode 100644 source/immediate.h create mode 100644 source/primitivetype.h create mode 100644 source/vertexarraybuilder.cpp create mode 100644 source/vertexarraybuilder.h create mode 100644 source/vertexbuilder.cpp create mode 100644 source/vertexbuilder.h create mode 100644 source/vertexformat.cpp create mode 100644 source/vertexformat.h diff --git a/source/immediate.cpp b/source/immediate.cpp new file mode 100644 index 00000000..f3413974 --- /dev/null +++ b/source/immediate.cpp @@ -0,0 +1,52 @@ +/* $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 diff --git a/source/immediate.h b/source/immediate.h new file mode 100644 index 00000000..b979973c --- /dev/null +++ b/source/immediate.h @@ -0,0 +1,44 @@ +/* $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 builder; + PrimitiveType type; + bool in_batch; + unsigned n_vertices; + + virtual void vertex_(float, float, float, float); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/primitivetype.h b/source/primitivetype.h new file mode 100644 index 00000000..459c18e7 --- /dev/null +++ b/source/primitivetype.h @@ -0,0 +1,33 @@ +/* $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 + +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 diff --git a/source/program.cpp b/source/program.cpp index b7f8577d..1d08270f 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -43,6 +43,11 @@ void Program::detach_shader(Shader &shader) } } +void Program::bind_attribute(int index, const string &name) +{ + glBindAttribLocation(id, index, name.c_str()); +} + bool Program::link() { for(list::iterator i=shaders.begin(); i!=shaders.end(); ++i) diff --git a/source/program.h b/source/program.h index 5b1ae29f..a77a70d7 100644 --- a/source/program.h +++ b/source/program.h @@ -27,6 +27,7 @@ public: 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; diff --git a/source/vertexarray.cpp b/source/vertexarray.cpp index 3c94b4cf..e7d73865 100644 --- a/source/vertexarray.cpp +++ b/source/vertexarray.cpp @@ -14,85 +14,13 @@ using namespace std; 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 &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 "<>=4) format=(format, static_cast(fmt&15)); } @@ -125,6 +53,20 @@ void VertexArray::clear() data.clear(); } +void VertexArray::reset(VertexFormat f) +{ + clear(); + format=NODATA; + for(uint fmt=f; fmt; fmt>>=4) + format=(format, static_cast(fmt&15)); + stride=get_stride(format); +} + +RefPtr VertexArray::modify() +{ + return new VertexArrayBuilder(*this, data); +} + void VertexArray::apply() const { if(vbuf) vbuf->bind(); @@ -191,5 +133,20 @@ void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const unsigned VertexArray::enabled_arrays=0; +VertexArray::Loader::Loader(VertexArray &a): + VertexArrayBuilder(a, a.data) +{ + add("vertex2", static_cast(&Loader::vertex)); + add("vertex3", static_cast(&Loader::vertex)); + add("vertex4", static_cast(&Loader::vertex)); + add("normal3", static_cast(&Loader::normal)); + add("texcoord1", static_cast(&Loader::texcoord)); + add("texcoord2", static_cast(&Loader::texcoord)); + add("texcoord3", static_cast(&Loader::texcoord)); + add("texcoord4", static_cast(&Loader::texcoord)); + add("color3", static_cast(&Loader::color)); + add("color4", static_cast(&Loader::color)); +} + } // namespace GL } // namespace Msp diff --git a/source/vertexarray.h b/source/vertexarray.h index 52b88882..9610905d 100644 --- a/source/vertexarray.h +++ b/source/vertexarray.h @@ -10,65 +10,25 @@ Distributed under the LGPL #include #include +#include #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 &data; - - VertexArrayBuilder(VertexArray &, std::vector &); - 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(); @@ -77,7 +37,8 @@ public: void use_vertex_buffer(); void use_vertex_buffer(VertexBuffer *); void clear(); - RefPtr modify() { return new VertexArrayBuilder(*this, data); } + void reset(VertexFormat); + RefPtr modify(); void apply() const; void update_data(); private: @@ -87,6 +48,8 @@ private: VertexBuffer *vbuf; bool own_vbuf; + VertexArray(const VertexArray &); + VertexArray &operator=(const VertexArray &); void set_array(unsigned, unsigned, unsigned) const; static unsigned enabled_arrays; diff --git a/source/vertexarraybuilder.cpp b/source/vertexarraybuilder.cpp new file mode 100644 index 00000000..5f469a98 --- /dev/null +++ b/source/vertexarraybuilder.cpp @@ -0,0 +1,71 @@ +/* $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 &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 diff --git a/source/vertexarraybuilder.h b/source/vertexarraybuilder.h new file mode 100644 index 00000000..54357677 --- /dev/null +++ b/source/vertexarraybuilder.h @@ -0,0 +1,38 @@ +/* $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 +#include "vertexbuilder.h" +#include "vertexformat.h" + +namespace Msp { +namespace GL { + +class VertexArray; + +class VertexArrayBuilder: public VertexBuilder +{ +public: + std::vector &data; + + VertexArrayBuilder(VertexArray &, std::vector &); + ~VertexArrayBuilder(); + +private: + VertexArray &array; + + VertexArrayBuilder(const VertexArrayBuilder &); + virtual void vertex_(float, float, float, float); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/vertexbuilder.cpp b/source/vertexbuilder.cpp new file mode 100644 index 00000000..0b1d3f30 --- /dev/null +++ b/source/vertexbuilder.cpp @@ -0,0 +1,20 @@ +/* $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 diff --git a/source/vertexbuilder.h b/source/vertexbuilder.h new file mode 100644 index 00000000..1b2d02d1 --- /dev/null +++ b/source/vertexbuilder.h @@ -0,0 +1,54 @@ +/* $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 diff --git a/source/vertexformat.cpp b/source/vertexformat.cpp new file mode 100644 index 00000000..25c2b023 --- /dev/null +++ b/source/vertexformat.cpp @@ -0,0 +1,69 @@ +/* $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 diff --git a/source/vertexformat.h b/source/vertexformat.h new file mode 100644 index 00000000..3a0eb718 --- /dev/null +++ b/source/vertexformat.h @@ -0,0 +1,40 @@ +/* $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 +#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 -- 2.45.2