- added subgear linkage
[antikythera] / src / gear.cc
index 6ce9d8a..697610d 100644 (file)
@@ -16,6 +16,8 @@ Gear::Gear()
        init_angle = 0;
        xform_valid = false;
 
+       supergear = 0;
+
        mesh = 0;
 }
 
@@ -24,12 +26,57 @@ 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;
-       init_angle = get_angular_pitch() * 3.0 / 8.0;
 }
 
 void Gear::set_axis(const Vec3 &axis)
@@ -38,10 +85,22 @@ void Gear::set_axis(const Vec3 &axis)
        xform_valid = false;
 }
 
+const Vec3 &Gear::get_axis() const
+{
+       return axis;
+}
+
 void Gear::set_position(const Vec3 &pos)
 {
-       this->pos = pos;
-       xform_valid = false;
+       if(!supergear) {
+               this->pos = pos;
+               xform_valid = false;
+       } else {
+               if(fabs(this->pos.z - pos.z) > 1e-5) {
+                       this->pos.z = pos.z;
+                       xform_valid = false;
+               }
+       }
 }
 
 const Vec3 &Gear::get_position() const
@@ -51,7 +110,8 @@ const Vec3 &Gear::get_position() const
 
 Vec3 Gear::get_global_position() const
 {
-       return pos;     // TODO
+       const Mat4 &m = get_matrix();
+       return m * Vec3(0, 0, 0);
 }
 
 void Gear::set_angle(float angle)
@@ -85,7 +145,7 @@ const Mat4 &Gear::get_dir_matrix() const
                calc_matrix();
                xform_valid = true;
        }
-       return xform;
+       return dir_xform;
 }
 
 float Gear::get_angular_pitch() const
@@ -100,7 +160,9 @@ void Gear::draw() const
                        abort();
                }
        }
-       calc_matrix();
+       if(!xform_valid) {
+               calc_matrix();
+       }
 
        glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
 
@@ -132,6 +194,30 @@ void Gear::draw() const
        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)
 {
        Gear *gear = (Gear*)cls;
@@ -176,8 +262,11 @@ bool Gear::gen_mesh()
        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);
@@ -198,4 +287,7 @@ void Gear::calc_matrix() const
        xform = dir_xform;
        xform.rotate_z(get_vis_rotation());
        xform.translate(pos);
+
+       axel_xform = dir_xform;
+       axel_xform.translate(pos);
 }