OpenGL (C Language) : 使用键盘制作要移动的形状(失真问题)
OpenGL (C Language) : Make the shapes to be moved with keyboard (distortion issue)
好吧,我们有以下用于 OpenGL 的 C(GLUT 项目)。我使用 CodeBlocks 来编译它(删除了额外的 main() 函数文件)。
我以一些例子为基础,如果我写 OpenGL 的方式不好,我深表歉意。主要是让它正常工作。
我需要的结果是:"Mr Robot"的所有形状(头、body、手、腿)都可以通过键盘方向键移动。它按预期工作,但从某些点来看,某些形状会变形。我不知道为什么以及如何解决它。
#include <GL/glut.h>
GLuint kefali_x1=5, kefali_y1=30, kefali_x2=15, kefali_y2=30, kefali_x3=15, kefali_y3=40, kefali_x4=5,kefali_y4=40;
GLuint soma_x1=0, soma_y1=10, soma_x2=20, soma_y2=10, soma_x3=20, soma_y3=30, soma_x4=0, soma_y4=30;
GLuint podia_x1=10, podia_y1=10, podia_x2=20, podia_y2=0, podia_x3=10, podia_y3=-5, podia_x4=0, podia_y4=0;
GLuint dexi_xeri_x1=20, dexi_xeri_y1=30, dexi_xeri_x2=30, dexi_xeri_y2=27.5, dexi_xeri_x3=20, dexi_xeri_y3=25;
GLuint aristero_xeri_x1=-10, aristero_xeri_y1=27.5, aristero_xeri_x2=0, aristero_xeri_y2=30, aristero_xeri_x3=0, aristero_xeri_y3=25;
// σύνθετο σχήμα
GLuint listID;
void MrRobot(GLsizei displayListID)
{
glNewList(displayListID,GL_COMPILE);
//Save current colour state
glPushAttrib(GL_CURRENT_BIT);
// σώμα
glColor3f(0.5,0.5,0.5);
glBegin(GL_POLYGON);
glVertex2f(soma_x1,soma_y1);
glVertex2f(soma_x2,soma_y2);
glVertex2f(soma_x3,soma_y3);
glVertex2f(soma_x4,soma_y4);
glEnd();
// κεφάλι
glColor3f(0,0,1);
glBegin(GL_POLYGON);
glVertex2f(kefali_x1,kefali_y1);
glVertex2f(kefali_x2,kefali_y2);
glVertex2f(kefali_x3,kefali_y3);
glVertex2f(kefali_x4,kefali_y4);
glEnd();
// πόδια
glColor3f(1,0,0);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(podia_x1,podia_y1);
glVertex2f(podia_x2,podia_y2);
glVertex2f(podia_x3,podia_y3);
glVertex2f(podia_x4,podia_y4);
glEnd();
// δεξί χέρι
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(dexi_xeri_x1,dexi_xeri_y1);
glVertex2f(dexi_xeri_x2,dexi_xeri_y2);
glVertex2f(dexi_xeri_x3,dexi_xeri_y3);
glEnd();
// αριστερό χέρι
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(aristero_xeri_x1,aristero_xeri_y1);
glVertex2f(aristero_xeri_x2,aristero_xeri_y2);
glVertex2f(aristero_xeri_x3,aristero_xeri_y3);
glEnd();
//Recall saved colour state
glPopAttrib();
glEndList();
}
void display()
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
listID=glGenLists(1);
MrRobot(listID);
//Execute the display list (the modelview matrix will be applied)
glCallList(listID);
glFlush();
}
void keyboard(unsigned char key,int x, int y)
{
printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);
if (key==GLUT_KEY_UP)
{
kefali_y1++;
kefali_y2++;
kefali_y3++;
kefali_y4++;
soma_y1++;
soma_y2++;
soma_y3++;
soma_y4++;
podia_y1++;
podia_y2++;
podia_y3++;
podia_y4++;
dexi_xeri_y1++;
dexi_xeri_y2++;
dexi_xeri_y3++;
aristero_xeri_y1++;
aristero_xeri_y2++;
aristero_xeri_y3++;
}
if (key==GLUT_KEY_DOWN)
{
kefali_y1--;
kefali_y2--;
kefali_y3--;
kefali_y4--;
soma_y1--;
soma_y2--;
soma_y3--;
soma_y4--;
podia_y1--;
podia_y2--;
podia_y3--;
podia_y4--;
dexi_xeri_y1--;
dexi_xeri_y2--;
dexi_xeri_y3--;
aristero_xeri_y1--;
aristero_xeri_y2--;
aristero_xeri_y3--;
}
if (key==GLUT_KEY_LEFT)
{
kefali_x1--;
kefali_x2--;
kefali_x3--;
kefali_x4--;
soma_x1--;
soma_x2--;
soma_x3--;
soma_x4--;
podia_x1--;
podia_x2--;
podia_x3--;
podia_x4--;
dexi_xeri_x1--;
dexi_xeri_x2--;
dexi_xeri_x3--;
aristero_xeri_x1--;
aristero_xeri_x2--;
aristero_xeri_x3--;
}
if (key==GLUT_KEY_RIGHT)
{
kefali_x1++;
kefali_x2++;
kefali_x3++;
kefali_x4++;
soma_x1++;
soma_x2++;
soma_x3++;
soma_x4++;
podia_x1++;
podia_x2++;
podia_x3++;
podia_x4++;
dexi_xeri_x1++;
dexi_xeri_x2++;
dexi_xeri_x3++;
aristero_xeri_x1++;
aristero_xeri_x2++;
aristero_xeri_x3++;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(800,600);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutCreateWindow("MrROBOT");
glMatrixMode(GL_MODELVIEW);
gluOrtho2D(-10,50,-10,50);
glScalef(0.4,0.4,0.4);
glutDisplayFunc(display);
glutSpecialFunc(keyboard);
glutMainLoop();
return 0;
}
您遇到以下问题,导致您的程序无法在屏幕上正确绘制所需的形状:
- 将顶点声明并递增为
GLuint
数据类型
- 将它们绘制成
GLfloat
s,这与上述矛盾,导致未定义的行为
只需更正该类型的每个规格:
glVertex2f(…_xi,…_yi);
进入
glVertex2i(…_xi,…_yi);
这应该可以解决 "distortion" 问题。
请理解,此答案并未针对您的编码风格,这并不好。 SO 不是教程站点。查看您的 post.
的评论
sorry if the way I wrote OpenGL is bad. The main thing is to make it work fine.
这两者通常是齐头并进的。如果您的 (OpenGL) 代码不好,您的程序将无法运行 "fine"。编写干净的代码,您的程序就有更好的机会正常工作。
所以这里有几个问题:为什么 xyz 有大量单独的(全局)变量?使用结构!为什么要使用显示列表进行即时绘制?这不是显示列表的用途,所以不要使用它们!为什么要统一更改顶点位置值而不是简单地更改转换?
干净的代码结构就是能够对程序进行推理。如果程序有问题,最好的调试方法之一就是清理代码;如果你不自欺欺人,通常所有的坏事都会变得清晰起来 "ah, it's just a quick hack"
这样是不是更容易理解了?它也确实有效
#include <stddef.h>
#include <stdio.h>
#include <GL/glut.h>
float robot_x = 0, robot_y = 0;
typedef GLfloat vec2[2];
enum { kefali_len = 4 };
vec2 const kefali[kefali_len] = { {5, 30}, {15, 30}, {15, 40}, {5, 40} };
enum { soma_len = 4 };
vec2 const soma[soma_len] = { {0, 10}, {20, 10}, {20, 30}, {0, 30} };
enum { podia_len = 4 };
vec2 const podia[podia_len] = { {10, 10}, {20, 0}, {10, -5}, {0, 0} };
enum { dexi_len = 3 };
vec2 const dexi[dexi_len] = { {20, 30}, {30, 27.5}, {20, 25} };
enum { aristero_len = 3};
vec2 const aristero[aristero_len] = { {-10, 27.5}, {0, 30}, {0, 25} };
static
void draw_vertices2(GLenum mode, vec2 const * const v, size_t n)
{
size_t i;
/* use of glBegin + glVertex is outdated since 1997. Whoever teaches
* is these days should either bring their coursework up to date
* or consider retirement. */
glBegin(mode);
for(i=0; i < n; ++i) {
glVertex2fv(v[i]);
}
glEnd();
}
static
void MrRobot(void)
{
//Save current colour state
glPushAttrib(GL_CURRENT_BIT);
// σώμα
glColor3f(0.5,0.5,0.5);
draw_vertices2(GL_POLYGON, soma, soma_len);
// κεφάλι
glColor3f(0,0,1);
draw_vertices2(GL_POLYGON, kefali, kefali_len);
glBegin(GL_POLYGON);
// πόδια
glColor3f(1,0,0);
draw_vertices2(GL_TRIANGLE_FAN, podia, podia_len);
// δεξί χέρι
glColor3f(0,1,0);
draw_vertices2(GL_TRIANGLES, dexi, dexi_len);
// αριστερό χέρι
glColor3f(0,1,0);
draw_vertices2(GL_TRIANGLES, aristero, aristero_len);
//Recall saved colour state
glPopAttrib();
}
static
GLuint generate_display_list_robot(void)
{
GLuint const list = glGenLists(1);
if( list ) {
glNewList(list, GL_COMPILE);
MrRobot();
glEndList();
}
return list;
}
static GLuint display_list_robot = 0;
static
void display(void)
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-10,50,-10,50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(0.4,0.4,0.4);
glPushMatrix();
glTranslatef(robot_x, robot_y, 0);
if( display_list_robot ) {
glCallList(display_list_robot);
} else {
MrRobot();
}
glPopMatrix();
glutSwapBuffers();
}
static
void keyboard(int key, int pointer_x, int pointer_y)
{
fprintf(stderr,
"\nKeyboard event.\nCharacter: %d\nMouse pointer position: x=%d y=%d",
(int)key,
(int)pointer_x,
(int)pointer_y );
switch( key ) {
case GLUT_KEY_UP: ++robot_y; break;
case GLUT_KEY_DOWN: --robot_y; break;
case GLUT_KEY_RIGHT: ++robot_x; break;
case GLUT_KEY_LEFT: --robot_x; break;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
size_t i;
glutInit(&argc,argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(800,600);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutCreateWindow("MrROBOT");
/* argv[0] is program name */
for(i = 1; i < argc; ++i) {
if( 'd' == argv[i][0] ) {
if( !display_list_robot ) {
display_list_robot = generate_display_list_robot();
}
}
}
glutDisplayFunc(display);
glutSpecialFunc(keyboard);
glutMainLoop();
return 0;
}
好吧,我们有以下用于 OpenGL 的 C(GLUT 项目)。我使用 CodeBlocks 来编译它(删除了额外的 main() 函数文件)。 我以一些例子为基础,如果我写 OpenGL 的方式不好,我深表歉意。主要是让它正常工作。
我需要的结果是:"Mr Robot"的所有形状(头、body、手、腿)都可以通过键盘方向键移动。它按预期工作,但从某些点来看,某些形状会变形。我不知道为什么以及如何解决它。
#include <GL/glut.h>
GLuint kefali_x1=5, kefali_y1=30, kefali_x2=15, kefali_y2=30, kefali_x3=15, kefali_y3=40, kefali_x4=5,kefali_y4=40;
GLuint soma_x1=0, soma_y1=10, soma_x2=20, soma_y2=10, soma_x3=20, soma_y3=30, soma_x4=0, soma_y4=30;
GLuint podia_x1=10, podia_y1=10, podia_x2=20, podia_y2=0, podia_x3=10, podia_y3=-5, podia_x4=0, podia_y4=0;
GLuint dexi_xeri_x1=20, dexi_xeri_y1=30, dexi_xeri_x2=30, dexi_xeri_y2=27.5, dexi_xeri_x3=20, dexi_xeri_y3=25;
GLuint aristero_xeri_x1=-10, aristero_xeri_y1=27.5, aristero_xeri_x2=0, aristero_xeri_y2=30, aristero_xeri_x3=0, aristero_xeri_y3=25;
// σύνθετο σχήμα
GLuint listID;
void MrRobot(GLsizei displayListID)
{
glNewList(displayListID,GL_COMPILE);
//Save current colour state
glPushAttrib(GL_CURRENT_BIT);
// σώμα
glColor3f(0.5,0.5,0.5);
glBegin(GL_POLYGON);
glVertex2f(soma_x1,soma_y1);
glVertex2f(soma_x2,soma_y2);
glVertex2f(soma_x3,soma_y3);
glVertex2f(soma_x4,soma_y4);
glEnd();
// κεφάλι
glColor3f(0,0,1);
glBegin(GL_POLYGON);
glVertex2f(kefali_x1,kefali_y1);
glVertex2f(kefali_x2,kefali_y2);
glVertex2f(kefali_x3,kefali_y3);
glVertex2f(kefali_x4,kefali_y4);
glEnd();
// πόδια
glColor3f(1,0,0);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(podia_x1,podia_y1);
glVertex2f(podia_x2,podia_y2);
glVertex2f(podia_x3,podia_y3);
glVertex2f(podia_x4,podia_y4);
glEnd();
// δεξί χέρι
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(dexi_xeri_x1,dexi_xeri_y1);
glVertex2f(dexi_xeri_x2,dexi_xeri_y2);
glVertex2f(dexi_xeri_x3,dexi_xeri_y3);
glEnd();
// αριστερό χέρι
glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex2f(aristero_xeri_x1,aristero_xeri_y1);
glVertex2f(aristero_xeri_x2,aristero_xeri_y2);
glVertex2f(aristero_xeri_x3,aristero_xeri_y3);
glEnd();
//Recall saved colour state
glPopAttrib();
glEndList();
}
void display()
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
listID=glGenLists(1);
MrRobot(listID);
//Execute the display list (the modelview matrix will be applied)
glCallList(listID);
glFlush();
}
void keyboard(unsigned char key,int x, int y)
{
printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);
if (key==GLUT_KEY_UP)
{
kefali_y1++;
kefali_y2++;
kefali_y3++;
kefali_y4++;
soma_y1++;
soma_y2++;
soma_y3++;
soma_y4++;
podia_y1++;
podia_y2++;
podia_y3++;
podia_y4++;
dexi_xeri_y1++;
dexi_xeri_y2++;
dexi_xeri_y3++;
aristero_xeri_y1++;
aristero_xeri_y2++;
aristero_xeri_y3++;
}
if (key==GLUT_KEY_DOWN)
{
kefali_y1--;
kefali_y2--;
kefali_y3--;
kefali_y4--;
soma_y1--;
soma_y2--;
soma_y3--;
soma_y4--;
podia_y1--;
podia_y2--;
podia_y3--;
podia_y4--;
dexi_xeri_y1--;
dexi_xeri_y2--;
dexi_xeri_y3--;
aristero_xeri_y1--;
aristero_xeri_y2--;
aristero_xeri_y3--;
}
if (key==GLUT_KEY_LEFT)
{
kefali_x1--;
kefali_x2--;
kefali_x3--;
kefali_x4--;
soma_x1--;
soma_x2--;
soma_x3--;
soma_x4--;
podia_x1--;
podia_x2--;
podia_x3--;
podia_x4--;
dexi_xeri_x1--;
dexi_xeri_x2--;
dexi_xeri_x3--;
aristero_xeri_x1--;
aristero_xeri_x2--;
aristero_xeri_x3--;
}
if (key==GLUT_KEY_RIGHT)
{
kefali_x1++;
kefali_x2++;
kefali_x3++;
kefali_x4++;
soma_x1++;
soma_x2++;
soma_x3++;
soma_x4++;
podia_x1++;
podia_x2++;
podia_x3++;
podia_x4++;
dexi_xeri_x1++;
dexi_xeri_x2++;
dexi_xeri_x3++;
aristero_xeri_x1++;
aristero_xeri_x2++;
aristero_xeri_x3++;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(800,600);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutCreateWindow("MrROBOT");
glMatrixMode(GL_MODELVIEW);
gluOrtho2D(-10,50,-10,50);
glScalef(0.4,0.4,0.4);
glutDisplayFunc(display);
glutSpecialFunc(keyboard);
glutMainLoop();
return 0;
}
您遇到以下问题,导致您的程序无法在屏幕上正确绘制所需的形状:
- 将顶点声明并递增为
GLuint
数据类型 - 将它们绘制成
GLfloat
s,这与上述矛盾,导致未定义的行为
只需更正该类型的每个规格:
glVertex2f(…_xi,…_yi);
进入
glVertex2i(…_xi,…_yi);
这应该可以解决 "distortion" 问题。
请理解,此答案并未针对您的编码风格,这并不好。 SO 不是教程站点。查看您的 post.
的评论sorry if the way I wrote OpenGL is bad. The main thing is to make it work fine.
这两者通常是齐头并进的。如果您的 (OpenGL) 代码不好,您的程序将无法运行 "fine"。编写干净的代码,您的程序就有更好的机会正常工作。
所以这里有几个问题:为什么 xyz 有大量单独的(全局)变量?使用结构!为什么要使用显示列表进行即时绘制?这不是显示列表的用途,所以不要使用它们!为什么要统一更改顶点位置值而不是简单地更改转换?
干净的代码结构就是能够对程序进行推理。如果程序有问题,最好的调试方法之一就是清理代码;如果你不自欺欺人,通常所有的坏事都会变得清晰起来 "ah, it's just a quick hack"
这样是不是更容易理解了?它也确实有效
#include <stddef.h>
#include <stdio.h>
#include <GL/glut.h>
float robot_x = 0, robot_y = 0;
typedef GLfloat vec2[2];
enum { kefali_len = 4 };
vec2 const kefali[kefali_len] = { {5, 30}, {15, 30}, {15, 40}, {5, 40} };
enum { soma_len = 4 };
vec2 const soma[soma_len] = { {0, 10}, {20, 10}, {20, 30}, {0, 30} };
enum { podia_len = 4 };
vec2 const podia[podia_len] = { {10, 10}, {20, 0}, {10, -5}, {0, 0} };
enum { dexi_len = 3 };
vec2 const dexi[dexi_len] = { {20, 30}, {30, 27.5}, {20, 25} };
enum { aristero_len = 3};
vec2 const aristero[aristero_len] = { {-10, 27.5}, {0, 30}, {0, 25} };
static
void draw_vertices2(GLenum mode, vec2 const * const v, size_t n)
{
size_t i;
/* use of glBegin + glVertex is outdated since 1997. Whoever teaches
* is these days should either bring their coursework up to date
* or consider retirement. */
glBegin(mode);
for(i=0; i < n; ++i) {
glVertex2fv(v[i]);
}
glEnd();
}
static
void MrRobot(void)
{
//Save current colour state
glPushAttrib(GL_CURRENT_BIT);
// σώμα
glColor3f(0.5,0.5,0.5);
draw_vertices2(GL_POLYGON, soma, soma_len);
// κεφάλι
glColor3f(0,0,1);
draw_vertices2(GL_POLYGON, kefali, kefali_len);
glBegin(GL_POLYGON);
// πόδια
glColor3f(1,0,0);
draw_vertices2(GL_TRIANGLE_FAN, podia, podia_len);
// δεξί χέρι
glColor3f(0,1,0);
draw_vertices2(GL_TRIANGLES, dexi, dexi_len);
// αριστερό χέρι
glColor3f(0,1,0);
draw_vertices2(GL_TRIANGLES, aristero, aristero_len);
//Recall saved colour state
glPopAttrib();
}
static
GLuint generate_display_list_robot(void)
{
GLuint const list = glGenLists(1);
if( list ) {
glNewList(list, GL_COMPILE);
MrRobot();
glEndList();
}
return list;
}
static GLuint display_list_robot = 0;
static
void display(void)
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-10,50,-10,50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(0.4,0.4,0.4);
glPushMatrix();
glTranslatef(robot_x, robot_y, 0);
if( display_list_robot ) {
glCallList(display_list_robot);
} else {
MrRobot();
}
glPopMatrix();
glutSwapBuffers();
}
static
void keyboard(int key, int pointer_x, int pointer_y)
{
fprintf(stderr,
"\nKeyboard event.\nCharacter: %d\nMouse pointer position: x=%d y=%d",
(int)key,
(int)pointer_x,
(int)pointer_y );
switch( key ) {
case GLUT_KEY_UP: ++robot_y; break;
case GLUT_KEY_DOWN: --robot_y; break;
case GLUT_KEY_RIGHT: ++robot_x; break;
case GLUT_KEY_LEFT: --robot_x; break;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
size_t i;
glutInit(&argc,argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(800,600);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutCreateWindow("MrROBOT");
/* argv[0] is program name */
for(i = 1; i < argc; ++i) {
if( 'd' == argv[i][0] ) {
if( !display_list_robot ) {
display_list_robot = generate_display_list_robot();
}
}
}
glutDisplayFunc(display);
glutSpecialFunc(keyboard);
glutMainLoop();
return 0;
}