diff Renderer/Test_/aquarium.cc @ 4:b5b462ac9b3b

Cerium Blender ball_bound
author Daiki KINJYO <e085722@ie.u-ryukyu.ac.jp>
date Mon, 29 Nov 2010 16:42:42 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Renderer/Test_/aquarium.cc	Mon Nov 29 16:42:42 2010 +0900
@@ -0,0 +1,310 @@
+#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 "SceneGraphRoot.h"
+#include "lindaapi.h"
+#include "aquarium.h"
+#include "aquarium.pb.h"
+
+#define GET_SERIAL_ID 65535
+
+int aquarium::last_player_id = 0;
+
+Viewer *aquarium::sgroot;
+linda_t aquarium::linda_addr = { "localhost", 10000 };
+int aquarium::linda;
+int aquarium::serial_id;
+int aquarium::width;
+int aquarium::start_x;
+char *aquarium::xml_file_name;
+
+const char *usr_help_str = "Usage: ./aquarium -linda LINDA_SERVER_NAME\n";
+void TMend(TaskManager *manager);
+
+extern void task_initialize();
+extern int init(TaskManager *manager, int argc, char *argv[]);
+extern Application *
+application() {
+    return new aquarium();
+}
+
+/*
+static void
+null_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
+{
+}
+*/
+
+static void
+null_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree)
+{
+}
+
+void
+aquarium::update_last_player_id() {
+	last_player_id++;
+	if (last_player_id == serial_id)
+		last_player_id++;
+}
+
+void
+aquarium::set_position(SceneGraphPtr node, unsigned char *reply) {
+	aqua::Position *pos = new aqua::Position();
+	pos->ParseFromArray(reply + LINDA_HEADER_SIZE, psx_get_datalength(reply));
+	node->xyz[0] = pos->x() - start_x;
+	node->xyz[1] = pos->y();
+	node->angle[0] = pos->angle_x();
+	node->angle[1] = pos->angle_y();
+	delete pos;
+}
+
+static void
+update_position_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
+{
+	// LindaServerから座標データを取得してオブジェクトに反映させる。
+	if (!node->resend_flag || node->seq_rd != node->seq) {
+		unsigned char *reply_rd = psx_reply(node->seq_rd);
+		if (reply_rd != NULL) {
+			aquarium::set_position(node, reply_rd);
+			psx_free(reply_rd);
+			return;
+		}
+	}
+	unsigned char *reply = psx_reply(node->seq);
+	if (reply != NULL) {
+//		aquarium::set_position(node, reply);
+		psx_free(reply);
+		node->seq = psx_wait_rd(aquarium::linda, node->id * 10 + 1);
+		node->resend_flag = true;
+	} else if (node->resend_flag) {
+		node->seq_rd = psx_rd(aquarium::linda, node->id * 10 + 1);
+		node->resend_flag = false;
+	}
+}
+
+SceneGraphPtr
+create_sg(Viewer *viewer, SceneGraphPtr par, unsigned char *data, int len, int serial_id)
+{
+    SceneGraphPtr child = viewer->sgroot->createSceneGraph();
+    viewer->sgroot->createFromXMLmemory(viewer->sgroot->tmanager, child, (char *)data, len);
+    child->set_move_collision(update_position_move, null_collision);
+    child->id = serial_id;
+	child->seq = psx_wait_rd(aquarium::linda, serial_id * 10 + 1);
+	child->seq_rd = psx_rd(aquarium::linda, serial_id * 10 + 1);
+	child->resend_flag = false;
+    par->addChild(child);
+    return child;
+}
+
+static void
+check_new_player_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
+{
+	unsigned char *reply_rd = psx_reply(node->seq_rd);
+	if (reply_rd != NULL) {
+		unsigned char *xml_data = reply_rd + LINDA_HEADER_SIZE;
+		int xml_len = psx_get_datalength(reply_rd);
+		create_sg(aquarium::sgroot, node, xml_data, xml_len, aquarium::last_player_id);
+		psx_free(reply_rd);
+		aquarium::update_last_player_id();
+		int tuple_id = aquarium::last_player_id * 10;
+		node->seq_rd = psx_rd(aquarium::linda, tuple_id);
+	}
+	// printf("rd id: %d\n", aquarium::last_player_id);
+}
+
+void *
+file_map(const char *filename, int *size) {
+    int fd;
+    void *addr;
+    struct stat sb;
+
+    if ((fd = open(filename, O_RDONLY)) == -1) {
+		fprintf(stderr, "Can't open %s\n", filename);
+		perror(NULL);
+    }
+    if (fstat(fd, &sb) == -1) {
+		fprintf(stderr, "Can't fstat %s\n", filename);
+		perror(NULL);
+    }
+    *size = sb.st_size;
+    addr = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == MAP_FAILED) {
+		perror("mmap error\n");
+		exit(EXIT_FAILURE);
+    }
+    close(fd);
+
+    return addr;
+}
+
+void callback_free(unsigned char *tuple, void *arg) {
+	psx_free(tuple);
+}
+
+void
+aquarium::send_position(SceneGraphPtr node) {
+	int pos_id = serial_id * 10 + 1;
+	psx_callback_in(linda, pos_id, callback_free, NULL);
+	aqua::Position *pos = new aqua::Position();
+	pos->set_x(node->xyz[0] + start_x);
+	pos->set_y(node->xyz[1]);
+	pos->set_angle_x(node->angle[0]);
+	pos->set_angle_y(node->angle[1]);
+	int size = pos->ByteSize();
+	unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size);
+	pos->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ
+	delete pos;
+	psx_out(linda, pos_id, msg, size);
+}
+
+void
+my_move(SceneGraphPtr node, void *sgroot_, int w, int h)
+{
+    SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_;
+    Pad *pad = sgroot->getController();
+	int flag = 0;
+    if (pad->right.isHold() || pad->left.isHold()) {
+		if (pad->right.isHold()) {
+			node->xyz[0] += 5.0f;
+			node->angle[1] = 0.0f;
+			flag = 1;
+		} else if (pad->left.isHold()) {
+			node->xyz[0] -= 5.0f;
+			node->angle[1] = 180.0f;
+			flag = 1;
+		}
+    }
+    
+    if (pad->down.isHold() || pad->up.isHold() ) {
+		if (pad->down.isHold()) {
+			node->xyz[1] += 5.0f;
+			flag = 1;
+		} else if (pad->up.isHold()) {
+			node->xyz[1] -= 5.0f;
+			flag = 1;
+		}
+    }
+
+	/* ここで座標を送信 */
+	if (flag || node->resend_flag) {
+		aquarium::send_position(node);
+	}
+}
+
+void
+aquarium::create_my_sg(Viewer *viewer, SceneGraphPtr par, int screen_w, int screen_h)
+{
+    int size;
+    void *addr = file_map(xml_file_name, &size);
+    SceneGraphPtr sgp = viewer->createSceneGraph();
+    viewer->createFromXMLmemory(sgp, (char *)addr, size);
+    sgp->set_move_collision(my_move, null_collision);
+
+    par->addChild(sgp);
+    sgp->c_xyz[0] = 0.0f;
+    sgp->c_xyz[1] = 0.0f;
+    sgp->c_xyz[2] = 0.0f;
+
+    int xml_id = serial_id * 10;
+    psx_out(linda, xml_id, (unsigned char *)addr, size);
+    int pos_id = serial_id * 10 + 1;
+    
+    aqua::Position *pos = new aqua::Position();
+    pos->set_x(0.0f + start_x);
+    pos->set_y(0.0f);
+    pos->set_angle_x(0.0f);
+    pos->set_angle_y(0.0f);
+    unsigned char *msg = (unsigned char *) viewer->manager->allocate(sizeof(unsigned char *) * size);
+    pos->SerializeToArray(msg, size);
+    psx_out(linda, pos_id, (unsigned char *)msg, pos->ByteSize());
+    delete pos;
+    sgp->seq = 0;
+    sgp->resend_flag = 0;
+}
+
+MainLoopPtr
+aquarium::init(Viewer *sgroot, int screen_w, int screen_h)
+{
+	this->sgroot = sgroot;
+	width = screen_w;
+	linda_connect(); // 接続に合わせて serial_id も取得
+	update_screen_scope();
+	SceneGraphPtr parent = sgroot->createSceneGraph();
+	parent->set_move_collision(check_new_player_move, null_collision);
+	
+	create_my_sg(sgroot, parent, screen_w, screen_h);
+	update_last_player_id();
+	
+	int tuple_id = aquarium::last_player_id * 10;
+	parent->seq_rd = psx_rd(linda, tuple_id);
+	sgroot->setSceneData(parent);
+	return sgroot;
+}
+
+void
+aquarium::linda_connect() {
+	init_linda(); // セレクタの初期化
+	linda = open_linda_java(linda_addr.hostname, linda_addr.port);
+	// serial_id の取得
+	int seq = psx_in(linda, GET_SERIAL_ID);
+	unsigned char *data = NULL;
+	do {
+		psx_sync_n();
+		data = psx_reply(seq);
+	} while (data == NULL);
+//	data[LINDA_HEADER_SIZE + psx_get_datalength(data)] = '\0';
+	serial_id = atoi((char *)data + LINDA_HEADER_SIZE);
+	psx_free(data);
+	printf("Get serial_id: %d\n", serial_id);
+}
+
+void
+aquarium::update_screen_scope() {
+	int seq = psx_in(linda, 1);
+	unsigned char *data = NULL;
+	do {
+		psx_sync_n();
+		data = psx_reply(seq);
+	} while (data == NULL);
+	aqua::Width *w = new aqua::Width();
+	w->ParseFromArray(data + LINDA_HEADER_SIZE, *(int *)(data + LINDA_DATA_LENGTH_OFFSET));
+	start_x = w->width(); // 現在の全長を取得
+	w->set_width(start_x + width); // 自分の横幅を足す
+	int size = w->ByteSize();
+	unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size);
+	w->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ
+	delete w;
+	psx_out(linda, 1, msg, size);
+	psx_sync_n();
+	printf("start_x = %d, width = %d\n", start_x, width);
+}
+
+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) {
+			aquarium::linda_addr.hostname = argv[i+1];
+        } else if (strcmp(argv[i],"-port") == 0 && i + 1 <= argc) {
+			aquarium::linda_addr.port = atoi(argv[i+1]);
+        } else if (strcmp(argv[i],"-xml") == 0 && i + 1 <= argc) {
+			aquarium::xml_file_name = argv[i+1];
+		}
+    }
+    return init(manager, argc, argv);
+}
+
+void
+TMend(TaskManager *manager)
+{
+    printf("aquarium end\n");
+}
+
+/* end */