⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gearsview.cpp

📁 C:Documents and SettingsAdministrator桌面VC++多媒体特效制作百例CHAR08Gears
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -