multisampling and shit
[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         init_angle = 0;
16
17         mesh = 0;
18 }
19
20 Gear::~Gear()
21 {
22         delete mesh;
23 }
24
25 void Gear::set_teeth(int nt, float tooth_pitch)
26 {
27         float circ = tooth_pitch * nt;
28         radius = circ / (2.0 * M_PI);
29         nteeth = nt;
30         init_angle = get_angular_pitch() * 3.0 / 8.0;
31 }
32
33 float Gear::get_rotation() const
34 {
35         return fmod(init_angle + angle, M_PI * 2.0);
36 }
37
38 float Gear::get_angular_pitch() const
39 {
40         return 2.0 * M_PI / (float)nteeth;
41 }
42
43 void Gear::draw() const
44 {
45         if(!mesh) {
46                 if(!((Gear*)this)->gen_mesh()) {
47                         abort();
48                 }
49         }
50         calc_matrix();
51
52         glPushMatrix();
53         glMultMatrixf(xform[0]);
54
55         mesh->draw();
56
57         glPushAttrib(GL_ENABLE_BIT);
58         glDisable(GL_LIGHTING);
59
60         glLineWidth(2.0);
61         glBegin(GL_LINES);
62         glColor3f(0, 0, 1);
63         glVertex3f(0, 0, -10);
64         glVertex3f(0, 0, 10);
65         glEnd();
66         glLineWidth(1.0);
67         glPopAttrib();
68
69         glPopMatrix();
70 }
71
72 static Vec2 rev_pos(float u, float v, void *cls)
73 {
74         Gear *gear = (Gear*)cls;
75
76         float y = ((v - 1.0 / 3.0) / (1.0 / 3.0) - 0.5);
77         if(y < -0.5) y = -0.5;
78         if(y > 0.5) y = 0.5;
79         y *= gear->thickness;
80
81         if(v < 0.001 || v > 0.999) {
82                 return Vec2(0, -y);
83         }
84
85         float nt = (float)gear->nteeth * 4.0;
86
87         int part = (int)(u * nt) % 4;   /* 4 parts to a tooth /#\_ */
88         float t = fmod(u * nt * 4.0, 1.0);
89
90         float offs;
91         switch(part) {
92         case 0:
93                 offs = t;
94                 break;
95         case 1:
96                 offs = 1.0f;
97                 break;
98         case 2:
99                 offs = 1.0f - t;
100                 break;
101         case 3:
102                 offs = 0.0f;
103         }
104
105         float inner_rad = gear->radius - gear->teeth_length;
106         return Vec2(inner_rad + offs * gear->teeth_length, -y);
107 }
108
109 bool Gear::gen_mesh()
110 {
111         mesh = new Mesh;
112         gen_revol(mesh, nteeth * 4, 3, rev_pos, 0, this);
113         mesh->explode();
114         mesh->calc_face_normals();
115
116         Mat4 rot;
117         rot.rotation_x(M_PI / 2.0);
118         mesh->apply_xform(rot, rot);
119
120         mesh->set_vis_vecsize(6.0);
121         return true;
122 }
123
124 void Gear::calc_matrix() const
125 {
126         Vec3 up = Vec3(0, 1, 0);
127         if(1.0 - fabs(dot(up, axis)) < 1e-4) {
128                 up = Vec3(0, 0, -1);
129         }
130         Vec3 right = normalize(cross(up, axis));
131         up = cross(axis, right);
132
133         xform = Mat4(right, up, axis);
134         xform.rotate_z(get_rotation());
135         xform.translate(pos);
136 }