0

这是书中编写的openGL SuperBible用于在屏幕上创建弹簧形点路径的代码:

#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度,我已经达到了这个形状。
在此处输入图像描述
但是在书中它被告知:
当这个程序运行时,你所看到的只是一个圆点,因为你最初是直接向下看 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)'  

而且我不知道如何将xRot和的更改值返回yRot给调用者函数,因为编译器不允许我定义Pass by referrence参数并且参数glutSpecialFunc是指向 void 函数的指针!

我的问题的编辑部分
作为 jblocksom 建议我将代码更改为如下所示:
1-在主开始之前定义和初始化全局变量:

int xRot = 0;
int yRot = 0;  

2- 在 main 的某处调用 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),该函数使用鼠标和按键的坐标作为输入参数,因此任何增量或减量都不会应用于鼠标坐标xRot,或者在调用后两者时将在左右yRot使用,并且仍然是等于零,不会有旋转。我需要传递和传递给函数但是如何??? 甚至将函数编写为: glRotatef(xRot, 1.0f, 0.0f, 0.0f)glRotatef(yRot, 0.0f, 1.0f, 0.0f)xRotyRotxRotyRotkeyboard

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)不会有任何区别!

4

1 回答 1

3

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

您需要在设置其他 GLUT 回调的glutSpecialFunc地方调用(例如)。为了克服编译错误,你可以这样称呼它:mainglutRenderFunc

glutSpecialFunc(keyboard);

它告诉 GLUTkeyboard()使用键和鼠标位置进行调用。

使xRotyRot变量在RenderScene全局中引用。

将函数签名更改keyboard为不使用xRotyRot作为变量名,以便它引用全局变量名:

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

您可能还需要glutPostRedisplay()在 结束时调用 to keyboard,这将告诉 GLUT 重绘场景。

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

于 2013-07-23T13:25:41.103 回答