Mercurial > hg > Members > e085722 > Cerium
diff Renderer/Engine/SceneGraphRoot.cc @ 0:04e28d8d3c6f
first commit
author | Daiki KINJYO <e085722@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 08 Nov 2010 01:23:25 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/SceneGraphRoot.cc Mon Nov 08 01:23:25 2010 +0900 @@ -0,0 +1,774 @@ +#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" + +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) +{ + HTask *task = sgroot->tmanager->create_task(id); + task->set_cpu(SPE_ANY); + task->add_inData(property, size); + task->add_outData(property, size); + task->add_param((memaddr)1); + 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) +{ + HTask *task = sgroot->tmanager->create_task(id); + task->set_cpu(SPE_ANY); + task->add_inData(property, size); + task->add_inData(pad, sizeof(Pad)); + task->add_outData(property, size); + task->set_post(post_func, (void*)property, 0); + wait_game_task->wait_for(task); + task->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; + + 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; + + 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 */