#include <GL/glew.h>
#include "gear.h"
#include "meshgen.h"
+#include "app.h"
Gear::Gear()
: axis(0, 0, 1)
teeth_length = 5;
thickness = 5;
bevel = 1.5;
+ init_angle = 0;
+ xform_valid = false;
+
+ supergear = 0;
mesh = 0;
+
+ color = Vec3(0.6, 0.6, 0.6);
+ roughness = 1.0;
+ metallic = false;
}
Gear::~Gear()
delete mesh;
}
+void Gear::attach(Gear *g)
+{
+ if(g->supergear) {
+ if(g->supergear == this) {
+ return;
+ }
+ g->supergear->detach(g);
+ }
+ g->supergear = this;
+ subgears.push_back(g);
+
+ // make co-axial
+ g->axis = axis;
+ g->pos.x = pos.x;
+ g->pos.y = pos.y;
+}
+
+bool Gear::detach(Gear *g)
+{
+ int nsubgears = (int)subgears.size();
+ for(int i=0; i<nsubgears; i++) {
+ if(subgears[i] == g) {
+ subgears.erase(subgears.begin() + i);
+ g->supergear = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+Gear *Gear::get_super() const
+{
+ return supergear;
+}
+
+void Gear::set_angular_offset(float offs)
+{
+ init_angle = offs;
+ xform_valid = false;
+}
+
+float Gear::get_angular_offset() const
+{
+ return init_angle;
+}
+
+void Gear::set_teeth(int nt, float tooth_pitch)
+{
+ float circ = tooth_pitch * nt;
+ radius = circ / (2.0 * M_PI);
+ nteeth = nt;
+}
+
+void Gear::set_axis(const Vec3 &axis)
+{
+ this->axis = normalize(axis);
+ xform_valid = false;
+}
+
+const Vec3 &Gear::get_axis() const
+{
+ return axis;
+}
+
+void Gear::set_position(const Vec3 &pos)
+{
+ if(!supergear) {
+ this->pos = pos;
+ } else {
+ this->pos = supergear->pos;
+ this->pos.z = pos.z;
+ }
+ xform_valid = false;
+
+ for(int i=0; i<(int)subgears.size(); i++) {
+ Vec3 subpos = this->pos;
+ subpos.z = subgears[i]->pos.z;
+ subgears[i]->set_position(subpos);
+ }
+}
+
+const Vec3 &Gear::get_position() const
+{
+ return pos;
+}
+
+Vec3 Gear::get_global_position() const
+{
+ const Mat4 &m = get_matrix();
+ return m * Vec3(0, 0, 0);
+}
+
+void Gear::set_angle(float angle)
+{
+ this->angle = angle;
+ xform_valid = false;
+}
+
+float Gear::get_angle() const
+{
+ return angle;
+}
+
+float Gear::get_vis_rotation() const
+{
+ return fmod(init_angle + angle, M_PI * 2.0);
+}
+
+const Mat4 &Gear::get_matrix() const
+{
+ if(!xform_valid) {
+ calc_matrix();
+ xform_valid = true;
+ }
+ return xform;
+}
+
+const Mat4 &Gear::get_dir_matrix() const
+{
+ if(!xform_valid) {
+ calc_matrix();
+ xform_valid = true;
+ }
+ return dir_xform;
+}
+
+float Gear::get_angular_pitch() const
+{
+ return 2.0 * M_PI / (float)nteeth;
+}
+
void Gear::draw() const
{
if(!mesh) {
abort();
}
}
- calc_matrix();
+ if(!xform_valid) {
+ calc_matrix();
+ }
+
+ glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_LIGHTING_BIT);
glPushMatrix();
glMultMatrixf(xform[0]);
+ if(opt_gear_wireframe) {
+ glPolygonOffset(1, 1);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ Vec3 diffuse = metallic ? Vec3(0, 0, 0) : color;
+ float col[] = {diffuse.x, diffuse.y, diffuse.z, 1.0};
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
+
+ Vec3 specular = (metallic ? color : Vec3(1, 1, 1)) * (1.0 - roughness);
+ float scol[] = {specular.x, specular.y, specular.z, 1.0};
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 1.0 + (1.0 - roughness) * 60.0);
+
mesh->draw();
- /*
- glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
- glColor3f(0, 1, 0);
- mesh->draw_normals();
+
+ if(opt_gear_wireframe) {
+ glColor3f(0.2, 0.4, 1.0);
+ mesh->draw_wire();
+ }
+
+ glPopMatrix();
glPopAttrib();
- */
+}
+
+void Gear::draw_wire(float wire_width) const
+{
+ if(!mesh) {
+ if(!((Gear*)this)->gen_mesh()) {
+ abort();
+ }
+ }
+ if(!xform_valid) {
+ calc_matrix();
+ }
+
+ glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
+ glLineWidth(wire_width);
+ glDisable(GL_LIGHTING);
+
+ glPushMatrix();
+ glMultMatrixf(xform[0]);
+
+ mesh->draw_wire();
glPopMatrix();
+ glPopAttrib();
}
static Vec2 rev_pos(float u, float v, void *cls)
mesh->explode();
mesh->calc_face_normals();
+ float fix_tooth_up = get_angular_pitch() * 3.0 / 8.0;
+
Mat4 rot;
rot.rotation_x(M_PI / 2.0);
+ rot.rotate_z(fix_tooth_up);
mesh->apply_xform(rot, rot);
mesh->set_vis_vecsize(6.0);
Vec3 right = normalize(cross(up, axis));
up = cross(axis, right);
- xform = Mat4(right, up, axis);
+ dir_xform = Mat4(right, up, axis);
+
+ xform = dir_xform;
+ xform.rotate_z(get_vis_rotation());
xform.translate(pos);
+
+ axel_xform = dir_xform;
+ axel_xform.translate(pos);
}