0

这是写在书openGL SuperBible代码来创建点屏幕上的弹簧形路径:使用箭头键来旋转refrence系统在OpenGL

#include "stdafx.h" 
#include <Windows.h> 
#include <gl\glut.h> 
#include <gl\GLU.h> 
#include <gl\GL.h> 
#include <math.h> 


// Define a constant for the value of PI 
#define GL_PI 3.1415f 



void ChangeSize(GLsizei , GLsizei); 
void SetupRC(); 
void RenderScene(void); 


int main(int argc, CHAR* argv[]) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
    glutCreateWindow("Points Example"); 
    glutDisplayFunc(RenderScene); 
    glutReshapeFunc(ChangeSize); 
    SetupRC(); 
    glutMainLoop(); 
    return 0; 
} 

// Change viewing volume and viewport. Called when window is resized 
void ChangeSize(GLsizei w, GLsizei h) 
{ 
    GLfloat nRange = 100.0f; 
    // Prevent a divide by zero 
    if(h == 0) 
     h = 1; 
    // Set Viewport to window dimensions 
    glViewport(0, 0, w, h); 
    // Reset projection matrix stack 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    // Establish clipping volume (left, right, bottom, top, near, far) 
    if (w <= h) 
     glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange); 
    else 
     glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); 
    // Reset Model view matrix stack 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 

// This function does any needed initialization on the rendering context 
void SetupRC() 
{ 
    // Black background 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    // Set drawing color to green 
    glColor3f(0.0f, 1.0f, 0.0f); 
} 

// Called to draw scene 
void RenderScene(void) 
{ 
    GLfloat x,y,z,angle; 
    int xRot,yRot; // Storage for coordinates and angles 
    xRot = 45; 
    yRot = 45; 
    // Clear the window with current clearing color 
    glClear(GL_COLOR_BUFFER_BIT); 
    // Save matrix state and do the rotation 
    glPushMatrix(); 
    glRotatef(xRot, 1.0f, 0.0f, 0.0f); 
    glRotatef(yRot, 0.0f, 1.0f, 0.0f); 
    // Call only once for all remaining points 
    glBegin(GL_POINTS); 
    z = -50.0f; 
    for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f) 
    { 
     x = 50.0f*sin(angle); 
     y = 50.0f*cos(angle); 
     // Specify the point and move the Z value up a little 
     glVertex3f(x, y, z); 
     z += 0.5f; 
    } 
    // Done drawing points 
    glEnd(); 
    // Restore transformations 
    glPopMatrix(); 
    // Flush drawing commands 
    glutSwapBuffers(); 
} 

其实通过设置xRot = yRot = 45度,我已经达到了这种状态。
enter image description here
但书中也被告知:
当运行这个程序,所有你看到的是一个点的圆圈 因为您最初直接向下看的z轴。要查看效果,请使用箭头键围绕x轴和y轴旋转绘图。
这意味着我们应该使用箭头键来增加或减少xRot和yRot的值。我已经做了一些努力来做到这一点。

1-编写的函数:

void _cdecl keyboard(int key ,int xRot,int yRot) 
{ 
    switch (key) 
    { 
    case GLUT_KEY_PAGE_UP: 
     yRot++; 
    case GLUT_KEY_PAGE_DOWN: 
     yRot--; 
    case GLUT_KEY_HOME: 
     xRot--; 
    case GLUT_KEY_END: 
     xRot++; 
    } 
} 

2-它的原型在代码的顶部:

void _cdecl keyboard(int,int,int); 

3-加入这两行代码的函数RenderScene体:

GLint key = GLUT_KEY_PAGE_UP; 
glutSpecialFunc(keyboard(key,xRot,yRot)); 

但我不确定它会工作。该代码获取错误:

error C2664: 'glutSpecialFunc' : cannot convert parameter 1 from 'void' to 'void (__cdecl *)(int,int,int)' 

,我不知道怎么的xRotyRot更改后的值返回给调用函数,因为编译器不会让我定义Pass by referrence参数和glutSpecialFunc参数是一个void函数的指针!

我的问题的编辑部分
作为jblocksom建议我改变了代码是这样的:
1定义,只是主开始前初始化的全局变量:

int xRot = 0; 
int yRot = 0; 

2-通话主要在某处的glutSpecialFunc

glutSpecialFunc(keyboard); 
glutDisplayFunc(RenderScene); 
glutReshapeFunc(ChangeSize); 

3-改变键盘功能中的代码

void keyboard(int keyParam ,int mx,int my) 
{ 
    switch (keyParam) 
    { 
    case GLUT_KEY_PAGE_UP: 
     my++; 
    case GLUT_KEY_PAGE_DOWN: 
     my--; 
    case GLUT_KEY_HOME: 
     mx--; 
    case GLUT_KEY_END: 
     mx++; 
    } 
    glutPostRedisplay(); 
} 

没有编译和运行时错误。但它不起作用。我认为这是因为当我呼叫glutSpecialFunc(keyboard)时,该函数使用鼠标和键盘按钮的坐标作为输入参数,所以任何增量或减量应用于不是xRotyRot的鼠标坐标上,这将用于glRotatef(xRot, 1.0f, 0.0f, 0.0f)glRotatef(yRot, 0.0f, 1.0f, 0.0f),因此当调用两个后者xRotyRot仍然等于零,并且不会有旋转。 我需要通过xRotyRot函数keyboard但如何?
即使写功能:

void keyboard(int keyParam ,int mx,int my) 
{ 
    switch (keyParam) 
    { 
    case GLUT_KEY_PAGE_UP: 
     yRot++; 
    case GLUT_KEY_PAGE_DOWN: 
     yRot--; 
    case GLUT_KEY_HOME: 
     xRot--; 
    case GLUT_KEY_END: 
     xRot++; 
    } 
    glutPostRedisplay(); 
} 

,并调用它的形式glutSpecialFunc(keyboard)将没有任何区别!

回答

3

glutSpecialFunc用GLUT注册一个回调,当用户点击其中一个箭头键时被调用;你给它的函数,keyboard,不是你自称的东西。这就是为什么你不能从中返回任何东西。要从回调中获取数据,您需要设置一个全局变量。

您需要拨打glutSpecialFuncmain某处,其中设置了其他GLUT回调(例如glutRenderFunc)。为了让过去的编译错误,你会这样称呼它:

glutSpecialFunc(keyboard); 

告诉GLUT调用keyboard()与键和鼠标位置。

xRotyRot变量引用到RenderScene全局中。

变化keyboard函数签名不使用xRotyRot作为变量名,使其指向到全局的:

void _cdecl keyboard(int key, int mx, int my) 

你也可能需要glutPostRedisplay()呼叫在结束keyboard,这将告诉GLUT重绘场景。

希望之后,它应该工作,祝你好运!

+0

谢谢@jblocksom,但看到我的问题的编辑部分。我希望你能帮助我。 – sepideh