#c #opengl #rubiks-cube
#c #opengl #кубик рубика
Вопрос:
Я пытаюсь закодировать интерфейс для кубика Рубика.
Однако, когда я рисую это, на гранях куба остаются пятна:
Вот хорошо прокомментированный код. Может кто-нибудь, пожалуйста, помочь мне и, возможно, запустить код и сказать мне, где я могу ошибаться?
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
void init() {
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
static float x_degs = 0.0f;
static float y_degs = 0.0f;
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'q':
exit(EXIT_SUCCESS);
case 'h':
y_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'j':
x_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'k':
x_degs = 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'l':
y_degs = 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
}
}
// half the length of one card
static const float card_half_size = 1.0f;
// half the space between cards
static const float space_half_size = 0.1f;
// number of cards per face
static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card
const float start = - 3 * (card_half_size space_half_size);
// increment between center of cards
const float incr = 2 * (card_half_size space_half_size);
// half the size of a cube face
const float cube_half_size = 4 * (card_half_size space_half_size);
*/
// draw a card centered at the origin
void draw_card() {
glBegin(GL_QUADS);
glVertex3f(- card_half_size, - card_half_size, 0.0f);
glVertex3f(- card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, - card_half_size, 0.0f);
glEnd();
}
// draw a cube face made up of cards
void draw_card_face() {
const float cube_half_size = 4 * (card_half_size space_half_size);
const float start = - 3 * (card_half_size space_half_size);
const float incr = 2 * (card_half_size space_half_size);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
glVertex3f(- cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, - cube_half_size, -0.001f);
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
for (int i = 0; i < NUM_CARDS_PER_FACE; i )
for (int j = 0; j < NUM_CARDS_PER_FACE; j ) {
glPushMatrix();
glTranslatef(start i * incr, start j * incr, 0.0f);
draw_card();
glPopMatrix();
}
}
// draw a cube made up of cards
void draw_card_cube() {
const float cube_half_size = 4 * (card_half_size space_half_size);
// front face
glPushMatrix();
glTranslatef(0.0f, 0.0f, cube_half_size);
draw_card_face();
glPopMatrix();
// back face
glPushMatrix();
glTranslatef(0.0f, 0.0f, - cube_half_size);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// right face
glPushMatrix();
glTranslatef(cube_half_size, 0.0f, 0.0f);
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// left face
glPushMatrix();
glTranslatef(- cube_half_size, 0.0f, 0.0f);
glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// top face
glPushMatrix();
glTranslatef(0.0f, cube_half_size, 0.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
// bottom face
glPushMatrix();
glTranslatef(0.0f, - cube_half_size, 0.0f);
glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
glRotatef(y_degs, 0.0f, 1.0f, 0.0f);
gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
draw_card_cube();
glutSwapBuffers();
}
void reshape(int w, int h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(amp;argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Хорошо, я пересмотрел код так, что теперь я рисую голубые прямоугольники на расстоянии 0,01 f единиц вместо 0,001 f единиц, и это, кажется, исправило z-битву. Однако я хотел бы использовать glPolygonOffset (factor, units), чтобы исправить эту проблему, но я не смог этого сделать из-за следующего
причины:
- Я не знаю, как установить facor и units (я пробовал 1.0 для обоих).
- Я пробовал разные значения, но безрезультатно.
Вот код без кровотечения / сшивания / z-борьбы:
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
void init() {
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
static float x_degs = 0.0f;
static float y_degs = 0.0f;
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'q':
exit(EXIT_SUCCESS);
case 'h':
y_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'j':
x_degs -= 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'k':
x_degs = 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
case 'l':
y_degs = 1.0f;
glutPostRedisplay();
glutSwapBuffers();
break;
}
}
// half the length of one card
static const float card_half_size = 1.0f;
// half the space between cards
static const float space_half_size = 0.1f;
// number of cards per face
static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card
const float start = - 3 * (card_half_size space_half_size);
// increment between center of cards
const float incr = 2 * (card_half_size space_half_size);
// half the size of a cube face
const float cube_half_size = 4 * (card_half_size space_half_size);
*/
// draw a card centered at the origin
void draw_card() {
glBegin(GL_QUADS);
glVertex3f(- card_half_size, - card_half_size, 0.0f);
glVertex3f(- card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, card_half_size, 0.0f);
glVertex3f(card_half_size, - card_half_size, 0.0f);
glEnd();
}
// draw a cube face made up of cards
void draw_card_face() {
const float cube_half_size = 4 * (card_half_size space_half_size);
const float start = - 3 * (card_half_size space_half_size);
const float incr = 2 * (card_half_size space_half_size);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
glVertex3f(- cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, cube_half_size, -0.001f);
glVertex3f(cube_half_size, - cube_half_size, -0.001f);
glEnd();
glColor3f(1.0f, 1.0f, 1.0f);
for (int i = 0; i < NUM_CARDS_PER_FACE; i )
for (int j = 0; j < NUM_CARDS_PER_FACE; j ) {
glPushMatrix();
glTranslatef(start i * incr, start j * incr, 0.0f);
draw_card();
glPopMatrix();
}
}
// draw a cube made up of cards
void draw_card_cube() {
const float cube_half_size = 4 * (card_half_size space_half_size);
// front face
glPushMatrix();
glTranslatef(0.0f, 0.0f, cube_half_size);
draw_card_face();
glPopMatrix();
// back face
glPushMatrix();
glTranslatef(0.0f, 0.0f, - cube_half_size);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// right face
glPushMatrix();
glTranslatef(cube_half_size, 0.0f, 0.0f);
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// left face
glPushMatrix();
glTranslatef(- cube_half_size, 0.0f, 0.0f);
glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
draw_card_face();
glPopMatrix();
// top face
glPushMatrix();
glTranslatef(0.0f, cube_half_size, 0.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
// bottom face
glPushMatrix();
glTranslatef(0.0f, - cube_half_size, 0.0f);
glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
draw_card_face();
glPopMatrix();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
glRotatef(y_degs, 0.0f, 1.0f, 0.0f);
gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
draw_card_cube();
glutSwapBuffers();
}
void reshape(int w, int h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(amp;argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Комментарии:
1. «пятна на гранях куба». Есть ли вероятность появления изображения?
2. Я рекомендую использовать мягкое моющее средство и мягкую ткань.
3. Здравствуйте, я не уверен, как включить изображение в stack overflow, поэтому я поделился им на PicasaWeb здесь: ! ссылка
4. Вам не нужен
glutSwapBuffers()
обработчик клавиатуры, простоglutPostRedisplay()
s5. Дважды проверьте, сколько бит в вашем буфере глубины через
glGet()
иGL_DEPTH_BITS
. Некоторые пользователи могут получать 24- или 32-разрядные буферы глубины «по умолчанию», тогда как вы можете получать 16, если запускаете свою программу на виртуальной машине.
Ответ №1:
Я думаю, что вы рисуете свои шашки в виде копланарных квадратов граней вашего основного куба; если это так, проблема, с которой вы сталкиваетесь, называется «борьба с z».
Вы можете взглянуть на пункт 12.040, буферизация глубины, похоже, работает, но полигоны, похоже, просачиваются через полигоны, которые находятся перед ними. Что происходит? здесь : http://www.opengl.org/resources/faq/technical/depthbuffer.htm
В принципе, ваш буфер глубины не обладает достаточной точностью, чтобы определить, какой квадрат отображать для каждого пикселя, что вызывает проблему.
Вы можете либо вручную добавить смещение к вашим контрольным квадратам, чтобы переместить их подальше от куба; или использовать смещение глубины через glPolygonOffset
, чтобы решить проблему.
Ответ №2:
Я думаю, вы пытаетесь выполнить копланарный рендеринг. Изучите glPolygonOffset()
вместо использования небольших смещений Z, как вы делаете.
Комментарии:
1. Спасибо за ваши ответы. Да, я пытался выполнить копланарный рендеринг. Насколько glPolygonOffset () более стабилен, чем использование небольших смещений z, и как мне вообще использовать его в своем коде? Как мне выбрать два параметра для glPolygonOffset () и где разместить вызовы glPolygonOffset() в коде.
Ответ №3:
Это то, что я получаю из вашего кода, скомпилированного с gcc -std=c99 -lGL -lGLU -lglut a.c
: никаких пятен. Можете ли вы опубликовать свои? (Ubuntu 11.10, графический процессор Intel)
Комментарии:
1. Привет, спасибо за ваш ответ, например, верхняя грань полностью синяя, а не в клеточку. Теперь попробуйте ввести j, k, h, l, чтобы переместить куб. Смотрите ссылку выше, где я разместил изображение. Есть пятна (также Ubuntu 11.10 с gcc -std=c99 foo.c -lGL -lGLU -lglut
2. Куб «стабилен», если я его поворачиваю, по крайней мере, здесь. Из того, что вы опубликовали, я бы предположил, что некоторые вершины расположены очень близко друг к другу, и какой треугольник выигрывает поверхность, численно нестабилен. Не читайте код подробно, хотя.
3. Имеет ли значение тот факт, что я запускаю свой код внутри Oracle VirtualBox с Ubuntu 11.10? Моя видеокарта — NVIDIA GeForce 410M.
4. Кажется, единственное отличие — драйвер. Другие ответы, похоже, подтверждают нестабильность z-координаты, которую я также предложил.