]> git.tdb.fi Git - libs/gl.git/commitdiff
Add geometry builder for sphere
authorMikko Rasa <tdb@tdb.fi>
Wed, 25 Nov 2015 11:53:24 +0000 (13:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Wed, 25 Nov 2015 11:53:24 +0000 (13:53 +0200)
source/sphere.cpp [new file with mode: 0644]
source/sphere.h [new file with mode: 0644]

diff --git a/source/sphere.cpp b/source/sphere.cpp
new file mode 100644 (file)
index 0000000..0bedf15
--- /dev/null
@@ -0,0 +1,81 @@
+#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
diff --git a/source/sphere.h b/source/sphere.h
new file mode 100644 (file)
index 0000000..b69c408
--- /dev/null
@@ -0,0 +1,26 @@
+#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