/* $Id$
This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2008, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
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<unsigned, Attrib>::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<unsigned, Vector4>::iterator i=texc.begin(); i!=texc.end(); ++i)
+ vab.multitexcoord(i->first, i->second);
+ for(std::map<unsigned, Vector4>::iterator i=attr.begin(); i!=attr.end(); ++i)
+ vab.attrib(i->first, i->second);
vab.vertex(x, y, z, w);
if(in_batch)
/* $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
*/
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_multitex = true;
+ if(*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");
}
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<<t;
+ found.set(t);
offset += sz;
}
- set_array(GL_VERTEX_ARRAY, found&1, 1);
- set_array(GL_NORMAL_ARRAY, found&2, 2);
- set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
- set_array(GL_COLOR_ARRAY, found&8, 8);
- for(unsigned i=4; i<32; ++i)
- set_array(i-4, (found>>i)&1, 1<<i);
+ for(unsigned i=0; i<64; ++i)
+ if(enabled_arrays.is_set(i) && !found.is_set(i))
+ {
+ if(i==0)
+ glDisableClientState(GL_VERTEX_ARRAY);
+ else if(i==1)
+ glDisableClientState(GL_NORMAL_ARRAY);
+ else if(i==2)
+ glDisableClientState(GL_COLOR_ARRAY);
+ else if(i>=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();
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<N; ++i)
+ mask[i] = 0;
}
-unsigned VertexArray::enabled_arrays = 0;
+void VertexArray::ArrayMask::set(unsigned bit)
+{
+ mask[bit/B] |= 1<<(bit%B);
+}
+
+bool VertexArray::ArrayMask::is_set(unsigned bit) const
+{
+ return mask[bit/B]&(1<<(bit%B));
+}
VertexArray::Loader::Loader(VertexArray &a):
/* $Id$
This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
#ifndef MSP_GL_VERTEXARRAY_H_
#define MSP_GL_VERTEXARRAY_H_
+#include <climits>
#include <vector>
#include <msp/core/refptr.h>
#include <msp/datafile/loader.h>
};
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<float> data;
unsigned stride;
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);
/* $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
*/
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<unsigned char>(cr*255);
- u.c[1] = static_cast<unsigned char>(cg*255);
- u.c[2] = static_cast<unsigned char>(cb*255);
- u.c[3] = static_cast<unsigned char>(ca*255);
+ u.c[0] = static_cast<unsigned char>(col.r*255);
+ u.c[1] = static_cast<unsigned char>(col.g*255);
+ u.c[2] = static_cast<unsigned char>(col.b*255);
+ u.c[3] = static_cast<unsigned char>(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;
}
}
/* $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
*/
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);
};
+++ /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)
-{ }
-
-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
/* $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
*/
#define MSP_GL_VERTEXBUILDER_H_
#include <map>
+#include "color.h"
+#include "vector.h"
namespace Msp {
namespace GL {
*/
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<unsigned, Attrib> 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<unsigned, Vector4> texc;
+ std::map<unsigned, Vector4> attr;
};
} // namespace GL
{
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);
}
}
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
throw InvalidState("VertexFormat has no components");
VertexFormat r = f;
unsigned char *c = r.data+r.data[0];
- if(*c<ATTRIB1)
- throw InvalidState("Last component is not a generic attribute");
- // VertexArray uses an unsigned to store flags for enabled arrays
- if(i>=28)
- throw InvalidParameterValue("Generic attribute index out of range");
+ if((*c<TEXCOORD1 && i>0) || (*c<ATTRIB1 && i>=8) || i>=53)
+ throw InvalidParameterValue("Vertex component index out of range");
*c += i*4;
return r;
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