--- /dev/null
+#include "app.h"
+
+bool opt_gear_wireframe;
--- /dev/null
+#ifndef APP_H_
+#define APP_H_
+
+extern bool opt_gear_wireframe;
+
+#endif // APP_H_
#include <GL/glew.h>
#include "gear.h"
#include "meshgen.h"
+#include "app.h"
Gear::Gear()
: axis(0, 0, 1)
thickness = 5;
bevel = 1.5;
init_angle = 0;
+ xform_valid = false;
mesh = 0;
}
init_angle = get_angular_pitch() * 3.0 / 8.0;
}
-float Gear::get_rotation() const
+void Gear::set_axis(const Vec3 &axis)
+{
+ this->axis = normalize(axis);
+ xform_valid = false;
+}
+
+void Gear::set_position(const Vec3 &pos)
+{
+ this->pos = pos;
+ xform_valid = false;
+}
+
+const Vec3 &Gear::get_position() const
+{
+ return pos;
+}
+
+Vec3 Gear::get_global_position() const
+{
+ return pos; // TODO
+}
+
+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 xform;
+}
+
float Gear::get_angular_pitch() const
{
return 2.0 * M_PI / (float)nteeth;
}
calc_matrix();
+ glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
+
glPushMatrix();
glMultMatrixf(xform[0]);
+ if(opt_gear_wireframe) {
+ glPolygonOffset(1, 1);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+
mesh->draw();
- glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
+ if(opt_gear_wireframe) {
+ glColor3f(0.2, 0.4, 1.0);
+ mesh->draw_wire();
+ }
+
glLineWidth(2.0);
glBegin(GL_LINES);
glColor3f(0, 0, 1);
glVertex3f(0, 0, -10);
glVertex3f(0, 0, 10);
glEnd();
- glLineWidth(1.0);
- glPopAttrib();
glPopMatrix();
+ glPopAttrib();
}
static Vec2 rev_pos(float u, float v, void *cls)
Vec3 right = normalize(cross(up, axis));
up = cross(axis, right);
- xform = Mat4(right, up, axis);
- xform.rotate_z(get_rotation());
+ dir_xform = Mat4(right, up, axis);
+
+ xform = dir_xform;
+ xform.rotate_z(get_vis_rotation());
xform.translate(pos);
}
private:
Mesh *mesh;
- mutable Mat4 xform;
+ mutable Mat4 xform, dir_xform;
+ mutable bool xform_valid;
void calc_matrix() const;
float contour(float u);
public:
+
+ /* TODO hide most of this shit, especially the stuff which invalidate
+ * the transformation matrices
+ */
std::string name;
- Vec3 pos, axis; /* implicitly defines a plane eqn. */
- float pdist; /* derived: distance of plane from origin */
+ Vec3 pos, axis; // implicitly defines a plane eqn.
+ float pdist; // derived: distance of plane from origin
- float init_angle; /* initial starting angle */
- float angle; /* current angle of the gear */
+ float init_angle; // initial starting angle
+ float angle; // current angle of the gear
- int nteeth; /* number of teeth */
+ int nteeth; // number of teeth
- float radius; /* total radius of the gear, including teeth */
- float teeth_length; /* how far teeth extend past the radius */
- float thickness; /* thickness of the gear along the Z axis */
+ float radius; // total radius of the gear, including teeth
+ float teeth_length; // how far teeth extend past the radius
+ float thickness; // thickness of the gear along the Z axis
- float bevel; /* bevel size */
+ float bevel; // bevel size
std::vector<GearPin> pins;
std::vector<GearSlot> slots;
// sets the supplied number of teeth, and calculates the radius
// of the gear, to achieve the required tooth pitch
void set_teeth(int nt, float tooth_pitch);
+ void set_axis(const Vec3 &axis);
+ void set_position(const Vec3 &pos);
+ const Vec3 &get_position() const;
+ Vec3 get_global_position() const; // taking parent gear into account
+
+ void set_angle(float angle);
+ float get_angle() const;
- float get_rotation() const;
+ float get_vis_rotation() const;
+ const Mat4 &get_matrix() const;
+ const Mat4 &get_dir_matrix() const;
// returns the angle (in radians) from one tooth to the next
float get_angular_pitch() const;
#include "machine.h"
static float delta_angle(float a, float b);
-static float signed_delta_angle(float a, float b);
Machine::Machine()
{
}
if(meshing) {
- for(int i=0; i<ngears; i++) {
- delete [] meshing[i];
- }
+ delete [] meshing[0];
delete [] meshing;
}
delete [] visited;
if(!meshing) {
meshing = new bool*[ngears];
- for(int i=0; i<ngears; i++) {
- meshing[i] = new bool[ngears];
+ meshing[0] = new bool[ngears * ngears];
+
+ for(int i=1; i<ngears; i++) {
+ meshing[i] = meshing[i - 1] + ngears;
}
}
visited = new bool[ngears];
}
- // let's mesh everything together just for shits and giggles
+ // we're going to need the inverse of each gear's matrix, so let's cache it here
+ Mat4 *inv_xform = (Mat4*)alloca(ngears * sizeof *inv_xform);
for(int i=0; i<ngears; i++) {
- for(int j=0; j<ngears; j++) {
- meshing[i][j] = abs(i - j) & 1 ? true : false;
- if(meshing[i][j]) {
- printf("connecting %d - %d\n", i, j);
+ inv_xform[i] = transpose(gears[i]->get_dir_matrix());
+ }
+
+ for(int i=0; i<ngears; i++) {
+ for(int j=i; j<ngears; j++) {
+ meshing[i][j] = meshing[j][i] = false;
+
+ if(i == j) continue;
+
+ if(1.0 - fabs(dot(gears[i]->axis, gears[j]->axis)) < 1e-5) {
+ // co-planar, just check Z range after inverse-transforming to the XY plane
+ Vec3 pos_i = inv_xform[i] * gears[i]->get_position();
+ Vec3 pos_j = inv_xform[j] * gears[j]->get_position();
+
+ if(fabs(pos_i.z - pos_j.z) > (gears[i]->thickness + gears[j]->thickness) / 2.0) {
+ continue;
+ }
+ // Z interval match, check distance
+ float dsq = length_sq(pos_i.xy() - pos_j.xy());
+
+ float outer_rad_sum = gears[i]->radius + gears[j]->radius;
+ float inner_rad_sum = outer_rad_sum - gears[i]->teeth_length - gears[j]->teeth_length;
+
+ if(dsq <= outer_rad_sum * outer_rad_sum && dsq >= inner_rad_sum * inner_rad_sum) {
+ printf("connecting co-planar gears %d - %d\n", i, j);
+ meshing[i][j] = meshing[j][i] = true;
+ }
+
+ } else {
+ /* TODO: not co-planar
+ * - calc line of intersection between the two planes
+ * - find distance of each gear to that line
+ * - profit...
+ */
}
}
}
if(meshing[i][j]) {
assert(i != j);
- float tarc = gears[i]->get_angular_pitch(); // assumed to be the same for meshing gears
-
float frac_i = fmod(gears[i]->init_angle / gears[i]->get_angular_pitch() + 1.0, 1.0);
float frac_j = fmod(gears[j]->init_angle / gears[j]->get_angular_pitch() + 1.0, 1.0);
float delta = frac_j - frac_i;
return;
}
- gears[idx]->angle = angle;
+ gears[idx]->set_angle(angle);
visited[idx] = true;
int ngears = (int)gears.size();
float bpi = fmod(b + M_PI, 2.0 * M_PI);
return std::min(fabs(a - b), fabs(api - bpi));
}
-
-
-static float signed_delta_angle(float a, float b)
-{
- float api = fmod(a + M_PI, 2.0 * M_PI);
- float bpi = fmod(b + M_PI, 2.0 * M_PI);
-
- if(fabs(a - b) < fabs(api - bpi)) {
- return a - b;
- }
- return api - bpi;
-}
#else
#include <GL/glut.h>
#endif
+#include "app.h"
#include "machine.h"
bool init();
void mouse(int bn, int st, int x, int y);
void motion(int x, int y);
-static float cam_dist = 2;
+static float cam_dist = 0.5;
static float cam_theta, cam_phi;
static int prev_mx, prev_my;
static bool bnstate[8];
void draw_gears()
{
- /* world scale is in meters, gears are in millimeters, sclae by 1/1000 */
+ /* world scale is in meters, gears are in millimeters, scale by 1/1000 */
glPushMatrix();
glScalef(0.001, 0.001, 0.001);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- gluPerspective(50.0, (float)x / (float)y, 0.05, 100.0);
+ gluPerspective(50.0, (float)x / (float)y, 0.01, 100.0);
}
void keyb(unsigned char key, int x, int y)
switch(key) {
case 27:
exit(0);
+
+ case 'w':
+ opt_gear_wireframe = !opt_gear_wireframe;
+ glutPostRedisplay();
+ break;
}
}