Mercurial > hg > Game > Cerium
changeset 922:cb1023423861 draft
moving OpenGL mode now!
author | koba <koba@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 29 Jul 2010 22:56:58 +0900 |
parents | 841034b1d197 |
children | 382a48afb061 fada580e4604 |
files | Renderer/Engine/SceneGraph.cc Renderer/Engine/main.cc Renderer/Engine/viewer.h Renderer/Engine/viewerGL.cc Renderer/Engine/viewerGL.h Renderer/Engine/viewer_types.h |
diffstat | 6 files changed, 1081 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/Renderer/Engine/SceneGraph.cc Mon Jul 26 00:39:15 2010 +0900 +++ b/Renderer/Engine/SceneGraph.cc Thu Jul 29 22:56:58 2010 +0900 @@ -464,6 +464,7 @@ texture_image = converted; } + this->texture_image = texture_image; return texture_image; }
--- a/Renderer/Engine/main.cc Mon Jul 26 00:39:15 2010 +0900 +++ b/Renderer/Engine/main.cc Thu Jul 29 22:56:58 2010 +0900 @@ -2,6 +2,7 @@ #include "viewer.h" #include "viewerSDL.h" #include "viewerFB.h" +#include "viewerGL.h" #include "Application.h" /* prototype */ @@ -52,6 +53,8 @@ vtype = VTYPE_SDL; } else if (strcmp(argv[i+1], "fb") == 0) { vtype = VTYPE_FB; + } else if (strcmp(argv[i+1], "gl") == 0) { + vtype = VTYPE_GL; } i++; } @@ -67,7 +70,9 @@ } else if (vtype == VTYPE_FB) { ViewerDevice *dev = new ViewerFB(manager); screen = new Viewer(manager, dev, bpp, width, height, spenum); - }else{ + } else if (vtype == VTYPE_GL) { + screen = new cViewerGL(manager, bpp, width, height, spenum); + } else { ViewerDevice *dev = new ViewerSDL(manager); screen = new Viewer(manager, dev, bpp, width, height, spenum); }
--- a/Renderer/Engine/viewer.h Mon Jul 26 00:39:15 2010 +0900 +++ b/Renderer/Engine/viewer.h Thu Jul 29 22:56:58 2010 +0900 @@ -19,7 +19,7 @@ class Viewer : public MainLoop { public: - + Viewer(){}; Viewer(TaskManager *manager, ViewerDevice *dev, int bpp, int width, int height, int spenum); virtual ~Viewer() {} @@ -64,7 +64,7 @@ void clean_pixels() {} - void run_init(TaskManager *manager, Application *app); + virtual void run_init(TaskManager *manager, Application *app); void run_loop(HTaskPtr task_next); void run_draw(HTaskPtr task_next); void run_finish();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/viewerGL.cc Thu Jul 29 22:56:58 2010 +0900 @@ -0,0 +1,1019 @@ +#include "viewerGL.h" +#include "Func.h" +#include "TaskManager.h" +#include "lindaapi.h" +#include "viewer_types.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]; + } +} + + +int power_of_two(int input) +{ + int value = 1; + + while ( value < input ) + { + value <<= 1; + } + return value; +} + +cViewerGL::cViewerGL(TaskManager *m, int b, int w, int h, int _num) +{ + spe_num = _num; + manager = m; + + 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( -1000.0, 1000.0, 1000.0, -1000.0, -1000.0, 1000.0 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity( ); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glShadeModel(GL_SMOOTH); + + /* 多分使わない + p = (Uint32*)manager->allocate(screen->pitch*height); + bitmap = SDL_CreateRGBSurfaceFrom((void *)p, + screen->w, screen->h, + screen->format->BitsPerPixel, + screen->pitch, + redMask, greenMask, blueMask, alphaMask); + + return p; + */ +} + +void +cViewerGL::clean_pixels() +{ + // SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0)); + + glClearColor( 0.0, 0.0, 0.0, 1.0 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void +cViewerGL::clear_screen() +{ + // SDL_BlitSurface(bitmap, NULL, screen, NULL); + // SDL_UpdateRect(screen, 0, 0, 0, 0); + 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(); + } +} + +#if 0 +void +cViewerGL::free_device() +{ + free(bitmap->pixels); + SDL_FreeSurface(bitmap); +} +#endif + +void +cViewerGL::pickup_vertex() +{ + SDL_Surface* texture; + 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 image; + + SceneGraphPtr sg_top = sgroot->getDrawSceneGraph(); + SceneGraphPtr sg = sg_top; + + while (sg) { + if (sg->flag_drawable) { + texture = sg->texture_image; + image = SDL_GL_LoadTexture(texture); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, image); + 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]; + + // if (sg->texture_image != NULL) { + + + obj_draw(xyz1, tex_xy1, normal1); + obj_draw(xyz2, tex_xy2, normal2); + obj_draw(xyz3, tex_xy3, normal3); + + + //} + /* + triangle->tex_info.addr = sg->texture_info.pixels; + triangle->tex_info.width = sg->texture_info.t_w; + triangle->tex_info.height = sg->texture_info.t_h; + triangle->tex_info.scale_max = sg->texture_info.scale_max; + */ + } + glEnd( ); + 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::run_init(TaskManager *manager, Application *app) +{ + this->manager = manager; + + start_time = get_ticks(); + this_time = 0; + frames = 0; + + if (spe_num == 0) spe_num = 1; + + sgroot = new SceneGraphRoot(this->width, this->height); + sgroot->tmanager = manager; + + int light_num = 4; + int size = sizeof(float)*4*light_num; //xyz+alfa(4) * light_num(4) + int light_size = size / sizeof(float); + + light_xyz_stock = (float *)manager->allocate(size); + light_xyz = (float *)manager->allocate(size); + + for (int i = 0; i < light_size ; i++) { + light_xyz[i] = 0.0f; + } + + for(int i = 0; i < spe_num; i++) { + + HTaskPtr data_load = manager->create_task(DataAllocate); + data_load->set_param(0,(memaddr)size); + data_load->set_param(1,(memaddr)Light); + data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); + data_load->spawn(); + } + + size = light_num * sizeof(int); + light_switch = (int*)manager->allocate(size); + + for (int i = 0; i < light_num; i++) { + light_switch[i] = 0; + } + + for(int i = 0; i < spe_num; i++) { + HTaskPtr data_load = manager->create_task(DataAllocate); + data_load->set_param(0,(memaddr)size); + data_load->set_param(1,(memaddr)LightSwitch); + data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); + data_load->spawn(); + } + + size = 16; // LightSysSwitch は 4byte. 残り 12byte は DMA転送の為のパディング + + light_sysswitch = (int*)manager->allocate(size); + + for (unsigned int i = 0; i < size / sizeof(int); i++) { + light_sysswitch[i] = 0; + } + + for(int i = 0; i < spe_num; i++) { + HTaskPtr data_load = manager->create_task(DataAllocate); + data_load->set_param(0,(memaddr)size); + data_load->set_param(1,(memaddr)LightSysSwitch); + data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); + data_load->spawn(); + } + + MainLoop *mainloop = app->init(this, this->width, this->height); + mainloop->mainLoop(); +} + +#if 0 + HTaskPtr + cViewerGL::initLoop() + { + HTaskPtr task_next; + HTaskPtr task_tex; + + sgpack = (SceneGraphPack*)manager->allocate(sizeof(SceneGraphPack)); + sgpack->init(); + ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack)); + + spackList_length = (this->height + split_screen_h - 1) / split_screen_h; + spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*spackList_length); + printf("spackList %0x height %d\n",(unsigned int)spackList, this->height); + + /** + * SPU に送る address list は 16 バイト倍数でないといけない。 + * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような + * length_align を求めている。はみ出した部分は使われない + * (ex) spackList_length が 13 の場合 + * spackList_length_align = 16; + * 実際に送るデータは64バイトになるのでOK + * 14,15,16 の部分は何も入らない。 + */ +spackList_length_align = (spackList_length + 3)&(~3); + +/* 各 SPU が持つ、SpanPack の address list */ +spackList_ptr = + (SpanPack**)manager->allocate(sizeof(SpanPack*)*spackList_length_align); + +for (int i = 0; i < spackList_length; i++) { + spackList_ptr[i] = &spackList[i]; + } + +for (int i = 1; i <= spackList_length; i++) { + spackList[i-1].init(i*split_screen_h); + } + +task_next = manager->create_task(Dummy,0,0,0,0); + +// ここは、Iterator を用意するべきだよね +for (int i = 0; i < spe_num; i++) { + task_tex = manager->create_task(LoadTexture,0,0,0,0); + task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i)); + task_next->wait_for(task_tex); + task_tex->spawn(); + } + +return task_next; +} +#endif + +void +cViewerGL::mainLoop() +{ + while(1) { + run_loop(); + } +} + +GLuint +cViewerGL::SDL_GL_LoadTexture(SDL_Surface *surface) +{ + GLuint texture; + GLfloat texcoord[4]; + 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; +} + +void +cViewerGL::run_loop() +{ + clear_screen(); + + bool quit_flg; + quit_flg = quit_check(); + if (quit_flg == 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++; + // rendering(task_next); +} + + +#if 0 //要らないハズ +void +cViewerGL::run_collision() +{ +} + +void +post2rendering(SchedTask *s, void *viewer_, void *arg) +{ + Viewer *viewer = (Viewer *)viewer_; + HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0); + viewer->rendering(task_next); +} + +void +cViewerGL::rendering(HTaskPtr task_next) +{ + common_rendering(task_next, sgroot); + + // Barrier 同期 + // run_draw() を呼ぶ post2runDraw + task_next->set_post(post2runDraw, (void*)this, 0); // set_post(function(this->run_draw()), NULL) + task_next->spawn(); + + // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が cViewerGL::run_draw() を呼ぶ +} + +static void +post2runDraw(SchedTask *s, void *viewer_, void *arg) +{ + Viewer *viewer = (Viewer*)viewer_; + HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0); + viewer->run_draw(task_next); + +} + +void +cViewerGL::run_draw(HTaskPtr task_next) // 引数に post2runLoop を入れるようにする +{ + common_draw(task_next); + + task_next->set_post(post2runLoop, (void*)this, 0); // set_post(function(this->run_loop()), NULL) + task_next->spawn(); + // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が cViewerGL::run_loop() を呼ぶ + + +} + + +static void +post2speRendering(SchedTask *s, void *viewer_, void *arg) +{ + Viewer *viewer = (Viewer*)viewer_; + HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0); + viewer->spe_rendering(task_next); +} + +#if SPE_CREATE_POLYGON + +void +cViewerGL::create_pp_task(SceneGraphPtr sg, PolygonPackPtr pp_cur, HTaskPtr create_pp_wait, + int &pp_index, int &sg_index, int tri_num) +{ + + HTaskPtr create_pp = manager->create_task(CreatePolygon); + create_pp->set_inData(0, &sg->tri_pack[sg_index], sizeof(TrianglePack)*tri_num); + create_pp->set_inData(1, sg->texture_info, sizeof(texture_list)); + create_pp->set_inData(2, sg->sg_matrix, sizeof(float)*32); //わーい、マジックナンバー + create_pp->set_outData(0, &pp_cur->tri[pp_index], sizeof(TrianglePack)*tri_num); + create_pp->set_param(0, (memaddr)tri_num); + //create_pp->set_cpu(SPE_ANY); + create_pp_wait->wait_for(create_pp); + create_pp->spawn(); + + pp_index += tri_num; + sg_index += tri_num; +} + +#endif + +void +cViewerGL::common_rendering(HTaskPtr task_next, SceneGraphRoot *sgroot) +{ + +#if SPE_CREATE_POLYGON + + SceneGraphPtr sg = sgroot->getDrawSceneGraph(); + PolygonPackPtr pp_cur = ppack; + HTaskPtr create_pp_wait = manager->create_task(Dummy); + int pp_index = 0; + + pp_cur->init(); + + task_next->wait_for(create_pp_wait); + + while (sg) { + + if (sg->flag_drawable) { + + int sum_size = sg->size; + int tri_cur_num = MAX_SIZE_TRIANGLE; + int sg_index = 0; + + while (sum_size) { + + tri_cur_num -= sg->size/3; + + if (tri_cur_num < 0) { + + tri_cur_num = MAX_SIZE_TRIANGLE; + create_pp_task(sg, pp_cur, create_pp_wait, + pp_index, sg_index, tri_cur_num); + + PolygonPackPtr next = (PolygonPackPtr)manager->allocate(sizeof(PolygonPack)); + next->init(); + + pp_cur->next = next; + pp_cur = next; + pp_index = 0; + + } else { + + create_pp_task(sg, pp_cur, create_pp_wait, + pp_index, sg_index, tri_cur_num); + + } + + sum_size -= tri_cur_num*3; + + } + + + } + + + + 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; + } + } + } + } + } + + + int range_base = spe_num; + + // 切り上げのつもり + int range = (spackList_length + range_base - 1) / range_base; + + for (int i = 0; i < range_base; i++) { + int index_start = range*i; + int index_end = (index_start + range >= spackList_length) + ? spackList_length : index_start + range; + + HTaskPtr task_create_sp = manager->create_task(CreateSpan); + + task_create_sp->set_param(0,index_start); + + /** + * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲 + * [ 1.. 80] [ 81..160] [161..240] + * [241..320] [321..400] [401..480] + * + * ex. screen_height が 1080, spenum が 5 の場合、 + * [ 1..216] [217..432] [433..648] + * [649..864] [865..1080] + */ + + task_create_sp->set_param(1,index_start*split_screen_h + 1); + task_create_sp->set_param(2,index_end*split_screen_h); + + task_create_sp->add_inData(ppack, sizeof(PolygonPack)); + task_create_sp->add_inData(spackList_ptr, + sizeof(SpanPack*)*spackList_length_align); + task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack)); + + task_next->wait_for(task_create_sp); + task_create_sp->wait_for(create_pp_wait); + + task_create_sp->set_cpu(SPE_ANY); + task_create_sp->spawn(); + } + +#else + + HTaskPtr task_create_pp = manager->create_task(CreatePolygonFromSceneGraph); + + // SceneGraph(木構造) -> PolygonPack + + task_create_pp->set_param(0,(memaddr)sgroot->getDrawSceneGraph()); + task_create_pp->set_param(1,(memaddr)ppack); + + task_next->wait_for(task_create_pp); + + int range_base = spe_num; + + // 切り上げのつもり + int range = (spackList_length + range_base - 1) / range_base; + + for (int i = 0; i < range_base; i++) { + int index_start = range*i; + int index_end = (index_start + range >= spackList_length) + ? spackList_length : index_start + range; + + HTaskPtr task_create_sp = manager->create_task(CreateSpan); + + task_create_sp->set_param(0,index_start); + + /** + * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲 + * [ 1.. 80] [ 81..160] [161..240] + * [241..320] [321..400] [401..480] + * + * ex. screen_height が 1080, spenum が 5 の場合、 + * [ 1..216] [217..432] [433..648] + * [649..864] [865..1080] + */ + + task_create_sp->set_param(1,index_start*split_screen_h + 1); + task_create_sp->set_param(2,index_end*split_screen_h); + + task_create_sp->add_inData(ppack, sizeof(PolygonPack)); + task_create_sp->add_inData(spackList_ptr, + sizeof(SpanPack*)*spackList_length_align); + task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack)); + + task_next->wait_for(task_create_sp); + task_create_sp->wait_for(task_create_pp); + + task_create_sp->set_cpu(SPE_ANY); + task_create_sp->spawn(); + } + + task_create_pp->spawn(); + +#endif + +} + +HTaskPtr +cViewerGL::update_task_create(void *data, int size, + int load_id, int spe_id, HTaskPtr wait) +{ + + HTaskPtr data_update = manager->create_task(DataUpdate); + data_update->add_inData(data,size); + data_update->set_param(0,size); + data_update->set_param(1,load_id); + data_update->set_cpu((CPU_TYPE)(spe_id)); + if (wait != NULL) { + wait->wait_for(data_update); + } + data_update->spawn(); + + return data_update; + +} + +void +cViewerGL::common_draw(HTaskPtr task_next) +{ + + //task_next = manager->create_task(Dummy); + //task_next->set_post(post2runLoop, (void*)this); + + //Light info update + + //HTaskPtr data_update; + HTaskPtr data_update_wait; + int light_num = 4; + int size = sizeof(float)*4*light_num; //xyz+alpha(4) * light_num(4) + int light_size = size / sizeof(float); + + for (int i = 0; i < light_size; i++) { + light_xyz[i] = light_xyz_stock[i]; + } + + for (int i = 0; i < light_num; i++) { + light_switch[i] = light_switch_stock[i]; + } + + light_sysswitch[0] = light_sysswitch_stock; + + data_update_wait = manager->create_task(DataUpdate); + data_update_wait->add_inData(light_xyz,size); + data_update_wait->set_param(0,size); + data_update_wait->set_param(1,Light); + data_update_wait->set_cpu((CPU_TYPE)((int)SPE_0)); + + for (int i = 1; i < spe_num; i++) { + update_task_create(light_xyz,size,Light,(int)SPE_0+i,data_update_wait); + } + + size = light_num * sizeof(int); + + for (int i = 0; i < spe_num; i++) { + update_task_create(light_switch,size,LightSwitch,(int)SPE_0+i,data_update_wait); + } + + size = 16; // LightSysSwitch は 4byte. 残り 12byte は DMA転送の為のパディング + + for (int i = 0; i < spe_num; i++) { + update_task_create(light_sysswitch,size,LightSysSwitch,(int)SPE_0+i,data_update_wait); + } + + ppack->clear(); + for (int i = 0; i < spackList_length; i++) { + SpanPack *spack = &spackList[i]; + int startx = 1; + int endx = split_screen_w; + + int starty = spack->info.y_top - split_screen_h + 1; + //int endy = spack->info.y_top; + int rangey = (starty + split_screen_h - 1 > this->height) + ? this->height - starty + 1 : split_screen_h; + +#if 1 + + if(spack->info.size > 0) { + + int array_task_num = (this->width + split_screen_w - 1) / split_screen_w; + HTaskPtr task_draw_array = manager->create_task_array(DrawSpan, array_task_num, 6, 1, rangey); + Task *task_draw = 0; + + while (startx < this->width) { + + // Draw SpanPack + + task_draw = task_draw_array->next_task_array(DrawSpan,task_draw); + task_draw->set_param(0,(memaddr)&pixels[(startx-1) + this->width*(starty-1)]); + task_draw->set_param(1,this->width); + task_draw->set_param(2,startx); + task_draw->set_param(3,endx); + task_draw->set_param(4,rangey); + task_draw->set_param(5,spack->info.size); + + task_draw->set_inData(0,spack, sizeof(SpanPack)); + + for (int i = 0; i < rangey; i++) { + task_draw->set_outData(i, + &pixels[(startx-1) + this->width*(starty-1 + i) ], + (endx-startx+1)*sizeof(int)); + } + + startx += split_screen_w; + endx += split_screen_w; + + if (endx > this->width) { + endx = this->width; + } + + } + + task_draw_array->spawn_task_array(task_draw->next()); + task_draw_array->set_cpu(SPE_ANY); + task_next->wait_for(task_draw_array); + task_draw_array->wait_for(data_update_wait); + task_draw_array->spawn(); + + } else { + + memset(&pixels[(startx-1)+this->width*(starty-1)], + 0, (this->width)*sizeof(int)*rangey); + + } + +#else + + HTaskPtr task_draw; + + while (startx < this->width) { + if (spack->info.size > 0) { + // Draw SpanPack + task_draw = manager->create_task(DrawSpan); + + task_draw->set_param(0, + (memaddr)&pixels[(startx-1) + this->width*(starty-1)]); + task_draw->set_param(1,this->width); + task_draw->set_param(2,startx); + task_draw->set_param(3,endx); + task_draw->set_param(4,rangey); + task_draw->set_param(5,spack->info.size); + + task_draw->add_inData(spack, sizeof(SpanPack)); + + for (int i = 0; i < rangey; i++) { + task_draw->add_outData( + &pixels[(startx-1) + this->width*(starty-1 + i) ], + (endx-startx+1)*sizeof(int)); + } + + } else { + // 7.7.3 SL1 Data Cache Range Set to Zero コマンド + // を使って、DMAでclearするべき... ということは、 + // それもSPEでやる方が良い? + memset(&pixels[(startx-1)+this->width*(starty-1)], + 0, (this->width)*sizeof(int)*rangey); + break; + } + + task_draw->set_cpu(SPE_ANY); + task_next->wait_for(task_draw); + task_draw->wait_for(data_update_wait); + task_draw->spawn(); + + startx += split_screen_w; + endx += split_screen_w; + + if (endx > this->width) { + endx = this->width; + } + } +#endif + + } + + data_update_wait->spawn(); + +} +#endif + +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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/viewerGL.h Thu Jul 29 22:56:58 2010 +0900 @@ -0,0 +1,52 @@ +/** + * OpenGLを用いてレンダリングを行うクラスです。 + * MacOSX上での高速な動作を目的としたViewerです。 + * ViewerとViewerDevice 一体型です。 + * 通常の計算(Move, Collision)はそのままです。 + * 描画の部分はTaskを使わず、OpenGLで直に記述する予定です。 + **/ + +#ifndef INCLUDED_VIEWER_GL +#define INCLUDED_VIEWER_GL + +#include <SDL.h> +#include <SDL_opengl.h> +#include "viewer_types.h" +#include "TaskManager.h" +#include "KeyStat.h" +#include "MainLoop.h" +#include "Application.h" +#include "SceneGraphRoot.h" + + +class cViewerGL : public Viewer { + public: + cViewerGL(TaskManager *m, int b, int w, int h, int _num); + ~cViewerGL(){}; + + SDL_Surface *screen; + // SDL_Surface *bitmap; + + /* override function */ + void video_init(int bpp, int width, int height); + void clean_pixels(); + void clear_screen(); + // void free_device(); + + void run_init(TaskManager *manager, Application *app); + void run_loop(); + void run_finish(); + + void mainLoop(); + void pickup_vertex(); + void obj_draw(float *xyz, float *tex_xyz, float *normal_xyz); + GLuint SDL_GL_LoadTexture(SDL_Surface *surface); + + private: + /* measure for FPS (Frame Per Second) */ + int start_time; + int this_time; + int frames; +}; + +#endif