view Renderer/Engine/viewerGL.cc @ 930:35efda39c2d9

GL drawing speed up
author koba <koba@cr.ie.u-ryukyu.ac.jp>
date Fri, 30 Jul 2010 21:46:04 +0900
parents 0f4ae8246dc3
children 660e9190c40c
line wrap: on
line source

#include "viewerGL.h"


static void
ApplyMatrix(float *v, float *m)
{
  float t[4];

  t[0] = v[0];
  t[1] = v[1];
  t[2] = v[2];
  t[3] = v[3];

  for (int i = 0; i < 4; i++) {
    v[i] = t[0]*m[i] + t[1]*m[i+4] + t[2]*m[i+8] + t[3]*m[i+12];
  }
}

static void
ApplyNormalMatrix(float *v, float *m)
{
  float t[4];

  t[0] = v[0];
  t[1] = v[1];
  t[2] = v[2];

  for (int i = 0; i < 3; i++) {
    v[i] = t[0]*m[i] + t[1]*m[i+4] + t[2]*m[i+8];
  }
}

cViewerGL::cViewerGL(TaskManager *m, int b, int w, int h, int _num)
{
  spe_num = _num;
  manager = m;

  quit_flag = false;
  start_time = 0;
  this_time = 0;
  frames = 0;

  video_init(b, w, h);
}

void
cViewerGL::video_init(int bpp, int width, int height)
{
  int rgb_size[3];
  Uint32 sdl_flag = SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK;
  Uint32 video_flag = SDL_OPENGL;
  int value = 1;

  if (SDL_Init(sdl_flag) < 0) {
    fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
    exit(1);
  }

  /* See if we should detect the display depth */
  if ( bpp == 0 )
    {
      if ( SDL_GetVideoInfo()->vfmt->BitsPerPixel <= 8 )
        {
          bpp = 8;
        }
      else
        {
          bpp = 32;
        }
    }

  /* Initialize the bpp */
  switch (bpp)
    {
    case 8:
      rgb_size[0] = 3;
      rgb_size[1] = 3;
      rgb_size[2] = 2;
      break;
    case 15:
    case 16:
      rgb_size[0] = 5;
      rgb_size[1] = 5;
      rgb_size[2] = 5;
      break;
    default:
      rgb_size[0] = 8;
      rgb_size[1] = 8;
      rgb_size[2] = 8;
      break;
    }
  
  screen = SDL_SetVideoMode(width, height, bpp, video_flag);
  if (screen == NULL) {
    fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError());
    SDL_Quit();
    exit(1);
  }
  this->width = screen->w;
  this->height = screen->h;
  this->bpp = screen->format->BitsPerPixel;

  //各パラメータがちゃんと取れているか確認
  printf("Screen BPP: %d\n", SDL_GetVideoSurface()->format->BitsPerPixel);
  printf("\n");
  printf( "Vendor     : %s\n", glGetString( GL_VENDOR ) );
  printf( "Renderer   : %s\n", glGetString( GL_RENDERER ) );
  printf( "Version    : %s\n", glGetString( GL_VERSION ) );
  printf( "Extensions : %s\n", glGetString( GL_EXTENSIONS ) );
  printf("\n");

  SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &value );
  printf( "SDL_GL_RED_SIZE: requested %d, got %d\n", rgb_size[0],value);
  SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &value );
  printf( "SDL_GL_GREEN_SIZE: requested %d, got %d\n", rgb_size[1],value);
  SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &value );
  printf( "SDL_GL_BLUE_SIZE: requested %d, got %d\n", rgb_size[2],value);
  SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &value );
  printf( "SDL_GL_DEPTH_SIZE: requested %d, got %d\n", bpp, value );
  SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &value );
  printf( "SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value );

  //OpenGLの設定
  glViewport( 0, 0, width, height );
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity( );

  glOrtho( 0.0, width, height, 0.0, OPENGL_PARAM::near, OPENGL_PARAM::far );

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity( );

  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);
  glShadeModel(GL_SMOOTH);
}

void
cViewerGL::clean_pixels()
{
  glClearColor( 0.0, 0.0, 0.0, 1.0 );
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void
cViewerGL::clear_screen()
{
  GLenum gl_error;
  char* sdl_error;

  SDL_GL_SwapBuffers( );

  /* Check for error conditions. */
  gl_error = glGetError( );

  if( gl_error != GL_NO_ERROR )
    {
      fprintf( stderr, "OpenGL error: %d\n", gl_error );
    }

  sdl_error = SDL_GetError( );

  if( sdl_error[0] != '\0' )
    {
      fprintf(stderr, "SDL error '%s'\n", sdl_error);
      SDL_ClearError();
    }
}

void
cViewerGL::pickup_vertex()
{
  float xyz1[4], xyz2[4], xyz3[4];
  float tex_xy1[2], tex_xy2[2], tex_xy3[2];
  float normal1[4],normal2[4],normal3[4];
  GLuint texture;

  SceneGraphPtr sg_top = sgroot->getDrawSceneGraph();
  SceneGraphPtr sg = sg_top;

  while (sg) {
    if (sg->flag_drawable) {
      texture = sg->gl_tex;
      glBindTexture(GL_TEXTURE_2D, texture);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

      glEnable(GL_TEXTURE_2D);
      glEnable(GL_BLEND);
      glBegin( GL_TRIANGLES);
      for (int i = 0; i < sg->size; i += 3) {
	xyz1[0] = sg->coord_xyz[(i+0)*3];
	xyz1[1] = sg->coord_xyz[(i+0)*3+1];
	xyz1[2] = sg->coord_xyz[(i+0)*3+2]*-1.0f;
	xyz1[3] = 1.0f;
	
	xyz2[0] = sg->coord_xyz[(i+1)*3];
	xyz2[1] = sg->coord_xyz[(i+1)*3+1];
	xyz2[2] = sg->coord_xyz[(i+1)*3+2]*-1.0f;
	xyz2[3] = 1.0f;
	
	xyz3[0] = sg->coord_xyz[(i+2)*3];
	xyz3[1] = sg->coord_xyz[(i+2)*3+1];
	xyz3[2] = sg->coord_xyz[(i+2)*3+2]*-1.0f;
	xyz3[3] = 1.0f;

	// sg->matrix = 回転行列*透視変換行列
	ApplyMatrix(xyz1, sg->matrix);
	ApplyMatrix(xyz2, sg->matrix);
	ApplyMatrix(xyz3, sg->matrix);

	xyz1[0] /= xyz1[2];
	xyz1[1] /= xyz1[2];
	xyz2[0] /= xyz2[2];
	xyz2[1] /= xyz2[2];
	xyz3[0] /= xyz3[2];
	xyz3[1] /= xyz3[2];
	
	tex_xy1[0] = sg->coord_tex[(i+0)*3];
	tex_xy1[1] = sg->coord_tex[(i+0)*3+1];
      	tex_xy2[0] = sg->coord_tex[(i+1)*3];
	tex_xy2[1] = sg->coord_tex[(i+1)*3+1];
	tex_xy3[0] = sg->coord_tex[(i+2)*3];
	tex_xy3[1] = sg->coord_tex[(i+2)*3+1];
	
	normal1[0] = sg->normal[(i+0)*3];
	normal1[1] = sg->normal[(i+0)*3+1];
	normal1[2] = sg->normal[(i+0)*3+2]*-1.0f;
	normal1[3] = 0.0f;

	normal2[0] = sg->normal[(i+1)*3];
	normal2[1] = sg->normal[(i+1)*3+1];
	normal2[2] = sg->normal[(i+1)*3+2]*-1.0f;
	normal2[3] = 0.0f;

	normal3[0] = sg->normal[(i+2)*3];
	normal3[1] = sg->normal[(i+2)*3+1];
	normal3[2] = sg->normal[(i+2)*3+2]*-1.0f;
	normal3[3] = 0.0f;

	ApplyNormalMatrix(normal1,sg->real_matrix);
	ApplyNormalMatrix(normal2,sg->real_matrix);
	ApplyNormalMatrix(normal3,sg->real_matrix);

	normal1[0] /= normal1[2];
	normal1[1] /= normal1[2];
	
	normal2[0] /= normal2[2];
	normal2[1] /= normal2[2];
	
	normal3[0] /= normal3[2];
	normal3[1] /= normal3[2];

	obj_draw(xyz1, tex_xy1, normal1);
	obj_draw(xyz2, tex_xy2, normal2);
	obj_draw(xyz3, tex_xy3, normal3);
      }
      glEnd( );
      glDisable(GL_BLEND);
      glDisable(GL_TEXTURE_2D);
    }
   
    if (sg->children != NULL) {
      sg = sg->children;
    } else if (sg->brother != NULL) {
      sg = sg->brother;
    } else {
      while (sg) {
	if (sg->brother != NULL) {
	  sg = sg->brother;
	  break;
	} else {
	  if (sg->parent == NULL) {
	    sg = NULL;
	    break;
	  } else {
	    sg = sg->parent;
	  }
	}
      }
    }

  }
}

void
cViewerGL::obj_draw(float *xyz, float *tex_xyz, float *normal_xyz)
{  
  glTexCoord2f(tex_xyz[0], tex_xyz[1]);
  glVertex3f(xyz[0], xyz[1], xyz[2]);
  glNormal3f(normal_xyz[0], normal_xyz[1], normal_xyz[2]);
}

void
cViewerGL::mainLoop()
{
  while(!quit_flag) {
    run_loop();
  }
}

void
cViewerGL::run_loop()
{
  clear_screen();

  quit_flag = quit_check();
  if (quit_flag == true) {
    this_time = get_ticks();
    run_finish();
    return;
  }

  clean_pixels();

  sgroot->updateControllerState();
  sgroot->allExecute(width, height);
  light_xyz_stock = sgroot->getLightVector();
  light_switch_stock = sgroot->getLightSwitch();
  light_sysswitch_stock = sgroot->getLightSysSwitch();
  pickup_vertex();
  
  psx_sync_n();
  frames++;
}

void
cViewerGL::run_finish()
{
  if (this_time != start_time) {
    printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0);
  }
  
  delete sgroot;
  quit();
}

/* end */