diff TaskManager/Test/test_render/SceneGraph.cpp @ 137:6cf991f28c6c

SceneGraphPack の代わりに、今は SceneGraph をそのまま使う様に設定。
author gongo@gendarme.cr.ie.u-ryukyu.ac.jp
date Fri, 28 Nov 2008 10:07:48 +0900
parents
children 3fd24be89d02
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TaskManager/Test/test_render/SceneGraph.cpp	Fri Nov 28 10:07:48 2008 +0900
@@ -0,0 +1,371 @@
+#include <iostream>
+#include <SDL.h>
+#include <SDL_opengl.h>
+#include <SDL_image.h>
+#include <libxml/parser.h>
+#include "SceneGraph.h"
+#include "xml.h"
+#include "sys.h"
+
+using namespace std;
+
+extern int decode(char *cont, FILE *outfile);
+
+static void
+no_move(SceneGraphPtr self) {}
+
+static void
+no_collision(SceneGraphPtr self, SceneGraphPtr tree) {}
+
+SceneGraph::SceneGraph(void)
+{
+    next = NULL;
+    last = NULL;
+
+    parent = NULL;
+    brother = NULL;
+    children = NULL;
+    lastChild = NULL;
+    move = no_move;
+    collision = no_collision;
+}
+
+
+/* construct polygon from xmlNode.  */
+SceneGraph::SceneGraph(xmlNodePtr surface)
+{
+#if 1
+    next = NULL;
+    last = NULL;
+    parent = NULL;
+    brother = NULL;
+    children = NULL;
+    lastChild = NULL;
+    move = no_move;
+    collision = no_collision;
+#else
+    // こうしたいんだけどなー
+    this->SceneGraph();
+#endif
+
+    size = atoi((char *)xmlGetProp(surface,(xmlChar *)"size"));
+    name = (char *)xmlGetProp(surface,(xmlChar *)"name");
+    parent_name = (char *)xmlGetProp(surface,(xmlChar *)"parent");
+
+    data = new float[size*3*3];
+
+    get_data(surface->children);
+}
+
+
+/* XMLファイルからポリゴンを作成  */
+SceneGraph*
+SceneGraph::createFromXMLfile(char *xmlfile)
+{
+    xmlDocPtr doc;
+    xmlNodePtr cur;
+    SceneGraph *root = NULL, *tmp, *parent;
+
+    /* パース 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(cur);
+	if ( tmp->parent_name==NULL || 0==strcmp(tmp->parent_name, "NULL")) {
+	    /* このsurfaceがroot  */
+	    root = tmp;
+	} else {
+	    /* 親はこのsurfaceより前に定義されているものとする (していい?)  */
+	    //  ここで parent_name を用いるのは間違っていて、
+	    //   *cur->properties->children から探すべきらしい kono
+	    parent = root->searchSceneGraph(tmp->parent_name);
+	    if (parent==NULL) {
+		fprintf(stderr, "[%s] No such parent %s\n",
+			tmp->name, tmp->parent_name);
+		root->addChild(tmp);
+	    } else {
+		parent->addChild(tmp);
+	    }
+	    root->add_next(tmp);
+	}
+    }
+  
+    xmlFreeDoc(doc);
+    return root;
+}
+
+/* 子供を追加  */
+SceneGraph*
+SceneGraph::addChild(SceneGraph *child)
+{
+    SceneGraph *tmp;
+
+    /* childrenのリストの最後に加える */
+    if (this->lastChild != NULL) {
+	tmp = this->lastChild;
+	tmp->children = child;
+    }
+
+    this->lastChild = child;
+
+    if (this->children == NULL) {
+	this->children = child;
+    }
+
+    child->parent = this;
+
+    return child;
+}
+
+/* thisの子や子孫にnameのものが存在すればそいつを返す なければNULL.  */
+SceneGraph*
+SceneGraph::searchSceneGraph(char *name)
+{
+    SceneGraph* tmp;
+    SceneGraph* result;
+
+    /* 本人か  */
+    if( 0==strcmp(this->name, name) ) return this;
+
+    /* 子供から再帰的に探す  */
+    for(tmp = this->children; tmp; tmp = tmp->next) {
+	if ((result=tmp->searchSceneGraph(name)) != NULL)
+	    return result;
+    }
+
+    /* 無かったら NULL.  */
+    return NULL;
+}
+
+void
+SceneGraph::tree_check(void)
+{
+    SceneGraph *t = this;
+
+    while(t)
+    {
+	cout << "my_name : " << t->name << endl;
+	if(t->children != NULL)
+	{
+	    cout << "--move children : " << t->children->name << endl;
+	    t = t->children;
+	}
+	else if(t->brother != NULL)
+	{
+	    cout << "--move brother : " << t->brother->name << endl;
+	    t = t->brother;
+	}
+	else
+	{
+	    while(t)
+	    {
+		if(t->brother != NULL)
+		{
+		    cout << "--move brother : " << t->brother->name << endl;
+		    t = t->brother;
+		    break;
+		}
+		else
+		{
+		    if(t->parent)
+		    {
+			cout << "--move parent : " << t->parent->name << endl;
+		    }
+		    t = t->parent;
+		}
+	    }
+	}
+    }
+}
+
+
+void
+SceneGraph::print_member(void)
+{
+    cout << "size = " << size << endl;
+    cout << "name = " << name << endl;
+    cout << "parent_name = " << parent_name << endl;
+
+    if (parent != NULL) {
+	cout << "parent->name = " << parent->name << endl;
+    }
+
+    if (children != NULL) {
+	cout << "children->name = " << children->name << endl;
+    }
+}
+
+
+/*
+ * surface nodeからポリゴンの情報を読み出す 再帰しない
+ */
+void
+SceneGraph::get_data(xmlNodePtr cur)
+{
+    char *cont;
+    //char *image_name;
+
+    for(;cur;cur=cur->next)
+    {
+	if(!xmlStrcmp(cur->name,(xmlChar*)"coordinate"))
+        {
+	    cont = (char *)xmlNodeGetContent(cur);
+	    pickup_coordinate(cont);
+        }
+	else if(!xmlStrcmp(cur->name,(xmlChar*)"normal"))
+        {
+	    cont = (char *)xmlNodeGetContent(cur);
+	    pickup_normal(cont);
+        }
+	else if(!xmlStrcmp(cur->name,(xmlChar*)"model"))
+        {
+	    cont = (char *)xmlNodeGetContent(cur);
+	    pickup_model(cont);
+        }
+	else if(!xmlStrcmp(cur->name,(xmlChar*)"texture"))
+        {
+	    cont = (char *)xmlNodeGetContent(cur);
+	    pickup_texture(cont);
+	}
+	else if(!xmlStrcmp(cur->name,(xmlChar*)"image"))
+        {
+	    char image_name[20] = "/tmp/image_XXXXXX";
+	    int fd = mkstemp(image_name);
+	    FILE *outfile = fdopen(fd, "wb");
+	    if(NULL == outfile)
+	    {
+		cout << "error open file\n";
+	    }
+	    cont = (char *)xmlNodeGetContent(cur);
+	    //decode(cont, image_name);
+	    decode(cont, outfile);
+	    fclose(outfile);
+
+	    texture_image = IMG_Load(image_name);
+
+	    /**
+	     * image を 32bit(RGBA) に変換する
+	     */
+	    SDL_Surface *tmpImage
+		= SDL_CreateRGBSurface(SDL_HWSURFACE, texture_image->w,
+				       texture_image->h, 32,
+				       redMask, greenMask, blueMask, alphaMask);
+	    SDL_Surface *converted;
+	    converted = SDL_ConvertSurface(texture_image,
+					   tmpImage->format, SDL_HWSURFACE);
+	    if( converted != NULL){
+		SDL_FreeSurface(texture_image);
+		texture_image = converted;
+	    }
+
+	    //load_texture(image_name);
+	    if(unlink(image_name))
+	    {
+		cout << "unlink error\n";
+	    }
+        }
+    }
+}
+
+
+void
+SceneGraph::delete_data(void)
+{
+    SceneGraph *n,*m;
+
+    n = this;
+    delete [] n->data;
+
+    if (next)
+    {
+	for(n = this->next; n; n=m)
+	{
+	    m = n->next;
+	    delete [] n->data;
+	    delete n;
+	}
+    }
+}
+
+void
+SceneGraph::move_execute(void)
+{
+    (*move)(this);
+}
+
+void
+SceneGraph::collision_check(SceneGraph *tree)
+{
+    (*collision)(this, tree);
+}
+
+void
+SceneGraph::all_execute(void)
+{
+    SceneGraphPtr top = this;
+    SceneGraphPtr t = top;
+
+    while (t) {
+	t->move_execute();
+	t->collision_check(top);
+
+	if (t->parent != NULL) {
+	    get_matrix(t->matrix, t->angle, t->xyz, t->parent->matrix);
+	} else {
+	    get_matrix(t->matrix, t->angle, t->xyz, NULL);
+	}
+
+	if (t->children != NULL) {
+	    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 {
+			t = t->parent;
+		    }
+		}
+	    }
+	}
+    }
+}
+
+void
+SceneGraph::set_move_collision(SceneGraphPtr node, move_func new_move,
+			       collision_func new_collision)
+{
+    node->move = new_move;
+    node->collision = new_collision;
+}
+
+void
+SceneGraph::add_next(SceneGraphPtr next)
+{
+    /* next のリストの最後に加える */
+    if (this->next != NULL) {
+	SceneGraphPtr tmp = this->last;
+	tmp->next = next;
+    } else {
+	this->next = next;
+    }
+
+    this->last = next;
+}