23 color = Vec3(0.6, 0.6, 0.6);
33 void Gear::attach(Gear *g)
36 if(g->supergear == this) {
39 g->supergear->detach(g);
42 subgears.push_back(g);
50 bool Gear::detach(Gear *g)
52 int nsubgears = (int)subgears.size();
53 for(int i=0; i<nsubgears; i++) {
54 if(subgears[i] == g) {
55 subgears.erase(subgears.begin() + i);
63 Gear *Gear::get_super() const
68 void Gear::set_angular_offset(float offs)
74 float Gear::get_angular_offset() const
79 void Gear::set_teeth(int nt, float tooth_pitch)
81 if(tooth_pitch <= 0) {
82 tooth_pitch = this->tooth_pitch;
84 this->tooth_pitch = tooth_pitch;
86 float circ = tooth_pitch * nt;
87 radius = circ / (2.0 * M_PI);
91 void Gear::set_axis(const Vec3 &axis)
93 this->axis = normalize(axis);
97 const Vec3 &Gear::get_axis() const
102 void Gear::set_position(const Vec3 &pos)
107 this->pos = supergear->pos;
112 for(int i=0; i<(int)subgears.size(); i++) {
113 Vec3 subpos = this->pos;
114 subpos.z = subgears[i]->pos.z;
115 subgears[i]->set_position(subpos);
119 const Vec3 &Gear::get_position() const
124 Vec3 Gear::get_global_position() const
126 const Mat4 &m = get_matrix();
127 return m * Vec3(0, 0, 0);
130 void Gear::set_angle(float angle)
136 float Gear::get_angle() const
141 float Gear::get_vis_rotation() const
143 return fmod(init_angle + angle, M_PI * 2.0);
146 const Mat4 &Gear::get_matrix() const
155 const Mat4 &Gear::get_dir_matrix() const
164 float Gear::get_angular_pitch() const
166 return 2.0 * M_PI / (float)nteeth;
169 void Gear::draw() const
172 if(!((Gear*)this)->gen_mesh()) {
180 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_LIGHTING_BIT);
183 glMultMatrixf(xform[0]);
185 if(opt_gear_wireframe) {
186 glPolygonOffset(1, 1);
187 glEnable(GL_POLYGON_OFFSET_FILL);
190 Vec3 diffuse = metallic ? Vec3(0, 0, 0) : color;
191 float col[] = {diffuse.x, diffuse.y, diffuse.z, 1.0};
192 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
194 Vec3 specular = (metallic ? color : Vec3(1, 1, 1)) * (1.0 - roughness);
195 float scol[] = {specular.x, specular.y, specular.z, 1.0};
196 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol);
197 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 1.0 + (1.0 - roughness) * 60.0);
201 glDisable(GL_LIGHTING);
203 if(opt_gear_wireframe) {
204 glColor3f(0.2, 0.4, 1.0);
212 void Gear::draw_wire(float wire_width) const
215 if(!((Gear*)this)->gen_mesh()) {
223 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
224 glLineWidth(wire_width);
225 glDisable(GL_LIGHTING);
228 glMultMatrixf(xform[0]);
236 static Vec2 rev_pos(float u, float v, void *cls)
238 Gear *gear = (Gear*)cls;
240 float y = ((v - 1.0 / 3.0) / (1.0 / 3.0) - 0.5);
241 if(y < -0.5) y = -0.5;
243 y *= gear->thickness;
245 if(v < 0.001 || v > 0.999) {
249 float nt = (float)gear->nteeth * 4.0;
251 int part = (int)(u * nt) % 4; /* 4 parts to a tooth /#\_ */
252 float t = fmod(u * nt * 4.0, 1.0);
269 float inner_rad = gear->radius - gear->teeth_length;
270 return Vec2(inner_rad + offs * gear->teeth_length, -y);
273 bool Gear::gen_mesh()
276 gen_revol(mesh, nteeth * 4, 3, rev_pos, 0, this);
278 mesh->calc_face_normals();
280 float fix_tooth_up = get_angular_pitch() * 3.0 / 8.0;
283 rot.rotation_x(M_PI / 2.0);
284 rot.rotate_z(fix_tooth_up);
285 mesh->apply_xform(rot, rot);
287 mesh->set_vis_vecsize(6.0);
291 void Gear::calc_matrix() const
293 Vec3 up = Vec3(0, 1, 0);
294 if(1.0 - fabs(dot(up, axis)) < 1e-4) {
297 Vec3 right = normalize(cross(up, axis));
298 up = cross(axis, right);
300 dir_xform = Mat4(right, up, axis);
303 xform.rotate_z(get_vis_rotation());
304 xform.translate(pos);
306 axel_xform = dir_xform;
307 axel_xform.translate(pos);