1 #ifdef CLUSTER_INSIDES
2
3 #ifndef CLUSTER_H
4 #define CLUSTER_H
5
6 #include "tiles.h"
7 #include "bbox_tree.h"
8 #include "e3d.h"
9 #include "lights.h"
10 #include "particles.h"
11 #ifdef MAP_EDITOR
12 #include "map_editor/2d_objects.h"
13 #include "map_editor/3d_objects.h"
14 #else
15 #include "2d_objects.h"
16 #include "3d_objects.h"
17 #endif
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 /*!
24 * \ingroup maps
25 * \brief Update the occupation array with the height map
26 *
27 * Mark the fields in the occupation array that are walkable.
28 *
29 * \param occupied The occupation array
30 * \param height_map The height map
31 */
update_occupied_with_height_map(char * occupied,const unsigned char * height_map)32 static __inline__ void update_occupied_with_height_map (char* occupied, const unsigned char* height_map)
33 {
34 int i;
35
36 for (i = 0; i < tile_map_size_x*tile_map_size_y*6*6; i++)
37 if (height_map[i]) occupied[i] = 1;
38 }
39
40 /*!
41 * \ingroup maps
42 * \brief Update the occupation array with the tile map
43 *
44 * Mark the fields in the occupation array that are occupied by
45 * ground tiles
46 *
47 * \param occupied The occupation array
48 * \param tile_map The tile map
49 */
update_occupied_with_tile_map(char * occupied,const unsigned char * tile_map)50 static __inline__ void update_occupied_with_tile_map (char* occupied, const unsigned char* tile_map)
51 {
52 int nx = tile_map_size_x * 6;
53 int ny = tile_map_size_y * 6;
54 int x, y, idx;
55
56 idx = 0;
57 for (y = 0; y < ny; y += 6)
58 {
59 for (x = 0; x < nx; x += 6, idx++)
60 {
61 if (tile_map[idx] != 255)
62 {
63 int offset = y*nx + x;
64 int i, j;
65
66 for (j = 0; j < 6; j++)
67 for (i = 0; i < 6; i++)
68 occupied[offset+j*nx+i] = 1;
69 }
70 }
71 }
72 }
73
74 /*!
75 * \ingroup maps
76 * \brief Update the occupation array with a bounding box
77 *
78 * Mark the fields in the occupation array that are included in
79 * the bounding box.
80 *
81 * \param occupied The occupation array
82 * \param box The axis aligned bounding box
83 */
update_occupied_with_bbox(char * occupied,const AABBOX * box)84 static __inline__ void update_occupied_with_bbox (char* occupied, const AABBOX* box)
85 {
86 int xs = (int) (box->bbmin[X] / 0.5f);
87 int ys = (int) (box->bbmin[Y] / 0.5f);
88 int xe = (int) (box->bbmax[X] / 0.5f) + 1;
89 int ye = (int) (box->bbmax[Y] / 0.5f) + 1;
90 int x, y;
91
92 if (xs < 0) xs = 0;
93 if (ys < 0) ys = 0;
94 if (xe > tile_map_size_x*6) xe = tile_map_size_x*6;
95 if (ye > tile_map_size_y*6) ye = tile_map_size_y*6;
96
97 for (y = ys; y < ye; y++)
98 {
99 for (x = xs; x < xe; x++)
100 occupied[y*tile_map_size_x*6+x] = 1;
101 }
102 }
103
104 /*!
105 * \ingroup maps
106 * \brief Update the occupation array with a 3D objec t
107 *
108 * Mark the fields in the occupation array that are included in
109 * the bounding box of the 3D object.
110 *
111 * \param occupied The occupation array
112 * \param id The position in objects_list of the 3D object
113 */
114
update_occupied_with_3d(char * occupied,int id)115 static __inline__ void update_occupied_with_3d (char* occupied, int id)
116 {
117 const e3d_object* obj;
118 int i;
119 AABBOX box;
120 #ifdef MAP_EDITOR
121 MATRIX4x4 matrix;
122 #endif
123
124 if (id < 0 || id >= MAX_OBJ_3D || !objects_list[id])
125 return;
126
127 obj = objects_list[id]->e3d_data;
128 if (!obj)
129 return;
130
131 for (i = 0; i < obj->material_no; i++)
132 {
133 box.bbmin[X] = obj->materials[i].min_x;
134 box.bbmin[Y] = obj->materials[i].min_y;
135 box.bbmin[Z] = obj->materials[i].min_z;
136 box.bbmax[X] = obj->materials[i].max_x;
137 box.bbmax[Y] = obj->materials[i].max_y;
138 box.bbmax[Z] = obj->materials[i].max_z;
139 #ifdef MAP_EDITOR
140 // the map editor doesn't store the object transformation matrices
141 calc_rotation_and_translation_matrix (matrix,
142 objects_list[id]->x_pos, objects_list[id]->y_pos, objects_list[id]->z_pos,
143 objects_list[id]->x_rot, objects_list[id]->y_rot, objects_list[id]->z_rot);
144 matrix_mul_aabb (&box, matrix);
145 #else
146 matrix_mul_aabb (&box, objects_list[id]->matrix);
147 #endif
148
149 update_occupied_with_bbox (occupied, &box);
150 }
151 }
152
153 /*!
154 * \ingroup maps
155 * \brief Update the occupation array with a 2D object
156 *
157 * Mark the fields in the occupation array that are included in
158 * the bounding box of the 2D object.
159 *
160 * \param occupied The occupation array
161 * \param id The index in obj_2d_list of the 2D object
162 */
update_occupied_with_2d(char * occupied,int id)163 static __inline__ void update_occupied_with_2d (char* occupied, int id)
164 {
165 AABBOX box;
166
167 if (get_2d_bbox (id, &box))
168 update_occupied_with_bbox (occupied, &box);
169 }
170
171 /*!
172 * \ingroup maps
173 * \brief Update the occupation array with a light
174 *
175 * Mark the position of the light as occupied
176 *
177 * \param occupied The occupation array
178 * \param id The index in lights_list of the light
179 */
update_occupied_with_light(char * occupied,int id)180 static __inline__ void update_occupied_with_light (char* occupied, int id)
181 {
182 int x, y;
183
184 if (id < 0 || id >= MAX_LIGHTS)
185 return;
186
187 x = (int) (lights_list[id]->pos_x / 0.5f);
188 y = (int) (lights_list[id]->pos_y / 0.5f);
189
190 if (x >= 0 && x < tile_map_size_x*6 && y >= 0 && y < tile_map_size_y*6)
191 occupied[y*tile_map_size_x*6+x] = 1;
192 }
193
194 /*!
195 * \ingroup maps
196 * \brief Update the occupation array with a particle system
197 *
198 * Mark the fields in the occupation array that are included in
199 * the bounding box of the particle system.
200 *
201 * \param occupied The occupation array
202 * \param id The index in particles_list of the particle system
203 */
update_occupied_with_particle_system(char * occupied,int id)204 static __inline__ void update_occupied_with_particle_system (char* occupied, int id)
205 {
206 AABBOX box;
207
208 if (id < 0 || id >= MAX_PARTICLE_SYSTEMS || !particles_list[id])
209 return;
210
211 calc_bounding_box_for_particle_sys (&box, particles_list[id]);
212 update_occupied_with_bbox (occupied, &box);
213 }
214
215 /*!
216 * \ingroup maps
217 * \brief Set the cluster map from file data
218 *
219 * Allocate and read the cluster map from file data.
220 *
221 * \param data The cluster data from the map file
222 * \note Either this function should be used, or when no cluster data is
223 * present in the file, compute_clusters() should be used. Doing
224 * both will lead to memory leaks and unnecesary CPU usage.
225 */
226 void set_clusters (const char* data);
227
228 #ifdef MAP_EDITOR
229 /*!
230 * \ingroup maps
231 * \brief Get file data for the cluster map
232 *
233 * Serialize the cluster map data, and return it through
234 * character array \a data of length \a len.
235 *
236 * \param data Address where to store the pointer to the data
237 * \param len The length of the data in bytes
238 * \note The array in \a *data will be dynamically allocated, and should
239 * be \c free'd by the caller.
240 */
241 void get_clusters (char** data, int *len);
242 #endif
243
244 /*!
245 * \ingroup maps
246 * \brief Group occupied areas into clusters
247 *
248 * Detect and number contiguous occupied areas in the occupation array.
249 *
250 * \param occupied The occupation array
251 * \note When reading maps, this function should only be used when the
252 * cluster map is not present in the file, otherwise
253 * set_clusters() should be used. Doing both will lead to memory
254 * leaks and unnecesary CPU usage.
255 */
256 void compute_clusters (const char* occupied);
257
258 /*!
259 * \ingroup maps
260 * \brief Get the cluster number of a position
261 *
262 * Get the number of the visibility cluster to which point
263 * (\a x, \a y) belongs.
264 *
265 * \param x the x coordinate of the point to check
266 * \param y the y coordinate of the point to check
267 * \retval short The number of the visibility cluster, or 0 if the point
268 * is not inside any cluster.
269 */
270 short get_cluster (int x, int y);
271
272 /*!
273 * \ingroup maps
274 * \brief Destroy the clusters array
275 *
276 * Free the memory associated with the clusters array, and clear
277 * the pointer associated with it.
278 */
279 void destroy_clusters_array ();
280
281 #ifndef MAP_EDITOR
282 /*!
283 * \ingroup maps
284 * \brief Get the cluster where the actor is currently on
285 *
286 * Check the cluster map at the actor's current position, and
287 * return the number of the cluster that he's currently in.
288 *
289 * \retval short The number of the actor's current visibility cluster
290 */
291 short get_actor_cluster ();
292 #endif
293
294 extern short current_cluster;
295
296 #ifdef __cplusplus
297 } // extern "C"
298 #endif
299
300 #endif // CLUSTER_H
301
302 #endif // CLUSTER_INSIDES
303