Mercurial > hg > Members > kono > Cerium
view TaskManager/Test/test_render/SceneGraph.cpp @ 139:c948f4ebde62
fix
author | gongo@charles.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Fri, 28 Nov 2008 13:51:54 +0900 |
parents | 3fd24be89d02 |
children | 861271089c43 |
line wrap: on
line source
#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, int screen_w, int screen_h) {} static void no_collision(SceneGraphPtr self, int screen_w, int screen_h, SceneGraphPtr tree) {} SceneGraph::SceneGraph(void) { next = NULL; last = NULL; parent = NULL; brother = NULL; children = NULL; lastChild = NULL; stack_xyz[0] = 0.0f; stack_xyz[2] = 0.0f; stack_xyz[1] = 0.0f; stack_angle[0] = 0.0f; stack_angle[1] = 0.0f; stack_angle[2] = 0.0f; 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; } /* 兄弟を追加 */ SceneGraph* SceneGraph::addBrother(SceneGraph *bro) { SceneGraphPtr sg = this->brother; if (sg != NULL) { while (sg->brother) { sg = sg->brother; } sg->brother = bro; } else { this->brother = bro; } if (this->parent) { parent->addChild(bro); } return bro; } /* 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(int w, int h) { (*move)(this, w, h); } void SceneGraph::collision_check(int w, int h, SceneGraph *tree) { (*collision)(this, w, h, tree); } void SceneGraph::all_execute(int screen_w, int screen_h) { SceneGraphPtr top = this; SceneGraphPtr t = top; while (t) { t->move_execute(screen_w, screen_h); t->collision_check(screen_w, screen_h, 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; } SceneGraph* SceneGraph::clone(void) { SceneGraphPtr p = new SceneGraph; memcpy(p, this, sizeof(SceneGraph)); // どっかで関数にまとめるか p->next = NULL; p->last = NULL; p->parent = NULL; p->brother = NULL; p->children = NULL; p->lastChild = NULL; p->move = no_move; p->collision = no_collision; p->stack_xyz[0] = 0.0f; p->stack_xyz[2] = 0.0f; p->stack_xyz[1] = 0.0f; p->stack_angle[0] = 0.0f; p->stack_angle[1] = 0.0f; p->stack_angle[2] = 0.0f; return p; }