view Renderer/Engine/SceneGraphRoot.cc @ 507:735f76483bb2

Reorganization..
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 12 Oct 2009 09:39:35 +0900
parents
children 8148c81d2660
line wrap: on
line source

#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 "SGList.h"

int cnt = 0;

SceneGraphRoot::SceneGraphRoot(float w, float h)
{
    sg_src = new SceneGraphPtr[SGLIST_LENGTH];
    camera = new Camera(w, h);
    iterator = new SceneGraphIterator;
    controller = create_controller();

    sg_exec_tree = NULL;
    sg_draw_tree = NULL;
    sg_available_list = NULL;
    sg_remove_list = NULL;

    // TODO
    //   今はとりあえず camera を Root にしています
    //   今はそれすらもしてません
    //sg_exec_tree = camera;
}

SceneGraphRoot::~SceneGraphRoot(void)
{
    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--;
    }

    delete [] sg_src;
    delete camera;
    delete iterator;
    delete controller;
}

/**
 * xml ファイルから生成された SceneGraph を sg_src に登録する。
 *
 * @param sg SceneGraph created by xmlfile
 */
void
SceneGraphRoot::registSceneGraph(SceneGraphPtr sg)
{
    for (int i = 0; i < SGLIST_LENGTH; i++) {
		if (strcmp(sg->name, sglist_table[i]) == 0) {
			sg->sgid = i;
			sg_src[i] = sg;
			return;
		}
    }

    fprintf(stderr, "error: (%s:%3d) Can't find Scene \"%s\"\n",
			__FUNCTION__, __LINE__, sg->name);
}

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);
}

SceneGraphPtr
SceneGraphRoot::createSceneGraph(int id)
{
    SceneGraphPtr src;
    SceneGraphPtr p;

    if (id < 0 || id > SGLIST_LENGTH) {
		return NULL;
    }

    /* オリジナルの SceneGraph */
    src = sg_src[id];

    /* ユーザーにはオリジナルの clone を返す */
    p = src->clone();

    addNext(p);

    return p;
}

/**
 * 何も表示しない、move,collision もしない SceneGraph を生成
 * いずれ、Transform3D 的なものに回す予定
 */
SceneGraphPtr
SceneGraphRoot::createSceneGraph(void)
{
    SceneGraphPtr p = new SceneGraph;

    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[0]; is_end(t); t++){
	  SceneGraphPtr s = application->scenegraph_factory(t); // SceneGraphNode を作る
	  t->scenegraph = s; // property list には SceneGraphへのポインタが入っている
	  application->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;

    }

    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);
        } 

		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::allRemove(SceneGraphPtr list)
{
    SceneGraphPtr p = list;

    while (p) {
		SceneGraphPtr p1 = p->next;
		delete p;
		p = p1;
		cnt--;
    }
}

void
SceneGraphRoot::checkRemove(void)
{
    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(void)
{
    return sg_exec_tree;
}

SceneGraphPtr
SceneGraphRoot::getDrawSceneGraph(void)
{
    return sg_draw_tree;
}

void
SceneGraphRoot::updateControllerState(void)
{
    controller->check();
}

void
SceneGraphRoot::setSceneData(SceneGraphPtr sg)
{
    sg_exec_tree = sg;
}

Pad*
SceneGraphRoot::getController(void)
{
    return controller;
}

SceneGraphIteratorPtr
SceneGraphRoot::getIterator(void)
{
    iterator->set(sg_remove_list);
    return iterator;
}

SceneGraphIteratorPtr
SceneGraphRoot::getIterator(SceneGraphPtr list)
{
    iterator->set(list);
    return iterator;
}

CameraPtr
SceneGraphRoot::getCamera(void)
{
    return camera;
}