--- /dev/null
+#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 = normalize(cross(side1, side2));
+ binorm = normalize(cross(norm, side1));
+ }
+}
+
+void GridBuilder::build(PrimitiveBuilder &builder) const
+{
+ float l1_sq = dot(side1, side1);
+ float l2 = dot(side2, binorm);
+ 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(generate_tbn)
+ {
+ builder.tangent(side1);
+ builder.binormal(binorm);
+ }
+
+ for(unsigned j=0; j<=v_div; ++j)
+ {
+ Vector3 row = side2*(j*1.0f/v_div);
+ float v = dot(row, binorm)*v_scale;
+ for(unsigned i=0; i<=u_div; ++i)
+ {
+ Vector3 p = row+side1*(i*1.0f/u_div);
+ float u = dot(p, side1)*u_scale;
+ builder.texcoord(u, v);
+ builder.vertex(origin+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