From: Mikko Rasa Date: Thu, 15 Jul 2010 11:21:23 +0000 (+0000) Subject: Support multiple sets of texture coordinates in VertexArrays X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=4443707c752ab8ee288f1c22be08cf82f27439d7;p=libs%2Fgl.git Support multiple sets of texture coordinates in VertexArrays Allow more generic vertex attributes Fix memory allocation bug when copying VertexFormats Refactor the internals of VertexBuilder Add overloads of VertexBuilder functions that take Vector* or Color --- diff --git a/source/primitivebuilder.cpp b/source/primitivebuilder.cpp index e032a441..22106a34 100644 --- a/source/primitivebuilder.cpp +++ b/source/primitivebuilder.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2008, 2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -55,11 +55,12 @@ PrimitiveType PrimitiveBuilder::get_type() const void PrimitiveBuilder::vertex_(float x, float y, float z, float w) { - vab.texcoord(ts, tt, tr, tq); - vab.color(cr, cg, cb, ca); - vab.normal(nx, ny, nz); - for(std::map::iterator i=av.begin(); i!=av.end(); ++i) - vab.attrib(i->first, i->second.x, i->second.y, i->second.z, i->second.w); + vab.color(col); + vab.normal(nor); + for(std::map::iterator i=texc.begin(); i!=texc.end(); ++i) + vab.multitexcoord(i->first, i->second); + for(std::map::iterator i=attr.begin(); i!=attr.end(); ++i) + vab.attrib(i->first, i->second); vab.vertex(x, y, z, w); if(in_batch) diff --git a/source/vertexarray.cpp b/source/vertexarray.cpp index 8381d8ad..6d669902 100644 --- a/source/vertexarray.cpp +++ b/source/vertexarray.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -67,9 +67,17 @@ void VertexArray::reset(const VertexFormat &f) format = f; stride = get_stride(format); + bool has_multitex = false; bool has_gen_attrs = false; - for(const unsigned char *c=format.begin(); (!has_gen_attrs && c!=format.end()); ++c) - has_gen_attrs = (*c>=ATTRIB1); + for(const unsigned char *c=format.begin(); c!=format.end(); ++c) + { + if(*c>=TEXCOORD1+4 && *c=ATTRIB1) + has_gen_attrs = true; + } + if(has_multitex) + static RequireVersion _ver(1, 3); if(has_gen_attrs) static RequireExtension _ext("GL_ARB_vertex_program"); } @@ -84,43 +92,81 @@ void VertexArray::apply() const const float *base = vbuf?0:&data[0]; unsigned offset = 0; - unsigned found = 0; + ArrayMask found; unsigned bpv = stride*sizeof(float); + unsigned active_tex = 0; for(const unsigned char *c=format.begin(); c!=format.end(); ++c) { unsigned sz = (*c&3)+1; unsigned t = *c>>2; + bool en = enabled_arrays.is_set(t); switch(t) { case 0: glVertexPointer(sz, GL_FLOAT, bpv, base+offset); + if(!en) + glEnableClientState(GL_VERTEX_ARRAY); break; case 1: glNormalPointer(GL_FLOAT, bpv, base+offset); + if(!en) + glEnableClientState(GL_NORMAL_ARRAY); break; case 2: - glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset); - break; - case 3: if(sz==1) glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset); else glColorPointer(sz, GL_FLOAT, bpv, base+offset); + if(!en) + glEnableClientState(GL_COLOR_ARRAY); break; default: - glVertexAttribPointerARB(t-4, sz, GL_FLOAT, false, bpv, base+offset); + if(t<11) + { + if(t>3 || active_tex) + { + glClientActiveTexture(GL_TEXTURE0+(t-3)); + active_tex = t-3; + } + glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset); + if(!en) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + glVertexAttribPointerARB(t-11, sz, GL_FLOAT, false, bpv, base+offset); + if(!en) + glEnableVertexAttribArrayARB(t-11); + } break; } - found |= 1<>i)&1, 1<=3 && i<11) + { + if(i>3 || active_tex) + glClientActiveTexture(GL_TEXTURE0+(i-3)); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + glDisableVertexAttribArrayARB(i-11); + } + + enabled_arrays = found; + + if(active_tex) + glClientActiveTexture(GL_TEXTURE0); if(vbuf) vbuf->unbind(); @@ -144,27 +190,24 @@ float *VertexArray::append() return &*data.end()-stride; } -void VertexArray::set_array(unsigned array, bool en, unsigned mask) const +VertexArray::ArrayMask VertexArray::enabled_arrays; + + +VertexArray::ArrayMask::ArrayMask() { - if((enabled_arrays&mask) && !en) - { - if(mask<16) - glDisableClientState(array); - else - glDisableVertexAttribArrayARB(array); - enabled_arrays &= ~mask; - } - else if(!(enabled_arrays&mask) && en) - { - if(mask<16) - glEnableClientState(array); - else - glEnableVertexAttribArrayARB(array); - enabled_arrays |= mask; - } + for(unsigned i=0; i #include #include #include @@ -31,6 +32,22 @@ public: }; private: + struct ArrayMask + { + enum + { + B = (sizeof(unsigned)*CHAR_BIT), + N = (63+B)/B + }; + + unsigned mask[N]; + + ArrayMask(); + + void set(unsigned); + bool is_set(unsigned) const; + }; + VertexFormat format; std::vector data; unsigned stride; @@ -56,10 +73,9 @@ public: float *append(); float *operator[](unsigned i) { return &data[0]+i*stride; } const float *operator[](unsigned i) const { return &data[0]+i*stride; } -private: - void set_array(unsigned, bool, unsigned) const; - static unsigned enabled_arrays; +private: + static ArrayMask enabled_arrays; }; void array_element(int); diff --git a/source/vertexarraybuilder.cpp b/source/vertexarraybuilder.cpp index 70d1ee58..5c0a0196 100644 --- a/source/vertexarraybuilder.cpp +++ b/source/vertexarraybuilder.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -25,51 +25,45 @@ void VertexArrayBuilder::vertex_(float x, float y, float z, float w) float *ptr = array.append(); for(const unsigned char *c=array.get_format().begin(); c!=array.get_format().end(); ++c) { - unsigned size = (*c&3)+1; - unsigned type = *c>>2; - switch(type) + unsigned sz = (*c&3)+1; + unsigned t = *c>>2; + switch(t) { case 0: *ptr++ = x; *ptr++ = y; - if(size>=3) *ptr++ = z; - if(size>=4) *ptr++ = w; + if(sz>=3) *ptr++ = z; + if(sz>=4) *ptr++ = w; break; case 1: - *ptr++ = nx; - *ptr++ = ny; - *ptr++ = nz; + *ptr++ = nor.x; + *ptr++ = nor.y; + *ptr++ = nor.z; break; case 2: - *ptr++ = ts; - if(size>=2) *ptr++ = tt; - if(size>=3) *ptr++ = tr; - if(size>=4) *ptr++ = tq; - break; - case 3: - if(size==1) + if(sz==1) { union { unsigned char c[4]; float f; } u; - u.c[0] = static_cast(cr*255); - u.c[1] = static_cast(cg*255); - u.c[2] = static_cast(cb*255); - u.c[3] = static_cast(ca*255); + u.c[0] = static_cast(col.r*255); + u.c[1] = static_cast(col.g*255); + u.c[2] = static_cast(col.b*255); + u.c[3] = static_cast(col.a*255); *ptr++ = u.f; } else { - *ptr++ = cr; - *ptr++ = cg; - *ptr++ = cb; - if(size>=4) *ptr++ = ca; + *ptr++ = col.r; + *ptr++ = col.g; + *ptr++ = col.b; + if(sz>=4) *ptr++ = col.a; } break; default: - const Attrib &a = av[type-4]; + const Vector4 &a = (t<11 ? texc[t-3] : attr[t-11]); *ptr++ = a.x; - if(size>=2) *ptr++ = a.y; - if(size>=3) *ptr++ = a.z; - if(size>=4) *ptr++ = a.w; + if(sz>=2) *ptr++ = a.y; + if(sz>=3) *ptr++ = a.z; + if(sz>=4) *ptr++ = a.w; break; } } diff --git a/source/vertexarraybuilder.h b/source/vertexarraybuilder.h index 0065c536..3b1f8216 100644 --- a/source/vertexarraybuilder.h +++ b/source/vertexarraybuilder.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2008, 2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -19,14 +19,15 @@ class VertexArray; class VertexArrayBuilder: public VertexBuilder { +private: + VertexArray &array; + + VertexArrayBuilder(const VertexArrayBuilder &); public: VertexArrayBuilder(VertexArray &); ~VertexArrayBuilder(); private: - VertexArray &array; - - VertexArrayBuilder(const VertexArrayBuilder &); virtual void vertex_(float, float, float, float); }; diff --git a/source/vertexbuilder.cpp b/source/vertexbuilder.cpp deleted file mode 100644 index 3d3ec79b..00000000 --- a/source/vertexbuilder.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* $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) -{ } - -void VertexBuilder::attrib(unsigned i, float x, float y, float z, float w) -{ - Attrib &a = av[i]; - a.x = x; - a.y = y; - a.z = z; - a.w = w; -} - -} // namespace GL -} // namespace Msp diff --git a/source/vertexbuilder.h b/source/vertexbuilder.h index 8235c7af..e7f9b132 100644 --- a/source/vertexbuilder.h +++ b/source/vertexbuilder.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -9,6 +9,8 @@ Distributed under the LGPL #define MSP_GL_VERTEXBUILDER_H_ #include +#include "color.h" +#include "vector.h" namespace Msp { namespace GL { @@ -24,39 +26,98 @@ data. Attributes can be read from protected member variables. */ class VertexBuilder { -protected: - struct Attrib - { - float x, y, z, w; - }; - public: - VertexBuilder(); + VertexBuilder(): nor(0, 0, 1) { } + 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(unsigned char r, unsigned char g, unsigned char b) { color(r, g, b, 255); } - void color(unsigned char r, unsigned char g, unsigned char b, unsigned char 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; } - void attrib(unsigned i, float x) { attrib(i, x, 0, 0, 1); } - void attrib(unsigned i, float x, float y) { attrib(i, x, y, 0, 1); } - void attrib(unsigned i, float x, float y, float z) { attrib(i, x, y, z, 1); } - void attrib(unsigned i, float x, float y, float z, float w); + 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 vertex(const Vector4 &v) + { vertex(v.x, v.y, v.z, v.w); } + protected: - float cr, cg, cb, ca; // Color - float ts, tt, tr, tq; // TexCoord - float nx, ny, nz; // Normal - std::map av; + virtual void vertex_(float x, float y, float z, float w) =0; + +public: + void normal(float x, float y, float z) + { normal(Vector3(x, y, z)); } + + void normal(const Vector3 &n) + { nor = n; } + + 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) + { texcoord(Vector4(s, t, r, q)); } + + void texcoord(const Vector4 &t) + { multitexcoord(0, t); } + + void multitexcoord(unsigned i, float s) + { multitexcoord(i, s, 0, 0, 1); } - virtual void vertex_(float, float, float, float) =0; + void multitexcoord(unsigned i, float s, float t) + { multitexcoord(i, s, t, 0, 1); } + + void multitexcoord(unsigned i, float s, float t, float r) + { multitexcoord(i, s, t, r, 1); } + + void multitexcoord(unsigned i, float s, float t, float r, float q) + { multitexcoord(i, Vector4(s, t, r, q)); } + + void multitexcoord(unsigned i, const Vector4 &t) + { texc[i] = t; } + + void color(unsigned char r, unsigned char g, unsigned char b) + { color(r, g, b, 255); } + + void color(unsigned char r, unsigned char g, unsigned char b, unsigned char 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) + { color(Color(r, g, b, a)); } + + void color(const Color &c) + { col = c; } + + void attrib(unsigned i, float x) + { attrib(i, x, 0, 0, 1); } + + void attrib(unsigned i, float x, float y) + { attrib(i, x, y, 0, 1); } + + void attrib(unsigned i, float x, float y, float z) + { attrib(i, x, y, z, 1); } + + void attrib(unsigned i, float x, float y, float z, float w) + { attrib(i, Vector4(x, y, z, w)); } + + void attrib(unsigned i, const Vector4 &a) + { attr[i] = a; } + +protected: + Vector3 nor; + Color col; + std::map texc; + std::map attr; }; } // namespace GL diff --git a/source/vertexformat.cpp b/source/vertexformat.cpp index e56397e2..dc8ff23e 100644 --- a/source/vertexformat.cpp +++ b/source/vertexformat.cpp @@ -31,7 +31,7 @@ VertexFormat::VertexFormat(const VertexFormat &f): { if(f.data) { - data = new unsigned char[f.data[0]/8+8]; + data = new unsigned char[(f.data[0]&~7)+8]; memcpy(data, f.data, f.data[0]+1); } } @@ -41,7 +41,7 @@ VertexFormat &VertexFormat::operator=(const VertexFormat &f) delete[] data; if(f.data) { - data = new unsigned char[f.data[0]/8+8]; + data = new unsigned char[(f.data[0]&~7)+8]; memcpy(data, f.data, f.data[0]+1); } else @@ -94,11 +94,8 @@ VertexFormat operator,(const VertexFormat &f, unsigned i) throw InvalidState("VertexFormat has no components"); VertexFormat r = f; unsigned char *c = r.data+r.data[0]; - if(*c=28) - throw InvalidParameterValue("Generic attribute index out of range"); + if((*c0) || (*c=8) || i>=53) + throw InvalidParameterValue("Vertex component index out of range"); *c += i*4; return r; diff --git a/source/vertexformat.h b/source/vertexformat.h index 3e36c18f..4dc780b2 100644 --- a/source/vertexformat.h +++ b/source/vertexformat.h @@ -19,14 +19,14 @@ enum VertexComponent VERTEX3, VERTEX4, NORMAL3 = 6, - TEXCOORD1 = 8, + COLOR4_UBYTE = 8, + COLOR3_FLOAT = 10, + COLOR4_FLOAT, + TEXCOORD1 = 12, TEXCOORD2, TEXCOORD3, TEXCOORD4, - COLOR4_UBYTE = 12, - COLOR3_FLOAT = 14, - COLOR4_FLOAT, - ATTRIB1 = 16, + ATTRIB1 = 44, ATTRIB2, ATTRIB3, ATTRIB4