2

使用openGL,我可以在屏幕中心绘制轴(x,y和z),但我不能在每行的末尾绘制它们的箭头。在 2d 中,我看到了一个使用 GL_LINE_STRIP 的示例代码,但在 3D 中,我搜索了很多,但没有找到任何示例;现在我只是在每行的末尾放一个点;但实际上它很丑陋。

我怎么画它?这段代码只是在适当的位置绘制 z 轴的圆柱体;怎么设置别人?

void Axis_3D (void)
{
    GLUquadric* cyl = gluNewQuadric();
    GLUquadric* cy2 = gluNewQuadric();
    GLUquadric* cy3 = gluNewQuadric();

   // gluCylinder (cyl, 0.02, 0.02, 4, 16, 1);        // Body of axis.

    glColor3f (1,1,1);                                // Make arrow head white.
    glPushMatrix ();
       glTranslatef (0.0,0.0,4);
       gluCylinder(cyl, 0.04, 0.000, 0.1, 12,1);   // Cone at end of axis.

       glTranslatef (0.0,4,0.0);
       gluCylinder  (cy2, 0.04, 0.001, 0.1, 12,1);

       glTranslatef (4,0.0,0.0);
       gluCylinder  (cy3, 0.04, 0.001, 0.1, 12,1);
    glPopMatrix ();
}

太感谢了!

4

3 回答 3

8

我使用这些函数在一个可爱的小模拟程序中绘制箭头。玩得开心使用它们:)

#define RADPERDEG 0.0174533

void Arrow(GLdouble x1,GLdouble y1,GLdouble z1,GLdouble x2,GLdouble y2,GLdouble z2,GLdouble D)
{
  double x=x2-x1;
  double y=y2-y1;
  double z=z2-z1;
  double L=sqrt(x*x+y*y+z*z);

    GLUquadricObj *quadObj;

    glPushMatrix ();

      glTranslated(x1,y1,z1);

      if((x!=0.)||(y!=0.)) {
        glRotated(atan2(y,x)/RADPERDEG,0.,0.,1.);
        glRotated(atan2(sqrt(x*x+y*y),z)/RADPERDEG,0.,1.,0.);
      } else if (z<0){
        glRotated(180,1.,0.,0.);
      }

      glTranslatef(0,0,L-4*D);

      quadObj = gluNewQuadric ();
      gluQuadricDrawStyle (quadObj, GLU_FILL);
      gluQuadricNormals (quadObj, GLU_SMOOTH);
      gluCylinder(quadObj, 2*D, 0.0, 4*D, 32, 1);
      gluDeleteQuadric(quadObj);

      quadObj = gluNewQuadric ();
      gluQuadricDrawStyle (quadObj, GLU_FILL);
      gluQuadricNormals (quadObj, GLU_SMOOTH);
      gluDisk(quadObj, 0.0, 2*D, 32, 1);
      gluDeleteQuadric(quadObj);

      glTranslatef(0,0,-L+4*D);

      quadObj = gluNewQuadric ();
      gluQuadricDrawStyle (quadObj, GLU_FILL);
      gluQuadricNormals (quadObj, GLU_SMOOTH);
      gluCylinder(quadObj, D, D, L-4*D, 32, 1);
      gluDeleteQuadric(quadObj);

      quadObj = gluNewQuadric ();
      gluQuadricDrawStyle (quadObj, GLU_FILL);
      gluQuadricNormals (quadObj, GLU_SMOOTH);
      gluDisk(quadObj, 0.0, D, 32, 1);
      gluDeleteQuadric(quadObj);

    glPopMatrix ();

}
void drawAxes(GLdouble length)
{
    glPushMatrix();
    glTranslatef(-length,0,0);
    Arrow(0,0,0, 2*length,0,0, 0.2);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0,-length,0);
    Arrow(0,0,0, 0,2*length,0, 0.2);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0,0,-length);
    Arrow(0,0,0, 0,0,2*length, 0.2);
    glPopMatrix();
}
于 2013-10-12T10:53:16.270 回答
2

当我破解我的平截头体插图程序时,我写了一个小箭头绘图辅助函数draw_arrow,它绘制了一个屏幕对齐的箭头 + 注释(使用 glutStorkeCharacter)。

请注意,它使用固定函数管道模型视图矩阵来确定局部空间基向量。如果要在基于着色器的管道中使用它,则必须通过附加参数将模型视图矩阵传递给它。

https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/frustum/frustum.c

void draw_arrow(
    float ax, float ay, float az,  /* starting point in local space */
    float bx, float by, float bz,  /* starting point in local space */
    float ah, float bh,            /* arrow head size start and end */
    char const * const annotation, /* annotation string */
    float annot_size               /* annotation string height (local units) */ )
{
    int i;

    GLdouble mv[16];
    glGetDoublev(GL_MODELVIEW_MATRIX, mv);

    /* We're assuming the modelview RS part is (isotropically scaled)
     * orthonormal, so the inverse is the transpose.
     * The local view direction vector is the 3rd column of the matrix;
     * assuming the view direction to be the normal on the arrows tangent
     * space  taking the cross product of this with the arrow direction
     * yields the binormal to be used as the orthonormal base to the 
     * arrow direction to be used for drawing the arrowheads */

    double d[3] = {
          bx - ax,
          by - ay,
          bz - az
    };
    normalize_v(d);

    double r[3] = { mv[0], mv[4], mv[8] };
    int rev = scalarproduct_v(d, r) < 0.;

    double n[3] = { mv[2], mv[6], mv[10] };
    {
        double const s = scalarproduct_v(d,n);
        for(int i = 0; i < 3; i++)
            n[i] -= d[i]*s;
    }
    normalize_v(n);

    double b[3];
    crossproduct_v(n, d, b);

    /* Make a 60° arrowhead ( sin(60°) = 0.866... ) */
    GLfloat const pos[][3] = {
        {ax, ay, az},
        {bx, by, bz},
        { ax + (0.866*d[0] + 0.5*b[0])*ah,
          ay + (0.866*d[1] + 0.5*b[1])*ah,
          az + (0.866*d[2] + 0.5*b[2])*ah },
        { ax + (0.866*d[0] - 0.5*b[0])*ah,
          ay + (0.866*d[1] - 0.5*b[1])*ah,
          az + (0.866*d[2] - 0.5*b[2])*ah },
        { bx + (-0.866*d[0] + 0.5*b[0])*bh,
          by + (-0.866*d[1] + 0.5*b[1])*bh,
          bz + (-0.866*d[2] + 0.5*b[2])*bh },
        { bx + (-0.866*d[0] - 0.5*b[0])*bh,
          by + (-0.866*d[1] - 0.5*b[1])*bh,
          bz + (-0.866*d[2] - 0.5*b[2])*bh }
    };
    GLushort const idx[][2] = {
        {0, 1},
        {0, 2}, {0, 3},
        {1, 4}, {1, 5}
    };
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, pos);

    glDrawElements(GL_LINES, 2*5, GL_UNSIGNED_SHORT, idx);
    glDisableClientState(GL_VERTEX_ARRAY);

    if(annotation) {
        float w = 0;
        for(char const *c = annotation; *c; c++)
            w += glutStrokeWidth(GLUT_STROKE_ROMAN, *c);
        w *= annot_size / 100.;

        float tx = (ax + bx)/2.;
        float ty = (ay + by)/2.;
        float tz = (az + bz)/2.;

        GLdouble r[16] = {
            d[0], d[1], d[2], 0,
            b[0], b[1], b[2], 0,
            n[0], n[1], n[2], 0,
               0,    0,    0, 1
        };
        glPushMatrix();
        glTranslatef(tx, ty, tz);
        glMultMatrixd(r);
        if(rev)
            glScalef(-1, -1, 1);
        glTranslatef(-w/2., annot_size*0.1, 0);
        draw_strokestring(GLUT_STROKE_ROMAN, annot_size, annotation);
        glPopMatrix();
    }
}

帮助自己。

于 2013-10-12T11:18:40.737 回答
0

我使用 The Quantum Physicist 的帮助并将其与我自己的代码合并,最后绘制了这个 Axes :

#define RADPERDEG 0.0174533
void Arrow(GLdouble x1,GLdouble y1,GLdouble z1,GLdouble x2,GLdouble y2,GLdouble z2,GLdouble D)
{
  double x=x2-x1;
  double y=y2-y1;
  double z=z2-z1;
  double L=sqrt(x*x+y*y+z*z);

    GLUquadricObj *quadObj;
    GLUquadric* cyl = gluNewQuadric();
    GLUquadric* cy2 = gluNewQuadric();
    GLUquadric* cy3 = gluNewQuadric();
    glPushMatrix ();

      glTranslated(x1,y1,z1);

      if((x!=0.)||(y!=0.)) {
        glRotated(atan2(y,x)/RADPERDEG,0.,0.,1.);
        glRotated(atan2(sqrt(x*x+y*y),z)/RADPERDEG,0.,1.,0.);
      } else if (z<0){
        glRotated(180,1.,0.,0.);
      }

      glTranslatef(0,0,L-4*D);

      gluQuadricDrawStyle (cyl, GLU_FILL);
      gluQuadricNormals (cyl, GLU_SMOOTH);
      glColor3f (1,1,1); 
      glTranslatef (0.0,0.0,4);
      gluCylinder(cyl, 0.04, 0.0, 1.0, 12,1);
      gluDeleteQuadric(cyl);

      glTranslatef(0,0,-L+4*D);

      gluQuadricDrawStyle (cy2, GLU_FILL);
      gluQuadricNormals (cy2, GLU_SMOOTH);
      glColor3f (1,1,1);
      glTranslatef (0.0,4,0.0);
      gluCylinder(cy2, 0.4, 0.4,L-1.6, 12,1);
      gluDeleteQuadric(cy2);

    glPopMatrix();

}
void drawAxes(GLdouble length)
{
    glPushMatrix();
    glTranslatef(-length,0,0);
    Arrow(0,0,0, 2*length,0,0,0.2);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0,-length,0);
    Arrow(0,0,0, 0,2*length,0,0.2);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0,0,-length);
    Arrow(0,0,0, 0,0,2*length,0.2);
    glPopMatrix();
}
于 2013-10-13T08:28:40.620 回答