]> git.tdb.fi Git - libs/gl.git/blobdiff - source/capsule.cpp
Add classes for building some geometric shapes
[libs/gl.git] / source / capsule.cpp
diff --git a/source/capsule.cpp b/source/capsule.cpp
new file mode 100644 (file)
index 0000000..86f5d57
--- /dev/null
@@ -0,0 +1,88 @@
+/* $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