view Renderer/Engine/SceneGraphRoot.cc @ 1319:31455d34e502 draft

collada file reader minor changes.
author Taiki TAIRA <e095767@ie.u-ryukyu.ac.jp>
date Sun, 18 Dec 2011 09:39:14 +0900
parents a788b093ef79
children bbfcc1652518
line wrap: on
line source


#include <SDL_image.h>
#include <libxml/parser.h>
#include "SceneGraphRoot.h"
#include "xml.h"
#include "matrix_calc.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;

static TextureHash sgid_hash;

SceneGraphRoot *sgroot;

SceneGraphRoot::SceneGraphRoot(float w, float h, TaskManager *manager)
{

    sgroot = this;
    sgroot->tmanager = manager;

    // SGLIST_LENGTH 決め打ちかぁ、動的生成にする場合上限決めておいた方がいいのかな
    //
    sg_src = (SceneGraphPtr*) malloc(sizeof(SceneGraphPtr)*SGLIST_LENGTH);

    camera = new Camera(w, h, this, sgroot->tmanager);

    iterator = new SceneGraphIterator;
    controller = create_controller();

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


    screen_w = (int)w;
    screen_h = (int)h;

    light_init();
 
    move_finish_flag = 0;

    gtask_array = NULL;

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

    if (gtask_array != NULL) {
	delete gtask_array;
    }
}

void
SceneGraphRoot::light_init()
{

   int light_num = 4;
    light_sysswitch = 0;

    for (int i = 0; i < light_num; i++) {

        light[i] = new SceneGraph(sgroot->tmanager);
	light[i]->xyz[0] = 0;
	light[i]->xyz[1] = 0;
	light[i]->xyz[2] = 0;
	light[i]->xyz[3] = 1.0f;

	light_switch[i] = 0;

    }

    for (int i = 0; i < 4; i++) {
        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;
    }

}


/**
 * 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;
    sgid_hash.sg_hash_regist((const char*)sg->name, sg->sgid);
}


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

/*文字列の生成*/
void
SceneGraphRoot::createStringFont(TaskManager *manager, SceneGraphPtr root,
				 const char *string,int pixels,int screen_w,
				 int screen_h,Uint32 color)
{
    SceneGraphPtr text;
  float width_shift = 0;
  int i;
  int length = strlen(string);
  for (i = 0; i < length;) {
    int len = 0;
    unsigned char initial = string[i];
    while (1) {
      unsigned char mask = 0x80;
      if (mask & initial) {
	len++;
      } else {
	if (len == 0) len++;
	break;
      }
      initial <<= 1;
    }
    char *obj_name;
    float scale[] = {1,1,1};
    sgroot->createFont(manager,"/Library/Fonts/Osaka.ttf", pixels, color, &string[i], len, &obj_name);
    text = sgroot->createSceneGraph(obj_name);
    text->xyz[0] = screen_w/2 + width_shift -100;
    text->xyz[1] = screen_h/2;
    text->xyz[2] = -100;
    width_shift += text->seq;
    root->addChild(text);
    get_matrix_scale(text->matrix, text->angle, text->xyz, scale, root->matrix);
    i += len;
  }
}

void
SceneGraphRoot::createFont(TaskManager *manager,const char *font, int pixels,
			   Uint32 color,const char *string_name, int len,
			   char **obj_name)
{
  *obj_name = (char *)malloc(sizeof(char) * 12);
  char sname[] = "char:";
  memcpy(*obj_name, sname, 5);
  memcpy(*obj_name + 5, string_name, len);
  (*obj_name)[5+len] = '\0';
  printf("%d",sgid_hash.get_sgid(*obj_name));
  if (sgid_hash.get_sgid(*obj_name) != -1) {
    return;
  }
  SceneGraphPtr tmp = new SceneGraph(manager, font, pixels, color,
				     *obj_name);
  registSceneGraph(tmp);
}

/* XMLファイルからポリゴンを作成  */
void
SceneGraphRoot::createFromXMLfile(TaskManager *manager, const char *xmlfile)
{
    xmlDocPtr doc;
    xmlNodePtr cur;
    SceneGraphPtr tmp;

    /* パース DOM生成
       xmlParseFile:ファイルに含まれるXML文書を分析する
       xmlDocGetRootElement:ドキュメントルートを指定する。
       よって、以下のcurにはドキュメントルートの位置が入っている
     */
    doc = xmlParseFile(xmlfile);
    cur = xmlDocGetRootElement(doc);

    /* ??  */
    xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D");

    /* XMLのノードを一つずつ解析  */
    for (cur=cur->children; cur; cur=cur->next) {
      /*初期化:curをドキュメントルートの一個下に設定
	継続条件:curが真である
	再初期化:次のノードへ
       */

      /* 扱うのはsurfaceオンリーなので、ノードの名前がsurfaceでないなら
	 以下の処理を行なわずにスキップする
      */
      if (xmlStrcmp(cur->name,(xmlChar*)"surface") != 0) {
	continue;
      }
      
      /* ポリゴン(SceneGraph)生成
	 SceneGraph:SceneGraph.cc、L186
      */
	tmp = new SceneGraph(manager, cur);
	
	//シーングラフを登録
	registSceneGraph(tmp);
    }
    //解放
    xmlFreeDoc(doc);
}

/*static const char*
get_property(const char *name, xmlNodePtr cur){
   xmlAttr *p=cur->properties; 
   if (p==0) return "";
   for ( ;p; p=p->next) {
       if ( xmlStrcmp(p->name, (xmlChar*)name) !=0 ) {
	   xmlNode* n=p->children;
	  if ( n==NULL ) return "";
	  const char * v=(const char*)n->content;
	  if ( v==NULL ) return "";
	  return v;
       }
   }
   return "";
}*/

typedef struct source {
    char *id;
    union {
        float *array;
        char *alias;
    }u;
    int count;
    struct source *next;
} SOURCE;
typedef SOURCE *SOURCE_P;

typedef struct list {
    SOURCE_P first;
    SOURCE_P end;
} LIST;
typedef LIST *LIST_P;

/* add source list */
static void
addSource(LIST_P list, SOURCE_P src) {
    if (list->first == NULL && list->end == NULL) {
        list->first = list->end = src;
        return;
    }
    list->end->next = src;
    list->end = src;
}

/* compare a with b. Using to compare id */
static int
strcmp_a(const char *a, const char *b)
{
    while (*a && *a++ == *b++);
    if (*a) return 0;
    return a[-1] > b[-1] ? 1:-1;
}

static float
get_point(char *id, int position, LIST_P list)
{
    SOURCE_P cur = list->first;
    for (;cur ; cur=cur->next) {
        if (!strcmp_a(id, cur->id)) {
            if (cur->count == 0) //alias 
                return get_point(cur->u.alias, position, list);
            float *a = cur->u.array;
            if (position <= cur->count) {
                return a[position];
            }
       }
    }
}

/**
 * co
 */
static SOURCE_P
most_match(const char *id , LIST_P list)
{
    SOURCE_P src,cur;
    int tmplength;
    int strlength;
    for (cur=list->first ;cur!=list->end ;cur=cur->next) {
        for (strlength=0;id[strlength+1]==cur->id[strlength];strlength++); 
        if (tmplength < strlength) {
            tmplength = strlength;
            src = cur;
        }
    }
    return src;
}

struct collada_state {
    int polylist;

    const char *polylist_normal;
    const char *polylist_vertex;

    xmlChar *pid;

    char *vertex_src;
    int vertex_offset;
    int vertex_count;

    char *normal_src;
    int normal_offset;
    int normal_count;

    char *pcont;

    float *vcount;
    float *pcount;

    SOURCE_P normal_float;
    SOURCE_P vertex_float;

    char *vertices_src;
    int polylist_count;
};

static void 
xml_walk(SceneGraphRoot* self, xmlNodePtr cur, struct collada_state *s, LIST_P list)
{

    int in_polylist=0;

    printf("name = %s, child:%s\n", (char *)cur->name, (char *)cur->children);


    if (!xmlStrcmp(cur->name, (xmlChar*)"polylist")) {

        s->polylist_count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));

        s->polylist=1;
        in_polylist=1;

    } else if (!xmlStrcmp(cur->name, (xmlChar*)"vertices")) {

         s->vertices_src = (char*)xmlGetProp(cur, (xmlChar*)"source");

         s->pid = xmlGetProp(cur, (xmlChar*)"id");
         s->vcount = (float*)malloc(sizeof(float)*s->polylist_count);
         s->pcount = malloc(sizeof(float)*sum); 


    } else if (s->polylist && !xmlStrcmp(cur->name, (xmlChar*)"input")) {

        char *semantic = (char*)xmlGetProp(cur, (xmlChar*)"semantic");

        if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"VERTEX")) {

             s->vertex_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
             s->vertex_offset = atoi((char*)xmlGetProp(cur, (xmlChar*)"offset"));
             
             s->vertex_float = most_match(s->vertices_src, list);

         } else if (!xmlStrcmp((xmlChar*)semantic, (xmlChar*)"NORMAL")) {

            s->normal_src = (char*)xmlGetProp(cur, (xmlChar*)"source");
            s->normal_offset = atoi((char*)xmlGetProp(cur, (xmlChar*)"offset"));
            
            s->normal_float = most_match(s->normal_src, list);
         }
                
    } else if (!xmlStrcmp(cur->name, (xmlChar*)"vcount")) {

            char *vcont = (char*)xmlNodeGetContent(cur);

            for (int i=0; s->vcont!=NULL; i++) {
            /* store vcount list */
                 vcont = pickup_float(vcont, s->vcount+i);
            }
        
    } else if (!xmlStrcmp(cur->name, (xmlChar*)"p")) {

        /* input の source="TEXCOORD" がない場合のみ */

        s->pcont = (char*)xmlNodeGetContent(cur);

        for (int i=0; s->pcont != NULL; i++) {
            s->pcont = pickup_float(s->pcont, s->pcount+i);
        } 
        
        int vertexp[s->vertex_count]; 

        float *vertex_table; 
        float *normal_table;

        /* まだ<p>のidをどう探してこようか検討中 */
        for (int i = 0; i < s->polylist_count; i++) {
            vertexp[i] = s->pcount[2*i];
            normal_table[i] = u.array[s->pcount[2*i+1]];
        }

        for (int i=0; vertexp[i];i++) {
            if (s->vcount[i] == 4) {
                for (int j=0; j > s->vcont[i]; j++) {
                    vertex_table[i] =  u.array[vertexp[i]];
                    vertex_table[i+3] =  u.array[vertexp[i+1]];
                    i += 2;
                }
            if (s->vcount[i] == 3) {
                for (int j=0; j > s->vcount[i]; j++) {
                    vertex_table[i] =  u.array[vertexp[i]];
                }
            }
        }
        /* ここまで */

        s->polylist = 0;
        in_polylist = 0;
               
    } else if (!xmlStrcmp(cur->name, (xmlChar*)"float_array")) {

        SOURCE_P src = (SOURCE_P)malloc(sizeof(SOURCE));
        
        char *id = (char*)xmlGetProp(cur, (xmlChar*)"id");
        src->id = (char*)xmlGetProp(cur, (xmlChar*)"id");
        
        int count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));
        src->count = atoi((char*)xmlGetProp(cur, (xmlChar*)"count"));
        src->u.array = (float*)malloc(sizeof(float) * src->count);
        
        char *cont =(char*)xmlNodeGetContent(cur);
        //const char *id = get_property("id", cur);
        //int count = atoi(get_property("count", cur));

        /* store float inpoint list */
        for (int i = 0; cont != NULL; i++) {
            cont = pickup_float(cont, src->u.array+i);
        }

        src->next = NULL;
        addSource(list, src);
        printf("id:%s count:%d cont:%s\n", id, count, cont);
        
    }
   
    for (cur=cur->children; cur; cur=cur->next){
        xml_walk(self, cur, s, list);
    }    
}

void
init_list(LIST_P list) {
      list->first = NULL;
        list->end = NULL;
}

void
SceneGraphRoot::createFromCOLLADAfile(TaskManager *manager, const char *xmlColladafile)
{
	/*make parse dom*/
	xmlDocPtr doc;
	xmlNodePtr cur;
	//,cur_images,cur_effects,cur_geometries,cur_visual_scenes;
	//SceneGraphPtr tmp;

	doc = xmlParseFile(xmlColladafile);
	cur = xmlDocGetRootElement(doc);

	/*エラー処理……だけど何書けばいいのか謎。とりあえず-1返してみる*/
	if(xmlStrcmp(cur->name, (xmlChar*)"COLLADA")){
		return ;
     }

	/* node analyze */
    struct collada_state *s;
	for(cur=cur->children; cur; cur=cur->next){

        LIST list;
        init_list(&list);

	    xml_walk(this, cur, s, &list);
    }
	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(this->tmanager);

    /* 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(this->tmanager);

    /* move, collision に sgroot を渡したいのでここで sgroot を渡しておく*/
    p->sgroot = (void *)this;

    addNext(p);

    return p;
}

int
SceneGraphRoot::getSgid(const char *name)
{
  return sgid_hash.get_sgid(name);
}

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(sgroot->tmanager);

    /* move, collision に sgroot を渡したいのでここで sgroot を渡しておく*/
    p->sgroot = (void *)this;

    addNext(p);
    p->flag_drawable = 0;

    return p;
}


void
SceneGraphRoot::lightCalc()
{
    int light_num = 4;
    float light_vector_tmp[16];
    
    for (int i = 0; i < 4; i++) {
        light_vector_tmp[i*4]   = 0.0f;
        light_vector_tmp[i*4+1] = 0.0f;
        light_vector_tmp[i*4+2] = 0.0f;
        light_vector_tmp[i*4+3] = 1.0f;
    }


    for (int i = 0; i < light_num; i++) {

        get_matrix(light[i]->matrix, light[i]->angle, light[i]->xyz, camera->matrix);
      	ApplyMatrix(&light_vector_tmp[i*4], light[i]->matrix);

        light_vector_tmp[i*4] /= light_vector_tmp[i*4+3];
        light_vector_tmp[i*4+1] /= light_vector_tmp[i*4+3];
        light_vector_tmp[i*4+2] /= light_vector_tmp[i*4+3];

	/*SIMD演算のため*/
	light_vector_tmp[i*4+2] *= -1;
	light_vector_tmp[i*4+3] *= -1;

    for (int i = 0; i < 4; i++) {
        light_vector[i*4] = light_vector_tmp[i*4];
        light_vector[i*4+1] = light_vector_tmp[i*4+1];
        light_vector[i*4+2] = light_vector_tmp[i*4+2];
        light_vector[i*4+3] = light_vector_tmp[i*4+3];
    }




    }
}

void
SceneGraphRoot::flip()
{
    // 前フレームで描画した 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;
}

void
SceneGraphRoot::allExecute(int screen_w, int screen_h)
{
    SceneGraphPtr list = sg_available_list;

    flip();

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

    lightCalc();

    if(sg_exec_tree != NULL) {
	return;
    }

    /* ここで、scenegraph node の matrix に演算する座標変換は、
     * world->view->perspective まで。 
     *
     * CreatePolygonFromSceneGraph で perspective の座標系で lighting の演算を行い、その後
     * screen 変換をするので。
     *
     * その際に、camera がもつ screen matrix を Task に渡す必要がある
     * Task に screen matrix を渡す部分は viewer.cc にある
     *
     * world 変換は node が持つ matrix で行う
     * view->perspective 変換は camera が持つ matrix で行う
     *

     *
     * (w) = world matrix
     * (v) = view matrix
     * (p) = perspective matrix
     * (s) = screen matrix
     *
     * --- copyTree ---
     *
     * node->(wvp) = node->(w) * node->parent->(w) * ..... camera->(v) * camera->(p)
     *
     * --- CreatePolygonFromSceneGraph ---
     * 
     * (polygon_vertex) * node->(wvp)
     * (light_position) * node->(wvp)
     * (normal_vector) * normal_matrix
     *
     * lighting(polygon_vertex, light_position, normal_vector)
     *
     * (polygon_vertex) * camera->(s)
     */

    matrix4x4(camera->matrix, camera->m_view, camera->m_pers);
    copyTree(sg_draw_tree, camera);

    // 現在、allExecute が終わった時点では
    // camera->children が User SceneGraph の root になる

    /**
     * NULL じゃなかったら、setSceneData が呼ばれてるから
     * そっちを次の Scene にする
     */

    sg_exec_tree = camera->children;
}

void
SceneGraphRoot::copyTree(SceneGraphPtr t, SceneGraphPtr cur_parent)
{
    // SceneGraphPtr t = sg_draw_tree;

    /*removeのflagをもとにtreeを形成*/

    while (t) {
	SceneGraphPtr c = NULL;
	if (!t->isRemoved()) {
	    c = t->clone(this->tmanager);
	    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;
		    }
		}
	    }
	}
    }

}


void
SceneGraphRoot::treeApply(int screen_w, int screen_h)
{
    // don't calcurate sg_draw_tree's brother
    transTree(sg_draw_tree->children, camera);
}


/**
 *     破壊的に変換行列の親子関係を計算する
 */
void
SceneGraphRoot::transTree(SceneGraphPtr t, SceneGraphPtr cur_parent)
{
    // SceneGraphPtr t = sg_draw_tree;

    /*removeのflagをもとにtreeを形成*/
    while (t) {
	SceneGraphPtr c = NULL;
	if (!t->isRemoved()) {
	    /*親の回転、座標から、子の回転、座標を算出*/
	    matrix4x4(t->matrix,t->matrix,cur_parent->matrix);
	} 
	if (t->children != NULL && c != NULL) {
	    cur_parent = t;
	    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;
		    }
		}
	    }
	}
    }

}

/*
  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);
	ApplyMatrix(&light_vector[i*4], light[i]->matrix);

	light_vector[i*4] /= light_vector[i*4+3];
	light_vector[i*4+1] /= light_vector[i*4+3];
	light_vector[i*4+2] /= light_vector[i*4+3];


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


void
printSceneGraph(SceneGraphPtr t)
{
    while (t) {
	if (!t->isRemoved()) {
	    if (t->name) printf("name: %s ",t->name);
	    printf("x=%g y=%g z=%g\n",t->xyz[0],t->xyz[1],t->xyz[2]);
	}
	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;
		    }
		}
	    }
	}
    }
}

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::task_array_init(int id, int task_num, int param, int inData_num, int outData_num)
{
    gtask_array = new GTaskArray;
    gtask_array->init(id, task_num, param, inData_num, outData_num);
}

void
SceneGraphRoot::create_task_array()
{
    gtask_array->create_task_array(this->tmanager);
}

void
SceneGraphRoot::task_array_finish()
{
    gtask_array->finish();
}

void
SceneGraphRoot::set_gtask_array(int id, void *property, int size, PostFunction post_func)
{
    gtask_array->next_task_array(id);

    gtask_array->game_task->set_inData(0, property, size);
    gtask_array->game_task->set_outData(0, property, size);

}

void
SceneGraphRoot::set_gtask_array(int id, void *property, void *pad, int size, PostFunction post_func)
{
    gtask_array->next_task_array(id);

    gtask_array->game_task->set_inData(0, property, size);
    gtask_array->game_task->set_inData(1, pad, sizeof(Pad));
    gtask_array->game_task->set_outData(0, property, size);

}

void
SceneGraphRoot::set_game_task(int id, void *property, int size)
{
    HTask *task = sgroot->tmanager->create_task(id);
    task->set_cpu(SPE_ANY);
    task->add_inData(property, size);
    task->add_outData(property, size);
    task->spawn();
}

void
SceneGraphRoot::set_game_task(int id, void *property, void *pad, int size)
{
    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->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;
    SceneGraphRoot *sgroottmp = (SceneGraphRoot*)sgroot_;
/*
  ObjPropertyPtr property = (ObjPropertyPtr)node->propertyptr;
  node->xyz[0] = property->x;
  node->xyz[1] = property->y;
*/
    sgroottmp->set_game_task(move, (void*)e, size);
}

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;
    SceneGraphRoot *sgroottmp = (SceneGraphRoot*)sgroot_;
    void *pad = (void*)sgroottmp->getController();

/*
    ObjPropertyPtr property = (ObjPropertyPtr)node->propertyptr;
    property->root = node;
    node->xyz[0] = property->x;
    node->xyz[1] = property->y;
*/

    sgroottmp->set_game_task(move, (void*)e, pad, size);
}

void
SceneGraphRoot::set_move_task(SceneGraphPtr node, int move, void *property, int size)
{
    node->move = main_task_move;
    node->move_id = move;
    node->propertyptr = property;
    node->property_size = size;
}

void
SceneGraphRoot::set_pad_task(SceneGraphPtr node, int move, void *property, int size)
{
    node->move = pad_task_move;
    node->move_id = move;
    node->propertyptr = property;
    node->property_size = size;
}

/* end */