#include #include #include #ifdef MAP_EDITOR2 #include "../map_editor2/global.h" #else #include "global.h" #endif #define INVALID -1 #define GROUND 0 #define PLANT 1 #define FENCE 2 #ifndef NEW_FRUSTUM #define SECTOR_SIZE_X 15 #define SECTOR_SIZE_Y 15 #endif obj_2d *obj_2d_list[MAX_OBJ_2D]; #ifndef NEW_FRUSTUM int nearby_2d_objects[MAX_NEARBY_2D_OBJECTS]; int no_nearby_2d_objects=0; int regenerate_near_2d_objects=1; #endif int map_meters_size_x; int map_meters_size_y; float texture_scale=12.0; void draw_2d_object(obj_2d * object_id) { float render_x_start,render_y_start,u_start,v_start,u_end,v_end; float x_pos,y_pos,z_pos; float x_rot,y_rot,z_rot; float x_size,y_size; int object_type; obj_2d_def *obj_def_pointer; if(!object_id->display) return; // not currently on the map, ignore it obj_def_pointer=object_id->obj_pointer; u_start=obj_def_pointer->u_start; u_end=obj_def_pointer->u_end; v_start=obj_def_pointer->v_start; v_end=obj_def_pointer->v_end; x_size=obj_def_pointer->x_size; y_size=obj_def_pointer->y_size; render_x_start=-x_size/2.0f; object_type=obj_def_pointer->object_type; if(object_type==GROUND)render_y_start=-y_size/2; else render_y_start=0; glPushMatrix();//we don't want to affect the rest of the scene x_pos=object_id->x_pos; y_pos=object_id->y_pos; z_pos=object_id->z_pos; #ifdef NEW_FRUSTUM if (object_type != PLANT) { glMultMatrixf(object_id->matrix); z_rot = object_id->z_rot; } else { glTranslatef (x_pos, y_pos, 0); x_rot = object_id->x_rot + 90; y_rot = object_id->y_rot; z_rot=-rz; glRotatef(z_rot, 0.0f, 0.0f, 1.0f); glRotatef(x_rot, 1.0f, 0.0f, 0.0f); glRotatef(y_rot, 0.0f, 1.0f, 0.0f); } #else glTranslatef (x_pos, y_pos, 0); x_rot=object_id->x_rot; y_rot=object_id->y_rot; z_rot=object_id->z_rot; //find out what kind of object we have if(object_type==FENCE)x_rot+=90; if(object_type==PLANT) { x_rot+=90; z_rot=-rz; } glRotatef(z_rot, 0.0f, 0.0f, 1.0f); glRotatef(x_rot, 1.0f, 0.0f, 0.0f); glRotatef(y_rot, 0.0f, 1.0f, 0.0f); #endif get_and_set_texture_id(obj_def_pointer->texture_id); #ifdef NEW_LIGHTING if (use_new_lighting) reset_material(); #endif if(!have_multitexture || dungeon || (!clouds_shadows && !use_shadow_mapping)) { glBegin(GL_QUADS); glTexCoord2f(u_start,v_start); glVertex3f(render_x_start,render_y_start,z_pos); glTexCoord2f(u_start,v_end); glVertex3f(render_x_start,render_y_start+y_size,z_pos); glTexCoord2f(u_end,v_end); glVertex3f(render_x_start+x_size,render_y_start+y_size,z_pos); glTexCoord2f(u_end,v_start); glVertex3f(render_x_start+x_size,render_y_start,z_pos); glEnd(); } else { float m,x,y,x1,y1; float cos_m,sin_m; glBegin(GL_QUADS); m=(-z_rot)*M_PI/180; cos_m=cos(m); sin_m=sin(m); x=render_x_start; y=render_y_start; x1=x*cos_m+y*sin_m; y1=y*cos_m-x*sin_m; x1=x_pos+x1; y1=y_pos+y1; ELglMultiTexCoord2fARB(base_unit,u_start,v_start); ELglMultiTexCoord2fARB(detail_unit,x1/texture_scale +clouds_movement_u,y1/texture_scale +clouds_movement_v); glVertex3f(x,y,z_pos); x=render_x_start; y=render_y_start+y_size; x1=x*cos_m+y*sin_m; y1=y*cos_m-x*sin_m; x1=x_pos+x1; y1=y_pos+y1; ELglMultiTexCoord2fARB(base_unit,u_start,v_end); ELglMultiTexCoord2fARB(detail_unit,x1/texture_scale +clouds_movement_u,y1/texture_scale +clouds_movement_v); glVertex3f(x,y,z_pos); x=render_x_start+x_size; y=render_y_start+y_size; x1=x*cos_m+y*sin_m; y1=y*cos_m-x*sin_m; x1=x_pos+x1; y1=y_pos+y1; ELglMultiTexCoord2fARB(base_unit,u_end,v_end); ELglMultiTexCoord2fARB(detail_unit,x1/texture_scale +clouds_movement_u,y1/texture_scale +clouds_movement_v); glVertex3f(x,y,z_pos); x=render_x_start+x_size; y=render_y_start; x1=x*cos_m+y*sin_m; y1=y*cos_m-x*sin_m; x1=x_pos+x1; y1=y_pos+y1; ELglMultiTexCoord2fARB(base_unit,u_end,v_start); ELglMultiTexCoord2fARB(detail_unit,x1/texture_scale +clouds_movement_u,y1/texture_scale +clouds_movement_v); glVertex3f(x,y,z_pos); glEnd(); } glPopMatrix();//restore the scene #ifdef OPENGL_TRACE CHECK_GL_ERRORS(); #endif //OPENGL_TRACE } obj_2d_def * load_obj_2d_def(char *file_name) { int f_size; int i,k,l; FILE *f = NULL; char cur_dir[200]={0}; obj_2d_def *cur_object; char *obj_file_mem; char texture_file_name[256] = {0}; char *handle_obj_file_mem; float x_size,y_size; float alpha_test; int file_x_len; int file_y_len; int u_start,u_end,v_start,v_end; cur_object=calloc(1, sizeof(obj_2d_def)); //get the current directory l=strlen(file_name); //parse the string backwards, until we find a / while(l>0) { if(file_name[l]=='/' || file_name[l]=='\\')break; l--; } i=0; if(l)//prevent invalid dir names { while(l>=0) { cur_dir[i]=file_name[i]; i++; l--; } cur_dir[i+1]=0; } f = my_fopen (file_name, "rb"); if(!f) { free(cur_object); return NULL; } fseek (f, 0, SEEK_END); f_size = ftell (f); //ok, allocate memory for it obj_file_mem = calloc ( f_size+1, sizeof(char) ); handle_obj_file_mem = obj_file_mem; fseek (f, 0, SEEK_SET); fread (obj_file_mem, 1, f_size, f); fclose (f); //ok, the file is loaded, so parse it file_x_len=get_integer_after_string("file_x_len:",obj_file_mem,f_size); file_y_len=get_integer_after_string("file_y_len:",obj_file_mem,f_size); u_start=get_integer_after_string("u_start:",obj_file_mem,f_size); u_end=get_integer_after_string("u_end:",obj_file_mem,f_size); v_start=get_integer_after_string("v_start:",obj_file_mem,f_size); v_end=get_integer_after_string("v_end:",obj_file_mem,f_size); x_size=get_float_after_string("x_size:",obj_file_mem,f_size); y_size=get_float_after_string("y_size:",obj_file_mem,f_size); alpha_test=get_float_after_string("alpha_test:",obj_file_mem,f_size); if(alpha_test<0)alpha_test=0; //get the proper u/v coordinates cur_object->u_start=(float)u_start/file_x_len; cur_object->u_end=(float)u_end/file_x_len; cur_object->v_start=1.0f-(float)v_start/file_y_len; cur_object->v_end=1.0f-(float)v_end/file_y_len; cur_object->x_size=x_size; cur_object->y_size=y_size; cur_object->alpha_test=alpha_test; //now find the texture name i=get_string_occurance("texture:",obj_file_mem,40,0); obj_file_mem+=i; k=0; //find the file name while(k<128) { if(obj_file_mem[k]!=' ' && obj_file_mem[k]!=0x0a)break; k++; } //we found the beginning of the file name //now, copy the current directory string to the file_name string i=strlen(cur_dir); l=0; while(ltexture_id=load_texture_cache_deferred(texture_file_name,0); //now get the object type i=get_string_occurance("type:",obj_file_mem,f_size,0); obj_file_mem+=i; k=0; for(k=0;k<10;k++) { if(obj_file_mem[k]==0x0a) { cur_object->object_type=INVALID; break; } if(obj_file_mem[k]==' ')continue; if(obj_file_mem[k]=='g' || obj_file_mem[k]=='G') { cur_object->object_type=GROUND; break; } if(obj_file_mem[k]=='p' || obj_file_mem[k]=='P') { cur_object->object_type=PLANT; break; } if(obj_file_mem[k]=='f' || obj_file_mem[k]=='F') { cur_object->object_type=FENCE; break; } } free(handle_obj_file_mem); return cur_object; } //Tests to see if an obj_2d object is already loaded. //If it is, return the handle. //If not, load it, and return the handle obj_2d_def * load_obj_2d_def_cache(char * file_name) { int i; //int j; int file_name_length; obj_2d_def * obj_2d_def_id; file_name_length=strlen(file_name); for(i=0;ifile_name, fname, 80); our_object->x_pos=x_pos; our_object->y_pos=y_pos; our_object->z_pos=z_pos; our_object->x_rot=x_rot; our_object->y_rot=y_rot; our_object->z_rot=z_rot; our_object->obj_pointer=returned_obj_2d_def; our_object->display= 1; our_object->state= 0; obj_2d_list[i]=our_object; #ifdef NEW_FRUSTUM len_x = (returned_obj_2d_def->x_size); len_y = (returned_obj_2d_def->y_size); bbox.bbmin[X] = -len_x*0.5f; bbox.bbmax[X] = len_x*0.5f; if (returned_obj_2d_def->object_type == GROUND) { bbox.bbmin[Y] = -len_y*0.5f; bbox.bbmax[Y] = len_y*0.5f; } else { bbox.bbmin[Y] = 0.0f; bbox.bbmax[Y] = len_y; if (returned_obj_2d_def->object_type == PLANT) { x_rot += 90.0f; z_rot = 0.0f; #ifdef M_SQRT2 bbox.bbmin[X] *= M_SQRT2; bbox.bbmax[X] *= M_SQRT2; bbox.bbmin[Y] *= M_SQRT2; bbox.bbmax[Y] *= M_SQRT2; #else //M_SQRT2 bbox.bbmin[X] *= sqrt(2); bbox.bbmax[X] *= sqrt(2); bbox.bbmin[Y] *= sqrt(2); bbox.bbmax[Y] *= sqrt(2); #endif //M_SQRT2 } else if (returned_obj_2d_def->object_type == FENCE) x_rot += 90.0f; } bbox.bbmin[Z] = z_pos; bbox.bbmax[Z] = z_pos; calc_rotation_and_translation_matrix(our_object->matrix, x_pos, y_pos, 0.0f, x_rot, y_rot, z_rot); matrix_mul_aabb(&bbox, our_object->matrix); if (returned_obj_2d_def->alpha_test) alpha_test = 1; else alpha_test = 0; texture_id = returned_obj_2d_def->texture_id; if ((main_bbox_tree_items != NULL) && (dynamic == 0)) add_2dobject_to_list(main_bbox_tree_items, i, bbox, alpha_test, texture_id); else add_2dobject_to_abt(main_bbox_tree, i, bbox, alpha_test, texture_id, dynamic); #else //get the current sector sector = (short) ((y_pos/SECTOR_SIZE_Y) * (map_meters_size_x/SECTOR_SIZE_X) + (x_pos/SECTOR_SIZE_X)); our_object->sector=sector; regenerate_near_2d_objects=1;//We've added a new object... #endif return i; } #ifndef NEW_FRUSTUM int get_nearby_2d_objects() { int i; float x,y; int sx,sy,ex,ey,j,k; #ifdef MAP_EDITOR2 no_nearby_2d_objects=0; x = -camera_x; y = -camera_y; get_supersector(SECTOR_GET(global_x_pos,global_y_pos), &sx, &sy, &ex, &ey); #else actor *xxx=pf_get_our_actor(); no_nearby_2d_objects=0; if (xxx == NULL) return 0; x = -camera_x; y = -camera_y; get_supersector(SECTOR_GET(xxx->x_pos,xxx->y_pos), &sx, &sy, &ex, &ey); #endif for (i = sx; i <= ex; i++) { for (j = sy; j <= ey; j++) { for (k = 0; k < 100;k++) { int l = sectors[(j*(tile_map_size_x>>2))+i].e2d_local[k]; if (l == -1) break; if (obj_2d_list[l] != NULL) { float dist1, dist2; dist1 = x - obj_2d_list[l]->x_pos; dist2 = y - obj_2d_list[l]->y_pos; if (dist1*dist1 + dist2*dist2 <= 220.0f) { nearby_2d_objects[no_nearby_2d_objects] = l; no_nearby_2d_objects++; } } } } } regenerate_near_2d_objects = 0; return no_nearby_2d_objects; } #endif #ifdef MAP_EDITOR2 void get_2d_object_under_mouse() { #ifndef NEW_FRUSTUM int i; float least_z = 1.0f; if(regenerate_near_2d_objects) if(!get_nearby_2d_objects()) return; glClearDepth(least_z); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glPushMatrix(); glLoadIdentity(); glRotatef(rx, 1.0f, 0.0f, 0.0f); glRotatef(rz, 0.0f, 0.0f, 1.0f); glTranslatef(camera_x, camera_y, camera_z); for(i=0;iobj_pointer) { draw_2d_object(obj_2d_list[nearby_2d_objects[i]]); if(evaluate_collision(&least_z)){ selected_2d_object = nearby_2d_objects[i]; } } } glPopMatrix(); #else unsigned int i, l; float least_z = 1.0f; //First draw everyone with the same alpha test glPushMatrix(); glClearDepth(least_z); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); for (i = get_intersect_start(main_bbox_tree, TYPE_2D_NO_ALPHA_OBJECT); i < get_intersect_stop(main_bbox_tree, TYPE_2D_NO_ALPHA_OBJECT); i++) { l = get_intersect_item_ID(main_bbox_tree, i); #ifdef EXTRA_DEBUG if (!obj_2d_list[l]) { ERR(); continue; } #endif draw_2d_object(obj_2d_list[l]); if(evaluate_collision(&least_z)){ selected_2d_object = l; } } //Then draw all that needs a change for (i = get_intersect_start(main_bbox_tree, TYPE_2D_ALPHA_OBJECT); i < get_intersect_stop(main_bbox_tree, TYPE_2D_ALPHA_OBJECT); i++) { l = get_intersect_item_ID(main_bbox_tree, i); #ifdef EXTRA_DEBUG if (!obj_2d_list[l]) { ERR(); continue; } #endif draw_2d_object(obj_2d_list[l]); if(evaluate_collision(&least_z)){ selected_2d_object = l; } } glPopMatrix(); #endif #ifdef OPENGL_TRACE CHECK_GL_ERRORS(); #endif //OPENGL_TRACE } #endif void display_2d_objects() { #ifndef NEW_FRUSTUM int i; if(regenerate_near_2d_objects) if(!get_nearby_2d_objects()) return; //First draw everyone with the same alpha test glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER,0.18f); if(have_multitexture && !dungeon && !(!clouds_shadows && !use_shadow_mapping)) { if(clouds_shadows) { //bind the detail texture ELglActiveTextureARB(detail_unit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, get_texture_id(ground_detail_text)); } ELglActiveTextureARB(base_unit); glEnable(GL_TEXTURE_2D); } for(i=0;iobj_pointer && !obj_2d_list[nearby_2d_objects[i]]->obj_pointer->alpha_test) { draw_2d_object(obj_2d_list[nearby_2d_objects[i]]); } } //Then draw all that needs a change for(i=0;iobj_pointer && obj_2d_list[nearby_2d_objects[i]]->obj_pointer->alpha_test){ glAlphaFunc(GL_GREATER,obj_2d_list[nearby_2d_objects[i]]->obj_pointer->alpha_test); draw_2d_object(obj_2d_list[nearby_2d_objects[i]]); } } #else unsigned int i, l, start, stop; int x, y; #ifdef SIMPLE_LOD int dist; #endif //SIMPLE_LOD x= -camera_x; y= -camera_y; //First draw everyone with the same alpha test glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.18f); if(have_multitexture && !dungeon && !(!clouds_shadows && !use_shadow_mapping)) { if(clouds_shadows) { //bind the detail texture ELglActiveTextureARB(detail_unit); glEnable(GL_TEXTURE_2D); //glBindTexture(GL_TEXTURE_2D, texture_cache[ground_detail_text].texture_id); glBindTexture(GL_TEXTURE_2D, get_texture_id(ground_detail_text)); } ELglActiveTextureARB(base_unit); glEnable(GL_TEXTURE_2D); } get_intersect_start_stop(main_bbox_tree, TYPE_2D_NO_ALPHA_OBJECT, &start, &stop); for (i = start; i < stop; i++) { l = get_intersect_item_ID(main_bbox_tree, i); #ifdef SIMPLE_LOD // simple size/distance culling dist= (x-obj_2d_list[l]->x_pos)*(x-obj_2d_list[l]->x_pos) + (y-obj_2d_list[l]->y_pos)*(y-obj_2d_list[l]->y_pos); if(/*dist > 10*10 &&*/ 1000*max2f(obj_2d_list[l]->obj_pointer->x_size, obj_2d_list[l]->obj_pointer->y_size)/(dist) < 5) continue; #endif //SIMPLE_LOD draw_2d_object(obj_2d_list[l]); } //Then draw all that needs a change get_intersect_start_stop(main_bbox_tree, TYPE_2D_ALPHA_OBJECT, &start, &stop); for (i = start; i < stop; i++) { l = get_intersect_item_ID(main_bbox_tree, i); #ifdef SIMPLE_LOD // simple size/distance culling dist= (x-obj_2d_list[l]->x_pos)*(x-obj_2d_list[l]->x_pos) + (y-obj_2d_list[l]->y_pos)*(y-obj_2d_list[l]->y_pos); if(/*dist > 10*10 &&*/ 1000*max2f(obj_2d_list[l]->obj_pointer->x_size, obj_2d_list[l]->obj_pointer->y_size)/(dist) < 5) continue; #endif //SIMPLE_LOD glAlphaFunc(GL_GREATER, obj_2d_list[l]->obj_pointer->alpha_test); draw_2d_object(obj_2d_list[l]); } #endif if(have_multitexture && !dungeon && !(!clouds_shadows && !use_shadow_mapping)) { //disable the multitexturing ELglActiveTextureARB(detail_unit); glDisable(GL_TEXTURE_2D); ELglActiveTextureARB(base_unit); } glDisable(GL_ALPHA_TEST); #ifdef OPENGL_TRACE CHECK_GL_ERRORS(); #endif //OPENGL_TRACE } #ifdef NEW_FRUSTUM void destroy_2d_object(int i) { if ((i < 0) || (i >= MAX_OBJ_2D)) return; if (obj_2d_list[i] == NULL) return; delete_2dobject_from_abt(main_bbox_tree, i, obj_2d_list[i]->obj_pointer->alpha_test); free(obj_2d_list[i]); obj_2d_list[i] = NULL; } #endif // for support of the 1.0.3 server, change if an object is to be displayed or not void set_2d_object (Uint8 display, const void *ptr, int len) { const Uint32 *id_ptr = ptr; // first look for the override to process ALL objects if (len < sizeof(*id_ptr) ){ int i; for (i = 0; i < MAX_OBJ_2D; i++) { if (obj_2d_list[i]){ obj_2d_list[i]->display= display; } } } else { int idx = 0; while(len >= sizeof(*id_ptr)){ Uint32 obj_id= id_ptr[idx]; if(obj_id < MAX_OBJ_2D && obj_2d_list[obj_id]){ obj_2d_list[obj_id]->display= display; idx++; len-= sizeof(*id_ptr); } } } } // for future expansion void state_2d_object (Uint8 state, const void *ptr, int len) { const Uint32 *id_ptr = ptr; // first look for the override to process ALL objects if (len < sizeof(*id_ptr) ){ int i; for (i = 0; i < MAX_OBJ_2D; i++) { if (obj_2d_list[i]){ obj_2d_list[i]->state= state; } } } else { int idx = 0; while(len >= sizeof(*id_ptr)){ Uint32 obj_id= id_ptr[idx]; if(obj_id < MAX_OBJ_2D && obj_2d_list[obj_id]){ obj_2d_list[obj_id]->state= state; idx++; len -= sizeof (*id_ptr); } } } }