view TaskManager/Test/simple_render/viewer.cpp @ 42:aa11038dbdc1

*** empty log message ***
author gongo
date Thu, 14 Feb 2008 18:27:37 +0900
parents babf9a330418
children 70a0ac46133e
line wrap: on
line source

#include <iostream>
#include <SDL.h>
#include <SDL_opengl.h>
#include <math.h>
#include "polygon.h"
//#include "demonstration.h"
//#include "scene.h"
#include "viewer.h"
#include "sys.h"
using namespace std;

#define redMask   0x00ff0000
#define greenMask 0x0000ff00
#define blueMask  0x000000ff
#define alphaMask 0

extern int create_sgp(SceneGraphPack *sgp, Polygon *sg);
extern int update_sgp(SceneGraphPack *sgp, SceneGraphPack *_sgp);
extern int create_pp(PolygonPack *pp, SceneGraphPack *sgp);

Viewer::Viewer(int b, int w, int h)
{
    bpp = b;
    width = w;
    height = h;
}


void Viewer::sdl_init()
{
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
	fprintf(stderr,"Couldn't initialize SDL: %s\n",SDL_GetError());
	exit( 1 );
    }
    screen = SDL_SetVideoMode( width, height, bpp, SDL_HWSURFACE );

    //manager = new TaskManager(1);
    //manager->init();
}


void Viewer::init()
{
    if(SDL_Init( SDL_INIT_VIDEO ) < 0)
    {
	cout << "Couldn't initialize SDL:" << SDL_GetError() << endl;
	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_OPENGL;
    video_flags = SDL_HWSURFACE;

    /* 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);

    screen = SDL_SetVideoMode(width, height, bpp, video_flags);
  
    if(screen == NULL)
    {
	cout << "Couldn't set GL mode: " <<  SDL_GetError() << endl;
	SDL_Quit();
	exit(1);
    }

    SDL_WM_SetCaption("SDL GL test", "testgl");

    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
  
    glOrtho(-width/10, width/10, -height/10, height/10, -40.0, 400.0);
  
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
  
    glEnable(GL_DEPTH_TEST);
  
    glDepthFunc(GL_LESS);
  
    glShadeModel(GL_SMOOTH);
}

int Viewer::get_ticks()
{
    int time;
    time = SDL_GetTicks();
    return time;
}

bool Viewer::quit_check()
{
    bool quit = false;
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
	if(event.type==SDL_QUIT)
	{
	    quit = true;
	    return quit;
	}
    }
    return quit;
}

void Viewer::quit()
{
    SDL_Quit();
}


void Viewer::swap_buffers()
{
    SDL_GL_SwapBuffers();
}


void Viewer::write_pixel(int x, int y,float z, Uint32 rgb) {
    SDL_PixelFormat *pf;
    pf = screen->format;
    //printf("x:%d y:%d z:%d\n",x,y,z);

    //cout << "write_pixel" << endl;
    //cout << x << "  " << y << endl;

    //cout << SDL_MapRGB(pf,0,0,150) << endl;

    x += width/2;
    y += height/2;

    static int diffz,diffz1;
    diffz1 = diffz;
    diffz = (zRow[x][y]>z);
    if(diffz != diffz1) {
	//printf("diffz :%d zRow[%d][%d] = %f z = %f\n",diffz,x,y,zRow[x][y],z);
    }
    //printf("x:%d,y:%d,z:%f,zRow:%f\n",x,y,z,zRow[x][y]);
    if(z < zRow[x][y]) { 
//	 printf("x:%d,y:%d,z:%d\n",x,y,z,zRow);
	if(x < width && x > 0 && y > 0 && y < height)
	{
	    //pixels[width*y + x] = SDL_MapRGB(pf,70,70,71);
	    zRow[x][y] = z;
	    y = height - y;
	    pixels[width*y + x] = rgb;
	}
    }
}

void Viewer::write_line(float x1, float y1, float x2, float y2, Uint32 rgb)
{
    //cout << "write_line("<< x1 << "," << y1 << "," << x2 << "," << y2 << ")"<< endl;

    //Uint32 rgb = 9830400;

    if(x1 > x2)
    {
	float x=0;
	float y=0;
	x=x1;
	y=y1;
	x1 = x2;
	y1 = y2;
	x2 = x;
	y2 = y;
    }
    float s = y1;

    if((int)x1 == (int)x2)
    {
	if(y1 > y2)
	{
	    float y=0;
	    y = y1;
	    y1 = y2;
	    y2 = y;
	}
	for(float i=y1; i<y2; i++)
	{
	    //write_pixel((int)x1,(int)i);
	    write_pixel((int)x1,(int)i,0,rgb);
	}
    }
    else 
    {
	float t = (y2 - y1)/(x2 - x1);
	if(t < -1)
	{
	    float f = 0;
	    for(float i=x1; i<x2; i++)
	    {
		for(float a=(int)t; a<0; a++)
		{
		    //write_pixel((int)i,(int)s);
		    write_pixel((int)i,(int)s,0,rgb);
		    s--;
		}
		f += t-(int)t;
		if(f <= -1)
		{
		    //write_pixel((int)i,(int)s);
		    write_pixel((int)i,(int)s,0,rgb);
		    f = 0;
		    s--;
		}
	    }
	}
	else if(t <= 1)
	{
	    for(float i=x1; i<x2; i++)
	    {
		//write_pixel((int)i,(int)s);
		write_pixel((int)i,(int)s,0,rgb);
		s += t;
	    }
	}
	else
	{
	    float f = 0;
	    for(float i=x1; i<x2; i++)
	    {
		for(float a=0; a<(int)t; a++)
		{
		    //write_pixel((int)i,(int)s);
		    write_pixel((int)i,(int)s,0,rgb);
		    s++;
		}
		f += t-(int)t;
		if(f >= 1)
		{
		    //write_pixel((int)i,(int)s);
		    write_pixel((int)i,(int)s,0,rgb);
		    f = 0;
		    s++;
		}
	    }
	}
    }
}

void Viewer::write_triangle(float x1, float y1, float x2, float y2, float x3, float y3, Uint32 rgb)
{
    write_line(x1,y1,x2,y2,rgb);
    write_line(x2,y2,x3,y3,rgb);
    write_line(x3,y3,x1,y1,rgb);
}

void Viewer::clean_pixels()
{
    for(int i=0; i<width*height; i++)
    {
	pixels[i] = 0x00;
    }
}

void Viewer::graph_line()
{
    int xl = width*height/2;
    int yl = width/2;
    for(int i=0; i<width; i++)
    {
	for(int t=0; t<height; t+=20)
	{
	    pixels[width*t+i] = 0x5a;
	}
	pixels[xl +i] = 0xff;
    }
    for(int i=0; i<height; i++)
    {
	for(int t=0; t<width; t+=20)
	{
	    pixels[i*width+t] = 0x5a;
	}
	pixels[i*width+yl] = 0xff;
    }
}


struct run_arg_t {
    int start_time;
    int this_time;
    int frames;
    SDL_Surface *bitmap;
    SDL_PixelFormat *pf;
    Uint32 background;
    Polygon *p;
    SceneGraphPack *sgp;
    PolygonPack *pp;    
};

#if 0
void
Viewer::run_init()
{
    struct run_arg_t *arg = new run_arg_t;
    HTaskPtr task;
    int fd;

    arg->start_time = get_ticks();
    arg->pf         = screen->format;
    arg->background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
    arg->p          = new Polygon;
    arg->p->set_data("cube.xml");
    arg->p->viewer  = this;
    arg->sgp        = new SceneGraphPack;
    create_sgp(arg->sgp, arg->p);
    arg->pp         = new PolygonPack;

    pixels = new Uint32[width*height];
    
    graph_line();

    arg->bitmap = SDL_CreateRGBSurfaceFrom((void *)pixels, width, height, 32,
				      width*4, redMask, greenMask,
				      blueMask, alphaMask);

    fd = manager->open("ViewerRunLoop");
    task = manager->create_task(fd, sizeof(struct run_arg_t),
				(unsigned int)arg, 0, NULL);      
    manager->spawn_task(task_create_pp);
    //manager->run();
}

void
Viewer::run_loop(struct run_arg_t *arg)
{
    HTaskPtr task_update_sgp = NULL;
    HTaskPtr task_create_pp = NULL;
    HTaskPtr task_finish = NULL;
    int fd_update_sgp;
    int fd_create_pp;
    int fd_finish;

    if (quit_check()) {
	arg->this_time = get_ticks();
	fd_finish = manager->open("ViewerRunFinish");
	task_finish = manager->create(fd_finish, sizeof(struct run_arg_t),
				      (unsigned int)arg, 0, NULL);
	manager->spawn_task(task_finish);
	return;
    }

    clean_pixels();

    this->zRow_init();
    graph_line();

    fd_update_sgp = manager->open("UpdateSGP");
    fd_create_pp  = manager->open("CreatePP");
    task_update_sgp =
	manager->create_task(fd_update_sgp,
			     sizeof(SceneGraphPack),
			     (unsigned int)arg->sgp,
			     (unsigned int)arg->sgp,
			     NULL);      
    task_create_pp =
	manager->create_task(fd_create_pp,
			     sizeof(SceneGraphPack),
			     (unsigned int)arg->sgp,
			     (unsigned int)arg->pp,
			     NULL);

    manager->spawn_task(task_update_sgp);
    manager->spawn_task(task_create_pp);
    manager->run();

    arg->p->draw(pp);    // test draw of PolygonPack
	
    SDL_BlitSurface(arg->bitmap, NULL, screen, NULL);
    SDL_UpdateRect(screen, 0, 0, 0, 0);

    //swap_buffers();
    arg->frames++;
}

void
Viewer::run_finish(struct run_arg_t *arg)
{
    if (arg->this_time != arg->start_time) {
	cout<< ((float)arg->frames/(this_time-start_time))*1000.0 << " FPS\n";
    }

    SDL_FreeSurface(arg->bitmap);
    delete [] pixels;
    arg->p->delete_data();
    delete arg->p;
    delete arg->sgp;
    delete arg->pp;
    quit();

    delete arg;
}
#endif

void Viewer::run()
{
    int frames = 0;
    int start_time, this_time;

    HTaskPtr task_create_sgp = NULL;
    HTaskPtr task_update_sgp = NULL;
    HTaskPtr task_create_pp = NULL;
    int fd_create_sgp;
    int fd_update_sgp;
    int fd_create_pp;

    start_time = get_ticks();

    SDL_Surface *bitmap = NULL;
    SDL_PixelFormat *pf;
    pf = screen->format;

    Uint32 background;
    background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);

    pixels = new Uint32[width*height];

    Polygon *p = new Polygon;
    p->set_data("cube.xml");
    //p->set_data("cube-p.xml");

    p->viewer = this;
    //p->screen = screen;

    SceneGraphPack *sgp = new SceneGraphPack;
    create_sgp(sgp,p);

    PolygonPack *pp = new PolygonPack;

    graph_line();

    float r = 0;
    float x = 0;
    float y = 0;
    float z = 0;

    bitmap = SDL_CreateRGBSurfaceFrom((void *)pixels, width, height, 32,
				      width*4, redMask, greenMask,
				      blueMask, alphaMask);

    // Loop until done.
    while(1)
    {
	// Destroy our GL context, etc.
	//if(quit_check() || scene->action_scene==NULL)
	if(quit_check())
	{
	    this_time = get_ticks();
	    if (this_time != start_time) 
	    {
		cout<<((float)frames/(this_time-start_time))*1000.0<<" FPS\n";
	    }
	    SDL_FreeSurface(bitmap);
	    delete pixels;
	    p->delete_data();
	    delete p;
	    delete sgp;
	    delete pp;
	    quit();
	    break;
	}
	/////////////////////
	clean_pixels();

	this->zRow_init();
	graph_line();

#if 0 // ここは update_sgp
	if(r > 360) r = 0;
	r+= 1.0;
	// r= 0;
	p->angle[0] = 0;
	p->angle[1] = r;
	p->angle[2] = 0;
	//p->child->angle[1] = r*2;
	//p->child->brother->angle[1] = r*3;
	//p->child->brother->child->angle[1] = r*4;
	x += 0.5;
	y += 0.5;
	z += 0.5;
	p->xyz[0] = x;
	p->xyz[1] = y;
	p->xyz[2] = z;
	//p->tree_draw();
#endif

#if 0
	update_sgp(sgp, sgp);
	create_pp(pp, sgp);
#else
	fd_update_sgp = manager->open("UpdateSGP");
	fd_create_pp  = manager->open("CreatePP");
	task_update_sgp =
	    manager->create_task(fd_update_sgp,
				 sizeof(SceneGraphPack),
				 (unsigned int)sgp,
				 (unsigned int)sgp,
				 NULL);      
	task_create_pp =
	    manager->create_task(fd_create_pp,
				 sizeof(SceneGraphPack),
				 (unsigned int)sgp,
				 (unsigned int)pp,
				 NULL);

	manager->spawn_task(task_update_sgp);
	manager->spawn_task(task_create_pp);
	manager->run();
#endif

	//p->draw(sgp); // test draw of SceneGraphPack
	p->draw(pp);    // test draw of PolygonPack
	
	// 一回のみ生成で、その後は再利用
	//bitmap = SDL_CreateRGBSurfaceFrom((void *)pixels, width, height, 32,
	//width*4, redMask, greenMask,
	//blueMask, alphaMask);
	
	//SDL_FillRect(screen, NULL, background);
	SDL_BlitSurface(bitmap, NULL, screen, NULL);
	SDL_UpdateRect(screen, 0, 0, 0, 0);
	

	/////////////////////

	//swap_buffers();
	++frames;
    }
}

void
Viewer::zRow_init()
{
    for (int i = 0; i < width; i++) {
	for (int j = 0; j < height; j++) {
	    zRow[i][j] = 65535;
	}
    }
}