void BoxBuilder::build_face(PrimitiveBuilder &builder, const Vector3 &o, const Vector3 &s1, const Vector3 &s2) const
{
+ float l1 = 1, l2 = 1;
+ if(tangent_attr>=0 || tex_fit!=STRETCH)
+ l1 = sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z);
+ if(binormal_attr>=0 || tex_fit!=STRETCH)
+ l2 = sqrt(s2.x*s2.x+s2.y*s2.y+s2.z*s2.z);
+
if(tangent_attr>=0)
- {
- builder.attrib(tangent_attr, s1.x, s1.y, s1.z);
- builder.attrib(binormal_attr, s2.x, s2.y, s2.z);
- }
+ builder.attrib(tangent_attr, s1.x/l1, s1.y/l1, s1.z/l1);
+ if(binormal_attr>=0)
+ builder.attrib(binormal_attr, s2.x/l2, s2.y/l2, s2.z/l2);
+
float u_size = 1;
float v_size = 1;
if(tex_fit!=STRETCH)
{
- float l1 = sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z);
- float l2 = sqrt(s2.x*s2.x+s2.y*s2.y+s2.z*s2.z);
if((l1<l2)==(tex_fit==CUT))
u_size = l1/l2;
else
v_size = l2/l1;
}
+
builder.begin(TRIANGLE_STRIP);
builder.texcoord(0, v_size);
builder.vertex(o.x+s2.x, o.y+s2.y, o.z+s2.z);
float sc = cos(sa);
float ss = sin(sa);
builder.normal(rs*sc, rs*ss, -rc);
- if(tangent_attr)
- {
+ if(tangent_attr>=0)
builder.attrib(tangent_attr, -ss, sc, 0);
+ if(binormal_attr>=0)
builder.attrib(binormal_attr, rc*sc, rc*ss, rs);
- }
builder.texcoord(j*u_scale, v);
builder.vertex(rs*sc*radius, rs*ss*radius, cz-rc*radius);
}
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include "cylinder.h"
+#include "primitivebuilder.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+CylinderBuilder::CylinderBuilder(float r, float l, unsigned s):
+ radius(r),
+ length(l),
+ segments(s)
+{
+ if(segments<3)
+ segments = 3;
+}
+
+void CylinderBuilder::build(PrimitiveBuilder &builder) const
+{
+ if(binormal_attr>=0)
+ builder.attrib(binormal_attr, 0, 1, 0);
+ for(unsigned i=0; i<2; ++i)
+ {
+ float z = (i-0.5)*length;
+ builder.normal(0, 0, i*2.0-1.0);
+ builder.texcoord(0.5, 0.5);
+ if(tangent_attr>=0)
+ builder.attrib(tangent_attr, (i ? 1 : -1), 0, 0);
+ builder.vertex(0, 0, z);
+ for(unsigned j=0; j<segments; ++j)
+ {
+ float a = j*M_PI*2/segments;
+ float c = cos(a);
+ float s = sin(a);
+ builder.texcoord(0.5+(i ? 0.5 : -0.5)*c, 0.5+0.5*s);
+ builder.vertex(radius*c, radius*s, z);
+ }
+ }
+
+ float u_scale = 1.0/segments;
+ float v_scale = 1;
+ adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, length);
+
+ if(binormal_attr>=0)
+ builder.attrib(binormal_attr, 0, 0, 1);
+ for(unsigned i=0; i<2; ++i)
+ {
+ float z = (i-0.5)*length;
+ for(unsigned j=0; j<=segments; ++j)
+ {
+ float a = j*M_PI*2/segments;
+ float c = cos(a);
+ float s = sin(a);
+ builder.normal(c, s, 0);
+ builder.texcoord(j*u_scale, i*v_scale);
+ if(tangent_attr>=0)
+ builder.attrib(tangent_attr, -s, c, 0);
+ builder.vertex(radius*c, radius*s, z);
+ }
+ }
+
+ unsigned base = 0;
+ for(unsigned i=0; i<2; ++i)
+ {
+ builder.begin(TRIANGLE_FAN);
+ builder.element(base);
+ for(unsigned j=0; j<=segments; ++j)
+ builder.element(base+1+j%segments);
+ builder.end();
+
+ base += segments+1;
+ }
+
+ builder.begin(TRIANGLE_STRIP);
+ 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
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef CYLINDER_H_
+#define CYLINDER_H_
+
+#include "geometrybuilder.h"
+
+namespace Msp {
+namespace GL {
+
+class CylinderBuilder: public GeometryBuilder
+{
+private:
+ float radius;
+ float length;
+ unsigned segments;
+
+public:
+ CylinderBuilder(float, float, unsigned = 16);
+
+ virtual void build(PrimitiveBuilder &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
return *this;
}
+void GeometryBuilder::adjust_texture_scale(float &u_scale, float &v_scale, float width, float height) const
+{
+ if(tex_fit!=STRETCH)
+ {
+ if((width<height)==(tex_fit==CUT))
+ u_scale *= width/height;
+ else
+ v_scale *= height/width;
+ }
+}
+
void GeometryBuilder::build(Mesh &mesh) const
{
MeshBuilder builder(mesh);
GeometryBuilder &tangent(unsigned);
GeometryBuilder &binormal(unsigned);
GeometryBuilder &texture_fit(TextureFit);
+protected:
+ void adjust_texture_scale(float &, float &, float, float) const;
+public:
virtual void build(PrimitiveBuilder &) const = 0;
void build(Mesh &) const;
};
--- /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
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_GRID_H_
+#define MSP_GL_GRID_H_
+
+#include "geometrybuilder.h"
+#include "vector.h"
+
+namespace Msp {
+namespace GL {
+
+class GridBuilder: public GeometryBuilder
+{
+private:
+ Vector3 origin;
+ Vector3 side1;
+ Vector3 side2;
+ Vector3 norm;
+ Vector3 binorm;
+ unsigned u_div;
+ unsigned v_div;
+ float u_origin;
+ float y_origin;
+
+public:
+ GridBuilder(float, float, unsigned = 4, unsigned = 4);
+ GridBuilder(const Vector3 &, const Vector3 &, unsigned = 4, unsigned = 4);
+ GridBuilder(const Vector3 &, const Vector3 &, const Vector3 &, unsigned = 4, unsigned = 4);
+private:
+ void init(bool);
+
+public:
+ virtual void build(PrimitiveBuilder &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif