--- /dev/null
+#include <cmath>
+#include "primitivebuilder.h"
+#include "sphere.h"
+
+namespace Msp {
+namespace GL {
+
+UvSphereBuilder::UvSphereBuilder(float r, unsigned s, unsigned n):
+ radius(r),
+ segments(s),
+ rings(n)
+{
+ if(segments<3)
+ segments = 3;
+
+ if(rings==0)
+ rings = (segments+1)/2;
+ else if(rings<2)
+ rings = 2;
+}
+
+void UvSphereBuilder::build(PrimitiveBuilder &builder) const
+{
+ float u_scale = 1.0f/segments;
+ float v_scale = 1.0f/rings;
+ adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, radius*M_PI);
+
+ for(unsigned i=0; i<=rings; ++i)
+ {
+ float av = i*M_PI/rings-M_PI/2;
+ float cv = cos(av);
+ float sv = sin(av);
+
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ float au = j*M_PI*2/segments;
+ float cu = cos(au);
+ float su = sin(au);
+
+ builder.normal(cv*cu, cv*su, sv);
+ builder.texcoord(j*u_scale, i*v_scale);
+ if(generate_tbn)
+ {
+ builder.tangent(-su, cu, 0);
+ builder.binormal(-sv*cu, -sv*su, cv);
+ }
+ builder.vertex(cv*cu*radius, cv*su*radius, sv*radius);
+ }
+ }
+
+ builder.begin(TRIANGLES);
+ for(unsigned j=0; j<segments; ++j)
+ {
+ builder.element(j);
+ builder.element(segments+2+j);
+ builder.element(segments+1+j);
+ }
+ unsigned top = (rings+1)*(segments+1)-1;
+ for(unsigned j=0; j<segments; ++j)
+ {
+ builder.element(top-j);
+ builder.element(top-(segments+2+j));
+ builder.element(top-(segments+1+j));
+ }
+ builder.end();
+
+ for(unsigned i=1; i<rings; ++i)
+ {
+ builder.begin(TRIANGLE_STRIP);
+ unsigned base = i*(segments+1);
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ builder.element(base+segments+1+j);
+ builder.element(base+j);
+ }
+ builder.end();
+ }
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+#ifndef MSP_GL_SPHERE_H_
+#define MSP_GL_SPHERE_H_
+
+#include "geometrybuilder.h"
+
+namespace Msp {
+namespace GL {
+
+class UvSphereBuilder: public GeometryBuilder
+{
+private:
+ float radius;
+ unsigned segments;
+ unsigned rings;
+
+public:
+ UvSphereBuilder(float, unsigned, unsigned = 0);
+
+ using GeometryBuilder::build;
+ virtual void build(PrimitiveBuilder &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif