--- /dev/null
+/* $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