+++ /dev/null
-#include <stdlib.h>
-#include <GL/glew.h>
-#include "gear.h"
-#include "meshgen.h"
-#include "app.h"
-
-Gear::Gear()
- : axis(0, 0, 1)
-{
- pdist = 0;
- angle = 0;
- teeth_length = 5;
- thickness = 5;
- bevel = 1.5;
- init_angle = 0;
- xform_valid = false;
-
- set_teeth(42, 10);
-
- 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)
-{
- if(tooth_pitch <= 0) {
- tooth_pitch = this->tooth_pitch;
- } else {
- this->tooth_pitch = 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) {
- if(!((Gear*)this)->gen_mesh()) {
- abort();
- }
- }
- 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();
-
- glDisable(GL_LIGHTING);
-
- 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)
-{
- Gear *gear = (Gear*)cls;
-
- float y = ((v - 1.0 / 3.0) / (1.0 / 3.0) - 0.5);
- if(y < -0.5) y = -0.5;
- if(y > 0.5) y = 0.5;
- y *= gear->thickness;
-
- if(v < 0.001 || v > 0.999) {
- return Vec2(0, -y);
- }
-
- float nt = (float)gear->nteeth * 4.0;
-
- int part = (int)(u * nt) % 4; /* 4 parts to a tooth /#\_ */
- float t = fmod(u * nt * 4.0, 1.0);
-
- float offs;
- switch(part) {
- case 0:
- offs = t;
- break;
- case 1:
- offs = 1.0f;
- break;
- case 2:
- offs = 1.0f - t;
- break;
- case 3:
- offs = 0.0f;
- }
-
- float inner_rad = gear->radius - gear->teeth_length;
- return Vec2(inner_rad + offs * gear->teeth_length, -y);
-}
-
-bool Gear::gen_mesh()
-{
- mesh = new Mesh;
- gen_revol(mesh, nteeth * 4, 3, rev_pos, 0, this);
- 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);
- return true;
-}
-
-void Gear::calc_matrix() const
-{
- Vec3 up = Vec3(0, 1, 0);
- if(1.0 - fabs(dot(up, axis)) < 1e-4) {
- up = Vec3(0, 0, -1);
- }
- Vec3 right = normalize(cross(up, axis));
- up = cross(axis, right);
-
- 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);
-}