c++ - Blade 的扭曲效果 (glRotatef) 不起作用

标签 c++ opengl glut

我正在尝试为 Blade 创建一个扭曲效果(不是旋转),但它根本不起作用。特别是,我正在尝试使用 glRotatef 函数来旋转轴并使其看起来像 Blade 在扭曲。

任何帮助都会很棒。

enter image description here

#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265

static GLfloat lpos[] = { 0.0, 0.0, 4.0, 1.0 };
static GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
static GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
static float alpha = 0.0;
static float beta = PI / 6.0;
static float zoom = 10.0;
static bool lightSource = true;
float twistConstant = 0;
float rotateConstant = 0;
float numberOfObj = 3;
float numberOfTriangles = 1;
static GLdouble cpos[3];



void DrawTopTriangleSet(){
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow);
    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow);
    glBegin(GL_TRIANGLE_STRIP);

    for (int i = 180; i >= 0; i = i - numberOfTriangles){
        if (i > 90){
            glPushMatrix();
            glLoadIdentity();
            glRotatef(i, 1, 0, 0);
            glPopMatrix();
        }
        glNormal3f(0, sin(PI / 4 + twistConstant), cos(PI / 4 + twistConstant - PI / 4));
        glVertex3f(i*PI / 180, 0, 0.5*sin(i*PI / 180));
        glVertex3f(i*PI / 180, 0.5*sin(i*PI / 180), twistConstant*-sin(i*PI / 180));
    }
    glEnd();
}

void DrawBottomTriangleSet(){
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow);
    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow);
    glBegin(GL_TRIANGLE_STRIP);

    for (int i = 180; i >= 0; i = i - numberOfTriangles){
        if (i > 90){
            glPushMatrix();
            glLoadIdentity();
            glRotatef(i, 1, 0, 0);
            glPopMatrix();
        }
        glNormal3f(0, -sin(PI / 4 + twistConstant), cos(PI / 4 + twistConstant - PI / 4));
        glVertex3f(i*PI / 180, -0.5*sin(i*PI / 180), twistConstant*sin(i*PI / 180));
        glVertex3f(i*PI / 180, 0, 0.5*sin(i*PI / 180));
    }

    glEnd();
}

void DrawBackTriangleSet(){
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow);
    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow);
    glBegin(GL_TRIANGLE_STRIP);


    for (int i = 180; i >= 0; i = i - numberOfTriangles){
        if (i > 90){
            glPushMatrix();
            glLoadIdentity();
            glRotatef(i, 1, 0, 0);
            glPopMatrix();
        }
        glNormal3f(0, 5 * sin(PI - twistConstant), 5 * cos(PI - twistConstant));
        glVertex3f(i*PI / 180, 0.5*sin(i*PI / 180), twistConstant*-sin(i*PI / 180));
        glVertex3f(i*PI / 180, -0.5*sin(i*PI / 180), twistConstant*sin(i*PI / 180));
    }
    glEnd();

}

void DrawInsideTriangleSet(){
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glBegin(GL_TRIANGLE_STRIP);

    for (int i = 180; i >= 0; i = i - numberOfTriangles){
        if (i > 90){
            glPushMatrix();
            glLoadIdentity();
            glRotatef(i, 1, 0, 0);
            glPopMatrix();
        }
        glVertex3f(i*PI / 180, 0.5*sin(i*PI / 180), twistConstant*-sin(i*PI / 180));
        glVertex3f(i*PI / 180, 0, 0.5*sin(i*PI / 180));
        glVertex3f(i*PI / 180, -0.5*sin(i*PI / 180), twistConstant*sin(i*PI / 180));
    }

    glEnd();
}

void writemessage()
{
    printf(" X => x++ <= Move light source in direction of +X\n");
    printf(" Y => y++ <= Move light source in direction of +Y\n");
    printf(" Z => z++ <= Move light source in direction of +Z\n");
    printf("\n");
    printf("^X => x-- <= Move light source in direction of -X\n");
    printf("^Y => y-- <= Move light source in direction of -Y\n");
    printf("^Z => z-- <= Move light source in direction of -Z\n");
    printf("\n");
    printf(" ^ => Move camera up\n");
    printf(" > => Move camera right\n");
    printf(" < => Move camera left\n");
    printf(" down arrow => Move camera down\n");
    printf("\n");
    printf(" t => More Twist\n");
    printf(" f => Less Twist\n");
    printf("\n");
    printf(" q => More Propeller\n");
    printf(" f => Less Propeller\n");
    printf("\n");
    printf(" w => More Triangles\n");
    printf(" s => Less Triangles\n");
    printf("\n");
    printf(" 0 => Toggling light source\n");
    printf("\n");
    printf(" r => Rotates Propeller\n");
    printf("\n");
    printf(" You can not move the light source when the light source is off !!!");
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.01, 20.0);
    glMatrixMode(GL_MODELVIEW);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    cpos[0] = zoom * cos(beta) * sin(alpha);
    cpos[1] = zoom * sin(beta);
    cpos[2] = zoom * cos(beta) * cos(alpha);
    gluLookAt(cpos[0], cpos[1], cpos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    if (lightSource == true){
        glLightfv(GL_LIGHT0, GL_POSITION, lpos);
        glMaterialfv(GL_FRONT, GL_EMISSION, white);
        glPushMatrix();
        glTranslatef(lpos[0], lpos[1], lpos[2]);
        glutSolidSphere(0.1, 10, 8);
        glPopMatrix();
        glMaterialfv(GL_FRONT, GL_EMISSION, black);
    }
    glRotatef(rotateConstant, 0, 0, 1);


    for (int i = 0; i < numberOfObj; i++){
        glPushMatrix();
        glRotatef(i * 360 / numberOfObj, 0, 0, 1);

        DrawTopTriangleSet();
        DrawBottomTriangleSet();
        DrawBackTriangleSet();
        DrawInsideTriangleSet();

        glPopMatrix();
    }


    // Cone
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, red);
    glPushMatrix();
    glTranslated(0, 0, -1.5);
    glutSolidCone(1, 2, 50, 50);
    glPopMatrix();

    // Back of Cone
    glMaterialfv(GL_FRONT, GL_EMISSION, black);
    glMaterialfv(GL_BACK, GL_EMISSION, black);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
    glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, red);
    glBegin(GL_POLYGON);
    glNormal3f(0, 0, 1);
    for (int i = 0; i <= 360; i++)
    {
        glVertex3f(cos(i*PI / 180) * 1, sin(i*PI / 180) * 1, -1.5);
    }

    glEnd();


    glutSwapBuffers();
    glFlush();
}


void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
    case 27:
        exit(0);
        break;
    case 'x':
        if (lightSource == true)
            lpos[0] = lpos[0] + 0.2;
        glutPostRedisplay();
        break;
    case 'X':
        if (lightSource == true)
            lpos[0] = lpos[0] - 0.2;
        glutPostRedisplay();
        break;
    case 'y':
        if (lightSource == true)
            lpos[1] = lpos[1] + 0.2;
        glutPostRedisplay();
        break;
    case 'Y':
        if (lightSource == true)
            lpos[1] = lpos[1] - 0.2;
        glutPostRedisplay();
        break;
    case 'z':
        if (lightSource == true)
            lpos[2] = lpos[2] + 0.2;
        glutPostRedisplay();
        break;
    case 'Z':
        if (lightSource == true)
            lpos[2] = lpos[2] - 0.2;
        glutPostRedisplay();
        break;

    case '+':
        if (zoom != 1.5)zoom = zoom - 0.5;
        glutPostRedisplay();
        break;
    case '-':
        if (zoom != 15)zoom = zoom + 0.5;
        glutPostRedisplay();
        break;
    case '0':
        if (lightSource == true){
            glDisable(GL_LIGHT0);
            lightSource = false;
        }
        else{
            glEnable(GL_LIGHT0);
            lightSource = true;
        }
        glutPostRedisplay();
        break;
    case 't':
        if (twistConstant <= PI/4){
            twistConstant = twistConstant + 0.05;
            glutPostRedisplay();
        }
        break;
    case 'f':
        if (twistConstant >= 0){
            twistConstant = twistConstant - 0.05;
            glutPostRedisplay();
        }
        break;
    case 'r':
        rotateConstant = rotateConstant + 2;
        glutPostRedisplay();

        break;
    case 'q':
        if (numberOfObj <= 6){
            numberOfObj++;
            glutPostRedisplay();
        }

        break;
    case 'a':
        if (numberOfObj >= 0){
            numberOfObj--;
            glutPostRedisplay();
        }

        break;
    case 's':
        if (numberOfTriangles <90){
            numberOfTriangles++;
            glutPostRedisplay();
        }

        break;
    case 'w':
        if (numberOfTriangles > 1){
            numberOfTriangles--;
            glutPostRedisplay();
        }

        break;
    default:
        break;
    }
}


void specialkey(GLint key, int x, int y)
{
    switch (key) {
    case GLUT_KEY_RIGHT:
        alpha = alpha + PI / 180;
        if (alpha > 2 * PI) alpha = alpha - 2 * PI;
        glutPostRedisplay();
        break;
    case GLUT_KEY_LEFT:
        alpha = alpha - PI / 180;
        if (alpha < 0) alpha = alpha + 2 * PI;
        glutPostRedisplay();
        break;
    case GLUT_KEY_UP:
        if (beta < 0.45*PI) beta = beta + PI / 180;
        glutPostRedisplay();
        break;
    case GLUT_KEY_DOWN:
        if (beta > -0.05*PI) beta = beta - PI / 180;
        glutPostRedisplay();
        break;


    default:
        break;
    }
}

int main(int argc, char** argv)
{
    writemessage();
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(1200, 800);
    glutInitWindowPosition(0, 0);
    glutCreateWindow(argv[0]);

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);

    glEnable(GL_LIGHTING);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    glEnable(GL_LIGHT0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 5.0, 10.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(specialkey);

    glutMainLoop();
    return 0;
}

最佳答案

glBegin()glEnd() 之间只有一组有限的 OpenGL 调用有效。修改当前转换的命令不在其中。有效调用的完整列表,复制自 glBegin() man page :

Only a subset of GL commands can be used between glBegin and glEnd. The commands are glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, and glEdgeFlag. Also, it is acceptable to use glCallList or glCallLists to execute display lists that include only the preceding commands. If any other GL command is executed between glBegin and glEnd, the error flag is set and the command is ignored.

每当您的 OpenGL 调用无法按预期工作时,您应该尝试调用 glGetError() 以查看它是否标记了任何错误。在这种情况下,您会看到无效调用的 GL_INVALID_OPERATION 错误。

由于您无法更改图元中间的变换,因此最好在计算点时简单地将扭曲效果所需的旋转应用于点。假设您想要围绕 x 轴进行扭曲,并且您在没有扭曲的情况下计算了 xyz,那么您可以使用类似:

float twistAng = someFactor * x;
float twistCos = cos(twistAng);
float twistSin = sin(twistAng);
float yTwisted = twistCos * y - twistSin * z;
float zTwisted = twistSin * y + twistCos * z;

然后你使用 (x, yTwisted, zTwisted) 作为你的顶点。

关于c++ - Blade 的扭曲效果 (glRotatef) 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26269582/

相关文章:

opengl - 在 GLUT 中使用鼠标滚轮

C++如何泛化类函数参数来处理多种类型的函数指针?

c++ - 在 map::at() 中内存字符串表示差异抛出错误

macos - 将 IOSurface 支持的纹理转换为 GL_TEXTURE_2D

opengl - 简单的 GLSL 聚光灯着色器

c++ - Glew 问题, Unresolved external 问题

c++ - 如何将 char* 转换为字符串?

c++ - 是否可以从覆盖(非事件)窗口获取 pixelcolor(x,y)?

c++ - 如何将opengl进程绑定(bind)到具体的gpu卡上?

c++ - 我的窗口在 OpenGL 中正在调整大小