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