1 #include <stdlib.h>
2 #include <math.h>
3 #include <string.h>
4 #include <SDL.h>
5 #include "3d_objects.h"
6 #include "2d_objects.h"
7 #include "asc.h"
8 #include "cursors.h"
9 #include "draw_scene.h"
10 #include "e3d.h"
11 #include "elconfig.h"
12 #include "errors.h"
13 #include "events.h"
14 #include "map.h"
15 #include "particles.h"
16 #include "platform.h"
17 #include "shadows.h"
18 #include "textures.h"
19 #include "tiles.h"
20 #include "translate.h"
21 #include "io/e3d_io.h"
22 #ifdef CLUSTER_INSIDES
23 #include "cluster.h"
24 #endif
25 #ifdef FSAA
26 #include "fsaa/fsaa.h"
27 #endif /* FSAA */
28
29 int use_3d_alpha_blend= 1;
30 #ifndef FASTER_MAP_LOAD
31 static int objects_list_placeholders = 0;
32 #endif
33 object3d *objects_list[MAX_OBJ_3D];
34
35 #include "eye_candy_wrapper.h"
36
37 e3d_object *load_e3d (const char *file_name);
38 void compute_clouds_map(object3d * object_id);
39 e3d_object *cur_e3d;
40 #ifdef DEBUG
41 int cur_e3d_count;
42 int e3d_count, e3d_total;
43 #endif //DEBUG
44
45 static int next_obj_3d = 0;
46
47 #ifdef FASTER_MAP_LOAD
inc_objects_list_placeholders(void)48 void inc_objects_list_placeholders(void)
49 {
50 next_obj_3d++;
51 }
52 #else
clear_objects_list_placeholders(void)53 void clear_objects_list_placeholders(void)
54 {
55 objects_list_placeholders = 0;
56 }
57
inc_objects_list_placeholders(void)58 void inc_objects_list_placeholders(void)
59 {
60 objects_list_placeholders++;
61 }
62 #endif
63
build_clouds_planes(object3d * obj)64 static __inline__ void build_clouds_planes(object3d* obj)
65 {
66 float w, cos_w, sin_w;
67
68 w = -obj->z_rot * M_PI / 180.0f;
69 cos_w = cos(w);
70 sin_w = sin(w);
71
72 obj->clouds_planes[0][0] = cos_w / texture_scale;
73 obj->clouds_planes[0][1] = sin_w / texture_scale;
74 obj->clouds_planes[0][2] = 1.0f / texture_scale;
75 obj->clouds_planes[0][3] = obj->x_pos / texture_scale;
76 obj->clouds_planes[1][0] = -sin_w / texture_scale;
77 obj->clouds_planes[1][1] = cos_w / texture_scale;
78 obj->clouds_planes[1][2] = 1.0f / texture_scale;
79 obj->clouds_planes[1][3] = obj->y_pos / texture_scale;
80 }
81
disable_buffer_arrays(void)82 void disable_buffer_arrays(void)
83 {
84 if (use_vertex_buffers)
85 {
86 ELglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
87 ELglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
88 }
89 if (use_compiled_vertex_array && (cur_e3d != NULL))
90 {
91 ELglUnlockArraysEXT();
92 }
93 cur_e3d = NULL;
94 }
95
draw_3d_object_detail(object3d * object_id,Uint32 material_index,Uint32 use_lightning,Uint32 use_textures,Uint32 use_extra_textures)96 void draw_3d_object_detail(object3d * object_id, Uint32 material_index, Uint32 use_lightning,
97 Uint32 use_textures, Uint32 use_extra_textures)
98 {
99 e3d_vertex_data* vertex_layout;
100 Uint8 * data_ptr;
101
102 // check for having to load the arrays
103 load_e3d_detail_if_needed(object_id->e3d_data);
104
105 CHECK_GL_ERRORS();
106 //also, update the last time this object was used
107 object_id->last_acessed_time = cur_time;
108
109 //debug
110
111 if (object_id->self_lit && (!is_day || dungeon) && use_lightning)
112 {
113 glColor3fv(object_id->color);
114 }
115
116 CHECK_GL_ERRORS();
117
118 glPushMatrix();//we don't want to affect the rest of the scene
119
120 glMultMatrixf(object_id->matrix);
121
122 CHECK_GL_ERRORS();
123
124 if (!dungeon && (clouds_shadows || use_shadow_mapping) && use_extra_textures)
125 {
126 VECTOR4 plane;
127
128 ELglActiveTextureARB(detail_unit);
129 memcpy(plane, object_id->clouds_planes[0], sizeof(VECTOR4));
130 plane[3] += clouds_movement_u;
131 glTexGenfv(GL_S, GL_EYE_PLANE, plane);
132 memcpy(plane, object_id->clouds_planes[1], sizeof(VECTOR4));
133 plane[3] += clouds_movement_v;
134 glTexGenfv(GL_T, GL_EYE_PLANE, plane);
135 ELglActiveTextureARB(base_unit);
136 }
137
138 // watch for a change
139 if (object_id->e3d_data != cur_e3d)
140 {
141 if ((cur_e3d != NULL) && (use_compiled_vertex_array))
142 {
143 ELglUnlockArraysEXT();
144 }
145
146 if (use_vertex_buffers)
147 {
148 ELglBindBufferARB(GL_ARRAY_BUFFER_ARB,
149 object_id->e3d_data->vertex_vbo);
150 data_ptr = 0;
151 }
152 else
153 {
154 data_ptr = object_id->e3d_data->vertex_data;
155 }
156
157 vertex_layout = object_id->e3d_data->vertex_layout;
158
159 if ((vertex_layout->normal_count > 0) && use_lightning)
160 {
161 glEnableClientState(GL_NORMAL_ARRAY);
162 glNormalPointer(vertex_layout->normal_type, vertex_layout->size,
163 data_ptr + vertex_layout->normal_offset);
164 }
165 else
166 {
167 glDisableClientState(GL_NORMAL_ARRAY);
168 glNormal3f(0.0f, 0.0f, 1.0f);
169 }
170
171 if (use_textures)
172 {
173 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
174 glTexCoordPointer(vertex_layout->texture_count, vertex_layout->texture_type,
175 vertex_layout->size, data_ptr + vertex_layout->texture_offset);
176 }
177 else
178 {
179 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
180 }
181
182 glVertexPointer(vertex_layout->position_count, vertex_layout->position_type,
183 vertex_layout->size, data_ptr + vertex_layout->position_offset);
184
185 if (use_vertex_buffers)
186 {
187 ELglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
188 object_id->e3d_data->indices_vbo);
189 }
190
191 // lock this new one
192 if (use_compiled_vertex_array)
193 {
194 ELglLockArraysEXT(0, object_id->e3d_data->vertex_no);
195 }
196 // gather statistics
197 if (object_id->e3d_data != cur_e3d)
198 {
199 #ifdef DEBUG
200 if ((cur_e3d_count > 0) && (cur_e3d != NULL))
201 {
202 e3d_count++;
203 e3d_total += cur_e3d_count;
204 }
205 cur_e3d_count = 0;
206 #endif //DEBUG
207 cur_e3d = object_id->e3d_data;
208 }
209 }
210 #ifdef DEBUG
211 cur_e3d_count++;
212 #endif //DEBUG
213
214 if (use_textures)
215 {
216 glEnable(GL_TEXTURE_2D);
217 bind_texture(object_id->e3d_data->materials[material_index].texture);
218 }
219 else
220 {
221 glDisable(GL_TEXTURE_2D);
222 }
223
224
225 if (use_draw_range_elements && ELglDrawRangeElementsEXT)
226 ELglDrawRangeElementsEXT(GL_TRIANGLES,
227 object_id->e3d_data->materials[material_index].triangles_indices_min,
228 object_id->e3d_data->materials[material_index].triangles_indices_max,
229 object_id->e3d_data->materials[material_index].triangles_indices_count,
230 object_id->e3d_data->index_type,
231 object_id->e3d_data->materials[material_index].triangles_indices_index);
232 else
233 glDrawElements(GL_TRIANGLES,
234 object_id->e3d_data->materials[material_index].triangles_indices_count,
235 object_id->e3d_data->index_type,
236 object_id->e3d_data->materials[material_index].triangles_indices_index);
237
238 glPopMatrix();//restore the scene
239 CHECK_GL_ERRORS();
240
241 //OK, let's check if our mouse is over...
242 #ifdef MAP_EDITOR2
243 if (selected_3d_object == -1 && read_mouse_now && mouse_in_sphere(object_id->x_pos, object_id->y_pos, object_id->z_pos, object_id->e3d_data->radius))
244 anything_under_the_mouse(object_id->id, UNDER_MOUSE_3D_OBJ);
245 #endif
246 }
247
draw_3d_objects(unsigned int object_type)248 void draw_3d_objects(unsigned int object_type)
249 {
250 unsigned int start, stop;
251 unsigned int i, l;
252 int is_selflit, is_transparent, is_ground;
253 #ifdef SIMPLE_LOD
254 int x, y, dist;
255 #endif
256 #ifdef CLUSTER_INSIDES_OLD
257 short cluster = get_actor_cluster ();
258 #endif
259
260 #ifdef SIMPLE_LOD
261 x= -camera_x;
262 y= -camera_y;
263 #endif
264
265 cur_e3d= NULL;
266 #ifdef DEBUG
267 cur_e3d_count= 0;
268 #endif //DEBUG
269
270 get_intersect_start_stop(main_bbox_tree, object_type, &start, &stop);
271 // nothing to draw?
272 if(start >= stop){
273 return;
274 }
275
276 // find the modes we need
277 is_selflit= is_self_lit_3d_object(object_type);
278 is_transparent= is_alpha_3d_object(object_type);
279 is_ground= is_ground_3d_object(object_type);
280 // set the modes we need
281 if (is_selflit && (!is_day || dungeon))
282 {
283 glDisable(GL_LIGHTING);
284 }
285
286 #ifdef FSAA
287 if (fsaa > 1)
288 {
289 glEnable(GL_MULTISAMPLE);
290 }
291 #endif /* FSAA */
292 if(is_transparent) {
293 #ifdef NEW_ALPHA
294 if(use_3d_alpha_blend){
295 glEnable(GL_BLEND);
296 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
297 }
298 #endif //NEW_ALPHA
299 //enable alpha filtering, so we have some alpha key
300 glEnable(GL_ALPHA_TEST);
301 if(is_ground)glAlphaFunc(GL_GREATER,0.23f);
302 else glAlphaFunc(GL_GREATER,0.3f);
303 glDisable(GL_CULL_FACE);
304 }
305
306 /*
307 // NOTICE: The below code is an ASSUMPTION that appropriate client
308 // states will be used!
309 */
310 if (!dungeon && (clouds_shadows||use_shadow_mapping))
311 {
312 ELglActiveTextureARB(detail_unit);
313 glEnable(GL_TEXTURE_GEN_S);
314 glEnable(GL_TEXTURE_GEN_T);
315 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
316 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
317 ELglActiveTextureARB(base_unit);
318 }
319 // now loop through each object
320 for (i=start; i<stop; i++)
321 {
322 int j;
323
324 j = get_intersect_item_ID(main_bbox_tree, i);
325 l = get_3dobject_index(j);
326 if (objects_list[l] == NULL) continue;
327 //track the usage
328 cache_use(objects_list[l]->e3d_data->cache_ptr);
329 if(!objects_list[l]->display) continue; // not currently on the map, ignore it
330 #ifdef CLUSTER_INSIDES_OLD
331 if (objects_list[l]->cluster && objects_list[l]->cluster != cluster)
332 // Object is in another cluster as actor, don't show it
333 continue;
334 #endif // CLUSTER_INSIDES_OLD
335 #ifdef SIMPLE_LOD
336 // simple size/distance culling
337 dist= (x-objects_list[l]->x_pos)*(x-objects_list[l]->x_pos) + (y-objects_list[l]->y_pos)*(y-objects_list[l]->y_pos);
338 if(objects_list[l]->e3d_data->materials && (10000*objects_list[l]->e3d_data->materials[get_3dobject_material(j)].max_size)/(dist) < ((is_transparent)?15:10)) continue;
339 #endif //SIMPLE_LOD
340
341 draw_3d_object_detail(objects_list[l], get_3dobject_material(j), 1, 1, 1);
342
343 #ifdef MAP_EDITOR2
344 if ((selected_3d_object == -1) && read_mouse_now && (get_cur_intersect_type(main_bbox_tree) == INTERSECTION_TYPE_DEFAULT))
345 #else
346 if (read_mouse_now && (get_cur_intersect_type(main_bbox_tree) == INTERSECTION_TYPE_DEFAULT))
347 #endif
348 {
349 anything_under_the_mouse(objects_list[l]->id, UNDER_MOUSE_3D_OBJ);
350 }
351 }
352
353 if (!dungeon && (clouds_shadows || use_shadow_mapping))
354 {
355 ELglActiveTextureARB(detail_unit);
356 glDisable(GL_TEXTURE_GEN_S);
357 glDisable(GL_TEXTURE_GEN_T);
358 ELglActiveTextureARB(base_unit);
359 }
360
361 disable_buffer_arrays();
362
363 // restore the settings
364 if (is_selflit && (!is_day || dungeon))
365 {
366 glEnable(GL_LIGHTING);
367 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
368 }
369 if(is_transparent) {
370 glEnable(GL_CULL_FACE);
371 #ifdef NEW_ALPHA
372 if(use_3d_alpha_blend){
373 glDisable(GL_BLEND);
374 }
375 #endif //NEW_ALPHA
376 glDisable(GL_ALPHA_TEST);
377 }
378 #ifdef FSAA
379 if (fsaa > 1)
380 {
381 glDisable(GL_MULTISAMPLE);
382 }
383 #endif /* FSAA */
384
385 CHECK_GL_ERRORS();
386
387 #ifdef DEBUG
388 // final statistics
389 if(cur_e3d_count > 0){
390 e3d_count++;
391 e3d_total+= cur_e3d_count;
392 }
393 cur_e3d_count= 0;
394 #endif //DEBUG
395 }
396
397 //Tests to see if an e3d object is already loaded. If it is, return the handle.
398 //If not, load it, and return the handle
load_e3d_cache(const char * file_name)399 static e3d_object *load_e3d_cache(const char* file_name)
400 {
401 e3d_object *e3d_id;
402
403 //do we have it already?
404 e3d_id = cache_find_item(cache_e3d, file_name);
405 if (e3d_id) return e3d_id;
406
407 //e3d not found in the cache, so load it, and store it
408 // allocate the memory
409 e3d_id = calloc(1, sizeof(e3d_object));
410 if (!e3d_id)
411 {
412 LOG_ERROR("Can't allocate data for file \"%s\"!", file_name);
413 return NULL;
414 }
415 // and fill in the data
416 safe_strncpy(e3d_id->file_name, file_name, sizeof(e3d_id->file_name));
417
418 e3d_id = load_e3d_detail(e3d_id);
419 if (!e3d_id)
420 {
421 LOG_ERROR("Can't load file \"%s\"!", file_name);
422 return NULL;
423 }
424
425 // Note, doing this after load_e3d_detail() means the cache size is not calculated correctly
426 // but doing it before load_e3d_detail() puts invalid objects into the cache if they fail to load.
427 // This needs fixing properly, but for now this works without other issues.
428 // see https://github.com/raduprv/Eternal-Lands/commit/1796c7944f4b11f67595e84ba42fa8e036621de5
429 e3d_id->cache_ptr = cache_add_item(cache_e3d, e3d_id->file_name,
430 e3d_id, sizeof(*e3d_id));
431
432 return e3d_id;
433 }
434
add_e3d_at_id(int id,const char * file_name,float x_pos,float y_pos,float z_pos,float x_rot,float y_rot,float z_rot,char self_lit,char blended,float r,float g,float b,unsigned int dynamic)435 int add_e3d_at_id(int id, const char* file_name,
436 float x_pos, float y_pos, float z_pos,
437 float x_rot, float y_rot, float z_rot, char self_lit, char blended,
438 float r, float g, float b, unsigned int dynamic)
439 {
440 char fname[128];
441 #ifdef FASTER_MAP_LOAD
442 const char *fbase;
443 #endif
444 e3d_object *returned_e3d;
445 object3d *our_object;
446 int i;
447 AABBOX bbox;
448 unsigned int texture_id;
449 unsigned int is_transparent, ground;
450
451 if (id < 0 || id >= MAX_OBJ_3D)
452 {
453 LOG_ERROR("Invalid object id %d", id);
454 return -1;
455 }
456
457 if (objects_list[id])
458 {
459 LOG_ERROR("There's already an object with ID %d", id);
460 return -1;
461 }
462
463 // convert to lower case and replace any '\' by '/'
464 clean_file_name(fname, file_name, sizeof(fname));
465 #ifdef FASTER_MAP_LOAD
466 fbase = strrchr(fname, '/');
467 if (fbase)
468 fbase++;
469 else
470 fbase = fname;
471 #endif
472
473 returned_e3d = load_e3d_cache(fname);
474 if (!returned_e3d)
475 {
476 LOG_ERROR(nasty_error_str, fname);
477 //replace it with the null object, to avoid object IDs corruption
478 safe_strncpy(fname, "./3dobjects/badobject.e3d", sizeof(fname));
479 returned_e3d = load_e3d_cache(fname);
480 if (!returned_e3d)
481 return -1; // umm, not even found the place holder, this is teh SUCK!!!
482 }
483 // now, allocate the memory
484 our_object = calloc(1, sizeof (object3d));
485
486 // and fill it in
487 safe_strncpy(our_object->file_name, fname, sizeof(our_object->file_name));
488 our_object->x_pos = x_pos;
489 our_object->y_pos = y_pos;
490 our_object->z_pos = z_pos;
491
492 our_object->x_rot = x_rot;
493 our_object->y_rot = y_rot;
494 our_object->z_rot = z_rot;
495
496 our_object->color[0] = r;
497 our_object->color[1] = g;
498 our_object->color[2] = b;
499 our_object->color[3] = 0.0f;
500
501 our_object->self_lit = self_lit;
502 our_object->blended = blended;
503 our_object->display = 1;
504 our_object->state = 0;
505
506 build_clouds_planes(our_object);
507
508 our_object->e3d_data = returned_e3d;
509
510 our_object->id = id;
511
512 our_object->flags = 0;
513
514 #ifdef FASTER_MAP_LOAD
515 if (is_harvestable(fbase))
516 our_object->flags |= OBJ_3D_HARVESTABLE;
517 if (is_entrable(fbase))
518 our_object->flags |= OBJ_3D_ENTRABLE;
519 if (*fbase && strcasecmp(fbase, "bag1.e3d") == 0)
520 our_object->flags |= OBJ_3D_BAG;
521 if (*fbase && strcasecmp(fbase, "branch1.e3d") == 0)
522 our_object->flags |= OBJ_3D_MINE;
523 #else // FASTER_MAP_LOAD
524 for(i = 0; i < sizeof(harvestable_objects)/sizeof(harvestable_objects[0]); i++) {
525 if(*harvestable_objects[i] && strstr(file_name, harvestable_objects[i]) != NULL) {
526 our_object->flags |= OBJ_3D_HARVESTABLE;
527 break;
528 }
529 }
530 for(i = 0; i < sizeof(entrable_objects)/sizeof(entrable_objects[0]); i++) {
531 if(*(entrable_objects[i]) && strstr(file_name, entrable_objects[i]) != NULL) {
532 our_object->flags |= OBJ_3D_ENTRABLE;
533 break;
534 }
535 }
536 if (strcasecmp(file_name, "") && strcasecmp(strrchr(file_name, '/')+1, "bag1.e3d") == 0) {
537 our_object->flags |= OBJ_3D_BAG;
538 }
539 if (strcasecmp(file_name, "") && strcasecmp(strrchr(file_name, '/')+1, "branch1.e3d") == 0) {
540 our_object->flags |= OBJ_3D_MINE;
541 }
542 #endif // FASTER_MAP_LOAD
543
544 #ifdef CLUSTER_INSIDES
545 our_object->cluster = get_cluster ((int)(x_pos/0.5f), (int)(y_pos/0.5f));
546 current_cluster = our_object->cluster;
547 #endif
548
549 objects_list[id] = our_object;
550 // watch the top end
551 if (id >= next_obj_3d)
552 next_obj_3d = id+1;
553
554 calc_rotation_and_translation_matrix(our_object->matrix, x_pos, y_pos, z_pos, x_rot, y_rot, z_rot);
555
556 // watch for needing to load the detailed information
557 //load_e3d_detail_if_needed(returned_e3d);
558
559 ground = returned_e3d->vertex_layout->normal_count == 0;
560
561 for (i = 0; i < returned_e3d->material_no; i++)
562 {
563 bbox.bbmin[X] = returned_e3d->materials[i].min_x;
564 bbox.bbmax[X] = returned_e3d->materials[i].max_x;
565 bbox.bbmin[Y] = returned_e3d->materials[i].min_y;
566 bbox.bbmax[Y] = returned_e3d->materials[i].max_y;
567 bbox.bbmin[Z] = returned_e3d->materials[i].min_z;
568 bbox.bbmax[Z] = returned_e3d->materials[i].max_z;
569
570 matrix_mul_aabb(&bbox, our_object->matrix);
571 texture_id = returned_e3d->materials[i].texture;
572 is_transparent = returned_e3d->materials[i].options != 0;
573 if (main_bbox_tree_items != NULL && dynamic == 0)
574 add_3dobject_to_list(main_bbox_tree_items,
575 get_3dobject_id(id, i), bbox, blended, ground,
576 is_transparent, self_lit, texture_id);
577 else
578 add_3dobject_to_abt(main_bbox_tree,
579 get_3dobject_id(id, i), bbox, blended, ground,
580 is_transparent, self_lit, texture_id, dynamic);
581 }
582
583 add_ec_effect_to_e3d(our_object);
584 ec_add_object_obstruction(our_object, returned_e3d, 2.0);
585 // LOG_DEBUG_VERBOSE("Bounding: %f, %f, %f -> %f, %f, %f\n", returned_e3d->min_x, returned_e3d->min_y, returned_e3d->min_z, returned_e3d->max_x, returned_e3d->max_y, returned_e3d->max_z);
586 // LOG_DEBUG_VERBOSE("Rotation: %f, %f, %f\n", our_object->x_rot, our_object->y_rot, our_object->z_rot);
587
588 return id;
589 }
590
add_e3d(const char * file_name,float x_pos,float y_pos,float z_pos,float x_rot,float y_rot,float z_rot,char self_lit,char blended,float r,float g,float b,unsigned int dynamic)591 int add_e3d(const char* file_name, float x_pos, float y_pos, float z_pos,
592 float x_rot, float y_rot, float z_rot, char self_lit, char blended,
593 float r, float g, float b, unsigned int dynamic)
594 {
595 int i;
596 #ifndef FASTER_MAP_LOAD
597 int j = 0;
598 #endif
599
600 #ifdef FASTER_MAP_LOAD
601 if (next_obj_3d < MAX_OBJ_3D && !objects_list[next_obj_3d])
602 return add_e3d_at_id(next_obj_3d, file_name, x_pos, y_pos, z_pos,
603 x_rot, y_rot, z_rot, self_lit, blended,
604 r, g, b, dynamic);
605
606 // Oh my, next_obj_3d is not free. Find a free spot in the e3d_list,
607 // but don't count on IDs being correct.
608 #endif
609 for (i = 0; i < MAX_OBJ_3D; i++)
610 {
611 if (!objects_list[i])
612 {
613 #ifndef FASTER_MAP_LOAD
614 if (j < objects_list_placeholders)
615 j++;
616 else
617 #endif
618 return add_e3d_at_id(i, file_name, x_pos, y_pos, z_pos,
619 x_rot, y_rot, z_rot, self_lit, blended,
620 r, g, b, dynamic);
621 }
622 }
623
624 // No free spot available
625 return -1;
626 }
627
628 #ifdef NEW_SOUND
get_3dobject_at_location(float x_pos,float y_pos)629 char * get_3dobject_at_location(float x_pos, float y_pos)
630 {
631 int i;
632 float offset = 0.5f;
633 for (i = 0; i < MAX_OBJ_3D; i++)
634 {
635 if (objects_list[i]
636 && objects_list[i]->x_pos > (x_pos - offset) && objects_list[i]->x_pos < (x_pos + offset)
637 && objects_list[i]->y_pos > (y_pos - offset) && objects_list[i]->y_pos < (y_pos + offset)
638 && objects_list[i]->display)
639 {
640 return objects_list[i]->file_name;
641 }
642 }
643 return "";
644 }
645 #endif // NEW_SOUND
646
display_objects(void)647 void display_objects(void)
648 {
649 CHECK_GL_ERRORS();
650 glEnable(GL_CULL_FACE);
651 glEnable(GL_COLOR_MATERIAL);
652 glEnableClientState(GL_VERTEX_ARRAY);
653 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
654
655 if (!dungeon && clouds_shadows)
656 {
657 //bind the detail texture
658 ELglActiveTextureARB(detail_unit);
659 glEnable(GL_TEXTURE_2D);
660 bind_texture_unbuffered(ground_detail_text);
661 ELglActiveTextureARB(base_unit);
662 glEnable(GL_TEXTURE_2D);
663 }
664
665 CHECK_GL_ERRORS();
666
667 draw_3d_objects(TYPE_3D_NO_BLEND_NO_GROUND_NO_ALPHA_SELF_LIT_OBJECT);
668 draw_3d_objects(TYPE_3D_NO_BLEND_NO_GROUND_NO_ALPHA_NO_SELF_LIT_OBJECT);
669 draw_3d_objects(TYPE_3D_NO_BLEND_GROUND_NO_ALPHA_SELF_LIT_OBJECT);
670 draw_3d_objects(TYPE_3D_NO_BLEND_GROUND_NO_ALPHA_NO_SELF_LIT_OBJECT);
671
672 CHECK_GL_ERRORS();
673 glDisable(GL_CULL_FACE);
674 glDisable(GL_COLOR_MATERIAL);
675 glDisableClientState(GL_VERTEX_ARRAY);
676 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
677 glDisableClientState(GL_COLOR_ARRAY);
678 glDisableClientState(GL_NORMAL_ARRAY);
679 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
680 if (!dungeon && clouds_shadows)
681 {
682 //disable the second texture unit
683 ELglActiveTextureARB(detail_unit);
684 glDisable(GL_TEXTURE_2D);
685 ELglActiveTextureARB(base_unit);
686 }
687 CHECK_GL_ERRORS();
688 }
689
display_ground_objects(void)690 void display_ground_objects(void)
691 {
692 CHECK_GL_ERRORS();
693 glEnable(GL_CULL_FACE);
694 glEnable(GL_COLOR_MATERIAL);
695 glEnableClientState(GL_VERTEX_ARRAY);
696 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
697
698 if (!dungeon && clouds_shadows)
699 {
700 //bind the detail texture
701 ELglActiveTextureARB(detail_unit);
702 glEnable(GL_TEXTURE_2D);
703 bind_texture_unbuffered(ground_detail_text);
704 ELglActiveTextureARB(base_unit);
705 glEnable(GL_TEXTURE_2D);
706 }
707
708 CHECK_GL_ERRORS();
709
710 draw_3d_objects(TYPE_3D_NO_BLEND_GROUND_ALPHA_SELF_LIT_OBJECT);
711 draw_3d_objects(TYPE_3D_NO_BLEND_GROUND_ALPHA_NO_SELF_LIT_OBJECT);
712
713 CHECK_GL_ERRORS();
714 glDisable(GL_CULL_FACE);
715 glDisable(GL_COLOR_MATERIAL);
716 glDisableClientState(GL_VERTEX_ARRAY);
717 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
718 glDisableClientState(GL_COLOR_ARRAY);
719 glDisableClientState(GL_NORMAL_ARRAY);
720 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
721 if (!dungeon && clouds_shadows)
722 {
723 //disable the second texture unit
724 ELglActiveTextureARB(detail_unit);
725 glDisable(GL_TEXTURE_2D);
726 ELglActiveTextureARB(base_unit);
727 }
728 CHECK_GL_ERRORS();
729 }
730
display_alpha_objects(void)731 void display_alpha_objects(void)
732 {
733 CHECK_GL_ERRORS();
734 glEnable(GL_COLOR_MATERIAL);
735 glEnableClientState(GL_VERTEX_ARRAY);
736 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
737
738 if (!dungeon && clouds_shadows)
739 {
740 //bind the detail texture
741 ELglActiveTextureARB(detail_unit);
742 glEnable(GL_TEXTURE_2D);
743 bind_texture_unbuffered(ground_detail_text);
744 ELglActiveTextureARB(base_unit);
745 glEnable(GL_TEXTURE_2D);
746 }
747
748 CHECK_GL_ERRORS();
749
750 draw_3d_objects(TYPE_3D_NO_BLEND_NO_GROUND_ALPHA_SELF_LIT_OBJECT);
751 draw_3d_objects(TYPE_3D_NO_BLEND_NO_GROUND_ALPHA_NO_SELF_LIT_OBJECT);
752
753 CHECK_GL_ERRORS();
754 glDisable(GL_COLOR_MATERIAL);
755 glDisableClientState(GL_VERTEX_ARRAY);
756 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
757 glDisableClientState(GL_COLOR_ARRAY);
758 glDisableClientState(GL_NORMAL_ARRAY);
759 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
760 if (!dungeon && clouds_shadows)
761 {
762 //disable the second texture unit
763 ELglActiveTextureARB(detail_unit);
764 glDisable(GL_TEXTURE_2D);
765 ELglActiveTextureARB(base_unit);
766 }
767 CHECK_GL_ERRORS();
768 }
769
display_blended_objects(void)770 void display_blended_objects(void)
771 {
772 CHECK_GL_ERRORS();
773 glEnable(GL_CULL_FACE);
774 glEnable(GL_BLEND);
775 glBlendFunc(GL_ONE,GL_ONE);
776 glEnable(GL_COLOR_MATERIAL);
777 glEnableClientState(GL_VERTEX_ARRAY);
778 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
779
780 if (!dungeon && clouds_shadows)
781 {
782 //bind the detail texture
783 ELglActiveTextureARB(detail_unit);
784 glEnable(GL_TEXTURE_2D);
785 bind_texture_unbuffered(ground_detail_text);
786 ELglActiveTextureARB(base_unit);
787 glEnable(GL_TEXTURE_2D);
788 }
789
790 CHECK_GL_ERRORS();
791
792 draw_3d_objects(TYPE_3D_BLEND_GROUND_NO_ALPHA_SELF_LIT_OBJECT);
793 draw_3d_objects(TYPE_3D_BLEND_GROUND_NO_ALPHA_NO_SELF_LIT_OBJECT);
794 draw_3d_objects(TYPE_3D_BLEND_GROUND_ALPHA_SELF_LIT_OBJECT);
795 draw_3d_objects(TYPE_3D_BLEND_GROUND_ALPHA_NO_SELF_LIT_OBJECT);
796
797 draw_3d_objects(TYPE_3D_BLEND_NO_GROUND_NO_ALPHA_SELF_LIT_OBJECT);
798 draw_3d_objects(TYPE_3D_BLEND_NO_GROUND_NO_ALPHA_NO_SELF_LIT_OBJECT);
799 draw_3d_objects(TYPE_3D_BLEND_NO_GROUND_ALPHA_SELF_LIT_OBJECT);
800 draw_3d_objects(TYPE_3D_BLEND_NO_GROUND_ALPHA_NO_SELF_LIT_OBJECT);
801
802 CHECK_GL_ERRORS();
803 glDisable(GL_CULL_FACE);
804 glDisable(GL_COLOR_MATERIAL);
805 glDisableClientState(GL_VERTEX_ARRAY);
806 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
807 glDisableClientState(GL_COLOR_ARRAY);
808 glDisableClientState(GL_NORMAL_ARRAY);
809 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
810 glDisable(GL_BLEND);
811 if (!dungeon && clouds_shadows)
812 {
813 //disable the second texture unit
814 ELglActiveTextureARB(detail_unit);
815 glDisable(GL_TEXTURE_2D);
816 ELglActiveTextureARB(base_unit);
817 }
818 CHECK_GL_ERRORS();
819 }
820
destroy_3d_object(int i)821 void destroy_3d_object(int i)
822 {
823 if (i < 0 || i >= MAX_OBJ_3D || !objects_list[i])
824 return;
825
826 ec_remove_obstruction_by_object3d(objects_list[i]);
827
828 delete_3dobject_from_abt(main_bbox_tree, i, objects_list[i]->blended, objects_list[i]->self_lit);
829 free(objects_list[i]);
830 objects_list[i] = NULL;
831 if (i == next_obj_3d-1)
832 {
833 while (next_obj_3d > 0 && !objects_list[next_obj_3d-1])
834 next_obj_3d--;
835 }
836 }
837
destroy_all_3d_objects(void)838 void destroy_all_3d_objects(void)
839 {
840 int i;
841
842 for (i = 0; i < MAX_OBJ_3D; i++)
843 {
844 if (objects_list[i])
845 {
846 ec_remove_obstruction_by_object3d(objects_list[i]);
847 if(!cache_find_item(cache_e3d, objects_list[i]->file_name))
848 destroy_e3d(objects_list[i]->e3d_data);
849 free(objects_list[i]);
850 objects_list[i] = NULL; // kill any reference to it
851 }
852 }
853
854 // reset the top pointer
855 next_obj_3d = 0;
856 }
857
free_e3d_va(e3d_object * e3d_id)858 Uint32 free_e3d_va(e3d_object *e3d_id)
859 {
860 set_all_intersect_update_needed(main_bbox_tree);
861
862 if (e3d_id == NULL)
863 return 0;
864
865 if (e3d_id->vertex_data != NULL)
866 {
867 free(e3d_id->vertex_data);
868 e3d_id->vertex_data = NULL;
869 }
870 if (e3d_id->indices != NULL)
871 {
872 free(e3d_id->indices);
873 e3d_id->indices = NULL;
874 }
875 if (e3d_id->vertex_vbo != 0)
876 {
877 ELglDeleteBuffersARB(1, &e3d_id->vertex_vbo);
878 e3d_id->vertex_vbo = 0;
879 }
880 if (e3d_id->indices_vbo != 0)
881 {
882 ELglDeleteBuffersARB(1, &e3d_id->indices_vbo);
883 e3d_id->indices_vbo = 0;
884 }
885
886 if (e3d_id->cache_ptr != NULL)
887 return (e3d_id->cache_ptr->size - sizeof(*e3d_id));
888 else
889 return sizeof(*e3d_id);
890 }
891
destroy_e3d(e3d_object * e3d_id)892 void destroy_e3d(e3d_object *e3d_id)
893 {
894 // release the detailed data
895 free_e3d_va(e3d_id);
896 // free the materials (not free'd in free_e3d_va)
897 if(e3d_id->materials) free(e3d_id->materials);
898 e3d_id->materials= NULL;
899 // and finally free the main object
900
901 ec_remove_obstruction_by_e3d_object(e3d_id);
902
903 free(e3d_id);
904 }
905
906 // for support of the 1.0.3 server, change if an object is to be displayed or not
set_3d_object(Uint8 display,const void * ptr,int len)907 void set_3d_object (Uint8 display, const void *ptr, int len)
908 {
909 const Uint32 *id_ptr = ptr;
910
911 // first look for the override to process ALL objects
912 if (len < sizeof(*id_ptr))
913 {
914 int i;
915 for (i = 0; i < next_obj_3d; i++)
916 {
917 if (objects_list[i])
918 objects_list[i]->display = display;
919 }
920 }
921 else
922 {
923 int idx = 0;
924 while (len >= sizeof(*id_ptr))
925 {
926 int obj_id = SDL_SwapLE32(id_ptr[idx]);
927 if (obj_id < next_obj_3d && objects_list[obj_id])
928 objects_list[obj_id]->display = display;
929 idx++;
930 len -= sizeof (*id_ptr);
931 }
932 }
933 }
934
935 // for future expansion
state_3d_object(Uint8 state,const void * ptr,int len)936 void state_3d_object (Uint8 state, const void *ptr, int len)
937 {
938 const Uint32 *id_ptr = ptr;
939
940 // first look for the override to process ALL objects
941 if (len < sizeof(*id_ptr))
942 {
943 int i;
944 for (i = 0; i < next_obj_3d; i++)
945 {
946 if (objects_list[i])
947 objects_list[i]->state= state;
948 }
949 }
950 else
951 {
952 int idx = 0;
953
954 while (len >= sizeof(*id_ptr))
955 {
956 int obj_id = SDL_SwapLE32(id_ptr[idx]);
957 if (obj_id < next_obj_3d && objects_list[obj_id])
958 objects_list[obj_id]->state = state;
959 idx++;
960 len -= sizeof (*id_ptr);
961 }
962 }
963 }
964