--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include "box.h"
+#include "primitivebuilder.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+BoxBuilder::BoxBuilder(float w, float h, float d):
+ origin(-w/2, -h/2, -d/2),
+ span(w, h, d)
+{ }
+
+BoxBuilder::BoxBuilder(const Vector3 &o, const Vector3 &s):
+ origin(o),
+ span(s)
+{ }
+
+void BoxBuilder::build(PrimitiveBuilder &builder) const
+{
+ builder.normal(1, 0, 0);
+ build_face(builder, Vector3(origin.x+span.x, origin.y, origin.z), Vector3(0, span.y, 0), Vector3(0, 0, span.z));
+ builder.normal(0, 1, 0);
+ build_face(builder, Vector3(origin.x+span.x, origin.y+span.y, origin.z), Vector3(-span.x, 0, 0), Vector3(0, 0, span.z));
+ builder.normal(-1, 0, 0);
+ build_face(builder, Vector3(origin.x, origin.y+span.y, origin.z), Vector3(0, -span.y, 0), Vector3(0, 0, span.z));
+ builder.normal(0, -1, 0);
+ build_face(builder, origin, Vector3(span.x, 0, 0), Vector3(0, 0, span.z));
+ builder.normal(0, 0, 1);
+ build_face(builder, Vector3(origin.x, origin.y, origin.z+span.z), Vector3(span.x, 0, 0), Vector3(0, span.y, 0));
+ builder.normal(0, 0, -1);
+ build_face(builder, Vector3(origin.x+span.x, origin.y, origin.z), Vector3(-span.x, 0, 0), Vector3(0, span.y, 0));
+}
+
+void BoxBuilder::build_face(PrimitiveBuilder &builder, const Vector3 &o, const Vector3 &s1, const Vector3 &s2) const
+{
+ if(tangent_attr>=0)
+ {
+ builder.attrib(tangent_attr, s1.x, s1.y, s1.z);
+ builder.attrib(binormal_attr, s2.x, s2.y, s2.z);
+ }
+ float u_size = 1;
+ float v_size = 1;
+ if(tex_fit!=STRETCH)
+ {
+ float l1 = sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z);
+ float l2 = sqrt(s2.x*s2.x+s2.y*s2.y+s2.z*s2.z);
+ if((l1<l2)==(tex_fit==CUT))
+ u_size = l1/l2;
+ else
+ v_size = l2/l1;
+ }
+ builder.begin(TRIANGLE_STRIP);
+ builder.texcoord(0, v_size);
+ builder.vertex(o.x+s2.x, o.y+s2.y, o.z+s2.z);
+ builder.texcoord(0, 0);
+ builder.vertex(o.x, o.y, o.z);
+ builder.texcoord(u_size, v_size);
+ builder.vertex(o.x+s1.x+s2.x, o.y+s1.y+s2.y, o.z+s1.z+s2.z);
+ builder.texcoord(u_size, 0);
+ builder.vertex(o.x+s1.x, o.y+s1.y, o.z+s1.z);
+ builder.end();
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_BOX_H_
+#define MSP_GL_BOX_H_
+
+#include "geometrybuilder.h"
+#include "vector.h"
+
+namespace Msp {
+namespace GL {
+
+class BoxBuilder: public GeometryBuilder
+{
+private:
+ Vector3 origin;
+ Vector3 span;
+
+public:
+ BoxBuilder(float, float, float);
+ BoxBuilder(const Vector3 &, const Vector3 &);
+
+ virtual void build(PrimitiveBuilder &) const;
+private:
+ void build_face(PrimitiveBuilder &, const Vector3 &, const Vector3 &, const Vector3 &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include "capsule.h"
+#include "primitivebuilder.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+CapsuleBuilder::CapsuleBuilder(float r, float l, unsigned s, unsigned n):
+ radius(r),
+ length(l),
+ segments(s),
+ rings(n)
+{
+ if(segments<3)
+ segments = 3;
+ rings |= 1;
+ if(rings<3)
+ rings = 3;
+}
+
+void CapsuleBuilder::build(PrimitiveBuilder &builder) const
+{
+ float u_scale = 1.0/segments;
+ float v_scale = 1/(length+radius*M_PI);
+ if(tex_fit!=STRETCH)
+ {
+ float l1 = radius*M_PI*2;
+ float l2 = length+radius*M_PI;
+ if((l1<l2)==(tex_fit==CUT))
+ u_scale *= l1/l2;
+ else
+ v_scale *= l2/l1;
+ }
+
+ builder.normal(0, 0, -1);
+ builder.texcoord(0.5, 0);
+ builder.vertex(0, 0, -length/2+radius);
+ for(unsigned i=1; i<rings; ++i)
+ {
+ float cz = length*(i>rings/2 ? 0.5 : -0.5);
+ float v = (i*radius*M_PI/rings+(i>rings/2 ? length : 0))*v_scale;
+ float ra = (i>rings/2 ? i-1 : i)*M_PI/(rings-1);
+ float rc = cos(ra);
+ float rs = sin(ra);
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ float sa = j*M_PI*2/segments;
+ float sc = cos(sa);
+ float ss = sin(sa);
+ builder.normal(rs*sc, rs*ss, -rc);
+ if(tangent_attr)
+ {
+ builder.attrib(tangent_attr, -ss, sc, 0);
+ builder.attrib(binormal_attr, rc*sc, rc*ss, rs);
+ }
+ builder.texcoord(j*u_scale, v);
+ builder.vertex(rs*sc*radius, rs*ss*radius, cz-rc*radius);
+ }
+ }
+ builder.normal(0, 0, 1);
+ builder.texcoord(0.5, (length+radius*M_PI)*v_scale);
+ builder.vertex(0, 0, length/2-radius);
+
+ for(unsigned i=0; i<segments; ++i)
+ {
+ builder.begin(GL::TRIANGLE_STRIP);
+ builder.element(0);
+ for(unsigned j=0; j+1<rings; ++j)
+ {
+ builder.element(1+j*(segments+1)+i+1);
+ builder.element(1+j*(segments+1)+i);
+ }
+ builder.element((segments+1)*(rings-1)+1);
+ builder.end();
+ }
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_CAPSULE_H_
+#define MSP_GL_CAPSULE_H_
+
+#include <msp/gl/geometrybuilder.h>
+
+namespace Msp {
+namespace GL {
+
+class CapsuleBuilder: public GeometryBuilder
+{
+private:
+ float radius;
+ float length;
+ unsigned segments;
+ unsigned rings;
+
+public:
+ CapsuleBuilder(float, float, unsigned = 16, unsigned = 9);
+
+ virtual void build(PrimitiveBuilder &) const;
+};
+
+} // namepace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "geometrybuilder.h"
+#include "meshbuilder.h"
+
+namespace Msp {
+namespace GL {
+
+GeometryBuilder::GeometryBuilder():
+ tangent_attr(-1),
+ binormal_attr(-1),
+ tex_fit(STRETCH)
+{ }
+
+GeometryBuilder &GeometryBuilder::tangent(unsigned t)
+{
+ tangent_attr = t;
+ return *this;
+}
+
+GeometryBuilder &GeometryBuilder::binormal(unsigned b)
+{
+ binormal_attr = b;
+ return *this;
+}
+
+GeometryBuilder &GeometryBuilder::texture_fit(TextureFit tf)
+{
+ tex_fit = tf;
+ return *this;
+}
+
+void GeometryBuilder::build(Mesh &mesh) const
+{
+ MeshBuilder builder(mesh);
+ build(builder);
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_GEOMETRYBUILDER_H_
+#define MSP_GL_GEOMETRYBUILDER_H_
+
+namespace Msp {
+namespace GL {
+
+class Mesh;
+class PrimitiveBuilder;
+
+class GeometryBuilder
+{
+public:
+ enum TextureFit
+ {
+ STRETCH,
+ CUT,
+ WRAP
+ };
+
+protected:
+ int tangent_attr;
+ int binormal_attr;
+ TextureFit tex_fit;
+
+ GeometryBuilder();
+
+public:
+ GeometryBuilder &tangent(unsigned);
+ GeometryBuilder &binormal(unsigned);
+ GeometryBuilder &texture_fit(TextureFit);
+
+ virtual void build(PrimitiveBuilder &) const = 0;
+ void build(Mesh &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif