OpenGL 恐龙模型错误 : gluTessCallback issue

标签 opengl 3d glut freeglut

我正在上一门计算机图形课,教我们如何将 OpenGL 与过剩库一起使用。我有一个最终项目的想法,该项目涉及将照明和纹理放在我在网上找到的恐龙模型上。我的第一步是简化现有的在线代码,这样我就可以开始我的项目了。

不幸的是,该模型的在线代码已损坏,我似乎无法弄清楚。我不确定 gluTessCallback 做了什么,但我的程序对这段代码的两行感到非常不安,这使得无法在 Visual Studio 2012 上运行该程序。

下面是代码,我已经指出了哪两行给我带来了麻烦。

typedef enum {
    RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
    LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
} displayLists;

GLfloat angle = -150;   /* in degrees */
GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE;
int moving, begin;
int W = 300, H = 300;
GLdouble bodyWidth = 2.0;
int newModel = 1;
GLfloat body[][2] = { { 0, 3 },{ 1, 1 },{ 5, 1 },{ 8, 4 },{ 10, 4 },{ 11, 5 },
{ 11, 11.5 },{ 13, 12 },{ 13, 13 },{ 10, 13.5 },{ 13, 14 },{ 13, 15 },{ 11, 16 },
{ 8, 16 },{ 7, 15 },{ 7, 13 },{ 8, 12 },{ 7, 11 },{ 6, 6 },{ 4, 3 },{ 3, 2 },
{ 1, 2 } };
GLfloat arm[][2] = { { 8, 10 },{ 9, 9 },{ 10, 9 },{ 13, 8 },{ 14, 9 },{ 16, 9 },
{ 15, 9.5 },{ 16, 10 },{ 15, 10 },{ 15.5, 11 },{ 14.5, 10 },{ 14, 11 },{ 14, 10 },
{ 13, 9 },{ 11, 11 },{ 9, 11 } };
GLfloat leg[][2] = { { 8, 6 },{ 8, 4 },{ 9, 3 },{ 9, 2 },{ 8, 1 },{ 8, 0.5 },{ 9, 0 },
{ 12, 0 },{ 10, 1 },{ 10, 2 },{ 12, 4 },{ 11, 6 },{ 10, 7 },{ 9, 7 } };
GLfloat eye[][2] = { { 8.75, 15 },{ 9, 14.7 },{ 9.6, 14.7 },{ 10.1, 15 },
{ 9.6, 15.25 },{ 9, 15.25 } };
GLfloat lightZeroPosition[] = { 10.0, 4.0, 10.0, 1.0 };
GLfloat lightZeroColor[] = { 0.8, 1.0, 0.8, 1.0 }; /* green-tinted */
GLfloat lightOnePosition[] = { -1.0, -2.0, 1.0, 0.0 };
GLfloat lightOneColor[] = { 0.6, 0.3, 0.2, 1.0 }; /* red-tinted */
GLfloat skinColor[] = { 0.1, 1.0, 0.1, 1.0 }, eyeColor[] = { 1.0, 0.2, 0.2, 1.0 };


void
extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
    GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
    static GLUtriangulatorObj *tobj = NULL;
    GLdouble vertex[3], dx, dy, len;
    int i;
    int count = dataSize / (int)(2 * sizeof(GLfloat));

    if (tobj == NULL) {
        tobj = gluNewTess();  /* create and initialize a GLU
                              polygon tesselation object */

        /////////////////////////////////////////////////////////////////////////////////////////
        // THESE LINES WILL NOT COMPILE. Says that the glBegin and glVertex2fv are incompatable.
        gluTessCallback(tobj, GLU_BEGIN, glBegin);
        gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky */
        /////////////////////////////////////////////////////////////////////////////////////////


        gluTessCallback(tobj, GLU_END, glEnd);
    }
    glNewList(side, GL_COMPILE);
    glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
                              tessellation */
    gluBeginPolygon(tobj);

    /////////////////////////////////////////////////////////////////////////////////////////
    // ALSO A PROBLEM WITH THIS SECTION OF CODE? 
    for (i = 0; i < count; i++) {
        vertex[0] = data[i][0];
        vertex[1] = data[i][1];
        vertex[2] = 0;
        gluTessVertex(tobj, vertex, data[i]);
    }
    gluEndPolygon(tobj);
    glEndList();
    /////////////////////////////////////////////////////////////////////////////////////////


    glNewList(edge, GL_COMPILE);
    glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
                            from being "smoothed" */
    glBegin(GL_QUAD_STRIP);
    for (i = 0; i <= count; i++) {
        /* mod function handles closing the edge */
        glVertex3f(data[i % count][0], data[i % count][1], 0.0);
        glVertex3f(data[i % count][0], data[i % count][1], thickness);
        /* Calculate a unit normal by dividing by Euclidean
        distance. We * could be lazy and use
        glEnable(GL_NORMALIZE) so we could pass in * arbitrary
        normals for a very slight performance hit. */
        dx = data[(i + 1) % count][1] - data[i % count][1];
        dy = data[i % count][0] - data[(i + 1) % count][0];
        len = sqrt(dx * dx + dy * dy);
        glNormal3f(dx / len, dy / len, 0.0);
    }
    glEnd();
    glEndList();
    glNewList(whole, GL_COMPILE);
    glFrontFace(GL_CW);
    glCallList(edge);
    glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
    glCallList(side);
    glPushMatrix();
    glTranslatef(0.0, 0.0, thickness);
    glFrontFace(GL_CCW);
    glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side */
    glCallList(side);
    glPopMatrix();
    glEndList();
}

void
makeDinosaur(void)
{
    GLfloat bodyWidth = 3.0;

    extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
        BODY_SIDE, BODY_EDGE, BODY_WHOLE);
    extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
        ARM_SIDE, ARM_EDGE, ARM_WHOLE);
    extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
        LEG_SIDE, LEG_EDGE, LEG_WHOLE);
    extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
        EYE_SIDE, EYE_EDGE, EYE_WHOLE);
    glNewList(DINOSAUR, GL_COMPILE);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
    glCallList(BODY_WHOLE);
    glPushMatrix();
    glTranslatef(0.0, 0.0, bodyWidth);
    glCallList(ARM_WHOLE);
    glCallList(LEG_WHOLE);
    glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
    glCallList(ARM_WHOLE);
    glTranslatef(0.0, 0.0, -bodyWidth / 4);
    glCallList(LEG_WHOLE);
    glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
    glCallList(EYE_WHOLE);
    glPopMatrix();
    glEndList();
}

void
recalcModelView(void)
{
    glPopMatrix();
    glPushMatrix();
    glRotatef(angle, 0.0, 1.0, 0.0);
    glTranslatef(-8, -8, -bodyWidth / 2);
    newModel = 0;
}

void
redraw(void)
{
    if (newModel)
        recalcModelView();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glCallList(DINOSAUR);
    glutSwapBuffers();
}

/* ARGSUSED2 */
void
mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        moving = 1;
        begin = x;
    }
    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
        moving = 0;
    }
}

/* ARGSUSED1 */
void
motion(int x, int y)
{
    if (moving) {
        angle = angle + (x - begin);
        begin = x;
        newModel = 1;
        glutPostRedisplay();
    }
}

GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;

void
controlLights(int value)
{
    switch (value) {
    case 1:
        lightZeroSwitch = !lightZeroSwitch;
        if (lightZeroSwitch) {
            glEnable(GL_LIGHT0);
        }
        else {
            glDisable(GL_LIGHT0);
        }
        break;
    case 2:
        lightOneSwitch = !lightOneSwitch;
        if (lightOneSwitch) {
            glEnable(GL_LIGHT1);
        }
        else {
            glDisable(GL_LIGHT1);
        }
        break;
    }
    glutPostRedisplay();
}

int
main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("glutdino");
    glutDisplayFunc(redraw);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutCreateMenu(controlLights);
    glutAddMenuEntry("Toggle right light", 1);
    glutAddMenuEntry("Toggle left light", 2);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    makeDinosaur();
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glMatrixMode(GL_PROJECTION);
    gluPerspective( /* field of view in degree */ 40.0,
        /* aspect ratio */ 1.0,
        /* Z near */ 1.0, /* Z far */ 40.0);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
        0.0, 0.0, 0.0,      /* center is at (0,0,0) */
        0.0, 1.0, 0.);      /* up is in postivie Y direction */
    glPushMatrix();       /* dummy push so we can pop on model
                          recalc */
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
    glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glutMainLoop();
    return 0;             /* ANSI C requires main to return int. */
}

我试着说清楚问题出在哪里。 OpenGl 让我无计可施。有没有什么地方可以在互联网上找到一个简单的 3D 恐龙模型来玩?

我希望您能就这个 gluTessCallback 问题向我提供一些见解,以便我可以正常工作。我只想要一个实体恐龙模型。

最佳答案

查看 man page ,传递给 gluTessCallback() 的回调签名取决于作为第二个参数传递的枚举值。这意味着,如果您使用的是 C++ 或使用函数原型(prototype)的 C 版本,则需要进行类型转换以将函数转换为 gluTessCallback() 所需的类型。

根据手册页,参数类型定义为 _GLUfuncptr。但是,该类型未在我发现的 glu.h header 中定义。根据规范和 header 的类型是一个没有参数且返回类型为 GLvoid 的函数。您可以为此定义自己的函数类型,然后转换为它:

typedef GLvoid (*TessFuncPtr)();

gluTessCallback(tobj, GLU_BEGIN, (TessFuncPtr)glBegin);
gluTessCallback(tobj, GLU_VERTEX, (TessFuncPtr)glVertex2fv);

如果您刚开始学习 OpenGL,您应该知道这段代码中的几乎所有调用都已弃用和过时。这包括:

  • 立即模式呈现(glBeginglEnd 等)。
  • 显示列表。
  • 矩阵堆栈。
  • 固定功能照明和 Material 定义。

我认为学习当前版本的 OpenGL 会更好。例如,您尝试使用的曲面分割功能是在将近 25 年前定义的。除了被弃用之外,我认为它一开始就没有被广泛使用。

关于OpenGL 恐龙模型错误 : gluTessCallback issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33600619/

相关文章:

opengl - OpenGL 的硬件要求

opengl - 在 GLSL 中对矩阵使用预乘顺序有什么缺点吗?

c++ - 使用 OpenGL 从文本文件绘制图像

c - OpenGL函数不输出任何错误但不起作用

c++ - GLUT - 什么是 imageloader.h,我怎样才能得到正确的?

使用 new 关键字创建的 C++ 对象不呈现;在堆栈上创建的对象确实

c++ - OpenGL-三角形没有被显示?

c++ - 如何从 View 矩阵获取当前相机位置?

c - 如何找到图形管道的瓶颈

javascript - 如何在 Three.js 中从一系列 3D 点创建 3D 多边形?