--- /dev/null
+#define _USE_MATH_DEFINES
+#include <cmath>
+#include "cylinder.h"
+#include "primitivebuilder.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+CylinderBuilder::CylinderBuilder(float r, float l, unsigned s):
+ radius(r),
+ length(l),
+ segments(s)
+{
+ if(segments<3)
+ segments = 3;
+}
+
+void CylinderBuilder::build(PrimitiveBuilder &builder) const
+{
+ if(generate_tbn)
+ builder.binormal(0, 1, 0);
+ for(unsigned i=0; i<2; ++i)
+ {
+ float z = (i-0.5)*length;
+ builder.normal(0, 0, i*2.0-1.0);
+ builder.texcoord(0.5, 0.5);
+ if(generate_tbn)
+ builder.tangent((i ? 1 : -1), 0, 0);
+ builder.vertex(0, 0, z);
+ for(unsigned j=0; j<segments; ++j)
+ {
+ float a = j*M_PI*2/segments;
+ float c = cos(a);
+ float s = sin(a);
+ builder.texcoord(0.5+(i ? 0.5 : -0.5)*c, 0.5+0.5*s);
+ builder.vertex(radius*c, radius*s, z);
+ }
+ }
+
+ float u_scale = 1.0/segments;
+ float v_scale = 1;
+ adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, length);
+
+ if(generate_tbn)
+ builder.binormal(0, 0, 1);
+ for(unsigned i=0; i<2; ++i)
+ {
+ float z = (i-0.5)*length;
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ float a = j*M_PI*2/segments;
+ float c = cos(a);
+ float s = sin(a);
+ builder.normal(c, s, 0);
+ builder.texcoord(j*u_scale, i*v_scale);
+ if(generate_tbn)
+ builder.tangent(-s, c, 0);
+ builder.vertex(radius*c, radius*s, z);
+ }
+ }
+
+ unsigned base = 0;
+ for(unsigned i=0; i<2; ++i)
+ {
+ builder.begin(TRIANGLE_FAN);
+ builder.element(base);
+ for(unsigned j=0; j<=segments; ++j)
+ builder.element(base+1+j%segments);
+ builder.end();
+
+ base += segments+1;
+ }
+
+ builder.begin(TRIANGLE_STRIP);
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ builder.element(base+segments+1+j);
+ builder.element(base+j);
+ }
+ builder.end();
+}
+
+} // namespace GL
+} // namespace Msp