/** * Create a gear wheel. * * @param inner_radius radius of hole at center * @param outer_radius radius at center of teeth * @param width width of gear * @param teeth number of teeth * @param tooth_depth depth of tooth * * @return pointer to the constructed struct gear */ static struct gear * create_gear (GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth) { GLfloat r0, r1, r2; GLfloat da; GearVertex *v; struct gear *gear; double s[5], c[5]; GLfloat normal[3]; int cur_strip = 0; int i; /* Allocate memory for the gear */ gear = malloc (sizeof *gear); if (gear == NULL) return NULL; /* Calculate the radii used in the gear */ r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0; r2 = outer_radius + tooth_depth / 2.0; da = 2.0 * M_PI / teeth / 4.0; /* Allocate memory for the triangle strip information */ gear->nstrips = STRIPS_PER_TOOTH * teeth; gear->strips = calloc (gear->nstrips, sizeof (*gear->strips)); /* Allocate memory for the vertices */ gear->vertices = calloc (VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices)); v = gear->vertices; for (i = 0; i < teeth; i++) { /* Calculate needed sin/cos for varius angles */ sincos (i * 2.0 * M_PI / teeth, &s[0], &c[0]); sincos (i * 2.0 * M_PI / teeth + da, &s[1], &c[1]); sincos (i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]); sincos (i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]); sincos (i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]); /* A set of macros for making the creation of the gears easier */ #define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] } #define SET_NORMAL(x, y, z) do { \ normal[0] = (x); normal[1] = (y); normal[2] = (z); \ } while(0) #define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) #define START_STRIP do { \ gear->strips[cur_strip].first = v - gear->vertices; \ } while(0); #define END_STRIP do { \ int _tmp = (v - gear->vertices); \ gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ cur_strip++; \ } while (0) #define QUAD_WITH_NORMAL(p1, p2) do { \ SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \ v = GEAR_VERT(v, (p1), -1); \ v = GEAR_VERT(v, (p1), 1); \ v = GEAR_VERT(v, (p2), -1); \ v = GEAR_VERT(v, (p2), 1); \ } while(0) { struct point { GLfloat x; GLfloat y; }; /* Create the 7 points (only x,y coords) used to draw a tooth */ struct point p[7] = { GEAR_POINT (r2, 1), // 0 GEAR_POINT (r2, 2), // 1 GEAR_POINT (r1, 0), // 2 GEAR_POINT (r1, 3), // 3 GEAR_POINT (r0, 0), // 4 GEAR_POINT (r1, 4), // 5 GEAR_POINT (r0, 4), // 6 }; /* Front face */ START_STRIP; SET_NORMAL (0, 0, 1.0); v = GEAR_VERT (v, 0, +1); v = GEAR_VERT (v, 1, +1); v = GEAR_VERT (v, 2, +1); v = GEAR_VERT (v, 3, +1); v = GEAR_VERT (v, 4, +1); v = GEAR_VERT (v, 5, +1); v = GEAR_VERT (v, 6, +1); END_STRIP; /* Inner face */ START_STRIP; QUAD_WITH_NORMAL (4, 6); END_STRIP; /* Back face */ START_STRIP; SET_NORMAL (0, 0, -1.0); v = GEAR_VERT (v, 6, -1); v = GEAR_VERT (v, 5, -1); v = GEAR_VERT (v, 4, -1); v = GEAR_VERT (v, 3, -1); v = GEAR_VERT (v, 2, -1); v = GEAR_VERT (v, 1, -1); v = GEAR_VERT (v, 0, -1); END_STRIP; /* Outer face */ START_STRIP; QUAD_WITH_NORMAL (0, 2); END_STRIP; START_STRIP; QUAD_WITH_NORMAL (1, 0); END_STRIP; START_STRIP; QUAD_WITH_NORMAL (3, 1); END_STRIP; START_STRIP; QUAD_WITH_NORMAL (5, 3); END_STRIP; } } gear->nvertices = (v - gear->vertices); /* Store the vertices in a vertex buffer object (VBO) */ glGenBuffers (1, &gear->vbo); glBindBuffer (GL_ARRAY_BUFFER, gear->vbo); glBufferData (GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex), gear->vertices, GL_STATIC_DRAW); return gear; }
/** * Create a gear wheel. * * @param inner_radius radius of hole at center * @param outer_radius radius at center of teeth * @param width width of gear * @param teeth number of teeth * @param tooth_depth depth of tooth * * @return pointer to the constructed struct gear */ static struct gear * create_gear(struct pipe_screen *screen, struct pipe_context *pipe, float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) { float r0, r1, r2; float da; GearVertex *v; struct gear *gear; double s[5], c[5]; float normal[3]; int cur_strip = 0; int i; /* Allocate memory for the gear */ gear = malloc(sizeof *gear); if (gear == NULL) return NULL; /* Calculate the radii used in the gear */ r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0; r2 = outer_radius + tooth_depth / 2.0; da = 2.0 * M_PI / teeth / 4.0; /* Allocate memory for the triangle strip information */ gear->nstrips = STRIPS_PER_TOOTH * teeth; gear->strips = calloc(gear->nstrips, sizeof (*gear->strips)); /* Allocate memory for the vertices */ gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices)); v = gear->vertices; for (i = 0; i < teeth; i++) { /* Calculate needed sin/cos for varius angles */ sincos_(i * 2.0 * M_PI / teeth, &s[0], &c[0]); sincos_(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]); sincos_(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]); sincos_(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]); sincos_(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]); /* A set of macros for making the creation of the gears easier */ #define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] } #define SET_NORMAL(x, y, z) do { \ normal[0] = (x); normal[1] = (y); normal[2] = (z); \ } while(0) #define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) #define START_STRIP do { \ gear->strips[cur_strip].first = v - gear->vertices; \ } while(0); #define END_STRIP do { \ int _tmp = (v - gear->vertices); \ gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ cur_strip++; \ } while (0) #define QUAD_WITH_NORMAL(p1, p2) do { \ SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \ v = GEAR_VERT(v, (p1), -1); \ v = GEAR_VERT(v, (p1), 1); \ v = GEAR_VERT(v, (p2), -1); \ v = GEAR_VERT(v, (p2), 1); \ } while(0) struct point { float x; float y; }; /* Create the 7 points (only x,y coords) used to draw a tooth */ struct point p[7] = { GEAR_POINT(r2, 1), // 0 GEAR_POINT(r2, 2), // 1 GEAR_POINT(r1, 0), // 2 GEAR_POINT(r1, 3), // 3 GEAR_POINT(r0, 0), // 4 GEAR_POINT(r1, 4), // 5 GEAR_POINT(r0, 4), // 6 }; /* Front face */ START_STRIP; SET_NORMAL(0, 0, 1.0); v = GEAR_VERT(v, 0, +1); v = GEAR_VERT(v, 1, +1); v = GEAR_VERT(v, 2, +1); v = GEAR_VERT(v, 3, +1); v = GEAR_VERT(v, 4, +1); v = GEAR_VERT(v, 5, +1); v = GEAR_VERT(v, 6, +1); END_STRIP; /* Inner face */ START_STRIP; QUAD_WITH_NORMAL(4, 6); END_STRIP; /* Back face */ START_STRIP; SET_NORMAL(0, 0, -1.0); v = GEAR_VERT(v, 6, -1); v = GEAR_VERT(v, 5, -1); v = GEAR_VERT(v, 4, -1); v = GEAR_VERT(v, 3, -1); v = GEAR_VERT(v, 2, -1); v = GEAR_VERT(v, 1, -1); v = GEAR_VERT(v, 0, -1); END_STRIP; /* Outer face */ START_STRIP; QUAD_WITH_NORMAL(0, 2); END_STRIP; START_STRIP; QUAD_WITH_NORMAL(1, 0); END_STRIP; START_STRIP; QUAD_WITH_NORMAL(3, 1); END_STRIP; START_STRIP; QUAD_WITH_NORMAL(5, 3); END_STRIP; } gear->nvertices = (v - gear->vertices); /* element layout */ struct pipe_vertex_element pipe_vertex_elements[] = { { /* positions */ .src_offset = 0x0, .instance_divisor = 0, .vertex_buffer_index = 0, .src_format = PIPE_FORMAT_R32G32B32_FLOAT }, { /* normals */ .src_offset = 0xc,