Mercurial > hg > Members > kono > Cerium
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; +}