OpenGL оценщик только частично горит - PullRequest
4 голосов
/ 18 ноября 2011

Я пытался создать небольшой генератор волн в OpenGL с C ++, используя оценщик.

enter image description here

Однако мне не повезло, так как мой оценщик получает толькочастично горит.

Почему это происходит?

Ниже я приведу полный исходный код для полноты картины, вам, вероятно, придется взглянуть только на init(), display() и константывверху файла.

#include <gl/glui.h>
#include <math.h>

const int DIMX = 500;
const int DIMY = 500;
const int INITIALPOS_X = 200;
const int INITIALPOS_Y = 200;


// Aspect ratio (calculated on the fly)
float xy_aspect;

// UI aux. matrices
float view_rotate[16] = { 1,0,0,0,
                          0,1,0,0,
                          0,0,1,0,
                          0,0,0,1 };

float obj_pos[] = { 0.0, 0.0, 0.0 };
float obj_pan[] = { 0.0, 0.0, 0.0 };

// Referential axis
double axis_radius_begin =  0.2;
double axis_radius_end   =  0.0;
double axis_lenght       = 16.0;
int axis_nslices = 8;
int axis_nstacks = 1;

// Light 0 properties
float light0_position[]  = {5.0, 5.0, 5.0, 0.0};
float light0_ambient[] =   {0.0, 0.0, 0.0, 1.0};
float light0_diffuse[] =   {0.6, 0.6, 0.6, 1.0};
float light0_specular[] =  {1.0, 1.0, 1.0, 1.0};
float light0_kc = 0.0;
float light0_kl = 1.0;
float light0_kq = 0.0;
double light0x = 5.0;
double light0y = 5.0;
double light0z = 5.0;
double symb_light0_radius = 0.2;
int symb_light0_slices = 8;
int symb_light0_stacks =8;

// Ambient light source properties
float light_ambient[] = {0.5, 0.5, 0.5, 1.0}; /* Set the background ambient lighting. */

// Windowing related variables
int main_window;
GLUquadric* glQ;
GLUI  *glui;

const unsigned int gridSize = 40;

float grid[gridSize][gridSize][3];

const int uSize = gridSize;
const int vSize = gridSize;

GLfloat ambient[] = {0.2, 0.2, 0.2, 1.0};
GLfloat position[] = {0.0, 0.0, 2.0, 1.0};
GLfloat mat_diffuse[] = {0.6, 0.6, 0.6, 1.0};
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
float mat_shininess[] = {50.0};


void display(void) {
    static float value = 0;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 50.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glTranslatef( obj_pos[0], obj_pos[1], -obj_pos[2]-25 );
    glTranslatef( obj_pan[0], obj_pan[1], obj_pan[2] );

    glRotated( 20.0, 1.0,0.0,0.0 );
    glRotated(-45.0, 0.0,1.0,0.0 );

    glMultMatrixf( view_rotate );

    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);


    glColor3f(1.0,0.0,0.0);
    glPushMatrix();
    glRotated(90.0, 0.0,1.0,0.0 );
    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);   
    glPopMatrix();


    glColor3f(0.0,1.0,0.0);
    glPushMatrix();
    glRotated(-90.0, 1.0,0.0,0.0 );
    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);   
    glPopMatrix();


    glColor3f(0.0,0.0,1.0);
    glPushMatrix();

    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);
    glPopMatrix();


    light0_position[0] = light0x;
    light0_position[1] = light0y;
    light0_position[2] = light0z;

    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

    glColor3f(1.0,1.0,0.0);
    gluQuadricOrientation( glQ, GLU_INSIDE);
    glPushMatrix();
        glTranslated(light0x,light0y,light0z);
        gluSphere(glQ, symb_light0_radius, symb_light0_slices, symb_light0_stacks);
    glPopMatrix();

    gluQuadricOrientation( glQ, GLU_OUTSIDE);

    gluQuadricDrawStyle(glQ, GLU_FILL);
    gluQuadricNormals(glQ, GLU_SMOOTH);
    gluQuadricOrientation(glQ, GLU_OUTSIDE);
    gluQuadricTexture(glQ, GL_FALSE);

    for (unsigned int y = 0; y < vSize; ++y) {
        for (unsigned int x = 0; x < uSize; ++x) {
            float xVal = 5*3.14/gridSize*x;
            float yVal = 5*3.14/gridSize*y;
            grid[y][x][0] = (float) x/gridSize*10.0;
            grid[y][x][1] = sin(xVal + value) + sin(yVal + value);
            grid[y][x][2] = (float) y/gridSize*10.0;
        }
    }

    glMap2f(GL_MAP2_VERTEX_3, 0, 1 , 3, uSize, 0, 1, uSize * 3, vSize, &grid[0][0][0]);
    glEvalMesh2(GL_FILL, 0, gridSize, 0, gridSize);

    value += 3.14/25;

    if (value > 3.14*2)
        value = 0;
    // swapping the buffers causes the rendering above to be shown
    glutSwapBuffers();
    glFlush();
}


/* Mouse handling */
void processMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {    
    }
    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    {   
    }

    glutPostRedisplay();

}

void processMouseMoved(int x, int y)
{

    // pedido de refrescamento da janela
    glutPostRedisplay();                

}

void processPassiveMouseMoved(int x, int y)
{

    // pedido de refrescamento da janela
    glutPostRedisplay();                
}

void reshape(int w, int h)
{
    int tx, ty, tw, th;

    GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
    glViewport( tx, ty, tw, th );
    xy_aspect = (float)tw / (float)th;

    glutPostRedisplay();

}


void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:      // tecla de escape termina o programa
         exit(0);
         break;
   }
}


void glut_idle( void )
{
  if ( glutGetWindow() != main_window ) 
    glutSetWindow(main_window);  

  glutPostRedisplay();

}

void init()
{
    glQ = gluNewQuadric();

    glFrontFace(GL_CCW);        // Front faces defined using a counterclockwise rotation
    glDepthFunc(GL_LEQUAL);     // Por defeito e GL_LESS
    glEnable(GL_DEPTH_TEST);    // Use a depth (z) buffer to draw only visible objects

    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

    // Face Culling para aumentar a velocidade
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);        // GL_FRONT, GL_BACK, GL_FRONT_AND_BACK


    // Define que modelo de iluminacao utilizar; consultar o manual de referencia
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_ambient);  // define luz ambiente
    glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, 1);

    // por defeito a cor de fundo e o preto
    // glClearColor(1.0,1.0,1.0,1.0);    // cor de fundo a branco


    // declaracoes para a fonte luz GL_LIGHT0
    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,  light0_kc);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION,    light0_kl);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0_kq);

    // NOTA: a direccao e a posicao de GL_LIGHT0 estao na rotina display(), pelo
    //       que as isntrucoes seguntes nao sao necessarias
    //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0);
    //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
    //glLightfv(GL_LIGHT0, GL_POSITION, light0_position);


    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glEnable(GL_NORMALIZE); 

    glEnable(GL_MAP2_VERTEX_3);
    glMapGrid2f(gridSize, 0.0, 1.0, gridSize, 0.0, 1.0);


    glShadeModel(GL_SMOOTH);
    glPolygonMode(GL_FRONT, GL_FILL);
    //glPolygonMode(GL_FRONT, GL_LINE);
}

void do_nothing(int key, int x, int y) {}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize (DIMX, DIMY);
    glutInitWindowPosition (INITIALPOS_X, INITIALPOS_Y);
    main_window = glutCreateWindow (argv[0]);

    glutDisplayFunc(display);
    GLUI_Master.set_glutReshapeFunc(reshape);
    GLUI_Master.set_glutKeyboardFunc (keyboard);
    GLUI_Master.set_glutMouseFunc(processMouse);      
    glutMotionFunc(processMouseMoved);
    glutPassiveMotionFunc(processPassiveMouseMoved);
    GLUI_Master.set_glutSpecialFunc( do_nothing );


    /*** Create the bottom subwindow ***/
    glui = GLUI_Master.create_glui_subwindow( main_window, GLUI_SUBWINDOW_BOTTOM );
    glui->set_main_gfx_window( main_window );

    GLUI_Rotation *view_rot = glui->add_rotation( "Rotation", view_rotate );
    view_rot->set_spin( 1.0 );

    glui->add_column( false );
    GLUI_Translation *trans_z = glui->add_translation( "Zoom", GLUI_TRANSLATION_Z, &obj_pos[2] );
    trans_z->set_speed( .1 );

    glui->add_column(false);
    GLUI_Translation *trans_pan = glui->add_translation("Pan", GLUI_TRANSLATION_XY, &obj_pan[0]);
    trans_pan->set_speed(.1);

    GLUI_Master.set_glutIdleFunc( glut_idle );

    init();

    glutMainLoop();

    return 0;
}

1 Ответ

2 голосов
/ 18 ноября 2011

Вы говорите, что оценщикам OpenGL не нужны нормали для установки. Это только отчасти правда. Вам не нужно устанавливать нормали, если вы включаете автоматически генерируемые нормали для оценщиков, вызывая:

glEnable(GL_AUTO_NORMAL);

Просто включение GL_NORMALIZE не сделает этого.

Но вы, конечно, можете также указать свои собственные нормали, указав контрольные точки для GL_MAP2_NORMAL так же, как для GL_MAP2_VERTEX_3.

И ответ не будет полным, если не упомянуть, что оценщики OpenGL сильно устарели и, скорее всего, реализованы драйвером мягко. Так что лучше просто набрать собственный код оценки Безье (который не очень сложен) и сгенерировать простую сетку, нарисованную как GL_TRIANGLES.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...