]> git.tdb.fi Git - libs/gl.git/blobdiff - source/grid.cpp
Add capsule and grid builders
[libs/gl.git] / source / grid.cpp
diff --git a/source/grid.cpp b/source/grid.cpp
new file mode 100644 (file)
index 0000000..524f2c5
--- /dev/null
@@ -0,0 +1,131 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include "grid.h"
+#include "primitivebuilder.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+GridBuilder::GridBuilder(float w, float h, unsigned u, unsigned v):
+       origin(-w/2, -h/2, 0),
+       side1(w, 0, 0),
+       side2(0, h, 0),
+       norm(0, 0, 1),
+       binorm(0, 1, 0),
+       u_div(u),
+       v_div(v)
+{
+       init(false);
+}
+
+GridBuilder::GridBuilder(const Vector3 &o, const Vector3 &s, unsigned u, unsigned v):
+       origin(o),
+       u_div(u),
+       v_div(v)
+{
+       if(abs(s.z)<abs(s.x) && abs(s.z)<abs(s.y))
+       {
+               side1 = Vector3(s.x, 0, 0);
+               side2 = Vector3(0, s.y, 0);
+       }
+       else if(abs(s.y)<abs(s.x))
+       {
+               side1 = Vector3(0, 0, s.z);
+               side2 = Vector3(s.x, 0, 0);
+       }
+       else
+       {
+               side1 = Vector3(0, s.y, 0);
+               side2 = Vector3(0, 0, s.z);
+       }
+       init(true);
+}
+
+GridBuilder::GridBuilder(const Vector3 &o, const Vector3 &s1, const Vector3 &s2, unsigned u, unsigned v):
+       origin(o),
+       side1(s1),
+       side2(s2),
+       u_div(u),
+       v_div(v)
+{
+       init(true);
+}
+
+void GridBuilder::init(bool compute_normals)
+{
+       if(u_div<1)
+               u_div = 1;
+       if(v_div<1)
+               v_div = 1;
+
+       if(compute_normals)
+       {
+               norm.x = side1.y*side2.z-side1.z*side2.y;
+               norm.y = side1.z*side2.x-side1.x*side2.z;
+               norm.z = side1.x*side2.y-side1.y*side2.x;
+               float l = sqrt(norm.x*norm.x+norm.y*norm.y+norm.z*norm.z);
+               norm.x /= l;
+               norm.y /= l;
+               norm.z /= l;
+
+               binorm.x = norm.y*side1.z-norm.z*side1.y;
+               binorm.y = norm.z*side1.x-norm.x*side1.z;
+               binorm.z = norm.x*side1.y-norm.y*side1.x;
+               l = sqrt(binorm.x*binorm.x+binorm.y*binorm.y+binorm.z*binorm.z);
+               binorm.x /= l;
+               binorm.y /= l;
+               binorm.z /= l;
+       }
+}
+
+void GridBuilder::build(PrimitiveBuilder &builder) const
+{
+       float l1_sq = side1.x*side1.x+side1.y*side1.y+side1.z*side1.z;
+       float l2 = side2.x*binorm.x+side2.y*binorm.y+side2.z*binorm.z;
+       float u_scale = 1/l1_sq;
+       float v_scale = 1/l2;
+       adjust_texture_scale(u_scale, v_scale, sqrt(l1_sq), l2);
+
+       builder.normal(norm.x, norm.y, norm.z);
+       if(tangent_attr>=0)
+               builder.attrib(tangent_attr, side1.x, side1.y, side1.z);
+       if(binormal_attr>=0)
+               builder.attrib(tangent_attr, binorm.x, binorm.y, binorm.z);
+
+       for(unsigned j=0; j<=v_div; ++j)
+       {
+               float v = j*1.0/v_div;
+               Vector3 row(origin.x+side2.x*v, origin.y+side2.y*v, origin.z+side2.z*v);
+               v = (row.x*binorm.x+row.y*binorm.y+row.z*binorm.z)*v_scale;
+               for(unsigned i=0; i<=u_div; ++i)
+               {
+                       float u = i*1.0/u_div;
+                       Vector3 p(row.x+side1.x*u, row.y+side1.y*u, row.z+side1.z*u);
+                       u = (p.x*side1.x+p.y*side1.y+p.z*side1.z)*u_scale;
+                       builder.texcoord(u, v);
+                       builder.vertex(p);
+               }
+       }
+
+       for(unsigned j=0; j<v_div; ++j)
+       {
+               builder.begin(TRIANGLE_STRIP);
+               for(unsigned i=0; i<=u_div; ++i)
+               {
+                       builder.element((j+1)*(u_div+1)+i);
+                       builder.element(j*(u_div+1)+i);
+               }
+               builder.end();
+       }
+}
+
+} // namespace GL
+} // namespace Msp