OpenGL крошечный сбой рендеринга, нужна помощь и советы

Вот мой код:

#include <stdlib.h>
#include <iostream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SDL.h>

using namespace std;

typedef unsigned short us;
typedef unsigned char uc;

bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]={
    { 0, 1 },
    { 0,-1 },
    { -1,0 },
    { 1,0 },
    { 1,1},
    { 1,-1 },
    { -1,-1 },
    { -1,1 }
};

us totalbots=15;

float zoomlvl=-70.f;
float camx=0.f,camy=0.f;

struct bot_data{
    float x,y,z;
    float r,g,b;
    float size; //    "radius" of the square
    us coold;
    us age;
    us trans:5;
    us dir:3,fac:2;
    bot_data(void);
    void move(void);
    void deliver(us bot);
};
struct bool_data{
    bool ch:1,ch2:1;
};

bot_data::bot_data(void){
    size=0.25f;
    fac=rand()%4;
    switch(fac){
    case 0:x=10.f,y=10.f,z=0.f;
        r=1.0f,g=0.f,b=0.f;
        break;
    case 1:x=-10.f,y=-10.f,z=0.f;
        r=0.0f,g=0.f,b=1.f;
        break;
    case 2:x=-10.f,y=10.f,z=0.f;
        r=1.0f,g=1.f,b=0.f;
        break;
    case 3:x=10.f,y=-10.f,z=0.f;
        r=0.0f,g=1.f,b=0.f;
        break;
    }
    coold=0;
    trans=0;
    age=0;
    dir=rand()%8;
}

bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;

void bot_data::move(void){
    float move=size/10.f;
    switch(dir){
    case 0:y+=move;
        break;
    case 1:y-=move;
        break;
    case 2:x-=move;
        break;
    case 3:x+=move;
        break;
    case 4:x+=move;
        y+=move;
        break;
    case 5:x+=move;
        y-=move;
        break;
    case 6:y-=move;
        x-=move;
        break;
    case 7:y+=move;
        x-=move;
        break;
    }
}
void bot_data::deliver(us bot){
    age=-10;
    totalbots+=3;
    float tmp=size-(size/4.f);
    size=0.25f;
    x-=size;
    y+=size;
    for(uc i=1;i<=3;i++){
        cubers[totalbots-i].fac=fac;
        switch(fac){
        case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
            break;
        case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
            break;
        case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        }
        cubers[totalbots-i].coold=coold;
        cubers[totalbots-i].size=size;
        switch(i){
        case 1:cubers[totalbots-i].x=x;
            cubers[totalbots-i].y=y-size*2;
            break;
        case 2:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y;
            break;
        case 3:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y-size*2;
            break;
        }
    }
}

void initkeys(void){
    for(uc i=0;i<255;i++){
        keystates[i]=false;
        skeystates[i]=false;
    }
}
void p_keys(unsigned char key, int x, int y){
    keystates[key]=true;
}
void keyup(unsigned char key, int x, int y){
    keystates[key]=false;
}
void sp_keys(int key, int x, int y){
    skeystates[key]=true;
}
void skeyup(int key, int x, int y){
    skeystates[key]=false;
}
void key_func(void){
    if (keystates['z']){
        if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
        else if (skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
        if(zoomlvl<-100.0f)zoomlvl=-100.f;
        else if(zoomlvl>-5.f)zoomlvl=-5.f;
    }
    else{
        if(skeystates[GLUT_KEY_UP])camy-=1.f;
        else if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
    }
    if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
    else if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
}
void render_p(us bot){
    glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
    glBegin(GL_QUADS);
    glVertex2f(cubers[bot].size,cubers[bot].size);
    glVertex2f(cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,cubers[bot].size);
    glEnd();
}
void process_cubers(void){
    for(us i=0;i<totalbots;i++){
        //glPushMatrix();
        glLoadIdentity();
        glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
        if(cubers[i].coold==0){
            cubers[i].move();
            cubers[i].trans++;
            if(cubers[i].trans==20){
                cubers[i].trans=0;
                cubers[i].coold=50;
                if(cubers[i].age<100){
                    cubers[i].size+=0.025f;
                }
                else if(cubers[i].age==150){
                    cubers[i].deliver(i);
                }
                cubers[i].dir=rand()%8;
                cubers[i].age+=10;
            }
        }
        else cubers[i].coold--;
        render_p(i);
        //glPopMatrix();
    }
}
void display(void){
    key_func();
    glClearColor(0.6f,0.6f,0.6f,1.f);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(camx,camy,zoomlvl);
    process_cubers();
    glutSwapBuffers();
    SDL_Delay(1000/30);
    glutPostRedisplay();
}
void resize(int width,int height){
    glViewport(0,0,(GLsizei)width,(GLsizei)height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,(GLfloat)width/(GLfloat)height,1.f,100.f);
    glMatrixMode(GL_MODELVIEW);
}
int main (int argc, char **argv) {
    initkeys();
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (640, 480);
    glutInitWindowPosition (0, 0); 
    glutCreateWindow ("opengl 1");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc(resize);
    glutKeyboardFunc(p_keys);
    glutKeyboardUpFunc(keyup);
    glutSpecialFunc(sp_keys);
    glutSpecialUpFunc(skeyup);
    glutMainLoop();
    return 0;
}

он отображает определенное количество упомянутых квадратов, которые перемещаются каждые определенные интервалы. их расстояние перемещения - их размер. каждый раз, когда они двигаются, они увеличиваются в размере, пока не достигнут предельного размера (в данном случае 1.f в радиусе), после определенного количества ходов (в нашем случае 15) квадрат будет разделен на 4 меньших квадрата и заполнит точное пространство его предшественник занят, это означает, что он должен выглядеть совершенно незаметно… проблема в том, что вместо этого я получаю рендеринг с разбивкой на секунды, похожий на слезу, после раскола квадрата, но кроме этого я не нашел никаких других проблем.

я подозреваю, что, возможно, я пропустил некоторую функцию gl, которую я должен был вызывать во время рендеринга новых 3-х квадратов (расщепление происходит путем добавления 3-х новых квадратов и уменьшения текущего до четверти его размера, а затем настройки всех квадраты.)

2 ответа

Решение

Попробуй это:

#include <GL/glew.h>
#include <GL/glut.h>

typedef unsigned short us;
typedef unsigned char uc;

bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]=
{
    { 0, 1 },
    { 0,-1 },
    { -1,0 },
    { 1,0 },
    { 1,1},
    { 1,-1 },
    { -1,-1 },
    { -1,1 }
};

us totalbots=15;

float zoomlvl=-70.f;
float camx=0.f,camy=0.f;

struct bot_data
{
    float x,y,z;
    float r,g,b;
    float size; //    "radius" of the square
    us coold;
    us age;
    us trans:5;
    us dir:3,fac:2;
    bot_data(void);
    void move(void);
    void deliver(us bot);
};

struct bool_data
{
    bool ch:1,ch2:1;
};

bot_data::bot_data(void)
{
    size=0.25f;
    fac=rand()%4;
    switch(fac){
    case 0:x=10.f,y=10.f,z=0.f;
        r=1.0f,g=0.f,b=0.f;
        break;
    case 1:x=-10.f,y=-10.f,z=0.f;
        r=0.0f,g=0.f,b=1.f;
        break;
    case 2:x=-10.f,y=10.f,z=0.f;
        r=1.0f,g=1.f,b=0.f;
        break;
    case 3:x=10.f,y=-10.f,z=0.f;
        r=0.0f,g=1.f,b=0.f;
        break;
    }
    coold=0;
    trans=0;
    age=0;
    dir=rand()%8;
}

bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;

void bot_data::move(void)
{
    float move=size/10.f;
    switch(dir){
    case 0:y+=move;
        break;
    case 1:y-=move;
        break;
    case 2:x-=move;
        break;
    case 3:x+=move;
        break;
    case 4:x+=move;
        y+=move;
        break;
    case 5:x+=move;
        y-=move;
        break;
    case 6:y-=move;
        x-=move;
        break;
    case 7:y+=move;
        x-=move;
        break;
    }
}

void bot_data::deliver(us bot)
{
    age=-10;
    totalbots+=3;
    float tmp=size-(size/4.f);
    size=0.25f;
    x-=size;
    y+=size;
    for(uc i=1;i<=3;i++){
        cubers[totalbots-i].fac=fac;
        switch(fac){
        case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
            break;
        case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
            break;
        case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        }
        cubers[totalbots-i].coold=coold;
        cubers[totalbots-i].size=size;
        switch(i){
        case 1:cubers[totalbots-i].x=x;
            cubers[totalbots-i].y=y-size*2;
            break;
        case 2:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y;
            break;
        case 3:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y-size*2;
            break;
        }
    }
}

void initkeys(void)
{
    for(uc i=0;i<255;i++){
        keystates[i]=false;
        skeystates[i]=false;
    }
}

void p_keys(unsigned char key, int x, int y)
{
    keystates[key]=true;
}

void keyup(unsigned char key, int x, int y)
{
    keystates[key]=false;
}

void sp_keys(int key, int x, int y)
{
    skeystates[key]=true;
}

void skeyup(int key, int x, int y)
{
    skeystates[key]=false;
}

void key_func(void)
{
    if (keystates['z'])
    {
        if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
        if(skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
        if(zoomlvl<-100.0f)zoomlvl=-100.f;
        if(zoomlvl>-5.f)zoomlvl=-5.f;
    }
    else
    {
        if(skeystates[GLUT_KEY_UP])camy-=1.f;
        if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
        if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
        if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
    }
}

void render_p(us bot)
{
    glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
    glBegin(GL_QUADS);
    glVertex2f(cubers[bot].size,cubers[bot].size);
    glVertex2f(cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,cubers[bot].size);
    glEnd();
}

void process_cubers(void)
{
    for(us i=0;i<totalbots;i++){
        if(cubers[i].coold==0){
            cubers[i].move();
            cubers[i].trans++;
            if(cubers[i].trans==20){
                cubers[i].trans=0;
                cubers[i].coold=50;
                if(cubers[i].age<100){
                    cubers[i].size+=0.025f;
                }
                else if(cubers[i].age==150){
                    cubers[i].deliver(i);
                }
                cubers[i].dir=rand()%8;
                cubers[i].age+=10;
            }
        }
        else cubers[i].coold--;
    }

    for(us i=0;i<totalbots;i++)
    {
        glPushMatrix();
        glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
        render_p(i);
        glPopMatrix();
    }
}

void display(void)
{
    key_func();
    glClearColor(0.6f,0.6f,0.6f,1.f);
    glClear (GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    gluPerspective(60, w / h,1.f,100.f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(camx,camy,zoomlvl);

    process_cubers();
    glutSwapBuffers();
}

void timer(int extra)
{
    glutPostRedisplay();
    glutTimerFunc(33, timer, 0);
}

int main (int argc, char **argv) 
{
    initkeys();
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize (640, 480);
    glutInitWindowPosition (0, 0); 
    glutCreateWindow ("opengl 1");
    glutDisplayFunc(display);
    glutKeyboardFunc(p_keys);
    glutKeyboardUpFunc(keyup);
    glutSpecialFunc(sp_keys);
    glutSpecialUpFunc(skeyup);
    glutTimerFunc(0, timer, 0);
    glutMainLoop();
    return 0;
}

Вы рисовали в цикле симуляции. Это разбивает это на две петли, сим затем рисует.

Способ рендеринга графики (OpenGL или иным образом) заключается в том, что он гарантирует "хороший" шов между двумя треугольниками, которые "точно" выровнены вдоль некоторого края, если вы представляете их как часть одной и той же полосы треугольника, то же самое (буфер вершин, индексный буфер) модельная пара или некоторая другая конструкция, которая группирует треугольники в одну единицу рендеринга.

Когда вы визуализируете "квад", вы действительно визуализируете полосу из двух треугольников, поэтому шов между двумя треугольниками выглядит хорошо.

При рендеринге двух отдельных четырехугольников, которые выровнены вдоль некоторого края, край может выглядеть плохо. Сглаживание может немного помочь решить проблему, но в конечном итоге вам нужно использовать один модуль рендеринга, если вы хотите избавиться от разрывов вдоль швов.

На рисунке показаны четыре четырехугольника (восемь треугольников), отображаемых в виде сетки. Диагонали находятся в пределах четырехугольников, поэтому разрывов не происходит, но поскольку все квадраты отображаются отдельно, вдоль их швов происходит разрыв.

рендеринг четырех четырехугольников

Другие вопросы по тегам