initial commit, first gear
[antikythera] / src / gear.cc
1 #include <GL/glew.h>
2 #include "gear.h"
3 #include "meshgen.h"
4
5 Gear::Gear()
6         : axis(0, 0, 1)
7 {
8         pdist = 0;
9         angle = 0;
10         nteeth = 42;
11         radius = 80;
12         teeth_length = 5;
13         thickness = 5;
14         bevel = 1.5;
15
16         mesh = 0;
17 }
18
19 Gear::~Gear()
20 {
21         delete mesh;
22 }
23
24 void Gear::draw() const
25 {
26         if(!mesh) {
27                 if(!((Gear*)this)->gen_mesh()) {
28                         abort();
29                 }
30         }
31         calc_matrix();
32
33         glPushMatrix();
34         glMultMatrixf(xform[0]);
35
36         mesh->draw();
37
38         /*
39         glPushAttrib(GL_ENABLE_BIT);
40         glDisable(GL_LIGHTING);
41         glColor3f(0, 1, 0);
42         mesh->draw_normals();
43         glPopAttrib();
44         */
45
46         glPopMatrix();
47 }
48
49 static Vec2 rev_pos(float u, float v, void *cls)
50 {
51         Gear *gear = (Gear*)cls;
52
53         float y = ((v - 1.0 / 3.0) / (1.0 / 3.0) - 0.5);
54         if(y < -0.5) y = -0.5;
55         if(y > 0.5) y = 0.5;
56         y *= gear->thickness;
57
58         if(v < 0.001 || v > 0.999) {
59                 return Vec2(0, -y);
60         }
61
62         float nt = (float)gear->nteeth * 4.0;
63
64         int part = (int)(u * nt) % 4;   /* 4 parts to a tooth /#\_ */
65         float t = fmod(u * nt * 4.0, 1.0);
66
67         float offs;
68         switch(part) {
69         case 0:
70                 offs = t;
71                 break;
72         case 1:
73                 offs = 1.0f;
74                 break;
75         case 2:
76                 offs = 1.0f - t;
77                 break;
78         case 3:
79                 offs = 0.0f;
80         }
81
82         float inner_rad = gear->radius - gear->teeth_length;
83         return Vec2(inner_rad + offs * gear->teeth_length, -y);
84 }
85
86 bool Gear::gen_mesh()
87 {
88         mesh = new Mesh;
89         gen_revol(mesh, nteeth * 4, 3, rev_pos, 0, this);
90         mesh->explode();
91         mesh->calc_face_normals();
92
93         Mat4 rot;
94         rot.rotation_x(M_PI / 2.0);
95         mesh->apply_xform(rot, rot);
96
97         mesh->set_vis_vecsize(6.0);
98         return true;
99 }
100
101 void Gear::calc_matrix() const
102 {
103         Vec3 up = Vec3(0, 1, 0);
104         if(1.0 - fabs(dot(up, axis)) < 1e-4) {
105                 up = Vec3(0, 0, -1);
106         }
107         Vec3 right = normalize(cross(up, axis));
108         up = cross(axis, right);
109
110         xform = Mat4(right, up, axis);
111         xform.translate(pos);
112 }