Mercurial > hg > Game > Cerium
view Renderer/Test/dynamic_create.cc @ 841:8d702fc5d77a draft
dynamic loading demo bug fix
author | kazz <kazz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 02 Jun 2010 01:39:15 +0900 |
parents | 91e2c96be77b |
children | de64695a7f02 |
line wrap: on
line source
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #include <arpa/inet.h> #include <rpc/types.h> #include <rpc/xdr.h> #include "SceneGraphRoot.h" #include "lindaapi.h" #include "dynamic_create.h" #define PORT 10000 #define SERIAL_REGIST_TUPLE_NO 1 #define RECV_DATA_SIZE sizeof(float) * 6 typedef struct client_ { int id; SceneGraphPtr sgp; struct client_ *next; } client_t; typedef struct { int tid; int sid; int read_id; SceneGraphPtr node; SceneGraphRoot *sgroot; TaskManager *manager; client_t *clist; } callback_arg; void client_list_init(TaskManager* manager, client_t *clist) { clist->id = -1; clist->next = clist; } void client_list_update(TaskManager *manager, client_t *clist, int id, SceneGraphPtr sgp) { } void client_list_delete(TaskManager *manager, client_t *clist, int id) { client_t *c, *prev; for (c = clist->next, prev = clist; c->next != clist; c = c->next) { if (c->id == id) { prev->next = c->next; return; } prev = clist; } if (c->id == id) { prev->next = c->next; return; } } static void earth_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree) { } static void moon_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree) { } static void set_position(SceneGraphPtr node, unsigned char *reply) { char *data = (char *)(reply + LINDA_HEADER_SIZE); // XDRの準備 XDR xdrs; xdrmem_create(&xdrs, data, RECV_DATA_SIZE, XDR_DECODE); for (int i = 0; i < 3; i++) { xdr_float(&xdrs, &node->xyz[i]); } } static void moon_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_; // LindaServerから座標データを取得してオブジェクトに反映させる。 unsigned char *reply_rd = psx_reply(node->seq_rd); if (reply_rd != NULL) { set_position(node, reply_rd); free(reply_rd); node->seq_rd = psx_wait_rd(sgroot->tid, node->id * 10 + 1); } } static void earth_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { // psx_sync_n(); in viewer::MainLoop } SceneGraphPtr create_sg(TaskManager *manager, SceneGraphRoot *sgroot, SceneGraphPtr parent, unsigned char *data, int len, int serial_id) { SceneGraphPtr child = sgroot->createSceneGraph(); parent->addChild(child); // 読み込んだオブジェクトは、すべて、child の child になる。 sgroot->createFromXMLmemory(sgroot->tmanager, child, (char *)data, len); child->set_move_collision(moon_move, moon_collision); child->id = serial_id; child->seq_rd = psx_wait_rd(sgroot->tid, serial_id * 10 + 1); return child; } static void callback_get_xml(unsigned char *xml_tuple, void *arg) { int xml_len = psx_get_datalength(xml_tuple); callback_arg *carg = (callback_arg *)arg; unsigned char *xml_data = xml_tuple + LINDA_HEADER_SIZE; SceneGraphPtr sgp; // ここで create sgp = create_sg(carg->manager, carg->sgroot, carg->node, xml_data, xml_len, carg->sid); printf("%s size %d loaded\n", sgp->children->name, xml_len); client_list_update(carg->manager, carg->clist, carg->sid, sgp); free(arg); free(xml_tuple); } static void callbacker(unsigned char *taple, void *arg) { int serial_id, xml_id; unsigned char *data; callback_arg *carg = (callback_arg *)arg; // 最初の4byteデータは使わない data = taple + LINDA_HEADER_SIZE; // clientのSerialIDを取得 serial_id = ntohl(*(int *)data); printf("serial id = %d\n", serial_id); // タプルを解放 // xml fileを取得する もうすでにxml fileが送信済みである事を期待 // つまり、送信者がserial_idを送る前にxml fileを送信していなくてはならない xml_id = serial_id * 10; callback_arg *copy_arg = (callback_arg *)carg->manager->allocate(sizeof(callback_arg)); *copy_arg = *carg; copy_arg->sid = serial_id; psx_callback_in(carg->tid, xml_id, callback_get_xml, (void *)copy_arg); /* dataは'\0'で終わっている事を期待 (writerで保証する) */ free(taple); // arg は使い回すらしい。 psx_callback_in(carg->tid, carg->read_id, callbacker, arg); } static char *linda = (char *)"localhost"; static void linda_init(TaskManager *manager, SceneGraphRoot *sgroot, client_t *clist, SceneGraphPtr node) { init_linda(); callback_arg *carg = (callback_arg *)manager->allocate(sizeof(callback_arg)); carg->tid = open_linda_java(linda, PORT); carg->sgroot = sgroot; carg->sgroot->tid = carg->tid; carg->read_id = SERIAL_REGIST_TUPLE_NO; carg->node = node; carg->manager = manager; carg->clist = clist; psx_callback_in(carg->tid, carg->read_id, callbacker, carg); } MainLoopPtr dynamic_create::init(Viewer *sgroot, int screen_w, int screen_h) { client_t *clist; clist = (client_t *)sgroot->manager->allocate(sizeof(client_t)); client_list_init(sgroot->manager, clist); SceneGraphPtr parent; parent = sgroot->createSceneGraph(); parent->set_move_collision(earth_move, earth_collision); linda_init(sgroot->manager, sgroot->sgroot, clist, parent); // SceneGraphRoot に、使用する SceneGraph を設定する // このとき、ユーザーが記述した SceneGraph の root を渡す。 sgroot->setSceneData(parent); return sgroot; } extern Application * application() { return new dynamic_create(); } const char *usr_help_str = "Usage: ./test_nogl [OPTION]\n"; extern int init(TaskManager *manager, int argc, char *argv[]); extern void task_initialize(); static void TMend(TaskManager *manager); int TMmain(TaskManager *manager, int argc, char *argv[]) { task_initialize(); manager->set_TMend(TMend); for(int i=0;i<argc;i++) { if (strcmp(argv[i],"-linda") == 0 && i+1<=argc) { linda = argv[i+1]; } } return init(manager, argc, argv); } void TMend(TaskManager *manager) { printf("test_nogl end\n"); } /* end */