view Renderer/Test/dynamic_create.cc @ 642:000a3bd205d1

minor fix
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 21 Nov 2009 10:12:25 +0900
parents 529188ae604d
children d0b8860c17f8
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 {
  caddr_t file_mmap;
  off_t size;
  } st_mmap_t;
*/

typedef struct client_ {
    int id;
    SceneGraphPtr sgp;
    struct client_ *next;
} client_t;

typedef struct {
    int tid;
    int sid;
    int read_id;
    SceneGraphPtr node;
    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, int screen_w, int screen_h,
		SceneGraphPtr tree)
{    
}

static void
moon_collision(SceneGraphPtr node, int screen_w, int screen_h,
	       SceneGraphPtr tree)
{
}

static void
moon_move(SceneGraphPtr node, int screen_w, int screen_h)
{
	// LindaServerから座標データを取得してオブジェクトに反映させる。
    unsigned char *reply = psx_reply(node->seq);
	if (reply != NULL) {
        char *data = (char *)(reply + LINDA_HEADER_SIZE);
		// XDRの準備
		XDR xdrs;
		xdrmem_create(&xdrs, data, RECV_DATA_SIZE, XDR_DECODE);
        // ntoh_float(&data[0]); ntoh_float(&data[1]);
		for (int i = 0; i < 3; i++) {
			xdr_float(&xdrs, &node->xyz[i]);
		}
		node->seq = psx_wait_rd(sgroot->tid, node->id * 10 + 1);
	}
}


static void
earth_move(SceneGraphPtr node, int screen_w, int screen_h)
{
    // psx_sync_n();  in viewer::MainLoop
}

SceneGraphPtr
create_sg(TaskManager *manager, 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 = 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
    //	fwrite(xml_data, 1, 10, stdout);
    sgp = create_sg(carg->manager, 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);    // タプルを解放
    //psx_del(carg->tid, SERIAL_REGIST_TUPLE_NO);
    
    // 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で保証する)  */
    //printf("get data[%d]: `%s'\n", len, data);
    free(taple);
    
    psx_callback_in(carg->tid, carg->read_id, callbacker, arg);
}

static char const *linda = "localhost";

void
linda_init(TaskManager *manager, client_t *clist, SceneGraphPtr node)
{
    init_linda();
    callback_arg *carg = (callback_arg *)manager->allocate(sizeof(callback_arg));

    carg->tid = open_linda_java(linda, PORT);
	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)
{
    //SceneGraphPtr earth;
    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);
//    parent->xyz[0] += 300;
//    parent->xyz[1] += 300;
    linda_init(sgroot->manager, 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 */