]> git.tdb.fi Git - libs/gl.git/commitdiff
Add capsule and grid builders
authorMikko Rasa <tdb@tdb.fi>
Wed, 26 Jan 2011 18:09:37 +0000 (18:09 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 26 Jan 2011 18:09:37 +0000 (18:09 +0000)
Fix some bugs in the other geometry builders

source/box.cpp
source/capsule.cpp
source/cylinder.cpp [new file with mode: 0644]
source/cylinder.h [new file with mode: 0644]
source/geometrybuilder.cpp
source/geometrybuilder.h
source/grid.cpp [new file with mode: 0644]
source/grid.h [new file with mode: 0644]

index 3d6f15fdc6f422e3259088de7a599b8eba6ba762..21d5f33f984ebfbbcb0411b3dcfa0148c3fe38c3 100644 (file)
@@ -42,22 +42,27 @@ void BoxBuilder::build(PrimitiveBuilder &builder) const
 
 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);
index 86f5d57a8d50d0f42f2cc2c5ea76e6012910c3e1..fd4dbb0fb5e974b793492845dfa918c3349729a3 100644 (file)
@@ -57,11 +57,10 @@ void CapsuleBuilder::build(PrimitiveBuilder &builder) const
                        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);
                }
diff --git a/source/cylinder.cpp b/source/cylinder.cpp
new file mode 100644 (file)
index 0000000..30c3530
--- /dev/null
@@ -0,0 +1,92 @@
+/* $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
diff --git a/source/cylinder.h b/source/cylinder.h
new file mode 100644 (file)
index 0000000..c671bfe
--- /dev/null
@@ -0,0 +1,32 @@
+/* $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
index 97c88e06def4cabe37d917d15ebc93ed119668ad..018ea44718d880f2d4c18d99ebe95adf8f120e55 100644 (file)
@@ -35,6 +35,17 @@ GeometryBuilder &GeometryBuilder::texture_fit(TextureFit tf)
        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);
index a0538b5933fe163b6ef04085b1dedfc32e402385..2e5a79faa06096c6ca6a129409b1df4909eb11b9 100644 (file)
@@ -35,7 +35,10 @@ public:
        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;
 };
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
diff --git a/source/grid.h b/source/grid.h
new file mode 100644 (file)
index 0000000..91b9ef2
--- /dev/null
@@ -0,0 +1,44 @@
+/* $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