📄 gearsview.cpp
字号:
// GearsView.cpp : implementation of the CGearsView class
//
#include "stdafx.h"
#include "Gears.h"
#include "GearsDoc.h"
#include "GearsView.h"
//wb add down
#include "gl\gl.h"
#include "gl\glu.h"
#include "gl\glaux.h"
#include <stdlib.h>
#include <math.h>
#ifndef WIN32
#include <unistd.h>
#endif
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265
#endif
#include <sys/types.h>
#include <stdio.h>
/* For portability... */
#undef fcos
#undef fsin
#undef fsqrt
#define fcos cos
#define fsin sin
#define fsqrt sqrt
static double d_near = 1.0;
static double d_far = 2000;
static int poo = 0;
typedef struct {
float rad, wid;
} Profile;
void flat_face(float ir, float or, float wd);
void draw_inside(float w1, float w2, float rad);
void draw_outside(float w1, float w2, float rad);
void tooth_side(int nt, float ir, float or, float tp, float tip, float wd);
int circle_subdiv;
void
gear(int nt, float wd, float ir, float or, float tp, float tip, int ns, Profile * ip)
{
/**
* nt - number of teeth
* wd - width of gear at teeth
* ir - inside radius absolute scale
* or - radius at outside of wheel (tip of tooth) ratio of ir
* tp - ratio of tooth in slice of circle (0..1] (1 = teeth are touching at base)
* tip - ratio of tip of tooth (0..tp] (cant be wider that base of tooth)
* ns - number of elements in wheel width profile
* *ip - list of float pairs {start radius, width, ...} (width is ratio to wd)
*
*/
/* gear lying on xy plane, z for width. all normals calulated
(normalized) */
float prev;
int k, t;
/* estimat # times to divide circle */
if (nt <= 0)
circle_subdiv = 64;
else {
/* lowest multiple of number of teeth */
circle_subdiv = nt;
while (circle_subdiv < 64)
circle_subdiv += nt;
}
/* --- draw wheel face --- */
/* draw horzontal, vertical faces for each section. if first
section radius not zero, use wd for 0.. first if ns == 0
use wd for whole face. last width used to edge. */
if (ns <= 0) {
flat_face(0.0, ir, wd);
} else {
/* draw first flat_face, then continue in loop */
if (ip[0].rad > 0.0) {
flat_face(0.0, ip[0].rad * ir, wd);
prev = wd;
t = 0;
} else {
flat_face(0.0, ip[1].rad * ir, ip[0].wid * wd);
prev = ip[0].wid;
t = 1;
}
for (k = t; k < ns; k++) {
if (prev < ip[k].wid) {
draw_inside(prev * wd, ip[k].wid * wd, ip[k].rad * ir);
} else {
draw_outside(prev * wd, ip[k].wid * wd, ip[k].rad * ir);
}
prev = ip[k].wid;
/* - draw to edge of wheel, add final face if needed - */
if (k == ns - 1) {
flat_face(ip[k].rad * ir, ir, ip[k].wid * wd);
/* now draw side to match tooth rim */
if (ip[k].wid < 1.0) {
draw_inside(ip[k].wid * wd, wd, ir);
} else {
draw_outside(ip[k].wid * wd, wd, ir);
}
} else {
flat_face(ip[k].rad * ir, ip[k + 1].rad * ir, ip[k].wid * wd);
}
}
}
/* --- tooth side faces --- */
tooth_side(nt, ir, or, tp, tip, wd);
/* --- tooth hill surface --- */
}
void
tooth_side(int nt, float ir, float or, float tp, float tip, float wd)
{
float i;
float end = 2.0 * M_PI / nt;
float x[6], y[6];
float s[3], c[3];
or = or * ir; /* or is really a ratio of ir */
for (i = 0; i < 2.0 * M_PI - end / 4.0; i += end) {
c[0] = fcos(i);
s[0] = fsin(i);
c[1] = fcos(i + end * (0.5 - tip / 2));
s[1] = fsin(i + end * (0.5 - tip / 2));
c[2] = fcos(i + end * (0.5 + tp / 2));
s[2] = fsin(i + end * (0.5 + tp / 2));
x[0] = ir * c[0];
y[0] = ir * s[0];
x[5] = ir * fcos(i + end);
y[5] = ir * fsin(i + end);
/* ---treat veritices 1,4 special to match strait edge of
face */
x[1] = x[0] + (x[5] - x[0]) * (0.5 - tp / 2);
y[1] = y[0] + (y[5] - y[0]) * (0.5 - tp / 2);
x[4] = x[0] + (x[5] - x[0]) * (0.5 + tp / 2);
y[4] = y[0] + (y[5] - y[0]) * (0.5 + tp / 2);
x[2] = or * fcos(i + end * (0.5 - tip / 2));
y[2] = or * fsin(i + end * (0.5 - tip / 2));
x[3] = or * fcos(i + end * (0.5 + tip / 2));
y[3] = or * fsin(i + end * (0.5 + tip / 2));
/* draw face trapezoids as 2 tmesh */
glNormal3f(0.0, 0.0, 1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[2], y[2], wd / 2);
glVertex3f(x[1], y[1], wd / 2);
glVertex3f(x[3], y[3], wd / 2);
glVertex3f(x[4], y[4], wd / 2);
glEnd();
glNormal3f(0.0, 0.0, -1.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[2], y[2], -wd / 2);
glVertex3f(x[1], y[1], -wd / 2);
glVertex3f(x[3], y[3], -wd / 2);
glVertex3f(x[4], y[4], -wd / 2);
glEnd();
/* draw inside rim pieces */
glNormal3f(c[0], s[0], 0.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[0], y[0], -wd / 2);
glVertex3f(x[1], y[1], -wd / 2);
glVertex3f(x[0], y[0], wd / 2);
glVertex3f(x[1], y[1], wd / 2);
glEnd();
/* draw up hill side */
{
float a, b, n;
/* calculate normal of face */
a = x[2] - x[1];
b = y[2] - y[1];
n = 1.0 / fsqrt(a * a + b * b);
a = a * n;
b = b * n;
glNormal3f(b, -a, 0.0);
}
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[1], y[1], -wd / 2);
glVertex3f(x[2], y[2], -wd / 2);
glVertex3f(x[1], y[1], wd / 2);
glVertex3f(x[2], y[2], wd / 2);
glEnd();
/* draw top of hill */
glNormal3f(c[1], s[1], 0.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[2], y[2], -wd / 2);
glVertex3f(x[3], y[3], -wd / 2);
glVertex3f(x[2], y[2], wd / 2);
glVertex3f(x[3], y[3], wd / 2);
glEnd();
/* draw down hill side */
{
float a, b, c;
/* calculate normal of face */
a = x[4] - x[3];
b = y[4] - y[3];
c = 1.0 / fsqrt(a * a + b * b);
a = a * c;
b = b * c;
glNormal3f(b, -a, 0.0);
}
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[3], y[3], -wd / 2);
glVertex3f(x[4], y[4], -wd / 2);
glVertex3f(x[3], y[3], wd / 2);
glVertex3f(x[4], y[4], wd / 2);
glEnd();
/* inside rim part */
glNormal3f(c[2], s[2], 0.0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x[4], y[4], -wd / 2);
glVertex3f(x[5], y[5], -wd / 2);
glVertex3f(x[4], y[4], wd / 2);
glVertex3f(x[5], y[5], wd / 2);
glEnd();
}
}
void
flat_face(float ir, float or, float wd)
{
int i;
float w;
/* draw each face (top & bottom ) * */
if (poo)
printf("Face : %f..%f wid=%f\n", ir, or, wd);
if (wd == 0.0)
return;
for (w = wd / 2; w > -wd; w -= wd) {
if (w > 0.0)
glNormal3f(0.0, 0.0, 1.0);
else
glNormal3f(0.0, 0.0, -1.0);
if (ir == 0.0) {
/* draw as t-fan */
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, w); /* center */
glVertex3f(or, 0.0, w);
for (i = 1; i < circle_subdiv; i++) {
glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * or,
fsin(2.0 * M_PI * i / circle_subdiv) * or,
w);
}
glVertex3f(or, 0.0, w);
glEnd();
} else {
/* draw as tmesh */
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(or, 0.0, w);
glVertex3f(ir, 0.0, w);
for (i = 1; i < circle_subdiv; i++) {
glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * or,
fsin(2.0 * M_PI * i / circle_subdiv) * or,
w);
glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * ir,
fsin(2.0 * M_PI * i / circle_subdiv) * ir,
w);
}
glVertex3f(or, 0.0, w);
glVertex3f(ir, 0.0, w);
glEnd();
}
}
}
void
draw_inside(float w1, float w2, float rad)
{
int i, j;
float c, s;
if (poo)
printf("Inside: wid=%f..%f rad=%f\n", w1, w2, rad);
if (w1 == w2)
return;
w1 = w1 / 2;
w2 = w2 / 2;
for (j = 0; j < 2; j++) {
if (j == 1) {
w1 = -w1;
w2 = -w2;
}
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(rad, 0.0, w1);
glVertex3f(rad, 0.0, w2);
for (i = 1; i < circle_subdiv; i++) {
c = fcos(2.0 * M_PI * i / circle_subdiv);
s = fsin(2.0 * M_PI * i / circle_subdiv);
glNormal3f(-c, -s, 0.0);
glVertex3f(c * rad,
s * rad,
w1);
glVertex3f(c * rad,
s * rad,
w2);
}
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(rad, 0.0, w1);
glVertex3f(rad, 0.0, w2);
glEnd();
}
}
void
draw_outside(float w1, float w2, float rad)
{
int i, j;
float c, s;
if (poo)
printf("Outsid: wid=%f..%f rad=%f\n", w1, w2, rad);
if (w1 == w2)
return;
w1 = w1 / 2;
w2 = w2 / 2;
for (j = 0; j < 2; j++) {
if (j == 1) {
w1 = -w1;
w2 = -w2;
}
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(1.0, 0.0, 0.0);
glVertex3f(rad, 0.0, w1);
glVertex3f(rad, 0.0, w2);
for (i = 1; i < circle_subdiv; i++) {
c = fcos(2.0 * M_PI * i / circle_subdiv);
s = fsin(2.0 * M_PI * i / circle_subdiv);
glNormal3f(c, s, 0.0);
glVertex3f(c * rad,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -