view testgl.c @ 0:01387a2e419e

initial version
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 07 Dec 2010 15:39:45 +0900
parents
children
line wrap: on
line source

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include "object.h"
#include "xml.h"
#include "Pad.h"


static int power_of_two(int input)
{
  int value = 1;

  while ( value < input )
    {
      value <<= 1;
    }
  return value;
}


GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
  GLuint texture;
  int w, h;
  SDL_Surface *image;
  SDL_Rect area;
  Uint32 saved_flags;
  Uint8  saved_alpha;

  /* Use the surface width and height expanded to powers of 2 */
  w = power_of_two(surface->w);
  h = power_of_two(surface->h);
  texcoord[0] = 0.0f;                     /* Min X */
  texcoord[1] = 0.0f;                     /* Min Y */
  texcoord[2] = (GLfloat)surface->w / w;  /* Max X */
  texcoord[3] = (GLfloat)surface->h / h;  /* Max Y */

  image = SDL_CreateRGBSurface(
			       SDL_SWSURFACE,
			       w, h,
			       32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
			       0x000000FF, 
			       0x0000FF00, 
			       0x00FF0000, 
			       0xFF000000
#else
			       0xFF000000,
			       0x00FF0000, 
			       0x0000FF00, 
			       0x000000FF
#endif
			       );
  if ( image == NULL )
    {
      return 0;
    }

  /* Save the alpha blending attributes */
  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
  saved_alpha = surface->format->alpha;
  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA )
    {
      SDL_SetAlpha(surface, 0, 0);
    }

  /* Copy the surface into the GL texture image */
  area.x = 0;
  area.y = 0;
  area.w = surface->w;
  area.h = surface->h;
  SDL_BlitSurface(surface, &area, image, &area);

  /* Restore the alpha blending attributes */
  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA )
    {
      SDL_SetAlpha(surface, saved_flags, saved_alpha);
    }

  /* Create an OpenGL texture for the image */
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D,
	       0,
	       GL_RGBA,
	       w, h,
	       0,
	       GL_RGBA,
	       GL_UNSIGNED_BYTE,
	       image->pixels);
  SDL_FreeSurface(image); /* No longer needed */

  return texture;
}

/*
float tes_angle[3] = {0,0,0};
void obj_draw(SURFACE *surfaces)
{
  int n;

  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, (GLuint)surfaces->texture);

  glTranslatef(surfaces->xyz[0],surfaces->xyz[1],surfaces->xyz[2]);

  glTranslatef(*(surfaces->data[2][0]), *(surfaces->data[2][0]+1), *(surfaces->data[2][0]+2));

  glRotatef(surfaces->angle[0], 1, 0, 0);
  glRotatef(surfaces->angle[1], 0, 1, 0);
  glRotatef(surfaces->angle[2], 0, 0, 1);
  
  glTranslatef(-*(surfaces->data[2][0]), -*(surfaces->data[2][0]+1), -*(surfaces->data[2][0]+2));
  
  glBegin( GL_TRIANGLES);
  for(n=0; n<surfaces->size; n++)
    {
      glTexCoord2f(*(surfaces->data[3][n]),*(surfaces->data[3][n]+1));
      glVertex3f(*(surfaces->data[0][n]),*(surfaces->data[0][n]+1),*(surfaces->data[0][n]+2));
      glNormal3f(*(surfaces->data[1][n]),*(surfaces->data[1][n]+1),*(surfaces->data[1][n]+2));
    }
  glEnd( );
  glDisable(GL_TEXTURE_2D);
}
*/


static SURFACE *next_draw_node(SURFACE *surfaces)
{
  SURFACE *node = surfaces;
  if(node->child != NULL)
    {
      glPushMatrix();
      return node->child;
    }
  else if(node->brother != NULL)
    {
      glPopMatrix();
      glPushMatrix();
      return node->brother;
    }
  else
    {
      node = node->parent;
      if(node != NULL)
	{
	  glPopMatrix();
	}
      while(node != NULL)
        {
          if(node->brother != NULL)
            {
	      glPopMatrix();
	      glPushMatrix();
	      return node->brother;
            }
          else
            {
              node = node->parent;
	      if(node != NULL)
		{
		  glPopMatrix();
		}
            }
        }
      return NULL;
    }
}

SURFACE *search_node(OBJECT *top, char *name)
{
  SURFACE *node;
  node = top->surfaces;
  while(node != NULL)
    {
      node = next_draw_node(node);
      if(!strcmp(node->image_name, name)
	{
	  return node;
	}
    }
}

void all_obj_draw(OBJECT *top)
{
  SURFACE *node;
  node = top->surfaces;
  glPushMatrix();
  while(node != NULL)
    {
      obj_draw(node);
      //if(node->child != NULL)
	{
	  node = next_draw_node(node);
	}
      /*
      else
	{
	  //node = node->next;
	}
      */
    }
  glPopMatrix();
}


static SURFACE *next_node(SURFACE *surfaces)
{
  SURFACE *node = surfaces;
  if(node->child != NULL)
    {
      return node->child;
    }
  else if(node->brother != NULL)
    {
      return node->brother;
    }
  else
    {
      node = node->parent;
      while(node != NULL)
        {
          if(node->brother != NULL)
            {
	      return node->brother;
            }
          else
            {
              node = node->parent;
            }
        }
      return NULL;
    }
}





void node_draw(OBJECT *top, char *name)
{
  SURFACE *node;
  for(node=top->surfaces; node!=NULL; node=next_node(node))
    {
      if(!strcmp(node->name, name))
        {
	  glPushMatrix();
          obj_draw(node);
	  glPopMatrix();
        }
    }
}



void node_prameter_change(OBJECT *top, char *name, float x, float y, float z, float ax, float ay, float az)
{
  SURFACE *node;
  for(node=top->surfaces; node!=NULL; node=next_node(node))
    {
      if(!strcmp(node->name, name))
      {
	node->xyz[0] = x;
	node->xyz[1] = y;
	node->xyz[2] = z;
	node->angle[0] = ax;
	node->angle[1] = ay;
	node->angle[2] = az;
      }
    }
}

void all_object_load_texture(OBJECT *top)
{
  SURFACE *node;
  SDL_Surface *image;
  GLfloat texcoord[4];
  for(node=top->surfaces; node!=NULL; node=next_node(node))
    { 
      //image = SDL_LoadBMP(node->image_name);
      //image = IMG_Load(node->image_name);
      image = LoadSprite(node, image);
      node->texture = (int *)SDL_GL_LoadTexture(image, texcoord);
      SDL_FreeSurface(image);
    }
}
	 

int RunGLTest( int argc, char* argv[], int bpp, int width, int height)
{
  int i;
  int rgb_size[3];
  int w = width;
  int h = height;
  int done = 0;
  int frames;
  Uint32 start_time, this_time;

  Uint32 video_flags;
  int value;

  OBJECT *obj;
  obj = read_xml_3d_file(argv[1]);


  if( SDL_Init( SDL_INIT_VIDEO ) < 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 = 16;  /* More doesn't seem to work */
	}
    }

  //video_flags = SDL_OPENGLBLIT;
  video_flags = SDL_OPENGL;
  
  for ( i=1; argv[i]; ++i ) 
    {
      if ( strcmp(argv[i], "-fullscreen") == 0 ) 
	{
	  video_flags |= SDL_FULLSCREEN;
	}
    }

  /* Initialize the display */
  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;
    }
  SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] );
  SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] );
  SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] );
  SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

  SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 );
  
  if ( SDL_SetVideoMode( w, h, bpp, video_flags ) == NULL ) 
    {
      fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError());
      SDL_Quit();
      exit(1);
    }

  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 );
  
  
  /* Set the window manager title bar */
  SDL_WM_SetCaption( "SDL GL test", "testgl" );
  
  glViewport( 0, 0, w, h );
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity( );
  
  glOrtho( -40.0, 40.0, -40.0, 40.0, -400.0, 400.0 );
  
  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity( );
  
  glEnable(GL_DEPTH_TEST);
  
  glDepthFunc(GL_LESS);
  
  glShadeModel(GL_SMOOTH);


  //load texture image
  all_object_load_texture(obj);

  
  /* Loop until done. */
  start_time = SDL_GetTicks();
  frames = 0;
  while( !done ) 
    {
      GLenum gl_error;
      char* sdl_error;
      SDL_Event event;
      while(SDL_PollEvent(&event))
	{
	  if(event.type==SDL_QUIT) goto QUIT;
	}
      
      /* Do our drawing, too. */
      glClearColor( 0.0, 0.0, 0.0, 1.0 );
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      Pad();
  
      //node_prameter_change(obj, "Cube", 0, 0, 0, 0, 1, 0);
      //node_prameter_change(obj, "Sphere.001", 0, 0, 0, 0, 1, 0);
      //node_prameter_change(obj, "Plane", 0, 0, 0, 0, 1, 0);
      //node_prameter_change(obj, "Plane.001", 0, 0, 0, 0, 1, 0);
      //node_prameter_change(obj, "Sphere", 0, 0, 0, 0, 1, 0);
  
      all_obj_draw(obj);
      //node_draw(obj, "Cube");

      glMatrixMode(GL_MODELVIEW);
      //glRotatef(1.0, 1.0, 1.0, 1.0);
      /*
      if(pad[0].up > 0)
	{
	  node_prameter_change(obj, "Plane", 0, 1, 0, 0, 0, 0);
	}
      else if(pad[0].down > 0)
	{
	  node_prameter_change(obj, "Plane", 0, -1, 0, 0, 0, 0);
	}

      if(pad[0].right > 0)
	{
	  node_prameter_change(obj, "Plane", 1, 0, 0, 0, 0, 0);
	}
      else if(pad[0].left > 0)
	{
	  node_prameter_change(obj, "Plane", -1, 0, 0, 0, 0, 0);
	}
      */
      SDL_GL_SwapBuffers( );
      
      /* Check for error conditions. */
      gl_error = glGetError( );
      
      if( gl_error != GL_NO_ERROR ) 
	{
	  fprintf( stderr, "testgl: OpenGL error: %s\n", (char *)gl_error );
	}
      
      sdl_error = SDL_GetError( );
      
      if( sdl_error[0] != '\0' ) 
	{
	  fprintf(stderr, "testgl: SDL error '%s'\n", sdl_error);
	  SDL_ClearError();
	}
     
      ++frames;
    }
  
  /* Destroy our GL context, etc. */
 QUIT:
  /* Print out the frames per second */
  this_time = SDL_GetTicks();
  if ( this_time != start_time ) 
    {
      printf("%2.2f FPS\n",((float)frames/(this_time-start_time))*1000.0);
    }
  SDL_Quit( );
  return(0);
}

int main(int argc, char *argv[])
{
  int i;
  int bpp = 0;
  int width = 640;
  int height = 480;
  for ( i=1; argv[i]; ++i )
    {
      if ( strcmp(argv[i], "-bpp") == 0 )
	{
	  bpp = atoi(argv[++i]);
	}
      if ( strcmp(argv[i], "-width") == 0 )
	{
	  width = atoi(argv[++i]);
	} 
      if ( strcmp(argv[i], "-height") == 0 ) 
	{
	  height = atoi(argv[++i]);
	}
    }
  RunGLTest(argc, argv, bpp, width, height);
  return 0;
}