dungeon_crawler
changeset 48:aa9e28670ae2
added sound playback, more to do
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 17 Sep 2012 08:40:59 +0300 |
parents | d52711f2b9a1 |
children | 303743485aba |
files | prototype/Makefile.in prototype/kdtree/kdtree.c prototype/kdtree/kdtree.h prototype/src/audio/audio.cc prototype/src/audio/audio.h prototype/src/audio/auman.cc prototype/src/audio/auman.h prototype/src/audio/sample.cc prototype/src/audio/sample.h prototype/src/audio/source.cc prototype/src/audio/source.h prototype/src/camera.cc prototype/src/camera.h prototype/src/dataset.h prototype/src/level.cc prototype/src/level.h prototype/src/main.cc prototype/src/material.cc prototype/src/material.h prototype/src/texman.cc prototype/src/texman.h prototype/src/texture.cc prototype/src/texture.h prototype/src/tile.cc prototype/src/tile.h prototype/src/tileset.cc prototype/src/tileset.h |
diffstat | 27 files changed, 1473 insertions(+), 117 deletions(-) [+] |
line diff
1.1 --- a/prototype/Makefile.in Sun Sep 16 08:16:50 2012 +0300 1.2 +++ b/prototype/Makefile.in Mon Sep 17 08:40:59 2012 +0300 1.3 @@ -1,6 +1,7 @@ 1.4 csrc = $(wildcard src/*.c) \ 1.5 $(wildcard vmath/*.c) \ 1.6 - $(wildcard drawtext/*.c) 1.7 + $(wildcard drawtext/*.c) \ 1.8 + $(wildcard kdtree/*.c) 1.9 1.10 ccsrc = $(wildcard src/*.cc) \ 1.11 $(wildcard src/audio/*.cc) \ 1.12 @@ -12,7 +13,7 @@ 1.13 1.14 warn = -Wall -Wno-format-extra-args -Wno-char-subscripts 1.15 1.16 -inc = -I. -Isrc/audio -Ivmath -Idrawtext `pkg-config --cflags freetype2` 1.17 +inc = -I. -Isrc -Ivmath -Idrawtext -Ikdtree `pkg-config --cflags freetype2` 1.18 1.19 CFLAGS = -pedantic $(warn) $(dbg) $(opt) $(inc) 1.20 CXXFLAGS = $(CFLAGS) $(cxx11_cflags)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/prototype/kdtree/kdtree.c Mon Sep 17 08:40:59 2012 +0300 2.3 @@ -0,0 +1,840 @@ 2.4 +/* 2.5 +This file is part of ``kdtree'', a library for working with kd-trees. 2.6 +Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org> 2.7 + 2.8 +Redistribution and use in source and binary forms, with or without 2.9 +modification, are permitted provided that the following conditions are met: 2.10 + 2.11 +1. Redistributions of source code must retain the above copyright notice, this 2.12 + list of conditions and the following disclaimer. 2.13 +2. Redistributions in binary form must reproduce the above copyright notice, 2.14 + this list of conditions and the following disclaimer in the documentation 2.15 + and/or other materials provided with the distribution. 2.16 +3. The name of the author may not be used to endorse or promote products 2.17 + derived from this software without specific prior written permission. 2.18 + 2.19 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 2.20 +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2.21 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 2.22 +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2.23 +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 2.24 +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2.25 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2.26 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2.27 +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 2.28 +OF SUCH DAMAGE. 2.29 +*/ 2.30 +/* single nearest neighbor search written by Tamas Nepusz <tamas@cs.rhul.ac.uk> */ 2.31 +#include <stdio.h> 2.32 +#include <stdlib.h> 2.33 +#include <string.h> 2.34 +#include <math.h> 2.35 +#include "kdtree.h" 2.36 + 2.37 +#define USE_LIST_NODE_ALLOCATOR 2.38 +#define NO_PTHREADS 2.39 +#define I_WANT_THREAD_BUGS 2.40 + 2.41 +#if defined(WIN32) || defined(__WIN32__) 2.42 +#include <malloc.h> 2.43 +#endif 2.44 + 2.45 +#ifdef USE_LIST_NODE_ALLOCATOR 2.46 + 2.47 +#ifndef NO_PTHREADS 2.48 +#include <pthread.h> 2.49 +#else 2.50 + 2.51 +#ifndef I_WANT_THREAD_BUGS 2.52 +#error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads." 2.53 +#endif /* I want thread bugs */ 2.54 + 2.55 +#endif /* pthread support */ 2.56 +#endif /* use list node allocator */ 2.57 + 2.58 +struct kdhyperrect { 2.59 + int dim; 2.60 + double *min, *max; /* minimum/maximum coords */ 2.61 +}; 2.62 + 2.63 +struct kdnode { 2.64 + double *pos; 2.65 + int dir; 2.66 + void *data; 2.67 + 2.68 + struct kdnode *left, *right; /* negative/positive side */ 2.69 +}; 2.70 + 2.71 +struct res_node { 2.72 + struct kdnode *item; 2.73 + double dist_sq; 2.74 + struct res_node *next; 2.75 +}; 2.76 + 2.77 +struct kdtree { 2.78 + int dim; 2.79 + struct kdnode *root; 2.80 + struct kdhyperrect *rect; 2.81 + void (*destr)(void*); 2.82 +}; 2.83 + 2.84 +struct kdres { 2.85 + struct kdtree *tree; 2.86 + struct res_node *rlist, *riter; 2.87 + int size; 2.88 +}; 2.89 + 2.90 +#define SQ(x) ((x) * (x)) 2.91 + 2.92 + 2.93 +static void clear_rec(struct kdnode *node, void (*destr)(void*)); 2.94 +static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim); 2.95 +static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq); 2.96 +static void clear_results(struct kdres *set); 2.97 + 2.98 +static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max); 2.99 +static void hyperrect_free(struct kdhyperrect *rect); 2.100 +static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect); 2.101 +static void hyperrect_extend(struct kdhyperrect *rect, const double *pos); 2.102 +static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos); 2.103 + 2.104 +#ifdef USE_LIST_NODE_ALLOCATOR 2.105 +static struct res_node *alloc_resnode(void); 2.106 +static void free_resnode(struct res_node*); 2.107 +#else 2.108 +#define alloc_resnode() malloc(sizeof(struct res_node)) 2.109 +#define free_resnode(n) free(n) 2.110 +#endif 2.111 + 2.112 + 2.113 + 2.114 +struct kdtree *kd_create(int k) 2.115 +{ 2.116 + struct kdtree *tree; 2.117 + 2.118 + if(!(tree = malloc(sizeof *tree))) { 2.119 + return 0; 2.120 + } 2.121 + 2.122 + tree->dim = k; 2.123 + tree->root = 0; 2.124 + tree->destr = 0; 2.125 + tree->rect = 0; 2.126 + 2.127 + return tree; 2.128 +} 2.129 + 2.130 +void kd_free(struct kdtree *tree) 2.131 +{ 2.132 + if(tree) { 2.133 + kd_clear(tree); 2.134 + free(tree); 2.135 + } 2.136 +} 2.137 + 2.138 +static void clear_rec(struct kdnode *node, void (*destr)(void*)) 2.139 +{ 2.140 + if(!node) return; 2.141 + 2.142 + clear_rec(node->left, destr); 2.143 + clear_rec(node->right, destr); 2.144 + 2.145 + if(destr) { 2.146 + destr(node->data); 2.147 + } 2.148 + free(node->pos); 2.149 + free(node); 2.150 +} 2.151 + 2.152 +void kd_clear(struct kdtree *tree) 2.153 +{ 2.154 + clear_rec(tree->root, tree->destr); 2.155 + tree->root = 0; 2.156 + 2.157 + if (tree->rect) { 2.158 + hyperrect_free(tree->rect); 2.159 + tree->rect = 0; 2.160 + } 2.161 +} 2.162 + 2.163 +void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)) 2.164 +{ 2.165 + tree->destr = destr; 2.166 +} 2.167 + 2.168 + 2.169 +static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim) 2.170 +{ 2.171 + int new_dir; 2.172 + struct kdnode *node; 2.173 + 2.174 + if(!*nptr) { 2.175 + if(!(node = malloc(sizeof *node))) { 2.176 + return -1; 2.177 + } 2.178 + if(!(node->pos = malloc(dim * sizeof *node->pos))) { 2.179 + free(node); 2.180 + return -1; 2.181 + } 2.182 + memcpy(node->pos, pos, dim * sizeof *node->pos); 2.183 + node->data = data; 2.184 + node->dir = dir; 2.185 + node->left = node->right = 0; 2.186 + *nptr = node; 2.187 + return 0; 2.188 + } 2.189 + 2.190 + node = *nptr; 2.191 + new_dir = (node->dir + 1) % dim; 2.192 + if(pos[node->dir] < node->pos[node->dir]) { 2.193 + return insert_rec(&(*nptr)->left, pos, data, new_dir, dim); 2.194 + } 2.195 + return insert_rec(&(*nptr)->right, pos, data, new_dir, dim); 2.196 +} 2.197 + 2.198 +int kd_insert(struct kdtree *tree, const double *pos, void *data) 2.199 +{ 2.200 + if (insert_rec(&tree->root, pos, data, 0, tree->dim)) { 2.201 + return -1; 2.202 + } 2.203 + 2.204 + if (tree->rect == 0) { 2.205 + tree->rect = hyperrect_create(tree->dim, pos, pos); 2.206 + } else { 2.207 + hyperrect_extend(tree->rect, pos); 2.208 + } 2.209 + 2.210 + return 0; 2.211 +} 2.212 + 2.213 +int kd_insertf(struct kdtree *tree, const float *pos, void *data) 2.214 +{ 2.215 + static double sbuf[16]; 2.216 + double *bptr, *buf = 0; 2.217 + int res, dim = tree->dim; 2.218 + 2.219 + if(dim > 16) { 2.220 +#ifndef NO_ALLOCA 2.221 + if(dim <= 256) 2.222 + bptr = buf = alloca(dim * sizeof *bptr); 2.223 + else 2.224 +#endif 2.225 + if(!(bptr = buf = malloc(dim * sizeof *bptr))) { 2.226 + return -1; 2.227 + } 2.228 + } else { 2.229 + bptr = buf = sbuf; 2.230 + } 2.231 + 2.232 + while(dim-- > 0) { 2.233 + *bptr++ = *pos++; 2.234 + } 2.235 + 2.236 + res = kd_insert(tree, buf, data); 2.237 +#ifndef NO_ALLOCA 2.238 + if(tree->dim > 256) 2.239 +#else 2.240 + if(tree->dim > 16) 2.241 +#endif 2.242 + free(buf); 2.243 + return res; 2.244 +} 2.245 + 2.246 +int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data) 2.247 +{ 2.248 + double buf[3]; 2.249 + buf[0] = x; 2.250 + buf[1] = y; 2.251 + buf[2] = z; 2.252 + return kd_insert(tree, buf, data); 2.253 +} 2.254 + 2.255 +int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data) 2.256 +{ 2.257 + double buf[3]; 2.258 + buf[0] = x; 2.259 + buf[1] = y; 2.260 + buf[2] = z; 2.261 + return kd_insert(tree, buf, data); 2.262 +} 2.263 + 2.264 +static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim) 2.265 +{ 2.266 + double dist_sq, dx; 2.267 + int i, ret, added_res = 0; 2.268 + 2.269 + if(!node) return 0; 2.270 + 2.271 + dist_sq = 0; 2.272 + for(i=0; i<dim; i++) { 2.273 + dist_sq += SQ(node->pos[i] - pos[i]); 2.274 + } 2.275 + if(dist_sq <= SQ(range)) { 2.276 + if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) { 2.277 + return -1; 2.278 + } 2.279 + added_res = 1; 2.280 + } 2.281 + 2.282 + dx = pos[node->dir] - node->pos[node->dir]; 2.283 + 2.284 + ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim); 2.285 + if(ret >= 0 && fabs(dx) < range) { 2.286 + added_res += ret; 2.287 + ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim); 2.288 + } 2.289 + if(ret == -1) { 2.290 + return -1; 2.291 + } 2.292 + added_res += ret; 2.293 + 2.294 + return added_res; 2.295 +} 2.296 + 2.297 +#if 0 2.298 +static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim) 2.299 +{ 2.300 + double dist_sq, dx; 2.301 + int i, ret, added_res = 0; 2.302 + 2.303 + if(!node) return 0; 2.304 + 2.305 + /* if the photon is close enough, add it to the result heap */ 2.306 + dist_sq = 0; 2.307 + for(i=0; i<dim; i++) { 2.308 + dist_sq += SQ(node->pos[i] - pos[i]); 2.309 + } 2.310 + if(dist_sq <= range_sq) { 2.311 + if(heap->size >= num) { 2.312 + /* get furthest element */ 2.313 + struct res_node *maxelem = rheap_get_max(heap); 2.314 + 2.315 + /* and check if the new one is closer than that */ 2.316 + if(maxelem->dist_sq > dist_sq) { 2.317 + rheap_remove_max(heap); 2.318 + 2.319 + if(rheap_insert(heap, node, dist_sq) == -1) { 2.320 + return -1; 2.321 + } 2.322 + added_res = 1; 2.323 + 2.324 + range_sq = dist_sq; 2.325 + } 2.326 + } else { 2.327 + if(rheap_insert(heap, node, dist_sq) == -1) { 2.328 + return =1; 2.329 + } 2.330 + added_res = 1; 2.331 + } 2.332 + } 2.333 + 2.334 + 2.335 + /* find signed distance from the splitting plane */ 2.336 + dx = pos[node->dir] - node->pos[node->dir]; 2.337 + 2.338 + ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim); 2.339 + if(ret >= 0 && fabs(dx) < range) { 2.340 + added_res += ret; 2.341 + ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim); 2.342 + } 2.343 + 2.344 +} 2.345 +#endif 2.346 + 2.347 +static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect) 2.348 +{ 2.349 + int dir = node->dir; 2.350 + int i; 2.351 + double dummy, dist_sq; 2.352 + struct kdnode *nearer_subtree, *farther_subtree; 2.353 + double *nearer_hyperrect_coord, *farther_hyperrect_coord; 2.354 + 2.355 + /* Decide whether to go left or right in the tree */ 2.356 + dummy = pos[dir] - node->pos[dir]; 2.357 + if (dummy <= 0) { 2.358 + nearer_subtree = node->left; 2.359 + farther_subtree = node->right; 2.360 + nearer_hyperrect_coord = rect->max + dir; 2.361 + farther_hyperrect_coord = rect->min + dir; 2.362 + } else { 2.363 + nearer_subtree = node->right; 2.364 + farther_subtree = node->left; 2.365 + nearer_hyperrect_coord = rect->min + dir; 2.366 + farther_hyperrect_coord = rect->max + dir; 2.367 + } 2.368 + 2.369 + if (nearer_subtree) { 2.370 + /* Slice the hyperrect to get the hyperrect of the nearer subtree */ 2.371 + dummy = *nearer_hyperrect_coord; 2.372 + *nearer_hyperrect_coord = node->pos[dir]; 2.373 + /* Recurse down into nearer subtree */ 2.374 + kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect); 2.375 + /* Undo the slice */ 2.376 + *nearer_hyperrect_coord = dummy; 2.377 + } 2.378 + 2.379 + /* Check the distance of the point at the current node, compare it 2.380 + * with our best so far */ 2.381 + dist_sq = 0; 2.382 + for(i=0; i < rect->dim; i++) { 2.383 + dist_sq += SQ(node->pos[i] - pos[i]); 2.384 + } 2.385 + if (dist_sq < *result_dist_sq) { 2.386 + *result = node; 2.387 + *result_dist_sq = dist_sq; 2.388 + } 2.389 + 2.390 + if (farther_subtree) { 2.391 + /* Get the hyperrect of the farther subtree */ 2.392 + dummy = *farther_hyperrect_coord; 2.393 + *farther_hyperrect_coord = node->pos[dir]; 2.394 + /* Check if we have to recurse down by calculating the closest 2.395 + * point of the hyperrect and see if it's closer than our 2.396 + * minimum distance in result_dist_sq. */ 2.397 + if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) { 2.398 + /* Recurse down into farther subtree */ 2.399 + kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect); 2.400 + } 2.401 + /* Undo the slice on the hyperrect */ 2.402 + *farther_hyperrect_coord = dummy; 2.403 + } 2.404 +} 2.405 + 2.406 +struct kdres *kd_nearest(struct kdtree *kd, const double *pos) 2.407 +{ 2.408 + struct kdhyperrect *rect; 2.409 + struct kdnode *result; 2.410 + struct kdres *rset; 2.411 + double dist_sq; 2.412 + int i; 2.413 + 2.414 + if (!kd) return 0; 2.415 + if (!kd->rect) return 0; 2.416 + 2.417 + /* Allocate result set */ 2.418 + if(!(rset = malloc(sizeof *rset))) { 2.419 + return 0; 2.420 + } 2.421 + if(!(rset->rlist = alloc_resnode())) { 2.422 + free(rset); 2.423 + return 0; 2.424 + } 2.425 + rset->rlist->next = 0; 2.426 + rset->tree = kd; 2.427 + 2.428 + /* Duplicate the bounding hyperrectangle, we will work on the copy */ 2.429 + if (!(rect = hyperrect_duplicate(kd->rect))) { 2.430 + kd_res_free(rset); 2.431 + return 0; 2.432 + } 2.433 + 2.434 + /* Our first guesstimate is the root node */ 2.435 + result = kd->root; 2.436 + dist_sq = 0; 2.437 + for (i = 0; i < kd->dim; i++) 2.438 + dist_sq += SQ(result->pos[i] - pos[i]); 2.439 + 2.440 + /* Search for the nearest neighbour recursively */ 2.441 + kd_nearest_i(kd->root, pos, &result, &dist_sq, rect); 2.442 + 2.443 + /* Free the copy of the hyperrect */ 2.444 + hyperrect_free(rect); 2.445 + 2.446 + /* Store the result */ 2.447 + if (result) { 2.448 + if (rlist_insert(rset->rlist, result, -1.0) == -1) { 2.449 + kd_res_free(rset); 2.450 + return 0; 2.451 + } 2.452 + rset->size = 1; 2.453 + kd_res_rewind(rset); 2.454 + return rset; 2.455 + } else { 2.456 + kd_res_free(rset); 2.457 + return 0; 2.458 + } 2.459 +} 2.460 + 2.461 +struct kdres *kd_nearestf(struct kdtree *tree, const float *pos) 2.462 +{ 2.463 + static double sbuf[16]; 2.464 + double *bptr, *buf = 0; 2.465 + int dim = tree->dim; 2.466 + struct kdres *res; 2.467 + 2.468 + if(dim > 16) { 2.469 +#ifndef NO_ALLOCA 2.470 + if(dim <= 256) 2.471 + bptr = buf = alloca(dim * sizeof *bptr); 2.472 + else 2.473 +#endif 2.474 + if(!(bptr = buf = malloc(dim * sizeof *bptr))) { 2.475 + return 0; 2.476 + } 2.477 + } else { 2.478 + bptr = buf = sbuf; 2.479 + } 2.480 + 2.481 + while(dim-- > 0) { 2.482 + *bptr++ = *pos++; 2.483 + } 2.484 + 2.485 + res = kd_nearest(tree, buf); 2.486 +#ifndef NO_ALLOCA 2.487 + if(tree->dim > 256) 2.488 +#else 2.489 + if(tree->dim > 16) 2.490 +#endif 2.491 + free(buf); 2.492 + return res; 2.493 +} 2.494 + 2.495 +struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z) 2.496 +{ 2.497 + double pos[3]; 2.498 + pos[0] = x; 2.499 + pos[1] = y; 2.500 + pos[2] = z; 2.501 + return kd_nearest(tree, pos); 2.502 +} 2.503 + 2.504 +struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z) 2.505 +{ 2.506 + double pos[3]; 2.507 + pos[0] = x; 2.508 + pos[1] = y; 2.509 + pos[2] = z; 2.510 + return kd_nearest(tree, pos); 2.511 +} 2.512 + 2.513 +/* ---- nearest N search ---- */ 2.514 +/* 2.515 +static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) 2.516 +{ 2.517 + int ret; 2.518 + struct kdres *rset; 2.519 + 2.520 + if(!(rset = malloc(sizeof *rset))) { 2.521 + return 0; 2.522 + } 2.523 + if(!(rset->rlist = alloc_resnode())) { 2.524 + free(rset); 2.525 + return 0; 2.526 + } 2.527 + rset->rlist->next = 0; 2.528 + rset->tree = kd; 2.529 + 2.530 + if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) { 2.531 + kd_res_free(rset); 2.532 + return 0; 2.533 + } 2.534 + rset->size = ret; 2.535 + kd_res_rewind(rset); 2.536 + return rset; 2.537 +}*/ 2.538 + 2.539 +struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range) 2.540 +{ 2.541 + int ret; 2.542 + struct kdres *rset; 2.543 + 2.544 + if(!(rset = malloc(sizeof *rset))) { 2.545 + return 0; 2.546 + } 2.547 + if(!(rset->rlist = alloc_resnode())) { 2.548 + free(rset); 2.549 + return 0; 2.550 + } 2.551 + rset->rlist->next = 0; 2.552 + rset->tree = kd; 2.553 + 2.554 + if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) { 2.555 + kd_res_free(rset); 2.556 + return 0; 2.557 + } 2.558 + rset->size = ret; 2.559 + kd_res_rewind(rset); 2.560 + return rset; 2.561 +} 2.562 + 2.563 +struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range) 2.564 +{ 2.565 + static double sbuf[16]; 2.566 + double *bptr, *buf = 0; 2.567 + int dim = kd->dim; 2.568 + struct kdres *res; 2.569 + 2.570 + if(dim > 16) { 2.571 +#ifndef NO_ALLOCA 2.572 + if(dim <= 256) 2.573 + bptr = buf = alloca(dim * sizeof *bptr); 2.574 + else 2.575 +#endif 2.576 + if(!(bptr = buf = malloc(dim * sizeof *bptr))) { 2.577 + return 0; 2.578 + } 2.579 + } else { 2.580 + bptr = buf = sbuf; 2.581 + } 2.582 + 2.583 + while(dim-- > 0) { 2.584 + *bptr++ = *pos++; 2.585 + } 2.586 + 2.587 + res = kd_nearest_range(kd, buf, range); 2.588 +#ifndef NO_ALLOCA 2.589 + if(kd->dim > 256) 2.590 +#else 2.591 + if(kd->dim > 16) 2.592 +#endif 2.593 + free(buf); 2.594 + return res; 2.595 +} 2.596 + 2.597 +struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range) 2.598 +{ 2.599 + double buf[3]; 2.600 + buf[0] = x; 2.601 + buf[1] = y; 2.602 + buf[2] = z; 2.603 + return kd_nearest_range(tree, buf, range); 2.604 +} 2.605 + 2.606 +struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range) 2.607 +{ 2.608 + double buf[3]; 2.609 + buf[0] = x; 2.610 + buf[1] = y; 2.611 + buf[2] = z; 2.612 + return kd_nearest_range(tree, buf, range); 2.613 +} 2.614 + 2.615 +void kd_res_free(struct kdres *rset) 2.616 +{ 2.617 + clear_results(rset); 2.618 + free_resnode(rset->rlist); 2.619 + free(rset); 2.620 +} 2.621 + 2.622 +int kd_res_size(struct kdres *set) 2.623 +{ 2.624 + return (set->size); 2.625 +} 2.626 + 2.627 +void kd_res_rewind(struct kdres *rset) 2.628 +{ 2.629 + rset->riter = rset->rlist->next; 2.630 +} 2.631 + 2.632 +int kd_res_end(struct kdres *rset) 2.633 +{ 2.634 + return rset->riter == 0; 2.635 +} 2.636 + 2.637 +int kd_res_next(struct kdres *rset) 2.638 +{ 2.639 + rset->riter = rset->riter->next; 2.640 + return rset->riter != 0; 2.641 +} 2.642 + 2.643 +void *kd_res_item(struct kdres *rset, double *pos) 2.644 +{ 2.645 + if(rset->riter) { 2.646 + if(pos) { 2.647 + memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos); 2.648 + } 2.649 + return rset->riter->item->data; 2.650 + } 2.651 + return 0; 2.652 +} 2.653 + 2.654 +void *kd_res_itemf(struct kdres *rset, float *pos) 2.655 +{ 2.656 + if(rset->riter) { 2.657 + if(pos) { 2.658 + int i; 2.659 + for(i=0; i<rset->tree->dim; i++) { 2.660 + pos[i] = rset->riter->item->pos[i]; 2.661 + } 2.662 + } 2.663 + return rset->riter->item->data; 2.664 + } 2.665 + return 0; 2.666 +} 2.667 + 2.668 +void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z) 2.669 +{ 2.670 + if(rset->riter) { 2.671 + if(*x) *x = rset->riter->item->pos[0]; 2.672 + if(*y) *y = rset->riter->item->pos[1]; 2.673 + if(*z) *z = rset->riter->item->pos[2]; 2.674 + } 2.675 + return 0; 2.676 +} 2.677 + 2.678 +void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z) 2.679 +{ 2.680 + if(rset->riter) { 2.681 + if(*x) *x = rset->riter->item->pos[0]; 2.682 + if(*y) *y = rset->riter->item->pos[1]; 2.683 + if(*z) *z = rset->riter->item->pos[2]; 2.684 + } 2.685 + return 0; 2.686 +} 2.687 + 2.688 +void *kd_res_item_data(struct kdres *set) 2.689 +{ 2.690 + return kd_res_item(set, 0); 2.691 +} 2.692 + 2.693 +/* ---- hyperrectangle helpers ---- */ 2.694 +static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max) 2.695 +{ 2.696 + size_t size = dim * sizeof(double); 2.697 + struct kdhyperrect* rect = 0; 2.698 + 2.699 + if (!(rect = malloc(sizeof(struct kdhyperrect)))) { 2.700 + return 0; 2.701 + } 2.702 + 2.703 + rect->dim = dim; 2.704 + if (!(rect->min = malloc(size))) { 2.705 + free(rect); 2.706 + return 0; 2.707 + } 2.708 + if (!(rect->max = malloc(size))) { 2.709 + free(rect->min); 2.710 + free(rect); 2.711 + return 0; 2.712 + } 2.713 + memcpy(rect->min, min, size); 2.714 + memcpy(rect->max, max, size); 2.715 + 2.716 + return rect; 2.717 +} 2.718 + 2.719 +static void hyperrect_free(struct kdhyperrect *rect) 2.720 +{ 2.721 + free(rect->min); 2.722 + free(rect->max); 2.723 + free(rect); 2.724 +} 2.725 + 2.726 +static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect) 2.727 +{ 2.728 + return hyperrect_create(rect->dim, rect->min, rect->max); 2.729 +} 2.730 + 2.731 +static void hyperrect_extend(struct kdhyperrect *rect, const double *pos) 2.732 +{ 2.733 + int i; 2.734 + 2.735 + for (i=0; i < rect->dim; i++) { 2.736 + if (pos[i] < rect->min[i]) { 2.737 + rect->min[i] = pos[i]; 2.738 + } 2.739 + if (pos[i] > rect->max[i]) { 2.740 + rect->max[i] = pos[i]; 2.741 + } 2.742 + } 2.743 +} 2.744 + 2.745 +static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos) 2.746 +{ 2.747 + int i; 2.748 + double result = 0; 2.749 + 2.750 + for (i=0; i < rect->dim; i++) { 2.751 + if (pos[i] < rect->min[i]) { 2.752 + result += SQ(rect->min[i] - pos[i]); 2.753 + } else if (pos[i] > rect->max[i]) { 2.754 + result += SQ(rect->max[i] - pos[i]); 2.755 + } 2.756 + } 2.757 + 2.758 + return result; 2.759 +} 2.760 + 2.761 +/* ---- static helpers ---- */ 2.762 + 2.763 +#ifdef USE_LIST_NODE_ALLOCATOR 2.764 +/* special list node allocators. */ 2.765 +static struct res_node *free_nodes; 2.766 + 2.767 +#ifndef NO_PTHREADS 2.768 +static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER; 2.769 +#endif 2.770 + 2.771 +static struct res_node *alloc_resnode(void) 2.772 +{ 2.773 + struct res_node *node; 2.774 + 2.775 +#ifndef NO_PTHREADS 2.776 + pthread_mutex_lock(&alloc_mutex); 2.777 +#endif 2.778 + 2.779 + if(!free_nodes) { 2.780 + node = malloc(sizeof *node); 2.781 + } else { 2.782 + node = free_nodes; 2.783 + free_nodes = free_nodes->next; 2.784 + node->next = 0; 2.785 + } 2.786 + 2.787 +#ifndef NO_PTHREADS 2.788 + pthread_mutex_unlock(&alloc_mutex); 2.789 +#endif 2.790 + 2.791 + return node; 2.792 +} 2.793 + 2.794 +static void free_resnode(struct res_node *node) 2.795 +{ 2.796 +#ifndef NO_PTHREADS 2.797 + pthread_mutex_lock(&alloc_mutex); 2.798 +#endif 2.799 + 2.800 + node->next = free_nodes; 2.801 + free_nodes = node; 2.802 + 2.803 +#ifndef NO_PTHREADS 2.804 + pthread_mutex_unlock(&alloc_mutex); 2.805 +#endif 2.806 +} 2.807 +#endif /* list node allocator or not */ 2.808 + 2.809 + 2.810 +/* inserts the item. if dist_sq is >= 0, then do an ordered insert */ 2.811 +/* TODO make the ordering code use heapsort */ 2.812 +static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq) 2.813 +{ 2.814 + struct res_node *rnode; 2.815 + 2.816 + if(!(rnode = alloc_resnode())) { 2.817 + return -1; 2.818 + } 2.819 + rnode->item = item; 2.820 + rnode->dist_sq = dist_sq; 2.821 + 2.822 + if(dist_sq >= 0.0) { 2.823 + while(list->next && list->next->dist_sq < dist_sq) { 2.824 + list = list->next; 2.825 + } 2.826 + } 2.827 + rnode->next = list->next; 2.828 + list->next = rnode; 2.829 + return 0; 2.830 +} 2.831 + 2.832 +static void clear_results(struct kdres *rset) 2.833 +{ 2.834 + struct res_node *tmp, *node = rset->rlist->next; 2.835 + 2.836 + while(node) { 2.837 + tmp = node; 2.838 + node = node->next; 2.839 + free_resnode(tmp); 2.840 + } 2.841 + 2.842 + rset->rlist->next = 0; 2.843 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/prototype/kdtree/kdtree.h Mon Sep 17 08:40:59 2012 +0300 3.3 @@ -0,0 +1,129 @@ 3.4 +/* 3.5 +This file is part of ``kdtree'', a library for working with kd-trees. 3.6 +Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org> 3.7 + 3.8 +Redistribution and use in source and binary forms, with or without 3.9 +modification, are permitted provided that the following conditions are met: 3.10 + 3.11 +1. Redistributions of source code must retain the above copyright notice, this 3.12 + list of conditions and the following disclaimer. 3.13 +2. Redistributions in binary form must reproduce the above copyright notice, 3.14 + this list of conditions and the following disclaimer in the documentation 3.15 + and/or other materials provided with the distribution. 3.16 +3. The name of the author may not be used to endorse or promote products 3.17 + derived from this software without specific prior written permission. 3.18 + 3.19 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 3.20 +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 3.21 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 3.22 +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 3.23 +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 3.24 +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3.25 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3.26 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3.27 +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 3.28 +OF SUCH DAMAGE. 3.29 +*/ 3.30 +#ifndef _KDTREE_H_ 3.31 +#define _KDTREE_H_ 3.32 + 3.33 +#ifdef __cplusplus 3.34 +extern "C" { 3.35 +#endif 3.36 + 3.37 +struct kdtree; 3.38 +struct kdres; 3.39 + 3.40 + 3.41 +/* create a kd-tree for "k"-dimensional data */ 3.42 +struct kdtree *kd_create(int k); 3.43 + 3.44 +/* free the struct kdtree */ 3.45 +void kd_free(struct kdtree *tree); 3.46 + 3.47 +/* remove all the elements from the tree */ 3.48 +void kd_clear(struct kdtree *tree); 3.49 + 3.50 +/* if called with non-null 2nd argument, the function provided 3.51 + * will be called on data pointers (see kd_insert) when nodes 3.52 + * are to be removed from the tree. 3.53 + */ 3.54 +void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)); 3.55 + 3.56 +/* insert a node, specifying its position, and optional data */ 3.57 +int kd_insert(struct kdtree *tree, const double *pos, void *data); 3.58 +int kd_insertf(struct kdtree *tree, const float *pos, void *data); 3.59 +int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data); 3.60 +int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data); 3.61 + 3.62 +/* Find the nearest node from a given point. 3.63 + * 3.64 + * This function returns a pointer to a result set with at most one element. 3.65 + */ 3.66 +struct kdres *kd_nearest(struct kdtree *tree, const double *pos); 3.67 +struct kdres *kd_nearestf(struct kdtree *tree, const float *pos); 3.68 +struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z); 3.69 +struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z); 3.70 + 3.71 +/* Find the N nearest nodes from a given point. 3.72 + * 3.73 + * This function returns a pointer to a result set, with at most N elements, 3.74 + * which can be manipulated with the kd_res_* functions. 3.75 + * The returned pointer can be null as an indication of an error. Otherwise 3.76 + * a valid result set is always returned which may contain 0 or more elements. 3.77 + * The result set must be deallocated with kd_res_free after use. 3.78 + */ 3.79 +/* 3.80 +struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num); 3.81 +struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num); 3.82 +struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z); 3.83 +struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z); 3.84 +*/ 3.85 + 3.86 +/* Find any nearest nodes from a given point within a range. 3.87 + * 3.88 + * This function returns a pointer to a result set, which can be manipulated 3.89 + * by the kd_res_* functions. 3.90 + * The returned pointer can be null as an indication of an error. Otherwise 3.91 + * a valid result set is always returned which may contain 0 or more elements. 3.92 + * The result set must be deallocated with kd_res_free after use. 3.93 + */ 3.94 +struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range); 3.95 +struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range); 3.96 +struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range); 3.97 +struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range); 3.98 + 3.99 +/* frees a result set returned by kd_nearest_range() */ 3.100 +void kd_res_free(struct kdres *set); 3.101 + 3.102 +/* returns the size of the result set (in elements) */ 3.103 +int kd_res_size(struct kdres *set); 3.104 + 3.105 +/* rewinds the result set iterator */ 3.106 +void kd_res_rewind(struct kdres *set); 3.107 + 3.108 +/* returns non-zero if the set iterator reached the end after the last element */ 3.109 +int kd_res_end(struct kdres *set); 3.110 + 3.111 +/* advances the result set iterator, returns non-zero on success, zero if 3.112 + * there are no more elements in the result set. 3.113 + */ 3.114 +int kd_res_next(struct kdres *set); 3.115 + 3.116 +/* returns the data pointer (can be null) of the current result set item 3.117 + * and optionally sets its position to the pointers(s) if not null. 3.118 + */ 3.119 +void *kd_res_item(struct kdres *set, double *pos); 3.120 +void *kd_res_itemf(struct kdres *set, float *pos); 3.121 +void *kd_res_item3(struct kdres *set, double *x, double *y, double *z); 3.122 +void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z); 3.123 + 3.124 +/* equivalent to kd_res_item(set, 0) */ 3.125 +void *kd_res_item_data(struct kdres *set); 3.126 + 3.127 + 3.128 +#ifdef __cplusplus 3.129 +} 3.130 +#endif 3.131 + 3.132 +#endif /* _KDTREE_H_ */
4.1 --- a/prototype/src/audio/audio.cc Sun Sep 16 08:16:50 2012 +0300 4.2 +++ b/prototype/src/audio/audio.cc Mon Sep 17 08:40:59 2012 +0300 4.3 @@ -2,15 +2,6 @@ 4.4 #include "openal.h" 4.5 #include "audio.h" 4.6 4.7 -#define CHECK_ERROR \ 4.8 - do { \ 4.9 - unsigned int err = alGetError(); \ 4.10 - if(err != 0) { \ 4.11 - fprintf(stderr, "%s:%d: AL error: %#x\n", __FILE__, __LINE__, err); \ 4.12 - abort(); \ 4.13 - } \ 4.14 - } while(0) 4.15 - 4.16 static ALCdevice *dev; 4.17 static ALCcontext *ctx; 4.18
5.1 --- a/prototype/src/audio/audio.h Sun Sep 16 08:16:50 2012 +0300 5.2 +++ b/prototype/src/audio/audio.h Mon Sep 17 08:40:59 2012 +0300 5.3 @@ -4,5 +4,4 @@ 5.4 bool init_audio(); 5.5 void destroy_audio(); 5.6 5.7 - 5.8 #endif /* AUDIO_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/prototype/src/audio/auman.cc Mon Sep 17 08:40:59 2012 +0300 6.3 @@ -0,0 +1,68 @@ 6.4 +#include <algorithm> 6.5 +#include <new> 6.6 +#include "auman.h" 6.7 + 6.8 +AudioManager::AudioManager() 6.9 +{ 6.10 + if(!(sources = kd_create(3))) { 6.11 + fprintf(stderr, "failed to create kd tree\n"); 6.12 + throw std::bad_alloc(); 6.13 + } 6.14 +} 6.15 + 6.16 +AudioManager::~AudioManager() 6.17 +{ 6.18 + kd_free(sources); 6.19 +} 6.20 + 6.21 +void AudioManager::clear() 6.22 +{ 6.23 + kd_clear(sources); 6.24 + 6.25 + for(auto s : active_set) { 6.26 + s->stop(); 6.27 + } 6.28 + active_set.clear(); 6.29 +} 6.30 + 6.31 +void AudioManager::add_source(AudioSource *s) 6.32 +{ 6.33 + Vector3 pos = s->get_position(); 6.34 + if(kd_insert3f(sources, pos.x, pos.y, pos.z, s) == -1) { 6.35 + fprintf(stderr, "AudioManager: failed to add source!\n"); 6.36 + } 6.37 +} 6.38 + 6.39 +void AudioManager::active_range(const Vector3 &pos, float range) 6.40 +{ 6.41 + std::set<AudioSource*> newset; 6.42 + 6.43 + // find all the sources in the given range and construct newset. 6.44 + struct kdres *results = kd_nearest_range3f(sources, pos.x, pos.y, pos.z, range); 6.45 + while(!kd_res_end(results)) { 6.46 + newset.insert((AudioSource*)kd_res_item_data(results)); 6.47 + kd_res_next(results); 6.48 + } 6.49 + kd_res_free(results); 6.50 + 6.51 + /* for each of the currently active sources, if they're not in the 6.52 + * new set, stop the playback. 6.53 + */ 6.54 + for(auto s : active_set) { 6.55 + if(newset.find(s) == newset.end()) { 6.56 + s->stop(); 6.57 + } 6.58 + } 6.59 + 6.60 + /* for each of the new active sources not found in the currently active 6.61 + * set, start the playback. 6.62 + */ 6.63 + for(auto s : newset) { 6.64 + if(active_set.find(s) == active_set.end()) { 6.65 + s->play(); 6.66 + } 6.67 + } 6.68 + 6.69 + // swap the current with the new, previous current will be destroyed at end of scope 6.70 + std::swap(active_set, newset); 6.71 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/prototype/src/audio/auman.h Mon Sep 17 08:40:59 2012 +0300 7.3 @@ -0,0 +1,23 @@ 7.4 +#ifndef AUMAN_H_ 7.5 +#define AUMAN_H_ 7.6 + 7.7 +#include <set> 7.8 +#include "kdtree.h" 7.9 +#include "source.h" 7.10 + 7.11 +class AudioManager { 7.12 +private: 7.13 + struct kdtree *sources; 7.14 + std::set<AudioSource*> active_set; 7.15 + 7.16 +public: 7.17 + AudioManager(); 7.18 + ~AudioManager(); 7.19 + 7.20 + void clear(); 7.21 + void add_source(AudioSource *s); 7.22 + 7.23 + void active_range(const Vector3 &pos, float range); 7.24 +}; 7.25 + 7.26 +#endif // AUMAN_H_
8.1 --- a/prototype/src/audio/sample.cc Sun Sep 16 08:16:50 2012 +0300 8.2 +++ b/prototype/src/audio/sample.cc Mon Sep 17 08:40:59 2012 +0300 8.3 @@ -5,6 +5,17 @@ 8.4 #include "openal.h" 8.5 #include "sample.h" 8.6 8.7 + 8.8 +#define CHECK_ERROR \ 8.9 + do { \ 8.10 + unsigned int err = alGetError(); \ 8.11 + if(err != 0) { \ 8.12 + fprintf(stderr, "%s:%d: AL error: %#x\n", __FILE__, __LINE__, err); \ 8.13 + abort(); \ 8.14 + } \ 8.15 + } while(0) 8.16 + 8.17 + 8.18 AudioSample::AudioSample() 8.19 { 8.20 albuffer = 0; 8.21 @@ -36,7 +47,7 @@ 8.22 printf("loading sample: %s: %ld samples/s, %s (%d chan)\n", fname, vinfo->rate, 8.23 vinfo->channels == 1 ? "mono" : "stereo", vinfo->channels); 8.24 8.25 - long num_samples = ov_pcm_total(&vf, -1); 8.26 + long num_samples = ov_pcm_total(&vf, -1) * vinfo->channels; 8.27 int16_t *samples = new int16_t[num_samples]; 8.28 8.29 long bufsz = num_samples * sizeof *samples; 8.30 @@ -62,6 +73,7 @@ 8.31 } 8.32 8.33 alBufferData(bufobj, alfmt, samples, bufsz, vinfo->rate); 8.34 + CHECK_ERROR; 8.35 if(alGetError()) { 8.36 fprintf(stderr, "failed to load sample data into OpenAL buffer: %u\n", bufobj); 8.37 goto err; 8.38 @@ -82,3 +94,19 @@ 8.39 } 8.40 return false; 8.41 } 8.42 + 8.43 +AudioSample *load_audio_sample(const char *fname) 8.44 +{ 8.45 + AudioSample *s = new AudioSample; 8.46 + 8.47 + if(!s->load(fname)) { 8.48 + delete s; 8.49 + s = 0; 8.50 + } 8.51 + return s; 8.52 +} 8.53 + 8.54 +void destroy_audio_sample(AudioSample *s) 8.55 +{ 8.56 + delete s; 8.57 +}
9.1 --- a/prototype/src/audio/sample.h Sun Sep 16 08:16:50 2012 +0300 9.2 +++ b/prototype/src/audio/sample.h Mon Sep 17 08:40:59 2012 +0300 9.3 @@ -1,6 +1,8 @@ 9.4 #ifndef SAMPLE_H_ 9.5 #define SAMPLE_H_ 9.6 9.7 +#include "dataset.h" 9.8 + 9.9 class AudioSample { 9.10 private: 9.11 unsigned int albuffer; 9.12 @@ -12,6 +14,13 @@ 9.13 ~AudioSample(); 9.14 9.15 bool load(const char *fname); 9.16 + 9.17 + friend class AudioSource; 9.18 }; 9.19 9.20 +typedef DataSet<AudioSample*> SampleSet; 9.21 + 9.22 +AudioSample *load_audio_sample(const char *fname); 9.23 +void destroy_audio_sample(AudioSample *s); 9.24 + 9.25 #endif // SAMPLE_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/prototype/src/audio/source.cc Mon Sep 17 08:40:59 2012 +0300 10.3 @@ -0,0 +1,73 @@ 10.4 +#include "openal.h" 10.5 +#include "source.h" 10.6 + 10.7 +AudioSource::AudioSource() 10.8 +{ 10.9 + sample = 0; 10.10 + 10.11 + alGenSources(1, &alsrc); 10.12 + alSourcei(alsrc, AL_LOOPING, AL_TRUE); 10.13 +} 10.14 + 10.15 +AudioSource::~AudioSource() 10.16 +{ 10.17 + if(alsrc) { 10.18 + if(is_playing()) { 10.19 + stop(); 10.20 + } 10.21 + alDeleteSources(1, &alsrc); 10.22 + } 10.23 +} 10.24 + 10.25 +void AudioSource::set_sample(const AudioSample *sample) 10.26 +{ 10.27 + stop(); 10.28 + 10.29 + if(sample) { 10.30 + if(!sample->albuffer) { 10.31 + fprintf(stderr, "%s: trying to attach null buffer!\n", __FUNCTION__); 10.32 + return; 10.33 + } 10.34 + alSourcei(alsrc, AL_BUFFER, sample->albuffer); 10.35 + } 10.36 + this->sample = sample; 10.37 +} 10.38 + 10.39 +const AudioSample *AudioSource::get_sample() const 10.40 +{ 10.41 + return sample; 10.42 +} 10.43 + 10.44 +void AudioSource::set_position(const Vector3 &pos, bool viewspace) 10.45 +{ 10.46 + alSourcei(alsrc, AL_SOURCE_RELATIVE, viewspace ? AL_TRUE : AL_FALSE); 10.47 + alSource3f(alsrc, AL_POSITION, pos.x, pos.y, pos.z); 10.48 +} 10.49 + 10.50 +Vector3 AudioSource::get_position() const 10.51 +{ 10.52 + float pos[3]; 10.53 + alGetSourcefv(alsrc, AL_POSITION, pos); 10.54 + return Vector3(pos[0], pos[1], pos[2]); 10.55 +} 10.56 + 10.57 +bool AudioSource::is_playing() const 10.58 +{ 10.59 + int state; 10.60 + alGetSourcei(alsrc, AL_SOURCE_STATE, &state); 10.61 + return state == AL_PLAYING; 10.62 +} 10.63 + 10.64 +void AudioSource::play() 10.65 +{ 10.66 + if(sample) { 10.67 + alSourcePlay(alsrc); 10.68 + } 10.69 +} 10.70 + 10.71 +void AudioSource::stop() 10.72 +{ 10.73 + if(sample) { 10.74 + alSourceStop(alsrc); 10.75 + } 10.76 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/prototype/src/audio/source.h Mon Sep 17 08:40:59 2012 +0300 11.3 @@ -0,0 +1,27 @@ 11.4 +#ifndef SOURCE_H_ 11.5 +#define SOURCE_H_ 11.6 + 11.7 +#include "vmath/vmath.h" 11.8 +#include "sample.h" 11.9 + 11.10 +class AudioSource { 11.11 +private: 11.12 + unsigned int alsrc; 11.13 + const AudioSample *sample; 11.14 + 11.15 +public: 11.16 + AudioSource(); 11.17 + ~AudioSource(); 11.18 + 11.19 + void set_sample(const AudioSample *sample); 11.20 + const AudioSample *get_sample() const; 11.21 + 11.22 + void set_position(const Vector3 &pos, bool viewspace = false); 11.23 + Vector3 get_position() const; 11.24 + 11.25 + bool is_playing() const; 11.26 + void play(); 11.27 + void stop(); 11.28 +}; 11.29 + 11.30 +#endif // SOURCE_H_
12.1 --- a/prototype/src/camera.cc Sun Sep 16 08:16:50 2012 +0300 12.2 +++ b/prototype/src/camera.cc Mon Sep 17 08:40:59 2012 +0300 12.3 @@ -132,6 +132,10 @@ 12.4 inval_cache(); 12.5 } 12.6 12.7 +const Vector3 &FpsCamera::get_position() const 12.8 +{ 12.9 + return pos; 12.10 +} 12.11 12.12 12.13 FlyCamera::FlyCamera()
13.1 --- a/prototype/src/camera.h Sun Sep 16 08:16:50 2012 +0300 13.2 +++ b/prototype/src/camera.h Mon Sep 17 08:40:59 2012 +0300 13.3 @@ -56,6 +56,8 @@ 13.4 13.5 public: 13.6 void input_move(float x, float y, float z); 13.7 + 13.8 + const Vector3 &get_position() const; 13.9 }; 13.10 13.11 class FlyCamera : public Camera {
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/prototype/src/dataset.h Mon Sep 17 08:40:59 2012 +0300 14.3 @@ -0,0 +1,68 @@ 14.4 +#ifndef DATASET_H_ 14.5 +#define DATASET_H_ 14.6 + 14.7 +#include <string.h> 14.8 +#include <string> 14.9 +#include <map> 14.10 +#include <functional> 14.11 +#include "datapath.h" 14.12 + 14.13 +template <typename T> 14.14 +class DataSet { 14.15 +private: 14.16 + mutable std::map<std::string, T> data; 14.17 + 14.18 + std::function<T(const char*)> load; 14.19 + std::function<void(T)> destroy; 14.20 + 14.21 +public: 14.22 + DataSet(std::function<T(const char*)> load_func, std::function<void(T)> destr_func); 14.23 + ~DataSet(); 14.24 + 14.25 + T get(const char *name) const; 14.26 +}; 14.27 + 14.28 +template <typename T> 14.29 +DataSet<T>::DataSet(std::function<T(const char*)> load_func, std::function<void(T)> destr_func) 14.30 +{ 14.31 + load = load_func; 14.32 + destroy = destr_func; 14.33 +} 14.34 + 14.35 +template <typename T> 14.36 +DataSet<T>::~DataSet() 14.37 +{ 14.38 + if(destroy) { 14.39 + for(auto it : data) { 14.40 + destroy(it.second); 14.41 + } 14.42 + } 14.43 +} 14.44 + 14.45 +template <typename T> 14.46 +T DataSet<T>::get(const char *name) const 14.47 +{ 14.48 + auto iter = data.find(name); 14.49 + if(iter != data.end()) { 14.50 + return iter->second; 14.51 + } 14.52 + 14.53 + const char *path, *slash; 14.54 + if((slash = strrchr(name, '/'))) { 14.55 + path = slash + 1; 14.56 + } else { 14.57 + path = name; 14.58 + } 14.59 + if(!(path = datafile_path(path))) { 14.60 + fprintf(stderr, "can't find data file: %s\n", name); 14.61 + return 0; 14.62 + } 14.63 + 14.64 + T res = load(path); 14.65 + if(res) { 14.66 + data[name] = res; 14.67 + } 14.68 + return res; 14.69 +} 14.70 + 14.71 +#endif // DATASET_H_
15.1 --- a/prototype/src/level.cc Sun Sep 16 08:16:50 2012 +0300 15.2 +++ b/prototype/src/level.cc Mon Sep 17 08:40:59 2012 +0300 15.3 @@ -107,6 +107,14 @@ 15.4 return Vector3(posx, 0, posy); 15.5 } 15.6 15.7 +void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const 15.8 +{ 15.9 + float posx = pos.x + cell_size * (float)xsz / 2.0f; 15.10 + float posy = pos.z + cell_size * (float)ysz / 2.0f; 15.11 + *xptr = (int)round(posx / cell_size); 15.12 + *yptr = (int)round(posy / cell_size); 15.13 +} 15.14 + 15.15 unsigned int Level::get_cell_dirmask(int x, int y) const 15.16 { 15.17 unsigned int dmask = TILE_ALL; 15.18 @@ -229,6 +237,16 @@ 15.19 } 15.20 15.21 15.22 +AudioSample *Level::get_sample(int x, int y, int which) const 15.23 +{ 15.24 + const GridCell *cell = get_cell(x, y); 15.25 + if(!cell) { 15.26 + return 0; 15.27 + } 15.28 + return cell->get_sample(which); 15.29 +} 15.30 + 15.31 + 15.32 GridCell::GridCell(Tile *tile) 15.33 { 15.34 if(tile) { 15.35 @@ -285,3 +303,14 @@ 15.36 psys_draw(ps); 15.37 } 15.38 } 15.39 + 15.40 +AudioSample *GridCell::get_sample(int which) const 15.41 +{ 15.42 + for(auto tile : tiles) { 15.43 + AudioSample *s = tile->get_sample(which); 15.44 + if(s) { 15.45 + return s; 15.46 + } 15.47 + } 15.48 + return 0; 15.49 +}
16.1 --- a/prototype/src/level.h Sun Sep 16 08:16:50 2012 +0300 16.2 +++ b/prototype/src/level.h Mon Sep 17 08:40:59 2012 +0300 16.3 @@ -4,9 +4,9 @@ 16.4 #include <vector> 16.5 #include "vmath/vmath.h" 16.6 #include "psys/psys.h" 16.7 +#include "tile.h" 16.8 16.9 class GridCell; 16.10 -class Tile; 16.11 16.12 class Level { 16.13 private: 16.14 @@ -30,6 +30,7 @@ 16.15 16.16 const GridCell *get_cell(int x, int y) const; 16.17 Vector3 get_cell_pos(int x, int y) const; 16.18 + void get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const; 16.19 unsigned int get_cell_dirmask(int x, int y) const; 16.20 16.21 void update(unsigned long msec, float dt); 16.22 @@ -37,6 +38,8 @@ 16.23 void draw() const; 16.24 void draw_lights() const; 16.25 void draw_post() const; 16.26 + 16.27 + AudioSample *get_sample(int x, int y, int which) const; 16.28 }; 16.29 16.30 class GridCell { 16.31 @@ -57,6 +60,8 @@ 16.32 void draw(unsigned int draw_mask) const; 16.33 void draw_lights(unsigned int draw_mask) const; 16.34 void draw_post(unsigned int draw_mask) const; 16.35 + 16.36 + AudioSample *get_sample(int which) const; 16.37 }; 16.38 16.39 #endif // LEVEL_H_
17.1 --- a/prototype/src/main.cc Sun Sep 16 08:16:50 2012 +0300 17.2 +++ b/prototype/src/main.cc Mon Sep 17 08:40:59 2012 +0300 17.3 @@ -5,7 +5,7 @@ 17.4 #include "opengl.h" 17.5 #include "psys/psys.h" 17.6 #include "level.h" 17.7 -#include "texman.h" 17.8 +#include "texture.h" 17.9 #include "camera.h" 17.10 #include "datapath.h" 17.11 #include "tileset.h" 17.12 @@ -14,7 +14,8 @@ 17.13 #include "cmdcon.h" 17.14 #include "cfg.h" 17.15 #include "timer.h" 17.16 -#include "audio.h" 17.17 +#include "audio/audio.h" 17.18 +#include "audio/source.h" 17.19 17.20 bool init(int xsz, int ysz); 17.21 void cleanup(); 17.22 @@ -43,6 +44,8 @@ 17.23 17.24 static bool show_con; 17.25 17.26 +static AudioSource *move_sound; 17.27 + 17.28 int main(int argc, char **argv) 17.29 { 17.30 glutInit(&argc, argv); 17.31 @@ -91,8 +94,17 @@ 17.32 17.33 add_data_path("."); 17.34 add_data_path("data"); 17.35 + add_data_path("data/audio"); 17.36 add_data_path("sdr"); 17.37 17.38 + if(cfg.sound && !init_audio()) { 17.39 + fprintf(stderr, "failed to initialize audio, continuing silently\n"); 17.40 + cfg.sound = false; 17.41 + } 17.42 + if(cfg.sound) { 17.43 + move_sound = new AudioSource; 17.44 + } 17.45 + 17.46 rend = new DeferredRenderer(); 17.47 if(!cfg.use_deferred || !rend->init(xsz, ysz)) { 17.48 printf("falling back to crappy renderer...\n"); 17.49 @@ -126,17 +138,13 @@ 17.50 17.51 cam.input_move(0, 0.5, 0); 17.52 17.53 - if(cfg.sound && !init_audio()) { 17.54 - fprintf(stderr, "failed to initialize audio, continuing silently\n"); 17.55 - cfg.sound = false; 17.56 - } 17.57 - 17.58 return true; 17.59 } 17.60 17.61 void cleanup() 17.62 { 17.63 if(cfg.sound) { 17.64 + delete move_sound; 17.65 destroy_audio(); 17.66 } 17.67 17.68 @@ -238,17 +246,22 @@ 17.69 float dx = 0, dy = 0; 17.70 17.71 // handle key input 17.72 + bool did_move = false; 17.73 if(keystate['w'] || keystate['W']) { 17.74 dy -= offs; 17.75 + did_move = true; 17.76 } 17.77 if(keystate['s'] || keystate['S']) { 17.78 dy += offs; 17.79 + did_move = true; 17.80 } 17.81 if(keystate['d'] || keystate['D']) { 17.82 dx += offs; 17.83 + did_move = true; 17.84 } 17.85 if(keystate['a'] || keystate['A']) { 17.86 dx -= offs; 17.87 + did_move = true; 17.88 } 17.89 17.90 cam.input_move(dx, 0, dy); 17.91 @@ -256,6 +269,24 @@ 17.92 tileset->update_tiles(msec); 17.93 level->update(msec, dt); 17.94 17.95 + // play the walking sound if we're walking 17.96 + int cellx, celly; 17.97 + level->get_cell_coords_at(cam.get_position(), &cellx, &celly); 17.98 + 17.99 + const AudioSample *move_sample; 17.100 + if(did_move && (move_sample = level->get_sample(cellx, celly, TILE_SAMPLE_WALK))) { 17.101 + if(move_sample != move_sound->get_sample()) { 17.102 + move_sound->stop(); 17.103 + move_sound->set_sample(move_sample); 17.104 + move_sound->play(); 17.105 + } 17.106 + } else { 17.107 + if(move_sound->get_sample()) { 17.108 + move_sound->stop(); 17.109 + move_sound->set_sample(0); 17.110 + } 17.111 + } 17.112 + 17.113 last_upd = msec; 17.114 } 17.115 17.116 @@ -287,6 +318,27 @@ 17.117 stereo_shift_pressed = true; 17.118 break; 17.119 17.120 + case 'p': 17.121 + { 17.122 + Vector3 pos = cam.get_position(); 17.123 + int cell_x, cell_y; 17.124 + level->get_cell_coords_at(pos, &cell_x, &cell_y); 17.125 + printf("Current position: [%.2f %.2f %.2f] cell: [%d %d]\n", pos.x, pos.y, pos.z, 17.126 + cell_x, cell_y); 17.127 + } 17.128 + break; 17.129 + 17.130 + case 'P': 17.131 + { 17.132 + Vector3 pos = cam.get_position(); 17.133 + int cell_x, cell_y; 17.134 + level->get_cell_coords_at(pos, &cell_x, &cell_y); 17.135 + AudioSample *sample = level->get_sample(cell_x, cell_y, TILE_SAMPLE_WALK); 17.136 + printf("walk sample: %p\n", (void*)sample); 17.137 + } 17.138 + break; 17.139 + 17.140 + 17.141 case '\n': 17.142 case '\r': 17.143 { 17.144 @@ -375,5 +427,5 @@ 17.145 unsigned int load_psys_tex(const char *fname, void *cls) 17.146 { 17.147 TextureSet *texset = tileset->get_textures(); 17.148 - return texset->get_texture(fname); 17.149 + return texset->get(fname); 17.150 }
18.1 --- a/prototype/src/material.cc Sun Sep 16 08:16:50 2012 +0300 18.2 +++ b/prototype/src/material.cc Mon Sep 17 08:40:59 2012 +0300 18.3 @@ -48,7 +48,7 @@ 18.4 for(int j=0; j<2; j++) { 18.5 aiString tex_name; 18.6 if(asstypes[i][j] > 0 && aiGetMaterialString(assmat, AI_MATKEY_TEXTURE(asstypes[i][j], 0), &tex_name) == 0) { 18.7 - tex[i] = texset->get_texture(tex_name.data); 18.8 + tex[i] = texset->get(tex_name.data); 18.9 break; 18.10 } else { 18.11 tex[i] = 0;
19.1 --- a/prototype/src/material.h Sun Sep 16 08:16:50 2012 +0300 19.2 +++ b/prototype/src/material.h Mon Sep 17 08:40:59 2012 +0300 19.3 @@ -2,7 +2,7 @@ 19.4 #define MATERIAL_H_ 19.5 19.6 #include "color.h" 19.7 -#include "texman.h" 19.8 +#include "texture.h" 19.9 19.10 enum { 19.11 TEXTYPE_DIFFUSE,
20.1 --- a/prototype/src/texman.cc Sun Sep 16 08:16:50 2012 +0300 20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 20.3 @@ -1,75 +0,0 @@ 20.4 -#include <string.h> 20.5 -#include "opengl.h" 20.6 -#include "imago2.h" 20.7 -#include "texman.h" 20.8 -#include "datapath.h" 20.9 - 20.10 -unsigned int load_texture(const char *fname); 20.11 - 20.12 -TextureSet::~TextureSet() 20.13 -{ 20.14 - for(auto iter : textures) { 20.15 - glDeleteTextures(1, &iter.second); 20.16 - } 20.17 -} 20.18 - 20.19 -unsigned int TextureSet::get_texture(const char *fname) const 20.20 -{ 20.21 - auto iter = textures.find(fname); 20.22 - if(iter != textures.end()) { 20.23 - return iter->second; 20.24 - } 20.25 - 20.26 - const char *path, *slash; 20.27 - if((slash = strrchr(fname, '/'))) { 20.28 - path = slash + 1; 20.29 - } else { 20.30 - path = fname; 20.31 - } 20.32 - if(!(path = datafile_path(path))) { 20.33 - fprintf(stderr, "can't find texture: %s\n", fname); 20.34 - return 0; 20.35 - } 20.36 - 20.37 - printf("loading texture: %s\n", path); 20.38 - unsigned int tex = load_texture(path); 20.39 - if(tex) { 20.40 - textures[fname] = tex; 20.41 - } else { 20.42 - fprintf(stderr, "failed to load texture: %s\n", path); 20.43 - } 20.44 - return tex; 20.45 -} 20.46 - 20.47 -unsigned int load_texture(const char *fname) 20.48 -{ 20.49 - struct img_pixmap img; 20.50 - 20.51 - img_init(&img); 20.52 - if(img_load(&img, fname) == -1) { 20.53 - img_destroy(&img); 20.54 - return 0; 20.55 - } 20.56 - 20.57 - unsigned int intfmt = img_glintfmt(&img); 20.58 - unsigned int fmt = img_glfmt(&img); 20.59 - unsigned int type = img_gltype(&img); 20.60 - 20.61 - unsigned int tex; 20.62 - glGenTextures(1, &tex); 20.63 - glBindTexture(GL_TEXTURE_2D, tex); 20.64 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 20.65 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 20.66 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 20.67 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 20.68 - 20.69 - if(GLEW_SGIS_generate_mipmap) { 20.70 - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 20.71 - glTexImage2D(GL_TEXTURE_2D, 0, intfmt, img.width, img.height, 0, fmt, type, img.pixels); 20.72 - } else { 20.73 - gluBuild2DMipmaps(GL_TEXTURE_2D, intfmt, img.width, img.height, fmt, type, img.pixels); 20.74 - } 20.75 - 20.76 - img_destroy(&img); 20.77 - return tex; 20.78 -}
21.1 --- a/prototype/src/texman.h Sun Sep 16 08:16:50 2012 +0300 21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 21.3 @@ -1,17 +0,0 @@ 21.4 -#ifndef TEXMAN_H_ 21.5 -#define TEXMAN_H_ 21.6 - 21.7 -#include <string> 21.8 -#include <map> 21.9 - 21.10 -class TextureSet { 21.11 -private: 21.12 - mutable std::map<std::string, unsigned int> textures; 21.13 - 21.14 -public: 21.15 - ~TextureSet(); 21.16 - 21.17 - unsigned int get_texture(const char *fname) const; 21.18 -}; 21.19 - 21.20 -#endif // TEXMAN_H_
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/prototype/src/texture.cc Mon Sep 17 08:40:59 2012 +0300 22.3 @@ -0,0 +1,41 @@ 22.4 +#include "opengl.h" 22.5 +#include "imago2.h" 22.6 +#include "texture.h" 22.7 + 22.8 +unsigned int load_texture(const char *fname) 22.9 +{ 22.10 + struct img_pixmap img; 22.11 + 22.12 + img_init(&img); 22.13 + if(img_load(&img, fname) == -1) { 22.14 + img_destroy(&img); 22.15 + return 0; 22.16 + } 22.17 + 22.18 + unsigned int intfmt = img_glintfmt(&img); 22.19 + unsigned int fmt = img_glfmt(&img); 22.20 + unsigned int type = img_gltype(&img); 22.21 + 22.22 + unsigned int tex; 22.23 + glGenTextures(1, &tex); 22.24 + glBindTexture(GL_TEXTURE_2D, tex); 22.25 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 22.26 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 22.27 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 22.28 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 22.29 + 22.30 + if(GLEW_SGIS_generate_mipmap) { 22.31 + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 22.32 + glTexImage2D(GL_TEXTURE_2D, 0, intfmt, img.width, img.height, 0, fmt, type, img.pixels); 22.33 + } else { 22.34 + gluBuild2DMipmaps(GL_TEXTURE_2D, intfmt, img.width, img.height, fmt, type, img.pixels); 22.35 + } 22.36 + 22.37 + img_destroy(&img); 22.38 + return tex; 22.39 +} 22.40 + 22.41 +void destroy_texture(unsigned int tex) 22.42 +{ 22.43 + glDeleteTextures(1, &tex); 22.44 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/prototype/src/texture.h Mon Sep 17 08:40:59 2012 +0300 23.3 @@ -0,0 +1,11 @@ 23.4 +#ifndef TEXTURE_H_ 23.5 +#define TEXTURE_H_ 23.6 + 23.7 +#include "dataset.h" 23.8 + 23.9 +typedef DataSet<unsigned int> TextureSet; 23.10 + 23.11 +unsigned int load_texture(const char *fname); 23.12 +void destroy_texture(unsigned int tex); 23.13 + 23.14 +#endif // TEXTURE_H_
24.1 --- a/prototype/src/tile.cc Sun Sep 16 08:16:50 2012 +0300 24.2 +++ b/prototype/src/tile.cc Mon Sep 17 08:40:59 2012 +0300 24.3 @@ -21,6 +21,8 @@ 24.4 { 24.5 tset = tileset; 24.6 last_upd = LONG_MIN; 24.7 + 24.8 + memset(samples, 0, sizeof samples); 24.9 } 24.10 24.11 Tile::~Tile() 24.12 @@ -39,6 +41,14 @@ 24.13 } 24.14 } 24.15 24.16 +AudioSample *Tile::get_sample(int sidx) const 24.17 +{ 24.18 + if(sidx >= 0 && sidx < MAX_TILE_SAMPLES) { 24.19 + return samples[sidx]; 24.20 + } 24.21 + return 0; 24.22 +} 24.23 + 24.24 const struct psys_attributes * const *Tile::get_unique_psys() const 24.25 { 24.26 return &psattr[0]; 24.27 @@ -85,6 +95,11 @@ 24.28 printf("loaded tile %s: %d meshes, %d lights\n", saved_fname, (int)meshes.size(), (int)lights.size()); 24.29 24.30 aiReleaseImport(scn); 24.31 + 24.32 + // XXX get the default audio samples for now 24.33 + SampleSet *sampleset = tset->get_samples(); 24.34 + samples[TILE_SAMPLE_WALK] = sampleset->get("walk_stone.ogg"); 24.35 + samples[TILE_SAMPLE_RUN] = sampleset->get("run_stone.ogg"); 24.36 return true; 24.37 } 24.38
25.1 --- a/prototype/src/tile.h Sun Sep 16 08:16:50 2012 +0300 25.2 +++ b/prototype/src/tile.h Mon Sep 17 08:40:59 2012 +0300 25.3 @@ -7,6 +7,7 @@ 25.4 #include <psys/psys.h> 25.5 #include "mesh.h" 25.6 #include "light.h" 25.7 +#include "audio/sample.h" 25.8 25.9 enum { 25.10 TILE_NORTH = 1, 25.11 @@ -16,12 +17,21 @@ 25.12 TILE_ALL = 0xffff 25.13 }; 25.14 25.15 +enum { 25.16 + TILE_SAMPLE_WALK, 25.17 + TILE_SAMPLE_RUN, 25.18 + 25.19 + MAX_TILE_SAMPLES 25.20 +}; 25.21 + 25.22 class TileSet; 25.23 25.24 class Tile { 25.25 private: 25.26 TileSet *tset; 25.27 25.28 + AudioSample *samples[MAX_TILE_SAMPLES]; 25.29 + 25.30 std::vector<Mesh*> meshes; 25.31 std::vector<unsigned int> mesh_side, light_side, psys_side; 25.32 std::vector<Light*> lights; 25.33 @@ -38,6 +48,8 @@ 25.34 Tile(TileSet *tileset = 0); 25.35 ~Tile(); 25.36 25.37 + AudioSample *get_sample(int sidx) const; 25.38 + 25.39 const struct psys_attributes * const *get_unique_psys() const; 25.40 int get_unique_psys_count() const; 25.41
26.1 --- a/prototype/src/tileset.cc Sun Sep 16 08:16:50 2012 +0300 26.2 +++ b/prototype/src/tileset.cc Mon Sep 17 08:40:59 2012 +0300 26.3 @@ -6,6 +6,11 @@ 26.4 26.5 static TileSet *active_tileset; 26.6 26.7 +TileSet::TileSet() 26.8 + : texset(load_texture, destroy_texture), 26.9 + sampleset(load_audio_sample, destroy_audio_sample) 26.10 +{ 26.11 +} 26.12 26.13 TileSet::~TileSet() 26.14 { 26.15 @@ -66,6 +71,16 @@ 26.16 return &texset; 26.17 } 26.18 26.19 +SampleSet *TileSet::get_samples() 26.20 +{ 26.21 + return &sampleset; 26.22 +} 26.23 + 26.24 +const SampleSet *TileSet::get_samples() const 26.25 +{ 26.26 + return &sampleset; 26.27 +} 26.28 + 26.29 Tile *TileSet::get_tile(const char *name) const 26.30 { 26.31 auto res = tiles.find(name);
27.1 --- a/prototype/src/tileset.h Sun Sep 16 08:16:50 2012 +0300 27.2 +++ b/prototype/src/tileset.h Mon Sep 17 08:40:59 2012 +0300 27.3 @@ -4,15 +4,18 @@ 27.4 #include <string> 27.5 #include <map> 27.6 #include "tile.h" 27.7 -#include "texman.h" 27.8 +#include "texture.h" 27.9 +#include "audio/sample.h" 27.10 27.11 class TileSet { 27.12 private: 27.13 std::map<std::string, Tile*> tiles; 27.14 27.15 TextureSet texset; 27.16 + SampleSet sampleset; 27.17 27.18 public: 27.19 + TileSet(); 27.20 ~TileSet(); 27.21 27.22 bool load(const char *fname); 27.23 @@ -20,6 +23,9 @@ 27.24 TextureSet *get_textures(); 27.25 const TextureSet *get_textures() const; 27.26 27.27 + SampleSet *get_samples(); 27.28 + const SampleSet *get_samples() const; 27.29 + 27.30 Tile *get_tile(const char *name) const; 27.31 27.32 void update_tiles(unsigned long msec);