-
Notifications
You must be signed in to change notification settings - Fork 0
/
bitmask.h
133 lines (117 loc) · 4.1 KB
/
bitmask.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* bitmask.c 1.0 (prerelease2)
* -------------------------
* Simple and efficient bitmask collision detection routines
* Copyright (C) 2002 Ulf Ekstrom except for the bitcount function.
*
* A bitmask is a simple array of bits, which can be used for
* 2d collision detection. Set 'unoccupied' area to zero and
* occupies areas to one and use the bitmask_overlap*() functions
* to check for collisions.
* The current implementation uses 32 bit wide stripes to hold
* the masks, but should work just as well with 64 bit sizes.
* (Note that the current bitcount function is 32 bit only!)
*
* The overlap tests uses the following offsets (which may be negative):
*
* +----+----------..
* |A | yoffset
* | +-+----------..
* +--|B
* |xoffset
* | |
* : :
*
* For optimal collision detection performance combine these functions
* with some kind of pre-sorting to avoid comparing objects far from
* each other.
*
* BUGS: No known bugs, even though they may certainly be in here somewhere.
* Possible performance improvements could be to remove the div in
* bitmask_overlap_pos() and to implement wider stripes if the masks used
* are wider than 64 bits on the average.
*
* Performance of the various functions goes something like:
* (relative timings, smaller is better)
*
* bitmask_overlap() 1.0
* bitmask_overlap_pos() 1.3
* bitmask_overlap_area() 1.6
*
* For maximum performance on my machine I use gcc with
* -O2 -fomit-frame-pointer -funroll-loops
*
*
* Please email bugs and comments to Ulf Ekstrom, ulfek@ifm.liu.se
*
*/
/*
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef BITMASK_H
#define BITMASK_H
#ifndef INLINE
# ifdef __GNUC__
# define INLINE __inline__
# else
# define INLINE __inline
# endif
#endif
#define BITW unsigned long int
#define BITW_LEN 32
#define BITW_MASK 31
#define BITN(n) ((BITW)1 << (n))
typedef struct bitmask
{
int w,h;
BITW *bits;
} bitmask;
/* Creates a bitmask of width w and height h.
* The mask is automatically cleared when created.
*/
bitmask *bitmask_create(int w, int h);
void bitmask_free(bitmask *m);
/* Returns nonzero if the bit at (x,y) is set.
* Coordinates start at (0,0)
*/
static INLINE int bitmask_getbit(const bitmask *m,int x,int y)
{
return m->bits[x/BITW_LEN*m->h + y] & BITN(x & BITW_MASK);
}
/* Sets the bit at (x,y) */
static INLINE void bitmask_setbit(bitmask *m,int x,int y)
{
m->bits[x/BITW_LEN*m->h + y] |= BITN(x & BITW_MASK);
}
/* Clears the bit at (x,y) */
static INLINE void bitmask_clearbit(bitmask *m,int x,int y)
{
m->bits[x/BITW_LEN*m->h + y] &= ~BITN(x & BITW_MASK);
}
/* Returns nonzero if the masks overlap with the given offset.
*/
int bitmask_overlap(const bitmask *a,const bitmask *b,int xoffset, int yoffset);
/* Like bitmask_overlap(), but will also give a point of intersection.
* x and y are given in the coordinates of mask a, and are untouched if the is no overlap
*/
int bitmask_overlap_pos(const bitmask *a,const bitmask *b,int xoffset, int yoffset, int *x, int *y);
/* Returns the number of overlapping 'pixels' */
int bitmask_overlap_area(const bitmask *a,const bitmask *b,int xoffset, int yoffset);
/* Draws mask b onto mask a (bitwise OR)
* Can be used to compose large (background?) mask from
* several submasks, which may speed up the testing.
*/
void bitmask_draw(bitmask *a,bitmask *b,int xoffset, int yoffset);
#endif