Mercurial > hg > Members > kono > Cerium
view Renderer/Engine/SceneGraphRoot.cc @ 1002:c79651141045
many changes.
author | koba <koba@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 24 Oct 2010 19:00:47 +0900 |
parents | 9a53faae88d8 |
children | 295b3c79fb44 |
line wrap: on
line source
#include <SDL.h> #include <SDL_image.h> #include <libxml/parser.h> #include "SceneGraphRoot.h" #include "xml.h" #include "sys.h" #include "TextureHash.h" #include "texture.h" #include "Application.h" //取りあえず動かす用 本来はA pplication 側で定義した post_func で値の更新するべき #include "../../../task_dandy/dandy.h" static int cnt = 0; static const int SGLIST_LENGTH = 138; static int sg_src_size = SGLIST_LENGTH ; static int sg_src_id = -1; static SceneGraphPtr *sg_src; SceneGraphRoot *sgroot; SceneGraphRoot::SceneGraphRoot(float w, float h) { // SGLIST_LENGTH 決め打ちかぁ、動的生成にする場合上限決めておいた方がいいのかな // sg_src = (SceneGraphPtr*) malloc(sizeof(SceneGraphPtr)*SGLIST_LENGTH); camera = new Camera(w, h, this); iterator = new SceneGraphIterator; controller = create_controller(); sg_exec_tree = NULL; sg_draw_tree = NULL; sg_available_list = NULL; sg_remove_list = NULL; sgroot = this; screen_w = (int)w; screen_h = (int)h; int light_num = 4; light_sysswitch = 0; for (int i = 0; i < light_num; i++) { light[i] = new SceneGraph; light[i]->xyz[0] = 0; light[i]->xyz[1] = 0; light[i]->xyz[2] = 0; light_switch[i] = 0; } move_finish_flag = 0; // TODO // 今はとりあえず camera を Root にしています // 今はそれすらもしてません //sg_exec_tree = camera; } SceneGraphRoot::~SceneGraphRoot() { SceneGraphPtr p = sg_available_list; while (p) { SceneGraphPtr tmp = p->next; delete p; p = tmp; cnt--; } p = sg_remove_list; while (p) { SceneGraphPtr tmp = p->next; delete p; p = tmp; cnt--; } free(sg_src); delete camera; int light_num = 4; for (int i = 0; i < light_num; i++) { delete light[i]; } delete iterator; delete controller; } /** * xml ファイルから生成された SceneGraph を sg_src に登録する。 * * @param sg SceneGraph created by xmlfile */ void SceneGraphRoot::registSceneGraph(SceneGraphPtr sg) { int dup; if ((dup = getSgid(sg->name))>=0) { // while... sg_src[dup]->name = ""; // we should remove this. but some one may use it... } if (sg_src_id+1> sg_src_size) { sg_src_size *= 2; sg_src = (SceneGraphPtr*)realloc(sg_src, sg_src_size*sizeof(SceneGraphPtr)); } sg->sgid = ++sg_src_id; sg_src[sg->sgid] = sg; } void SceneGraphRoot::addNext(SceneGraphPtr sg) { SceneGraphPtr last = sg_available_list; if (!last) { sg_available_list = sg; } else { while (last->next) { last = last->next; } last->next = sg; sg->prev = last; } cnt++; } /* XMLファイルからポリゴンを作成 */ void SceneGraphRoot::createFromXMLfile(TaskManager *manager, const char *xmlfile) { xmlDocPtr doc; xmlNodePtr cur; SceneGraphPtr tmp; /* パース DOM生成 */ doc = xmlParseFile(xmlfile); cur = xmlDocGetRootElement(doc); /* ?? */ xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"); /* XMLのノードを一つずつ解析 */ for (cur=cur->children; cur; cur=cur->next) { /* 扱うのはsurfaceオンリー */ if (xmlStrcmp(cur->name,(xmlChar*)"surface") != 0) { continue; } /* ポリゴン(SceneGraph)生成 */ tmp = new SceneGraph(manager, cur); registSceneGraph(tmp); } xmlFreeDoc(doc); } void SceneGraphRoot::createFromXMLmemory(TaskManager *manager, SceneGraph *node, char *data, int len) { xmlDocPtr doc; xmlNodePtr cur; // size は取れるはず、テスト用に mmap したデータを使う /* パース DOM生成 */ doc = xmlParseMemory(data, len); cur = xmlDocGetRootElement(doc); /* ?? */ xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"); /* XMLのノードを一つずつ解析 */ for (cur=cur->children; cur; cur=cur->next) { /* 扱うのはsurfaceオンリー */ if (xmlStrcmp(cur->name,(xmlChar*)"surface") != 0) { continue; } /* ポリゴン(SceneGraph)生成 */ SceneGraphPtr original = new SceneGraph(manager, cur); registSceneGraph(original); SceneGraphPtr clone = createSceneGraph(original->sgid); node->addChild(clone); } xmlFreeDoc(doc); } SceneGraphPtr SceneGraphRoot::createSceneGraph(int id) { SceneGraphPtr src; SceneGraphPtr p; if (id < 0 || id > sg_src_size) { printf("error: createSceneGraph(int id): id not found.\n"); return NULL; } /* オリジナルの SceneGraph */ src = sg_src[id]; /* ユーザーにはオリジナルの clone を返す */ p = src->clone(); /* move, collision に sgroot を渡したいのでここで sgroot を渡しておく*/ p->sgroot = (void *)this; addNext(p); return p; } SceneGraphPtr SceneGraphRoot::createSceneGraph(const char *name) { SceneGraphPtr src; SceneGraphPtr p; int id = getSgid(name); if (id < 0) { printf("error: createSceneGraph(name): name object not found.\n"); return NULL; } /* オリジナルの SceneGraph */ src = sg_src[id]; /* ユーザーにはオリジナルの clone を返す */ p = src->clone(); /* move, collision に sgroot を渡したいのでここで sgroot を渡しておく*/ p->sgroot = (void *)this; addNext(p); return p; } int SceneGraphRoot::getSgid(const char *name) { for(int i =0;i<= sg_src_id; i++) { if (sg_src[i] && strcmp(name,sg_src[i]->name) == 0) return i; } return -1; } int SceneGraphRoot::getLast() { if (sg_src_id>=0) return sg_src[sg_src_id]->sgid; return -1; } /** * 何も表示しない、move,collision もしない SceneGraph を生成 * いずれ、Transform3D 的なものに回す予定 */ SceneGraphPtr SceneGraphRoot::createSceneGraph() { SceneGraphPtr p = new SceneGraph; /* move, collision に sgroot を渡したいのでここで sgroot を渡しておく*/ p->sgroot = (void *)this; addNext(p); p->flag_drawable = 0; return p; } void SceneGraphRoot::speExecute(int screen_w, int screen_h) { SceneGraphPtr list = sg_available_list; // SceneGraphPtr t = sg_exec_tree; // SceneGraphPtr cur_parent = camera; // 前フレームで描画した SceneGraph は削除 allRemove(sg_remove_list); // 前フレームに作られた SceneGraph は描画用に移行 // 現フレームでの操作は以下の tree,list には適用されない sg_draw_tree = sg_exec_tree; sg_remove_list = sg_available_list; // 現フレームで新しく SceneGraph がコピーされるので初期化 sg_exec_tree = NULL; sg_available_list = NULL; camera->move_execute(screen_w, screen_h); camera->update(screen_w, screen_h); camera->children = NULL; camera->lastChild = NULL; list->move_execute(screen_w, screen_h); list->collision_check(screen_w, screen_h, list); list->frame++; list = list->next; if(sg_exec_tree != NULL) { return; } /*removeのflagをもとにtreeを形成*/ /* spe から送り返されてきた property の配列を見て生成する for()*/ /* for (Property *t = (Property*)app->property[0]; is_end(t); t++){ SceneGraphPtr s = app->scenegraph_factory(t); // SceneGraphNode を作る t->scenegraph = s; // property list には SceneGraphへのポインタが入っている app->scenegraph_connector(property[0], s); // add する } */ // 現在、allExecute が終わった時点では // camera->children が User SceneGraph の root になる /** * NULL じゃなかったら、setSceneData が呼ばれてるから * そっちを次の Scene にする */ sg_exec_tree = camera->children; } void SceneGraphRoot::allExecute(int screen_w, int screen_h) { SceneGraphPtr list = sg_available_list; SceneGraphPtr t = sg_exec_tree; SceneGraphPtr cur_parent = camera; // 前フレームで描画した SceneGraph は削除 allRemove(sg_remove_list); // 前フレームに作られた SceneGraph は描画用に移行 // 現フレームでの操作は以下の tree,list には適用されない sg_draw_tree = sg_exec_tree; sg_remove_list = sg_available_list; // 現フレームで新しく SceneGraph がコピーされるので初期化 sg_exec_tree = NULL; sg_available_list = NULL; camera->move_execute(screen_w, screen_h); camera->update(screen_w, screen_h); camera->children = NULL; camera->lastChild = NULL; /*まずは全部動作させる*/ while (list) { list->move_execute(screen_w, screen_h); list->collision_check(screen_w, screen_h, list); list->frame++; list = list->next; } int light_num = 4; for (int i = 0; i < light_num; i++) { get_matrix(light[i]->matrix, light[i]->angle, light[i]->xyz, camera->matrix); light_vector[i*4] = 0.0f; light_vector[i*4+1] = 0.0f; light_vector[i*4+2] = 0.0f; light_vector[i*4+3] = 1.0f; ApplyMatrix(&light_vector[i*4], light[i]->matrix); light_vector[i*4] /= light_vector[i*4+2]; light_vector[i*4+1] /= light_vector[i*4+2]; /*SIMD演算のため*/ light_vector[i*4+2] *= -1; light_vector[i*4+3] *= -1; } if(sg_exec_tree != NULL) { return; } /*removeのflagをもとにtreeを形成*/ while (t) { SceneGraphPtr c = NULL; if (!t->isRemoved()) { c = t->clone(); addNext(c); cur_parent->addChild(c); c->frame = t->frame; /*親の回転、座標から、子の回転、座標を算出*/ get_matrix(c->matrix, c->angle, c->xyz, cur_parent->matrix); /*法線用の行列。Cameraの行列を抜いている(Cameraのコンストラクタで、単位行列にしている)*/ get_matrix(c->real_matrix, c->angle, c->xyz, cur_parent->real_matrix); //get_matrix(c->real_matrix, c->angle, c->xyz, camera->real_matrix); } if (t->children != NULL && c != NULL) { cur_parent = c; t = t->children; } else if (t->brother != NULL) { t = t->brother; } else { while (t) { if (t->brother != NULL) { t = t->brother; break; } else { if (t->parent == NULL) { t = NULL; break; } else { cur_parent = cur_parent->parent; t = t->parent; } } } } } // 現在、allExecute が終わった時点では // camera->children が User SceneGraph の root になる /** * NULL じゃなかったら、setSceneData が呼ばれてるから * そっちを次の Scene にする */ sg_exec_tree = camera->children; } void SceneGraphRoot::oneExecute(int screen_w, int screen_h) { SceneGraphPtr list = sg_available_list; //SceneGraphPtr t = sg_exec_tree; //SceneGraphPtr cur_parent = camera; // 前フレームで描画した SceneGraph は削除 allRemove(sg_remove_list); // 前フレームに作られた SceneGraph は描画用に移行 // 現フレームでの操作は以下の tree,list には適用されない sg_draw_tree = sg_exec_tree; sg_remove_list = sg_available_list; // 現フレームで新しく SceneGraph がコピーされるので初期化 sg_exec_tree = NULL; sg_available_list = NULL; camera->move_execute(screen_w, screen_h); camera->update(screen_w, screen_h); camera->children = NULL; camera->lastChild = NULL; /* ここから */ list->move_execute(screen_w, screen_h); // ここで move_execute から実行される move_task の処理が終わるまで待ちたい //while(move_finish_flag == 0) {} //move_finish_flag = 0; list->create_sg_execute(); list->collision_check(screen_w, screen_h, list); /* ここまで exec_task にする */ /* ここから下を exec_task の post_func に*/ list->frame++; list = list->next; int light_num = 4; for (int i = 0; i < light_num; i++) { get_matrix(light[i]->matrix, light[i]->angle, light[i]->xyz, camera->matrix); light_vector[i*4] = 0.0f; light_vector[i*4+1] = 0.0f; light_vector[i*4+2] = 0.0f; light_vector[i*4+3] = 1.0f; ApplyMatrix(&light_vector[i*4], light[i]->matrix); light_vector[i*4] /= light_vector[i*4+2]; light_vector[i*4+1] /= light_vector[i*4+2]; } if(sg_exec_tree != NULL) { return; } } /* ExecMove task の post func として呼んでやる */ void SceneGraphRoot::move_finish() { list->collision_check(screen_w, screen_h, list); list->frame++; //list = list->next; int light_num = 4; for (int i = 0; i < light_num; i++) { get_matrix(light[i]->matrix, light[i]->angle, light[i]->xyz, camera->matrix); light_vector[i*4] = 0.0f; light_vector[i*4+1] = 0.0f; light_vector[i*4+2] = 0.0f; light_vector[i*4+3] = 1.0f; ApplyMatrix(&light_vector[i*4], light[i]->matrix); light_vector[i*4] /= light_vector[i*4+2]; light_vector[i*4+1] /= light_vector[i*4+2]; light_vector[i*4+2] *= -1; light_vector[i*4+3] *= -1; } //sgchange->viewer->light_xyz_stock = getLightVector(); } void SceneGraphRoot::appTaskRegist(regist_func new_register) { this->regist = new_register; } void SceneGraphRoot::regist_execute() { (*regist)(this); } void SceneGraphRoot::allRemove(SceneGraphPtr list) { SceneGraphPtr p = list; while (p) { SceneGraphPtr p1 = p->next; delete p; p = p1; cnt--; } } void SceneGraphRoot::checkRemove() { SceneGraphPtr p = sg_available_list; SceneGraphPtr p1; while (p) { p1 = p->next; if (p->isRemoved()) { sg_exec_tree = p->realRemoveFromTree(sg_exec_tree); sg_available_list = p->realRemoveFromList(sg_available_list); } delete p; p = p1; } } SceneGraphPtr SceneGraphRoot::getExecuteSceneGraph() { return sg_exec_tree; } SceneGraphPtr SceneGraphRoot::getDrawSceneGraph() { return sg_draw_tree; } void SceneGraphRoot::updateControllerState() { controller->check(); } void SceneGraphRoot::setSceneData(SceneGraphPtr sg) { sg_exec_tree = sg; } Pad* SceneGraphRoot::getController() { return controller; } SceneGraphIteratorPtr SceneGraphRoot::getIterator() { iterator->set(sg_remove_list); return iterator; } SceneGraphIteratorPtr SceneGraphRoot::getIterator(SceneGraphPtr list) { iterator->set(list); return iterator; } CameraPtr SceneGraphRoot::getCamera() { return camera; } SceneGraphPtr SceneGraphRoot::getLight(int id) { return light[id]; } float* SceneGraphRoot::getLightVector() { return light_vector; } int* SceneGraphRoot::getLightSwitch() { return light_switch; } int SceneGraphRoot::getLightSysSwitch() { return light_sysswitch; } void SceneGraphRoot::OnLightSwitch(int id) { light_switch[id] = 1; } void SceneGraphRoot::OffLightSwitch(int id) { light_switch[id] = 0; } void SceneGraphRoot::OnLightSysSwitch() { light_sysswitch = 1; } void SceneGraphRoot::OffLightSysSwitch() { light_sysswitch = 0; } void SceneGraphRoot::set_game_task(int id, void *property, int size, PostFunction post_func) { game_task = game_task_array->next_task_array(id, game_task); game_task->set_inData(0, property, size); game_task->set_outData(0, property, size); /* HTask *task = sgroot->tmanager->create_task(id); task->set_cpu(SPE_ANY); task->set_inData(0, property, size); task->set_outData(0, property, size); task->set_post(post_func, (void*)property, 0); wait_game_task->wait_for(task); task->spawn(); */ } void SceneGraphRoot::set_game_task(int id, void *property, void *pad, int size, PostFunction post_func) { game_task = game_task_array->next_task_array(id, game_task); game_task->set_inData(0, property, size); game_task->set_inData(1, pad, sizeof(Pad)); game_task->set_outData(0, property, size); /* HTask *task = sgroot->tmanager->create_task(id); task->set_cpu(SPE_ANY); task->set_inData(0, property, size); task->set_inData(0, pad, sizeof(Pad)); task->set_outData(0, property, size); task->set_post(post_func, (void*)property, 0); wait_game_task->wait_for(task); task->spawn(); */ } void SceneGraphRoot::task_array_init(int id, int task_num, int param, int inData_num, int outData_num) { game_task_array = tmanager->create_task_array(id, task_num, param, inData_num, outData_num); game_task = 0; } void SceneGraphRoot::task_array_finish() { game_task_array->spawn_task_array(game_task->next()); game_task_array->set_cpu(SPE_ANY); game_task_array->spawn(); } void main_task_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { int size = node->property_size; void *e = node->propertyptr; int move = node->move_id; PostFunction post_func = node->post_func; ObjPropertyPtr property = (ObjPropertyPtr)node->propertyptr; property->root = node; SceneGraphRoot *sgroottmp = (SceneGraphRoot*)sgroot_; sgroottmp->set_game_task(move, (void*)e, size, post_func); } void pad_task_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { int size = node->property_size; void *e = node->propertyptr; int move = node->move_id; PostFunction post_func = node->post_func; ObjPropertyPtr property = (ObjPropertyPtr)node->propertyptr; property->root = node; SceneGraphRoot *sgroottmp = (SceneGraphRoot*)sgroot_; void *pad = (void*)sgroottmp->getController(); sgroottmp->set_game_task(move, (void*)e, pad, size, post_func); } void SceneGraphRoot::set_move_task(SceneGraphPtr node, int move, void *property, int size, PostFunction post_func) { node->move = main_task_move; node->post_func = post_func; node->move_id = move; node->propertyptr = property; node->property_size = size; } void SceneGraphRoot::set_pad_task(SceneGraphPtr node, int move, void *property, int size, PostFunction post_func) { node->move = pad_task_move; node->post_func = post_func; node->move_id = move; node->propertyptr = property; node->property_size = size; } /* end */