シミュレーション屋のためのOpenGL入門 (おまけ)

シミュレーション屋のためのOpenGL入門

おまけ

1999.9.13

1. 棒を描く

gluに似たようなものがありますが、その簡略版を作ってみました。 座標軸などを描くのに便利です。 原点からz軸の正の方向にlength長さの半径radiusの正slices角柱を描きます。
void gliSolidPipe(GLdouble length, GLdouble radius, GLint slices)
/*
   length; 棒の長さ
   radius; 棒の半径
   slices; 多角形近似の角数
*/
{
  double dth, px0, px1, py0, py1;
  int i;
  glBoolean normal;

  normal = glIsEnabled(GL_NORMALIZE);
  glEnable(GL_NORMALIZE);
  dth = 2 * M_PI / slices;
  glBegin(GL_QUADS);
  px0 = radius; py0 = 0.0;
  for(i = 1;i <= slices;i++)
  {
    px1 = radius * cos(dth * i); py1 = radius * sin(dth * i);
    glVertex3d(px0, py0, length); glVertex3d(px0, py0, 0.0);
    glVertex3d(px1, py1, 0.0); glVertex3d(px1, py1, length);
    glNormal3d(px0 + px1, py0 + py1, 0.0);
    px0 = px1; py0 = py1;
  } 
  glEnd();
  if(!normal) glDisable(GL_NORMALIZE);
}

[目次に戻る]

2. 矢印を描く

矢印を描くプログラムです。 原点からz軸の正の方向に全体の長さがlength、尾の半径がtradius、 頭の半径がhradius、頭の長さがhlengthの矢印を描きます 尾の長さはlength-hlengthになります)。 頭はslices角錐と近似され、尾はslices角柱と近似されます。
void gliSolidArrow(GLdouble length, GLdouble tradius, GLdouble hradius,
                   GLdouble hlength, GLdouble slices)
/*
   length;  矢全体の長さ
   tradius; 尾の半径
   hradius; 頭の半径
   hlength; 頭の長さ
   slices;  多角形近似の角数
*/
{
  double dth, cs0, cs1, sn0, sn1;
  double tx0, tx1, ty0, ty1;
  double hx0, hx1, hy0, hy1;
  int i;
  GLboolean normal;

  normal = glIsEnabled(GL_NORMALIZE);
  glEnable(GL_NORMALIZE);
  dth = 2 * M_PI / slices;
  cs0 = 1.0; sn0 = 0.0;
  for(i = 1;i <= slices;i++)
  {
    cs1 = cos(dth * i); sn1 = sin(dth * i);
    tx0 = tradius * cs0; ty0 = tradius * sn0;
    tx1 = tradius * cs1; ty1 = tradius * sn1;
    hx0 = hradius * cs0; hy0 = hradius * sn0;
    hx1 = hradius * cs1; hy1 = hradius * sn1;
    glBegin(GL_QUADS);
     glNormal3d(cs0 + cs1, sn0 + sn1, 0.0);
     glVertex3d(tx0, ty0, length - hlength); glVertex3d(tx0, ty0, 0.0);
     glVertex3d(tx1, ty1, 0.0); glVertex3d(tx1, ty1, length - hlength);
    glEnd();
    glBegin(GL_TRIANGLES);
     glVertex3d(hx0, hy0, length - hlength);
     glVertex3d(hx1, hy1, length - hlength);
     glVertex3d(0.0, 0.0, length);
     glNormal3d(hlength * (hy1 - hy0) , hlength * (hx0 - hx1) ,
                hx0 * hy1 - hx1 * hy0);
    glEnd();
    glBegin(GL_TRIANGLES);
     glNormal3d(0.0, 0.0, -1.0);
     glVertex3d(tx0, ty0, 0.0); glVertex3d(tx1, ty1, 0.0);
     glVertex3d(0.0, 0.0, 0.0);
    glEnd();
    glBegin(GL_QUADS);
     glNormal3d(0.0, 0.0, -1.0);
     glVertex3d(tx0, ty0, length - hlength);
     glVertex3d(hx0, hy0, length - hlength);
     glVertex3d(hx1, hy1, length - hlength);
     glVertex3d(tx1, ty1, length - hlength);
    glEnd();

    cs0 = cs1; sn0 = sn1;
  } 
  if(!normal) glDisable(GL_NORMALIZE);
}

[目次に戻る]

3. 棒を描く(2)

gliSolidPipe()の拡張版で、2点間を結ぶ棒を描きます。
void gliSolidPipe2(GLdouble length, GLdouble radius, GLint slices,
                   GLdouble x0, GLdouble y0, GLdouble z0,
                   GLdouble x1, GLdouble y1, GLdouble z1)
/*
   length; 棒の長さ
   radius; 棒の半径
   slices; 多角形近似の角数
   x0, y0, z0; 棒の始点
   x1, y1, z1; 棒の終点
*/
{
  GLdouble m[16];
  GLdouble xx, yy, zz, a, b;

  xx=x1-x0; yy=y1-y0; zz=z1-z0;
  a=sqrt(xx*xx+yy*yy+zz*zz);
  if(z1>z0) b=sqrt(xx*xx+zz*zz);
  else      b=-sqrt(xx*xx+zz*zz);
  m[0]=zz*a/b;   m[1]=0.0; m[2]=-xx*a/b;  m[3]=0.0;
  m[4]=-xx*yy/b; m[5]=b;   m[6]=-yy*zz/b; m[7]=0.0;
  m[8]=xx;       m[9]=yy;  m[10]=zz;      m[11]=0.0;
  m[12]=x0;      m[13]=y0; m[14]=z0;      m[15]=1.0;
  glPushMatrix();
  glLoadMatrixd(m);
  gliSolidPipe(length, radius, slices);
  glPopMatrix();
}

[目次に戻る]


岩瀬康行(iwase@sci.hiroshima-u.ac.jp)