labyrinth

changeset 3:45b91185b298

android port
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 01 May 2015 04:36:50 +0300
parents e3b9707504df
children f35596f110bc
files Makefile android/AndroidManifest.xml android/Makefile proj.mk src/android/amain.c src/android/logger.c src/android/logger.h src/game.c src/game.h src/gles/sanegl.c src/gles/sanegl.h src/glut/main.c src/main.c src/mesh.c src/opengl.h src/timer.c src/timer.h
diffstat 17 files changed, 1282 insertions(+), 400 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Mon Apr 27 05:37:17 2015 +0300
     1.2 +++ b/Makefile	Fri May 01 04:36:50 2015 +0300
     1.3 @@ -1,14 +1,15 @@
     1.4 -src = $(wildcard src/*.c)
     1.5 +include proj.mk
     1.6 +src += src/glut/main.c
     1.7 +
     1.8  obj = $(src:.c=.o)
     1.9 -bin = lab
    1.10  
    1.11  sys = $(shell uname -s)
    1.12  
    1.13 -libgl_Linux = -lGL -lGLU -lglut
    1.14 -libgl_Darwin = -framework OpenGL -framework GLUT
    1.15 +libgl_Linux = -lGL -lGLU -lglut -lGLEW
    1.16 +libgl_Darwin = -framework OpenGL -framework GLUT -lGLEW
    1.17  
    1.18 -CFLAGS = -pedantic -Wall -g
    1.19 -LDFLAGS = $(libgl_$(sys)) -lm
    1.20 +CFLAGS = -pedantic -Wall -g $(incpaths)
    1.21 +LDFLAGS = $(libpaths) $(libgl_$(sys)) -lm
    1.22  
    1.23  $(bin): $(obj)
    1.24  	$(CC) -o $@ $(obj) $(LDFLAGS)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/android/AndroidManifest.xml	Fri May 01 04:36:50 2015 +0300
     2.3 @@ -0,0 +1,22 @@
     2.4 +<?xml version="1.0" encoding="utf-8"?>
     2.5 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     2.6 +	package="com.mutantstargoat.labyrinth"
     2.7 +	android:versionCode="1"
     2.8 +	android:versionName="1.0">
     2.9 +
    2.10 +	<uses-sdk android:minSdkVersion="9"/>
    2.11 +
    2.12 +	<application android:label="labyrinth"
    2.13 +		android:hasCode="false"
    2.14 +		android:debuggable="true">
    2.15 +
    2.16 +		<activity android:name="android.app.NativeActivity" android:label="Labyrinth">
    2.17 +			<meta-data android:name="android.app.lib_name" android:value="labyrinth"/>
    2.18 +
    2.19 +			<intent-filter>
    2.20 +				<action android:name="android.intent.action.MAIN"/>
    2.21 +				<action android:name="android.intent.category.LAUNCHER"/>
    2.22 +			</intent-filter>
    2.23 +		</activity>
    2.24 +	</application>
    2.25 +</manifest>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/android/Makefile	Fri May 01 04:36:50 2015 +0300
     3.3 @@ -0,0 +1,78 @@
     3.4 +root = ..
     3.5 +include $(root)/proj.mk
     3.6 +
     3.7 +# --- android settings ---
     3.8 +android_platform = android-22
     3.9 +name = $(bin)
    3.10 +pkgprefix = com.mutantstargoat
    3.11 +# ------------------------
    3.12 +native_app_glue_dir = $(NDK)/sources/android/native_app_glue
    3.13 +
    3.14 +src += $(wildcard $(root)/src/android/*.c) \
    3.15 +	   $(wildcard $(root)/src/gles/*.c) \
    3.16 +	   $(native_app_glue_dir)/android_native_app_glue.c
    3.17 +
    3.18 +obj = $(src:.c=.o) $(ccsrc:.cc=.o)
    3.19 +lib = libs/armeabi/lib$(name).so
    3.20 +apk-release = bin/$(name).apk
    3.21 +apk-debug = bin/$(name)-debug.apk
    3.22 +
    3.23 +pkg = $(pkgprefix).$(name)
    3.24 +act = android.app.NativeActivity
    3.25 +
    3.26 +CC = arm-linux-androideabi-gcc
    3.27 +CXX = arm-linux-androideabi-g++
    3.28 +
    3.29 +android_usr = $(NDK)/platforms/$(android_platform)/arch-arm/usr
    3.30 +android_inc = -I$(android_usr)/include -I$(native_app_glue_dir)
    3.31 +android_libs = -L$(android_usr)/lib -llog -landroid -lEGL -lGLESv1_CM
    3.32 +
    3.33 +CFLAGS = -std=c99 -Wall -g -DAPP_NAME=\"$(name)\" \
    3.34 +		 $(android_inc) -I$(root)/src/android -I$(root)/src/gles $(incpaths)
    3.35 +LDFLAGS = -Wl,--fix-cortex-a8 $(android_libs) $(libpaths)
    3.36 +
    3.37 +.PHONY: debug
    3.38 +debug: $(apk-debug)
    3.39 +
    3.40 +.PHONY: release
    3.41 +release: $(apk-release)
    3.42 +
    3.43 +$(apk-debug): $(lib) AndroidManifest.xml
    3.44 +	ant debug
    3.45 +
    3.46 +$(apk-release): $(lib) AndroidManifest.xml
    3.47 +	ant release
    3.48 +
    3.49 +.PHONY: lib
    3.50 +lib: $(lib)
    3.51 +
    3.52 +$(lib): $(obj)
    3.53 +	@mkdir -p libs/armeabi
    3.54 +	$(CC) -o $@ -shared $(obj) $(LDFLAGS)
    3.55 +
    3.56 +.PHONY: clean
    3.57 +clean:
    3.58 +	rm -f $(obj) $(lib) $(apk-release) $(apk-debug)
    3.59 +
    3.60 +.PHONY: install
    3.61 +install: install-debug
    3.62 +
    3.63 +.PHONY: install-debug
    3.64 +install-debug:
    3.65 +	adb install -r $(apk-debug)
    3.66 +
    3.67 +.PHONY: install-release
    3.68 +install-release:
    3.69 +	adb install -r $(apk-release)
    3.70 +
    3.71 +.PHONY: run
    3.72 +run:
    3.73 +	adb shell am start -n $(pkg)/$(act)
    3.74 +
    3.75 +.PHONY: stop
    3.76 +stop:
    3.77 +	adb shell am force-stop $(pkg)
    3.78 +
    3.79 +.PHONY: update-project
    3.80 +update-project: build.xml
    3.81 +	android update project --path . --target $(android_platform)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/proj.mk	Fri May 01 04:36:50 2015 +0300
     4.3 @@ -0,0 +1,7 @@
     4.4 +root ?= $(shell pwd)
     4.5 +
     4.6 +src = $(wildcard $(root)/src/*.c)
     4.7 +bin = labyrinth
     4.8 +
     4.9 +incpaths = -I$(root)/src
    4.10 +libpaths =
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/android/amain.c	Fri May 01 04:36:50 2015 +0300
     5.3 @@ -0,0 +1,251 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <EGL/egl.h>
     5.7 +#include <android_native_app_glue.h>
     5.8 +#include "logger.h"
     5.9 +#include "game.h"
    5.10 +#include "timer.h"
    5.11 +
    5.12 +
    5.13 +static void handle_command(struct android_app *app, int32_t cmd);
    5.14 +static int handle_input(struct android_app *app, AInputEvent *ev);
    5.15 +static int handle_touch_input(struct android_app *app, AInputEvent *ev);
    5.16 +static int init_gl(void);
    5.17 +static void destroy_gl(void);
    5.18 +
    5.19 +static EGLDisplay dpy;
    5.20 +static EGLSurface surf;
    5.21 +static EGLContext ctx;
    5.22 +
    5.23 +static struct android_app *app;
    5.24 +static int win_width, win_height;
    5.25 +
    5.26 +void android_main(struct android_app *app_ptr)
    5.27 +{
    5.28 +	app_dummy();
    5.29 +	app = app_ptr;
    5.30 +
    5.31 +	app->onAppCmd = handle_command;
    5.32 +	app->onInputEvent = handle_input;
    5.33 +
    5.34 +	start_logger();
    5.35 +
    5.36 +	for(;;) {
    5.37 +		int num_events;
    5.38 +		struct android_poll_source *pollsrc;
    5.39 +
    5.40 +		while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) {
    5.41 +			if(pollsrc) {
    5.42 +				pollsrc->process(app, pollsrc);
    5.43 +			}
    5.44 +		}
    5.45 +
    5.46 +		if(app->destroyRequested) {
    5.47 +			return;
    5.48 +		}
    5.49 +
    5.50 +		game_display(get_time_msec());
    5.51 +	}
    5.52 +}
    5.53 +
    5.54 +void set_mouse_pos(int x, int y)
    5.55 +{
    5.56 +}
    5.57 +
    5.58 +void set_mouse_cursor(int enable)
    5.59 +{
    5.60 +}
    5.61 +
    5.62 +static void handle_command(struct android_app *app, int32_t cmd)
    5.63 +{
    5.64 +	switch(cmd) {
    5.65 +	case APP_CMD_SAVE_STATE:
    5.66 +		/* save the application state to be reloaded on restart if needed */
    5.67 +		break;
    5.68 +
    5.69 +	case APP_CMD_INIT_WINDOW:
    5.70 +		if(init_gl() == -1) {
    5.71 +			exit(1);
    5.72 +		}
    5.73 +		/* initialize the application */
    5.74 +		if(game_init() == -1) {
    5.75 +			exit(1);	/* initialization failed, quit */
    5.76 +		}
    5.77 +		break;
    5.78 +
    5.79 +	case APP_CMD_TERM_WINDOW:
    5.80 +		/* cleanup */
    5.81 +		game_shutdown();
    5.82 +		destroy_gl();
    5.83 +		break;
    5.84 +
    5.85 +	case APP_CMD_GAINED_FOCUS:
    5.86 +		/* app focused */
    5.87 +		break;
    5.88 +
    5.89 +	case APP_CMD_LOST_FOCUS:
    5.90 +		/* app lost focus */
    5.91 +		break;
    5.92 +
    5.93 +	case APP_CMD_WINDOW_RESIZED:
    5.94 +	case APP_CMD_CONFIG_CHANGED:
    5.95 +		{
    5.96 +			int nx = ANativeWindow_getWidth(app->window);
    5.97 +			int ny = ANativeWindow_getHeight(app->window);
    5.98 +			if(nx != win_width || ny != win_height) {
    5.99 +				game_reshape(nx, ny);
   5.100 +				win_width = nx;
   5.101 +				win_height = ny;
   5.102 +			}
   5.103 +		}
   5.104 +		break;
   5.105 +
   5.106 +	default:
   5.107 +		break;
   5.108 +	}
   5.109 +}
   5.110 +
   5.111 +static int handle_input(struct android_app *app, AInputEvent *ev)
   5.112 +{
   5.113 +	int evtype = AInputEvent_getType(ev);
   5.114 +
   5.115 +	switch(evtype) {
   5.116 +	case AINPUT_EVENT_TYPE_MOTION:
   5.117 +		return handle_touch_input(app, ev);
   5.118 +
   5.119 +	default:
   5.120 +		break;
   5.121 +	}
   5.122 +	return 0;
   5.123 +}
   5.124 +
   5.125 +#define MAX_TOUCH_IDS	32
   5.126 +
   5.127 +static int handle_touch_input(struct android_app *app, AInputEvent *ev)
   5.128 +{
   5.129 +	int x, y, idx, touch_id;
   5.130 +	unsigned int action;
   5.131 +	static int prev_pos[MAX_TOUCH_IDS][2];
   5.132 +
   5.133 +	action = AMotionEvent_getAction(ev);
   5.134 +
   5.135 +	idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
   5.136 +		AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
   5.137 +	touch_id = AMotionEvent_getPointerId(ev, idx);
   5.138 +
   5.139 +	x = AMotionEvent_getX(ev, idx);
   5.140 +	y = AMotionEvent_getY(ev, idx);
   5.141 +
   5.142 +	switch(action & AMOTION_EVENT_ACTION_MASK) {
   5.143 +	case AMOTION_EVENT_ACTION_DOWN:
   5.144 +	case AMOTION_EVENT_ACTION_POINTER_DOWN:
   5.145 +		game_mouse_button(touch_id, 0, 1, x, y);
   5.146 +		if(touch_id < MAX_TOUCH_IDS) {
   5.147 +			prev_pos[touch_id][0] = x;
   5.148 +			prev_pos[touch_id][1] = y;
   5.149 +		}
   5.150 +		break;
   5.151 +
   5.152 +	case AMOTION_EVENT_ACTION_UP:
   5.153 +	case AMOTION_EVENT_ACTION_POINTER_UP:
   5.154 +		game_mouse_button(touch_id, 0, 0, x, y);
   5.155 +		if(touch_id < MAX_TOUCH_IDS) {
   5.156 +			prev_pos[touch_id][0] = x;
   5.157 +			prev_pos[touch_id][1] = y;
   5.158 +		}
   5.159 +		break;
   5.160 +
   5.161 +	case AMOTION_EVENT_ACTION_MOVE:
   5.162 +		{
   5.163 +			int i, pcount = AMotionEvent_getPointerCount(ev);
   5.164 +			for(i=0; i<pcount; i++) {
   5.165 +				int id = AMotionEvent_getPointerId(ev, i);
   5.166 +				if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
   5.167 +					game_mouse_motion(id, x, y);
   5.168 +					prev_pos[id][0] = x;
   5.169 +					prev_pos[id][1] = y;
   5.170 +				}
   5.171 +			}
   5.172 +		}
   5.173 +		break;
   5.174 +
   5.175 +	default:
   5.176 +		break;
   5.177 +	}
   5.178 +
   5.179 +	return 1;
   5.180 +}
   5.181 +
   5.182 +
   5.183 +static int init_gl(void)
   5.184 +{
   5.185 +	static const int eglattr[] = {
   5.186 +		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
   5.187 +		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
   5.188 +		EGL_RED_SIZE, 5,
   5.189 +		EGL_GREEN_SIZE, 5,
   5.190 +		EGL_BLUE_SIZE, 5,
   5.191 +		EGL_DEPTH_SIZE, 16,
   5.192 +		EGL_NONE
   5.193 +	};
   5.194 +	static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
   5.195 +
   5.196 +	EGLConfig eglcfg;
   5.197 +	int count, vis;
   5.198 +
   5.199 +	dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   5.200 +	if(!dpy || !eglInitialize(dpy, 0, 0)) {
   5.201 +		fprintf(stderr, "failed to initialize EGL\n");
   5.202 +		destroy_gl();
   5.203 +		return -1;
   5.204 +	}
   5.205 +
   5.206 +	if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
   5.207 +		fprintf(stderr, "no matching EGL config found\n");
   5.208 +		destroy_gl();
   5.209 +		return -1;
   5.210 +	}
   5.211 +
   5.212 +	/* configure the native window visual according to the chosen EGL config */
   5.213 +	eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
   5.214 +	ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
   5.215 +
   5.216 +	if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
   5.217 +		fprintf(stderr, "failed to create window\n");
   5.218 +		destroy_gl();
   5.219 +		return -1;
   5.220 +	}
   5.221 +
   5.222 +	if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
   5.223 +		fprintf(stderr, "failed to create OpenGL ES context\n");
   5.224 +		destroy_gl();
   5.225 +		return -1;
   5.226 +	}
   5.227 +	eglMakeCurrent(dpy, surf, surf, ctx);
   5.228 +
   5.229 +	eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width);
   5.230 +	eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height);
   5.231 +	game_reshape(win_width, win_height);
   5.232 +
   5.233 +	return 0;
   5.234 +}
   5.235 +
   5.236 +static void destroy_gl(void)
   5.237 +{
   5.238 +	if(!dpy) return;
   5.239 +
   5.240 +	eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   5.241 +
   5.242 +	if(ctx) {
   5.243 +		eglDestroyContext(dpy, ctx);
   5.244 +		ctx = 0;
   5.245 +	}
   5.246 +	if(surf) {
   5.247 +		eglDestroySurface(dpy, surf);
   5.248 +		surf = 0;
   5.249 +	}
   5.250 +
   5.251 +	eglTerminate(dpy);
   5.252 +	dpy = 0;
   5.253 +}
   5.254 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/android/logger.c	Fri May 01 04:36:50 2015 +0300
     6.3 @@ -0,0 +1,60 @@
     6.4 +#include <stdio.h>
     6.5 +#include <assert.h>
     6.6 +#include <unistd.h>
     6.7 +#include <pthread.h>
     6.8 +#include <android/log.h>
     6.9 +#include "logger.h"
    6.10 +
    6.11 +static void *thread_func(void *arg);
    6.12 +
    6.13 +static int pfd[2];
    6.14 +static pthread_t thr;
    6.15 +static int initialized;
    6.16 +
    6.17 +int start_logger(void)
    6.18 +{
    6.19 +	if(initialized) {
    6.20 +		return 1;
    6.21 +	}
    6.22 +
    6.23 +	/* set stdout to line-buffered, and stderr to unbuffered */
    6.24 +	setvbuf(stdout, 0, _IOLBF, 0);
    6.25 +	setvbuf(stderr, 0, _IONBF, 0);
    6.26 +
    6.27 +	if(pipe(pfd) == -1) {
    6.28 +		perror("failed to create logging pipe");
    6.29 +		return -1;
    6.30 +	}
    6.31 +	assert(pfd[0] > 2 && pfd[1] > 2);
    6.32 +
    6.33 +	/* redirect stdout & stderr to the write-end of the pipe */
    6.34 +	dup2(pfd[1], 1);
    6.35 +	dup2(pfd[1], 2);
    6.36 +
    6.37 +	/* start the logging thread */
    6.38 +	if(pthread_create(&thr, 0, thread_func, 0) == -1) {
    6.39 +		perror("failed to spawn logging thread");
    6.40 +		return -1;
    6.41 +	}
    6.42 +	pthread_detach(thr);
    6.43 +	return 0;
    6.44 +}
    6.45 +
    6.46 +static void *thread_func(void *arg)
    6.47 +{
    6.48 +	ssize_t rdsz;
    6.49 +	char buf[257];
    6.50 +
    6.51 +	__android_log_print(ANDROID_LOG_DEBUG, APP_NAME, "logger starting up...");
    6.52 +
    6.53 +	while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
    6.54 +		if(buf[rdsz - 1] == '\n') {
    6.55 +			--rdsz;
    6.56 +		}
    6.57 +		buf[rdsz] = 0;
    6.58 +		__android_log_write(ANDROID_LOG_DEBUG, APP_NAME, buf);
    6.59 +	}
    6.60 +
    6.61 +	__android_log_print(ANDROID_LOG_DEBUG, APP_NAME, "logger shutting down...");
    6.62 +	return 0;
    6.63 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/android/logger.h	Fri May 01 04:36:50 2015 +0300
     7.3 @@ -0,0 +1,6 @@
     7.4 +#ifndef LOGGER_H_
     7.5 +#define LOGGER_H_
     7.6 +
     7.7 +int start_logger(void);
     7.8 +
     7.9 +#endif	/* LOGGER_H_ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/game.c	Fri May 01 04:36:50 2015 +0300
     8.3 @@ -0,0 +1,356 @@
     8.4 +#include <stdio.h>
     8.5 +#include <stdlib.h>
     8.6 +#include <math.h>
     8.7 +#include "opengl.h"
     8.8 +#include "game.h"
     8.9 +#include "player.h"
    8.10 +#include "level.h"
    8.11 +#include "noise.h"
    8.12 +#include "texture.h"
    8.13 +#include "mesh.h"
    8.14 +
    8.15 +#define PLAYER_EYE_HEIGHT	1.65
    8.16 +
    8.17 +static void draw_scene(unsigned long msec);
    8.18 +
    8.19 +static int win_width, win_height;
    8.20 +static struct level level;
    8.21 +static struct player player;
    8.22 +static int mouselook, freelook = 1;
    8.23 +static char keystate[256];
    8.24 +
    8.25 +static struct mesh *monkey_mesh;
    8.26 +static unsigned int envmap;
    8.27 +static unsigned int win_tex;
    8.28 +
    8.29 +static int game_won;
    8.30 +
    8.31 +static float dbg_cam_dist = 0.0;
    8.32 +
    8.33 +
    8.34 +int game_init(void)
    8.35 +{
    8.36 +	glEnable(GL_DEPTH_TEST);
    8.37 +	glEnable(GL_CULL_FACE);
    8.38 +	glEnable(GL_LIGHTING);
    8.39 +	glEnable(GL_NORMALIZE);
    8.40 +
    8.41 +	glEnable(GL_LIGHT0);
    8.42 +	glEnable(GL_LIGHT1);
    8.43 +
    8.44 +	/* set a slightly bluish cold ambient light */
    8.45 +	{
    8.46 +		float ambient[] = {0.08, 0.1, 0.3, 1.0};
    8.47 +		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
    8.48 +	}
    8.49 +
    8.50 +	level_init(&level);
    8.51 +	if(level_load(&level, "data/0.level") == -1) {
    8.52 +		fprintf(stderr, "level loading failed\n");
    8.53 +		return -1;
    8.54 +	}
    8.55 +
    8.56 +	if(!(level.wall_tex = load_texture("data/wall.ppm"))) {
    8.57 +		return -1;
    8.58 +	}
    8.59 +	if(!(level.floor_tex = load_texture("data/floor.ppm"))) {
    8.60 +		return -1;
    8.61 +	}
    8.62 +	level.floor_tex_scale = 1.0;
    8.63 +	if(!(level.ceil_tex = load_texture("data/ceil.ppm"))) {
    8.64 +		return -1;
    8.65 +	}
    8.66 +	level.ceil_tex_scale = 2.0;
    8.67 +
    8.68 +
    8.69 +	if(!(monkey_mesh = load_mesh("data/monkey.obj"))) {
    8.70 +		return -1;
    8.71 +	}
    8.72 +	if(!(envmap = load_texture("data/refmap.ppm"))) {
    8.73 +		return -1;
    8.74 +	}
    8.75 +
    8.76 +	if(!(win_tex = load_texture("data/done.ppm"))) {
    8.77 +		return -1;
    8.78 +	}
    8.79 +
    8.80 +	player_init(&player, &level);
    8.81 +	return 0;
    8.82 +}
    8.83 +
    8.84 +void game_shutdown(void)
    8.85 +{
    8.86 +}
    8.87 +
    8.88 +static void update(unsigned long msec)
    8.89 +{
    8.90 +	static unsigned long prev_upd;
    8.91 +	float dfwd = 0.0f;
    8.92 +	float dright = 0.0f;
    8.93 +	float walk_speed = 8.0;
    8.94 +
    8.95 +	float dt = (float)(msec - prev_upd) / 1000.0f;
    8.96 +	prev_upd = msec;
    8.97 +
    8.98 +	if(game_won) return;
    8.99 +
   8.100 +	if(freelook) {
   8.101 +		if(keystate['w'] || keystate['W']) {
   8.102 +			dfwd += walk_speed * dt;
   8.103 +		}
   8.104 +		if(keystate['s'] || keystate['S']) {
   8.105 +			dfwd -= walk_speed * dt;
   8.106 +		}
   8.107 +		if(keystate['d'] || keystate['D']) {
   8.108 +			dright += walk_speed * dt * 0.6;
   8.109 +		}
   8.110 +		if(keystate['a'] || keystate['A']) {
   8.111 +			dright -= walk_speed * dt * 0.6;
   8.112 +		}
   8.113 +
   8.114 +		player_move(&player, dfwd, dright);
   8.115 +	}
   8.116 +
   8.117 +	if(level_cell_at(&level, player.x, player.y) == 'x') {
   8.118 +		game_won = 1;
   8.119 +	}
   8.120 +}
   8.121 +
   8.122 +void game_display(unsigned long msec)
   8.123 +{
   8.124 +	float flicker = 1.0f;
   8.125 +
   8.126 +	update(msec);
   8.127 +
   8.128 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   8.129 +
   8.130 +	glMatrixMode(GL_MODELVIEW);
   8.131 +	glLoadIdentity();
   8.132 +	glTranslatef(0, 0, -dbg_cam_dist);
   8.133 +	/* set view matrix according to player pos/rot */
   8.134 +	player_setup_view_matrix(&player);
   8.135 +	glTranslatef(0, -PLAYER_EYE_HEIGHT, 0);
   8.136 +
   8.137 +	/* setup lights */
   8.138 +	flicker = fbm1((float)msec / 500.0f, 2) * 0.4 + 0.6;
   8.139 +	set_light_position(0, player.x, PLAYER_EYE_HEIGHT + 0.2, player.y);
   8.140 +	set_light_color(0, 1.0 * flicker, 0.6 * flicker, 0.3 * flicker);
   8.141 +	set_light_attenuation(0, 0.5, 0, 0.04);
   8.142 +
   8.143 +	set_light_position(1, level.goal_pos[0], 0.8, level.goal_pos[1]);
   8.144 +	set_light_color(1, 0.955, 0.75, 0.06);
   8.145 +	set_light_attenuation(1, 0.9, 0, 0.05);
   8.146 +
   8.147 +	/* draw the scene */
   8.148 +	draw_scene(msec);
   8.149 +}
   8.150 +
   8.151 +void game_reshape(int x, int y)
   8.152 +{
   8.153 +	win_width = x;
   8.154 +	win_height = y;
   8.155 +	glViewport(0, 0, x, y);
   8.156 +	glMatrixMode(GL_PROJECTION);
   8.157 +	glLoadIdentity();
   8.158 +	gluPerspective(55.0, (float)x / (float)y, 0.5, 500.0);
   8.159 +}
   8.160 +
   8.161 +
   8.162 +static void draw_scene(unsigned long msec)
   8.163 +{
   8.164 +	float x, y;
   8.165 +	float tsec = (float)msec / 1000.0f;
   8.166 +
   8.167 +	level_draw(&level);
   8.168 +
   8.169 +	/* draw the golden monkey */
   8.170 +	if(level_obj_pos(&level, 'x', &x, &y)) {
   8.171 +		/* TODO: GLES doesn't have tex-gen... recalc manually */
   8.172 +#ifndef GL_MOBILE
   8.173 +		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
   8.174 +		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
   8.175 +		glEnable(GL_TEXTURE_GEN_S);
   8.176 +		glEnable(GL_TEXTURE_GEN_T);
   8.177 +
   8.178 +		glBindTexture(GL_TEXTURE_2D, envmap);
   8.179 +		glEnable(GL_TEXTURE_2D);
   8.180 +#endif
   8.181 +
   8.182 +		set_mtl_diffuse(0.1, 0.1, 0.1, 1);
   8.183 +		set_mtl_specular(0.955, 0.75, 0.06);
   8.184 +		set_mtl_shininess(80.0);
   8.185 +		set_mtl_emission(0.955, 0.75 * 0.7, 0.06 * 0.1);
   8.186 +
   8.187 +		glMatrixMode(GL_MODELVIEW);
   8.188 +		glPushMatrix();
   8.189 +		glTranslatef(x, 0.8 + sin(tsec * 2.0) * 0.1, y);
   8.190 +		glRotatef(tsec * 100.0, 0, 1, 0);
   8.191 +		glRotatef(sin(tsec * 3.0) * 10.0, 1, 0, 0);
   8.192 +		glScalef(0.3, 0.3, 0.3);
   8.193 +
   8.194 +		render_mesh(monkey_mesh);
   8.195 +
   8.196 +		glPopMatrix();
   8.197 +
   8.198 +		set_mtl_emission(0, 0, 0);
   8.199 +
   8.200 +#ifndef GL_MOBILE
   8.201 +		glDisable(GL_TEXTURE_2D);
   8.202 +
   8.203 +		glDisable(GL_TEXTURE_GEN_S);
   8.204 +		glDisable(GL_TEXTURE_GEN_T);
   8.205 +#endif
   8.206 +	}
   8.207 +
   8.208 +	/* draw the win text */
   8.209 +	if(game_won) {
   8.210 +		glMatrixMode(GL_MODELVIEW);
   8.211 +		glPushMatrix();
   8.212 +		glLoadIdentity();
   8.213 +		glMatrixMode(GL_PROJECTION);
   8.214 +		glPushMatrix();
   8.215 +		glLoadIdentity();
   8.216 +		glScalef((float)win_height / (float)win_width, 1, 1);
   8.217 +
   8.218 +		glBindTexture(GL_TEXTURE_2D, win_tex);
   8.219 +		glEnable(GL_TEXTURE_2D);
   8.220 +
   8.221 +		glEnable(GL_BLEND);
   8.222 +		glBlendFunc(GL_ONE, GL_ONE);
   8.223 +		glDisable(GL_LIGHTING);
   8.224 +
   8.225 +		glBegin(GL_QUADS);
   8.226 +		glTexCoord2f(0, 1); glVertex2f(-1, -1);
   8.227 +		glTexCoord2f(1, 1); glVertex2f(1, -1);
   8.228 +		glTexCoord2f(1, 0); glVertex2f(1, 1);
   8.229 +		glTexCoord2f(0, 0); glVertex2f(-1, 1);
   8.230 +		glEnd();
   8.231 +
   8.232 +		glDisable(GL_BLEND);
   8.233 +		glDisable(GL_TEXTURE_2D);
   8.234 +		glEnable(GL_LIGHTING);
   8.235 +
   8.236 +		glPopMatrix();
   8.237 +		glMatrixMode(GL_MODELVIEW);
   8.238 +		glPopMatrix();
   8.239 +	}
   8.240 +}
   8.241 +
   8.242 +static int warping_mouse;
   8.243 +
   8.244 +void game_keyboard(int key, int pressed)
   8.245 +{
   8.246 +	keystate[key] = pressed;
   8.247 +
   8.248 +	if(!pressed) return;
   8.249 +
   8.250 +	switch(key) {
   8.251 +	case 27:
   8.252 +		exit(0);
   8.253 +
   8.254 +	case 'a':
   8.255 +		if(!freelook && !game_won) {
   8.256 +			player_turn(&player, -90, 0);
   8.257 +		}
   8.258 +		break;
   8.259 +
   8.260 +	case 'd':
   8.261 +		if(!freelook && !game_won) {
   8.262 +			player_turn(&player, 90, 0);
   8.263 +		}
   8.264 +		break;
   8.265 +
   8.266 +	case 'w':
   8.267 +	case 's':
   8.268 +		if(!freelook && !game_won) {
   8.269 +			float prev_x = player.x;
   8.270 +			float prev_y = player.y;
   8.271 +			float sign = key == 'w' ? 1.0 : -1.0;
   8.272 +
   8.273 +			if(!player_move(&player, level.cell_size * sign, 0)) {
   8.274 +				player.x = prev_x;
   8.275 +				player.y = prev_y;
   8.276 +			}
   8.277 +		}
   8.278 +		break;
   8.279 +
   8.280 +	case '`':
   8.281 +	case '~':
   8.282 +		mouselook = !mouselook;
   8.283 +		if(mouselook) {
   8.284 +			warping_mouse = 1;
   8.285 +			set_mouse_pos(win_width / 2, win_height / 2);
   8.286 +			set_mouse_cursor(0);
   8.287 +		} else {
   8.288 +			set_mouse_cursor(1);
   8.289 +		}
   8.290 +		break;
   8.291 +
   8.292 +	case 'b':
   8.293 +	case 'B':
   8.294 +		freelook = !freelook;
   8.295 +		break;
   8.296 +
   8.297 +	case 'r':
   8.298 +	case 'R':
   8.299 +		game_won = 0;
   8.300 +		player_init(&player, &level);
   8.301 +		break;
   8.302 +
   8.303 +	default:
   8.304 +		break;
   8.305 +	}
   8.306 +}
   8.307 +
   8.308 +#define MAX_TOUCH_IDS	16
   8.309 +static struct {
   8.310 +	int bnstate[8];
   8.311 +	int prev_x, prev_y;
   8.312 +} mstate[MAX_TOUCH_IDS];
   8.313 +
   8.314 +void game_mouse_button(int id, int bn, int pressed, int x, int y)
   8.315 +{
   8.316 +	if(id >= MAX_TOUCH_IDS) return;
   8.317 +
   8.318 +	mstate[id].prev_x = x;
   8.319 +	mstate[id].prev_y = y;
   8.320 +	mstate[id].bnstate[bn] = pressed;
   8.321 +}
   8.322 +
   8.323 +void game_mouse_motion(int id, int x, int y)
   8.324 +{
   8.325 +	int dx, dy, cx, cy;
   8.326 +
   8.327 +	if(id >= MAX_TOUCH_IDS) return;
   8.328 +
   8.329 +	cx = win_width / 2;
   8.330 +	cy = win_height / 2;
   8.331 +
   8.332 +	if(warping_mouse) {
   8.333 +		warping_mouse = 0;
   8.334 +		return;
   8.335 +	}
   8.336 +
   8.337 +	dx = x - (mouselook ? cx : mstate[id].prev_x);
   8.338 +	dy = y - (mouselook ? cy : mstate[id].prev_y);
   8.339 +	mstate[id].prev_x = x;
   8.340 +	mstate[id].prev_y = y;
   8.341 +
   8.342 +	if(!dx && !dy) return;
   8.343 +
   8.344 +	if(mouselook || mstate[id].bnstate[0]) {
   8.345 +		player_turn(&player, dx * 0.5, dy * 0.5);
   8.346 +	}
   8.347 +	if(mstate[id].bnstate[2]) {
   8.348 +		dbg_cam_dist += 0.1 * dy;
   8.349 +		if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0;
   8.350 +	}
   8.351 +
   8.352 +	if(mouselook) {
   8.353 +		warping_mouse = 1;
   8.354 +		set_mouse_pos(cx, cy);
   8.355 +		mstate[id].prev_x = cx;
   8.356 +		mstate[id].prev_y = cy;
   8.357 +	}
   8.358 +}
   8.359 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/game.h	Fri May 01 04:36:50 2015 +0300
     9.3 @@ -0,0 +1,19 @@
     9.4 +#ifndef GAME_H_
     9.5 +#define GAME_H_
     9.6 +
     9.7 +int game_init(void);
     9.8 +void game_shutdown(void);
     9.9 +
    9.10 +void game_display(unsigned long msec);
    9.11 +void game_reshape(int x, int y);
    9.12 +
    9.13 +void game_keyboard(int key, int press);
    9.14 +void game_mouse_button(int id, int bn, int press, int x, int y);
    9.15 +void game_mouse_motion(int id, int x, int y);
    9.16 +
    9.17 +/* provided by the system frontend */
    9.18 +void set_mouse_pos(int x, int y);
    9.19 +void set_mouse_cursor(int enable);
    9.20 +
    9.21 +#endif /* GAME_H_ */
    9.22 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/gles/sanegl.c	Fri May 01 04:36:50 2015 +0300
    10.3 @@ -0,0 +1,185 @@
    10.4 +/*
    10.5 +SaneGL - a small library to bring back sanity to OpenGL ES 2.x
    10.6 +Copyright (C) 2011-2013  John Tsiombikas <nuclear@member.fsf.org>
    10.7 +
    10.8 +This program is free software: you can redistribute it and/or modify
    10.9 +it under the terms of the GNU General Public License as published by
   10.10 +the Free Software Foundation, either version 3 of the License, or
   10.11 +(at your option) any later version.
   10.12 +
   10.13 +This program is distributed in the hope that it will be useful,
   10.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.16 +GNU General Public License for more details.
   10.17 +
   10.18 +You should have received a copy of the GNU General Public License
   10.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   10.20 +*/
   10.21 +
   10.22 +#include <stdio.h>
   10.23 +#include <stdlib.h>
   10.24 +#include <string.h>
   10.25 +#include <math.h>
   10.26 +#include <assert.h>
   10.27 +#include "sanegl.h"
   10.28 +
   10.29 +#define MAX_VERTS	512
   10.30 +
   10.31 +static void gl_draw_immediate(void);
   10.32 +
   10.33 +typedef struct { float x, y; } vec2_t;
   10.34 +typedef struct { float x, y, z; } vec3_t;
   10.35 +typedef struct { float x, y, z, w; } vec4_t;
   10.36 +
   10.37 +static int prim = -1;
   10.38 +
   10.39 +static vec3_t cur_normal;
   10.40 +static vec4_t cur_color;
   10.41 +static vec2_t cur_texcoord;
   10.42 +
   10.43 +static vec4_t *vert_arr, *col_arr;
   10.44 +static vec3_t *norm_arr;
   10.45 +static vec2_t *texc_arr;
   10.46 +
   10.47 +static int num_verts, vert_calls;
   10.48 +
   10.49 +/* immediate mode rendering */
   10.50 +void gl_begin(int p)
   10.51 +{
   10.52 +	if(!vert_arr) {
   10.53 +		vert_arr = malloc(MAX_VERTS * sizeof *vert_arr);
   10.54 +		norm_arr = malloc(MAX_VERTS * sizeof *norm_arr);
   10.55 +		texc_arr = malloc(MAX_VERTS * sizeof *texc_arr);
   10.56 +		col_arr = malloc(MAX_VERTS * sizeof *col_arr);
   10.57 +		assert(vert_arr && norm_arr && texc_arr && col_arr);
   10.58 +	}
   10.59 +
   10.60 +	prim = p;
   10.61 +	num_verts = vert_calls = 0;
   10.62 +}
   10.63 +
   10.64 +void gl_end(void)
   10.65 +{
   10.66 +	if(num_verts > 0) {
   10.67 +		gl_draw_immediate();
   10.68 +	}
   10.69 +}
   10.70 +
   10.71 +static void gl_draw_immediate(void)
   10.72 +{
   10.73 +	int glprim;
   10.74 +
   10.75 +	glprim = prim == GL_QUADS ? GL_TRIANGLES : prim;
   10.76 +
   10.77 +	glEnableClientState(GL_VERTEX_ARRAY);
   10.78 +	glEnableClientState(GL_NORMAL_ARRAY);
   10.79 +	glEnableClientState(GL_COLOR_ARRAY);
   10.80 +	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   10.81 +
   10.82 +	glVertexPointer(4, GL_FLOAT, 0, vert_arr);
   10.83 +	glNormalPointer(GL_FLOAT, 0, norm_arr);
   10.84 +	glColorPointer(4, GL_FLOAT, 0, col_arr);
   10.85 +	glTexCoordPointer(2, GL_FLOAT, 0, texc_arr);
   10.86 +
   10.87 +	glDrawArrays(glprim, 0, num_verts);
   10.88 +
   10.89 +	glDisableClientState(GL_VERTEX_ARRAY);
   10.90 +	glDisableClientState(GL_NORMAL_ARRAY);
   10.91 +	glDisableClientState(GL_COLOR_ARRAY);
   10.92 +	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   10.93 +}
   10.94 +
   10.95 +void gl_vertex2f(float x, float y)
   10.96 +{
   10.97 +	gl_vertex4f(x, y, 0.0f, 1.0f);
   10.98 +}
   10.99 +
  10.100 +void gl_vertex3f(float x, float y, float z)
  10.101 +{
  10.102 +	gl_vertex4f(x, y, z, 1.0f);
  10.103 +}
  10.104 +
  10.105 +void gl_vertex4f(float x, float y, float z, float w)
  10.106 +{
  10.107 +	int i, buffer_full;
  10.108 +
  10.109 +	if(prim == GL_QUADS && vert_calls % 4 == 3) {
  10.110 +		for(i=0; i<2; i++) {
  10.111 +			col_arr[num_verts] = col_arr[num_verts - 3 + i];
  10.112 +			texc_arr[num_verts] = texc_arr[num_verts - 3 + i];
  10.113 +			norm_arr[num_verts] = norm_arr[num_verts - 3 + i];
  10.114 +			vert_arr[num_verts] = vert_arr[num_verts - 3 + i];
  10.115 +			num_verts++;
  10.116 +		}
  10.117 +	}
  10.118 +
  10.119 +	vert_arr[num_verts].x = x;
  10.120 +	vert_arr[num_verts].y = y;
  10.121 +	vert_arr[num_verts].z = z;
  10.122 +	vert_arr[num_verts].w = w;
  10.123 +
  10.124 +	col_arr[num_verts] = cur_color;
  10.125 +	norm_arr[num_verts] = cur_normal;
  10.126 +	texc_arr[num_verts] = cur_texcoord;
  10.127 +
  10.128 +	vert_calls++;
  10.129 +	num_verts++;
  10.130 +
  10.131 +	if(prim == GL_QUADS) {
  10.132 +		/* leave space for 6 more worst-case and don't allow flushes mid-quad */
  10.133 +		buffer_full = num_verts >= MAX_VERTS - 6 && vert_calls % 4 == 0;
  10.134 +	} else {
  10.135 +		buffer_full = num_verts >= MAX_VERTS - prim;
  10.136 +	}
  10.137 +
  10.138 +	if(buffer_full) {
  10.139 +		gl_draw_immediate();
  10.140 +		gl_begin(prim);	/* reset everything */
  10.141 +	}
  10.142 +}
  10.143 +
  10.144 +
  10.145 +void gl_normal3f(float x, float y, float z)
  10.146 +{
  10.147 +	cur_normal.x = x;
  10.148 +	cur_normal.y = y;
  10.149 +	cur_normal.z = z;
  10.150 +}
  10.151 +
  10.152 +
  10.153 +void gl_color3f(float r, float g, float b)
  10.154 +{
  10.155 +	cur_color.x = r;
  10.156 +	cur_color.y = g;
  10.157 +	cur_color.z = b;
  10.158 +	cur_color.w = 1.0f;
  10.159 +}
  10.160 +
  10.161 +void gl_color4f(float r, float g, float b, float a)
  10.162 +{
  10.163 +	cur_color.x = r;
  10.164 +	cur_color.y = g;
  10.165 +	cur_color.z = b;
  10.166 +	cur_color.w = a;
  10.167 +}
  10.168 +
  10.169 +
  10.170 +void gl_texcoord1f(float s)
  10.171 +{
  10.172 +	cur_texcoord.x = s;
  10.173 +	cur_texcoord.y = 0.0f;
  10.174 +}
  10.175 +
  10.176 +void gl_texcoord2f(float s, float t)
  10.177 +{
  10.178 +	cur_texcoord.x = s;
  10.179 +	cur_texcoord.y = t;
  10.180 +}
  10.181 +
  10.182 +void glu_perspective(float fov, float aspect, float nearz, float farz)
  10.183 +{
  10.184 +	float fovrad = M_PI * fov / 180.0;
  10.185 +	float halfsz = tan(fovrad) * nearz;
  10.186 +
  10.187 +	glFrustumf(-halfsz * aspect, halfsz * aspect, -halfsz, halfsz, nearz, farz);
  10.188 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/gles/sanegl.h	Fri May 01 04:36:50 2015 +0300
    11.3 @@ -0,0 +1,96 @@
    11.4 +/*
    11.5 +SaneGL - a small library to bring back sanity to OpenGL ES 2.x
    11.6 +Copyright (C) 2011-2013  John Tsiombikas <nuclear@member.fsf.org>
    11.7 +
    11.8 +This program is free software: you can redistribute it and/or modify
    11.9 +it under the terms of the GNU General Public License as published by
   11.10 +the Free Software Foundation, either version 3 of the License, or
   11.11 +(at your option) any later version.
   11.12 +
   11.13 +This program is distributed in the hope that it will be useful,
   11.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.16 +GNU General Public License for more details.
   11.17 +
   11.18 +You should have received a copy of the GNU General Public License
   11.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   11.20 +*/
   11.21 +
   11.22 +#ifndef SANEGL_H_
   11.23 +#define SANEGL_H_
   11.24 +
   11.25 +#include "opengl.h"
   11.26 +
   11.27 +#ifndef GL_POINTS
   11.28 +#define GL_POINTS			0
   11.29 +#endif
   11.30 +#ifndef GL_LINES
   11.31 +#define GL_LINES			1
   11.32 +#endif
   11.33 +#ifndef GL_TRIANGLES
   11.34 +#define GL_TRIANGLES		4
   11.35 +#endif
   11.36 +#ifndef GL_QUADS
   11.37 +#define GL_QUADS			7
   11.38 +#endif
   11.39 +
   11.40 +/* glGet stuff */
   11.41 +#ifndef GL_VIEWPORT
   11.42 +#define GL_VIEWPORT				0x0BA2
   11.43 +#endif
   11.44 +#ifndef GL_MODELVIEW_MATRIX
   11.45 +#define GL_MODELVIEW_MATRIX		0x0BA6
   11.46 +#endif
   11.47 +#ifndef GL_PROJECTION_MATRIX
   11.48 +#define GL_PROJECTION_MATRIX	0x0BA7
   11.49 +#endif
   11.50 +
   11.51 +#ifdef GLDEF
   11.52 +
   11.53 +#define glBegin				gl_begin
   11.54 +#define glEnd				gl_end
   11.55 +#define glVertex2f			gl_vertex2f
   11.56 +#define glVertex3f			gl_vertex3f
   11.57 +#define glVertex4f			gl_vertex4f
   11.58 +#define glNormal3f			gl_normal3f
   11.59 +#define glColor3f			gl_color3f
   11.60 +#define glColor4f			gl_color4f
   11.61 +#define glTexCoord1f		gl_texcoord1f
   11.62 +#define glTexCoord2f		gl_texcoord2f
   11.63 +#define glVertexAttrib2f	gl_vertex_attrib2f
   11.64 +#define glVertexAttrib3f	gl_vertex_attrib3f
   11.65 +#define glVertexAttrib4f	gl_vertex_attrib4f
   11.66 +
   11.67 +#define gluPerspective		glu_perspective
   11.68 +
   11.69 +#endif	/* GLDEF */
   11.70 +
   11.71 +#ifdef __cplusplus
   11.72 +extern "C" {
   11.73 +#endif
   11.74 +
   11.75 +/* immediate mode rendering */
   11.76 +void gl_begin(int prim);
   11.77 +void gl_end(void);
   11.78 +
   11.79 +void gl_vertex2f(float x, float y);
   11.80 +void gl_vertex3f(float x, float y, float z);
   11.81 +void gl_vertex4f(float x, float y, float z, float w);
   11.82 +
   11.83 +void gl_normal3f(float x, float y, float z);
   11.84 +
   11.85 +void gl_color3f(float r, float g, float b);
   11.86 +void gl_color4f(float r, float g, float b, float a);
   11.87 +
   11.88 +void gl_texcoord1f(float s);
   11.89 +void gl_texcoord2f(float s, float t);
   11.90 +
   11.91 +/* GLU */
   11.92 +
   11.93 +void glu_perspective(float fov, float aspect, float nearz, float farz);
   11.94 +
   11.95 +#ifdef __cplusplus
   11.96 +}
   11.97 +#endif
   11.98 +
   11.99 +#endif	/* SANEGL_H_ */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/glut/main.c	Fri May 01 04:36:50 2015 +0300
    12.3 @@ -0,0 +1,94 @@
    12.4 +#include <stdio.h>
    12.5 +#include <stdlib.h>
    12.6 +#include <math.h>
    12.7 +#include <assert.h>
    12.8 +#include "opengl.h"
    12.9 +
   12.10 +#ifdef __APPLE__
   12.11 +#include <GLUT/glut.h>
   12.12 +#else
   12.13 +#include <GL/glut.h>
   12.14 +#endif
   12.15 +
   12.16 +#include "game.h"
   12.17 +
   12.18 +static void display(void);
   12.19 +static void idle(void);
   12.20 +static void reshape(int x, int y);
   12.21 +static void key_down(unsigned char key, int x, int y);
   12.22 +static void key_up(unsigned char key, int x, int y);
   12.23 +static void mouse(int bn, int state, int x, int y);
   12.24 +static void motion(int x, int y);
   12.25 +
   12.26 +int main(int argc, char **argv)
   12.27 +{
   12.28 +	glutInit(&argc, argv);
   12.29 +	glutInitWindowSize(1280, 800);
   12.30 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
   12.31 +	glutCreateWindow("labyrinth game example");
   12.32 +
   12.33 +	glutDisplayFunc(display);
   12.34 +	glutIdleFunc(idle);
   12.35 +	glutReshapeFunc(reshape);
   12.36 +	glutKeyboardFunc(key_down);
   12.37 +	glutKeyboardUpFunc(key_up);
   12.38 +	glutMouseFunc(mouse);
   12.39 +	glutMotionFunc(motion);
   12.40 +    glutPassiveMotionFunc(motion);
   12.41 +
   12.42 +	glewInit();
   12.43 +
   12.44 +    if(game_init() == -1) {
   12.45 +		return 1;
   12.46 +	}
   12.47 +	glutMainLoop();
   12.48 +	return 0;
   12.49 +}
   12.50 +
   12.51 +void set_mouse_pos(int x, int y)
   12.52 +{
   12.53 +    glutWarpPointer(x, y);
   12.54 +}
   12.55 +
   12.56 +void set_mouse_cursor(int enable)
   12.57 +{
   12.58 +    glutSetCursor(enable ? GLUT_CURSOR_INHERIT : GLUT_CURSOR_NONE);
   12.59 +}
   12.60 +
   12.61 +static void display(void)
   12.62 +{
   12.63 +    game_display(glutGet(GLUT_ELAPSED_TIME));
   12.64 +
   12.65 +    glutSwapBuffers();
   12.66 +    assert(glGetError() == GL_NO_ERROR);
   12.67 +}
   12.68 +
   12.69 +static void idle(void)
   12.70 +{
   12.71 +	glutPostRedisplay();
   12.72 +}
   12.73 +
   12.74 +static void reshape(int x, int y)
   12.75 +{
   12.76 +    game_reshape(x, y);
   12.77 +}
   12.78 +
   12.79 +static void key_down(unsigned char key, int x, int y)
   12.80 +{
   12.81 +    game_keyboard(key, 1);
   12.82 +}
   12.83 +
   12.84 +static void key_up(unsigned char key, int x, int y)
   12.85 +{
   12.86 +    game_keyboard(key, 0);
   12.87 +}
   12.88 +
   12.89 +static void mouse(int bn, int state, int x, int y)
   12.90 +{
   12.91 +    game_mouse_button(0, bn - GLUT_LEFT_BUTTON, state == GLUT_DOWN ? 1 : 0, x, y);
   12.92 +}
   12.93 +
   12.94 +static void motion(int x, int y)
   12.95 +{
   12.96 +    game_mouse_motion(0, x, y);
   12.97 +}
    13.1 --- a/src/main.c	Mon Apr 27 05:37:17 2015 +0300
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,382 +0,0 @@
    13.4 -#include <stdio.h>
    13.5 -#include <stdlib.h>
    13.6 -#include <math.h>
    13.7 -#include <assert.h>
    13.8 -#include "opengl.h"
    13.9 -#include "player.h"
   13.10 -#include "level.h"
   13.11 -#include "noise.h"
   13.12 -#include "texture.h"
   13.13 -#include "mesh.h"
   13.14 -
   13.15 -#define PLAYER_EYE_HEIGHT	1.65
   13.16 -
   13.17 -static int init(void);
   13.18 -static void update(unsigned int msec);
   13.19 -static void display(void);
   13.20 -static void draw_scene(unsigned int msec);
   13.21 -static void idle(void);
   13.22 -static void reshape(int x, int y);
   13.23 -static void key_down(unsigned char key, int x, int y);
   13.24 -static void key_up(unsigned char key, int x, int y);
   13.25 -static void mouse(int bn, int state, int x, int y);
   13.26 -static void motion(int x, int y);
   13.27 -
   13.28 -static int win_width, win_height;
   13.29 -static struct level level;
   13.30 -static struct player player;
   13.31 -static int mouselook, freelook = 1;
   13.32 -static char keystate[256];
   13.33 -
   13.34 -static struct mesh *monkey_mesh;
   13.35 -static unsigned int envmap;
   13.36 -static unsigned int win_tex;
   13.37 -
   13.38 -static int game_won;
   13.39 -
   13.40 -static float dbg_cam_dist = 0.0;
   13.41 -
   13.42 -int main(int argc, char **argv)
   13.43 -{
   13.44 -	glutInit(&argc, argv);
   13.45 -	glutInitWindowSize(1280, 800);
   13.46 -	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
   13.47 -	glutCreateWindow("labyrinth game example");
   13.48 -
   13.49 -	glutDisplayFunc(display);
   13.50 -	glutIdleFunc(idle);
   13.51 -	glutReshapeFunc(reshape);
   13.52 -	glutKeyboardFunc(key_down);
   13.53 -	glutKeyboardUpFunc(key_up);
   13.54 -	glutMouseFunc(mouse);
   13.55 -	glutMotionFunc(motion);
   13.56 -
   13.57 -	if(init() == -1) {
   13.58 -		return 1;
   13.59 -	}
   13.60 -	glutMainLoop();
   13.61 -	return 0;
   13.62 -}
   13.63 -
   13.64 -
   13.65 -static int init(void)
   13.66 -{
   13.67 -	glEnable(GL_DEPTH_TEST);
   13.68 -	glEnable(GL_CULL_FACE);
   13.69 -	glEnable(GL_LIGHTING);
   13.70 -	glEnable(GL_NORMALIZE);
   13.71 -
   13.72 -	glEnable(GL_LIGHT0);
   13.73 -	glEnable(GL_LIGHT1);
   13.74 -
   13.75 -	/* set a slightly bluish cold ambient light */
   13.76 -	{
   13.77 -		float ambient[] = {0.08, 0.1, 0.3, 1.0};
   13.78 -		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
   13.79 -	}
   13.80 -
   13.81 -	level_init(&level);
   13.82 -	if(level_load(&level, "data/0.level") == -1) {
   13.83 -		fprintf(stderr, "level loading failed\n");
   13.84 -		return -1;
   13.85 -	}
   13.86 -
   13.87 -	if(!(level.wall_tex = load_texture("data/wall.ppm"))) {
   13.88 -		return -1;
   13.89 -	}
   13.90 -	if(!(level.floor_tex = load_texture("data/floor.ppm"))) {
   13.91 -		return -1;
   13.92 -	}
   13.93 -	level.floor_tex_scale = 1.0;
   13.94 -	if(!(level.ceil_tex = load_texture("data/ceil.ppm"))) {
   13.95 -		return -1;
   13.96 -	}
   13.97 -	level.ceil_tex_scale = 2.0;
   13.98 -
   13.99 -
  13.100 -	if(!(monkey_mesh = load_mesh("data/monkey.obj"))) {
  13.101 -		return -1;
  13.102 -	}
  13.103 -	if(!(envmap = load_texture("data/refmap.ppm"))) {
  13.104 -		return -1;
  13.105 -	}
  13.106 -
  13.107 -	if(!(win_tex = load_texture("data/done.ppm"))) {
  13.108 -		return -1;
  13.109 -	}
  13.110 -
  13.111 -	player_init(&player, &level);
  13.112 -	return 0;
  13.113 -}
  13.114 -
  13.115 -static void update(unsigned int msec)
  13.116 -{
  13.117 -	static unsigned int prev_upd;
  13.118 -	float dfwd = 0.0f;
  13.119 -	float dright = 0.0f;
  13.120 -	float walk_speed = 8.0;
  13.121 -
  13.122 -	float dt = (float)(msec - prev_upd) / 1000.0f;
  13.123 -	prev_upd = msec;
  13.124 -
  13.125 -	if(game_won) return;
  13.126 -
  13.127 -	if(freelook) {
  13.128 -		if(keystate['w'] || keystate['W']) {
  13.129 -			dfwd += walk_speed * dt;
  13.130 -		}
  13.131 -		if(keystate['s'] || keystate['S']) {
  13.132 -			dfwd -= walk_speed * dt;
  13.133 -		}
  13.134 -		if(keystate['d'] || keystate['D']) {
  13.135 -			dright += walk_speed * dt * 0.6;
  13.136 -		}
  13.137 -		if(keystate['a'] || keystate['A']) {
  13.138 -			dright -= walk_speed * dt * 0.6;
  13.139 -		}
  13.140 -
  13.141 -		player_move(&player, dfwd, dright);
  13.142 -	}
  13.143 -
  13.144 -	if(level_cell_at(&level, player.x, player.y) == 'x') {
  13.145 -		game_won = 1;
  13.146 -	}
  13.147 -}
  13.148 -
  13.149 -static void display(void)
  13.150 -{
  13.151 -	float flicker = 1.0f;
  13.152 -	unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
  13.153 -
  13.154 -	update(msec);
  13.155 -
  13.156 -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  13.157 -
  13.158 -	glMatrixMode(GL_MODELVIEW);
  13.159 -	glLoadIdentity();
  13.160 -	glTranslatef(0, 0, -dbg_cam_dist);
  13.161 -	/* set view matrix according to player pos/rot */
  13.162 -	player_setup_view_matrix(&player);
  13.163 -	glTranslatef(0, -PLAYER_EYE_HEIGHT, 0);
  13.164 -
  13.165 -	/* setup lights */
  13.166 -	flicker = fbm1((float)msec / 500.0f, 2) * 0.4 + 0.6;
  13.167 -	set_light_position(0, player.x, PLAYER_EYE_HEIGHT + 0.2, player.y);
  13.168 -	set_light_color(0, 1.0 * flicker, 0.6 * flicker, 0.3 * flicker);
  13.169 -	set_light_attenuation(0, 0.5, 0, 0.04);
  13.170 -
  13.171 -	set_light_position(1, level.goal_pos[0], 0.8, level.goal_pos[1]);
  13.172 -	set_light_color(1, 0.955, 0.75, 0.06);
  13.173 -	set_light_attenuation(1, 0.9, 0, 0.05);
  13.174 -
  13.175 -	/* draw the scene */
  13.176 -	draw_scene(msec);
  13.177 -
  13.178 -	glutSwapBuffers();
  13.179 -	assert(glGetError() == GL_NO_ERROR);
  13.180 -}
  13.181 -
  13.182 -static void draw_scene(unsigned int msec)
  13.183 -{
  13.184 -	float x, y;
  13.185 -	float tsec = (float)msec / 1000.0f;
  13.186 -
  13.187 -	level_draw(&level);
  13.188 -
  13.189 -	/* draw the golden monkey */
  13.190 -	if(level_obj_pos(&level, 'x', &x, &y)) {
  13.191 -		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  13.192 -		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  13.193 -		glEnable(GL_TEXTURE_GEN_S);
  13.194 -		glEnable(GL_TEXTURE_GEN_T);
  13.195 -
  13.196 -		glBindTexture(GL_TEXTURE_2D, envmap);
  13.197 -		glEnable(GL_TEXTURE_2D);
  13.198 -
  13.199 -		set_mtl_diffuse(0.1, 0.1, 0.1, 1);
  13.200 -		set_mtl_specular(0.955, 0.75, 0.06);
  13.201 -		set_mtl_shininess(80.0);
  13.202 -		set_mtl_emission(0.955, 0.75 * 0.7, 0.06 * 0.1);
  13.203 -
  13.204 -		glMatrixMode(GL_MODELVIEW);
  13.205 -		glPushMatrix();
  13.206 -		glTranslatef(x, 0.8 + sin(tsec * 2.0) * 0.1, y);
  13.207 -		glRotatef(tsec * 100.0, 0, 1, 0);
  13.208 -		glRotatef(sin(tsec * 3.0) * 10.0, 1, 0, 0);
  13.209 -		glScalef(0.3, 0.3, 0.3);
  13.210 -
  13.211 -		render_mesh(monkey_mesh);
  13.212 -
  13.213 -		glPopMatrix();
  13.214 -
  13.215 -		set_mtl_emission(0, 0, 0);
  13.216 -
  13.217 -		glDisable(GL_TEXTURE_2D);
  13.218 -
  13.219 -		glDisable(GL_TEXTURE_GEN_S);
  13.220 -		glDisable(GL_TEXTURE_GEN_T);
  13.221 -	}
  13.222 -
  13.223 -	/* draw the win text */
  13.224 -	if(game_won) {
  13.225 -		glMatrixMode(GL_MODELVIEW);
  13.226 -		glPushMatrix();
  13.227 -		glLoadIdentity();
  13.228 -		glMatrixMode(GL_PROJECTION);
  13.229 -		glPushMatrix();
  13.230 -		glLoadIdentity();
  13.231 -		glScalef((float)win_height / (float)win_width, 1, 1);
  13.232 -
  13.233 -		glBindTexture(GL_TEXTURE_2D, win_tex);
  13.234 -		glEnable(GL_TEXTURE_2D);
  13.235 -
  13.236 -		glEnable(GL_BLEND);
  13.237 -		glBlendFunc(GL_ONE, GL_ONE);
  13.238 -		glDisable(GL_LIGHTING);
  13.239 -
  13.240 -		glBegin(GL_QUADS);
  13.241 -		glTexCoord2f(0, 1); glVertex2f(-1, -1);
  13.242 -		glTexCoord2f(1, 1); glVertex2f(1, -1);
  13.243 -		glTexCoord2f(1, 0); glVertex2f(1, 1);
  13.244 -		glTexCoord2f(0, 0); glVertex2f(-1, 1);
  13.245 -		glEnd();
  13.246 -
  13.247 -		glDisable(GL_BLEND);
  13.248 -		glDisable(GL_TEXTURE_2D);
  13.249 -		glEnable(GL_LIGHTING);
  13.250 -
  13.251 -		glPopMatrix();
  13.252 -		glMatrixMode(GL_MODELVIEW);
  13.253 -		glPopMatrix();
  13.254 -	}
  13.255 -}
  13.256 -
  13.257 -static void idle(void)
  13.258 -{
  13.259 -	glutPostRedisplay();
  13.260 -}
  13.261 -
  13.262 -static void reshape(int x, int y)
  13.263 -{
  13.264 -	win_width = x;
  13.265 -	win_height = y;
  13.266 -	glViewport(0, 0, x, y);
  13.267 -	glMatrixMode(GL_PROJECTION);
  13.268 -	glLoadIdentity();
  13.269 -	gluPerspective(55.0, (float)x / (float)y, 0.5, 500.0);
  13.270 -}
  13.271 -
  13.272 -static int warping_mouse;
  13.273 -
  13.274 -static void key_down(unsigned char key, int x, int y)
  13.275 -{
  13.276 -	keystate[key] = 1;
  13.277 -
  13.278 -	switch(key) {
  13.279 -	case 27:
  13.280 -		exit(0);
  13.281 -
  13.282 -	case 'a':
  13.283 -		if(!freelook && !game_won) {
  13.284 -			player_turn(&player, -90, 0);
  13.285 -		}
  13.286 -		break;
  13.287 -
  13.288 -	case 'd':
  13.289 -		if(!freelook && !game_won) {
  13.290 -			player_turn(&player, 90, 0);
  13.291 -		}
  13.292 -		break;
  13.293 -
  13.294 -	case 'w':
  13.295 -	case 's':
  13.296 -		if(!freelook && !game_won) {
  13.297 -			float prev_x = player.x;
  13.298 -			float prev_y = player.y;
  13.299 -			float sign = key == 'w' ? 1.0 : -1.0;
  13.300 -
  13.301 -			if(!player_move(&player, level.cell_size * sign, 0)) {
  13.302 -				player.x = prev_x;
  13.303 -				player.y = prev_y;
  13.304 -			}
  13.305 -		}
  13.306 -		break;
  13.307 -
  13.308 -	case '`':
  13.309 -	case '~':
  13.310 -		mouselook = !mouselook;
  13.311 -		if(mouselook) {
  13.312 -			warping_mouse = 1;
  13.313 -			glutWarpPointer(win_width / 2, win_height / 2);
  13.314 -			glutPassiveMotionFunc(motion);
  13.315 -			glutSetCursor(GLUT_CURSOR_NONE);
  13.316 -		} else {
  13.317 -			glutPassiveMotionFunc(0);
  13.318 -			glutSetCursor(GLUT_CURSOR_INHERIT);
  13.319 -		}
  13.320 -		break;
  13.321 -
  13.322 -	case 'b':
  13.323 -	case 'B':
  13.324 -		freelook = !freelook;
  13.325 -		break;
  13.326 -
  13.327 -	case 'r':
  13.328 -	case 'R':
  13.329 -		game_won = 0;
  13.330 -		player_init(&player, &level);
  13.331 -		break;
  13.332 -
  13.333 -	default:
  13.334 -		break;
  13.335 -	}
  13.336 -}
  13.337 -
  13.338 -static void key_up(unsigned char key, int x, int y)
  13.339 -{
  13.340 -	keystate[key] = 0;
  13.341 -}
  13.342 -
  13.343 -static int bnstate[16];
  13.344 -static int prev_x, prev_y;
  13.345 -
  13.346 -static void mouse(int bn, int state, int x, int y)
  13.347 -{
  13.348 -	prev_x = x;
  13.349 -	prev_y = y;
  13.350 -	bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0;
  13.351 -}
  13.352 -
  13.353 -static void motion(int x, int y)
  13.354 -{
  13.355 -	int dx, dy;
  13.356 -	int cx = win_width / 2;
  13.357 -	int cy = win_height / 2;
  13.358 -
  13.359 -	if(warping_mouse) {
  13.360 -		warping_mouse = 0;
  13.361 -		return;
  13.362 -	}
  13.363 -
  13.364 -	dx = x - (mouselook ? cx : prev_x);
  13.365 -	dy = y - (mouselook ? cy : prev_y);
  13.366 -	prev_x = x;
  13.367 -	prev_y = y;
  13.368 -
  13.369 -	if(!dx && !dy) return;
  13.370 -
  13.371 -	if(mouselook || bnstate[0]) {
  13.372 -		player_turn(&player, dx * 0.5, dy * 0.5);
  13.373 -	}
  13.374 -	if(bnstate[2]) {
  13.375 -		dbg_cam_dist += 0.1 * dy;
  13.376 -		if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0;
  13.377 -	}
  13.378 -
  13.379 -	if(mouselook) {
  13.380 -		warping_mouse = 1;
  13.381 -		glutWarpPointer(cx, cy);
  13.382 -		prev_x = cx;
  13.383 -		prev_y = cy;
  13.384 -	}
  13.385 -}
    14.1 --- a/src/mesh.c	Mon Apr 27 05:37:17 2015 +0300
    14.2 +++ b/src/mesh.c	Fri May 01 04:36:50 2015 +0300
    14.3 @@ -1,11 +1,5 @@
    14.4 -#ifdef __APPLE__
    14.5 -#include <GLUT/glut.h>
    14.6 -#elif defined(WIN32)
    14.7 -#include <glut.h>
    14.8 -#else
    14.9 -#include <GL/glut.h>
   14.10 -#endif
   14.11 -
   14.12 +#include <stdlib.h>
   14.13 +#include "opengl.h"
   14.14  #include "mesh.h"
   14.15  #include "objfile.h"
   14.16  
    15.1 --- a/src/opengl.h	Mon Apr 27 05:37:17 2015 +0300
    15.2 +++ b/src/opengl.h	Fri May 01 04:36:50 2015 +0300
    15.3 @@ -1,11 +1,20 @@
    15.4  #ifndef OPENGL_H_
    15.5  #define OPENGL_H_
    15.6  
    15.7 -#ifdef __APPLE__
    15.8 -#include <GLUT/glut.h>
    15.9 +#ifdef __ANDROID__
   15.10 +#include <GLES/gl.h>
   15.11 +#include <GLES/glext.h>
   15.12 +#include <EGL/egl.h>
   15.13 +
   15.14 +#define GL_MOBILE
   15.15 +
   15.16  #else
   15.17 -#include <GL/glut.h>
   15.18 -#endif
   15.19 +
   15.20 +#include <GL/glew.h>
   15.21 +
   15.22 +#define GL_DESKTOP
   15.23 +
   15.24 +#endif	/* not __ANDROID__ */
   15.25  
   15.26  /* some helpers */
   15.27  
   15.28 @@ -18,4 +27,9 @@
   15.29  void set_mtl_shininess(float shin);
   15.30  void set_mtl_emission(float r, float g, float b);
   15.31  
   15.32 +#ifdef GL_MOBILE
   15.33 +#define GLDEF
   15.34 +#include "sanegl.h"
   15.35 +#endif
   15.36 +
   15.37  #endif	/* OPENGL_H_ */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/timer.c	Fri May 01 04:36:50 2015 +0300
    16.3 @@ -0,0 +1,71 @@
    16.4 +#include "timer.h"
    16.5 +
    16.6 +#if defined(__APPLE__) && !defined(__unix__)
    16.7 +#define __unix__
    16.8 +#endif
    16.9 +
   16.10 +#ifdef __unix__
   16.11 +#include <time.h>
   16.12 +#include <unistd.h>
   16.13 +#include <sys/time.h>
   16.14 +
   16.15 +#ifdef CLOCK_MONOTONIC
   16.16 +unsigned long get_time_msec(void)
   16.17 +{
   16.18 +	struct timespec ts;
   16.19 +	static struct timespec ts0;
   16.20 +
   16.21 +	clock_gettime(CLOCK_MONOTONIC, &ts);
   16.22 +	if(ts0.tv_sec == 0 && ts0.tv_nsec == 0) {
   16.23 +		ts0 = ts;
   16.24 +		return 0;
   16.25 +	}
   16.26 +	return (ts.tv_sec - ts0.tv_sec) * 1000 + (ts.tv_nsec - ts0.tv_nsec) / 1000000;
   16.27 +}
   16.28 +#else	/* no fancy POSIX clocks, fallback to good'ol gettimeofday */
   16.29 +unsigned long get_time_msec(void)
   16.30 +{
   16.31 +	struct timeval tv;
   16.32 +	static struct timeval tv0;
   16.33 +
   16.34 +	gettimeofday(&tv, 0);
   16.35 +	if(tv0.tv_sec == 0 && tv0.tv_usec == 0) {
   16.36 +		tv0 = tv;
   16.37 +		return 0;
   16.38 +	}
   16.39 +	return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
   16.40 +}
   16.41 +#endif	/* !posix clock */
   16.42 +
   16.43 +void sleep_msec(unsigned long msec)
   16.44 +{
   16.45 +	usleep(msec * 1000);
   16.46 +}
   16.47 +#endif
   16.48 +
   16.49 +#ifdef WIN32
   16.50 +#include <windows.h>
   16.51 +#pragma comment(lib, "winmm.lib")
   16.52 +
   16.53 +unsigned long get_time_msec(void)
   16.54 +{
   16.55 +	return timeGetTime();
   16.56 +}
   16.57 +
   16.58 +void sleep_msec(unsigned long msec)
   16.59 +{
   16.60 +	Sleep(msec);
   16.61 +}
   16.62 +#endif
   16.63 +
   16.64 +double get_time_sec(void)
   16.65 +{
   16.66 +	return get_time_msec() / 1000.0f;
   16.67 +}
   16.68 +
   16.69 +void sleep_sec(double sec)
   16.70 +{
   16.71 +	if(sec > 0.0f) {
   16.72 +		sleep_msec(sec * 1000.0f);
   16.73 +	}
   16.74 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/timer.h	Fri May 01 04:36:50 2015 +0300
    17.3 @@ -0,0 +1,10 @@
    17.4 +#ifndef TIMER_H_
    17.5 +#define TIMER_H_
    17.6 +
    17.7 +unsigned long get_time_msec(void);
    17.8 +void sleep_msec(unsigned long msec);
    17.9 +
   17.10 +double get_time_sec(void);
   17.11 +void sleep_sec(double sec);
   17.12 +
   17.13 +#endif	// TIMER_H_