www.pudn.com > map_editor.rar > reflection.c
#include "global.h" #includefloat mrandom(float max) { return ((float) max * (rand () % 8 )); } #ifdef NEW_E3D_FORMAT #include "../elc/e3d_object.h" void draw_3d_reflection(object3d * object_id) { int texture_id, i; float x_pos,y_pos,z_pos; float x_rot,y_rot,z_rot; void* data_ptr; int vertex_size; //also, update the last time this object was used object_id->last_acessed_time=cur_time; if(object_id->self_lit && (night_shadows_on || dungeon)) { glDisable(GL_LIGHTING); //set_material(object_id->r,object_id->g,object_id->b); glColor3f(object_id->r,object_id->g,object_id->b); } CHECK_GL_ERRORS(); 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; glTranslatef (x_pos, y_pos, z_pos); x_rot = object_id->x_rot; y_rot = object_id->y_rot; z_rot = object_id->z_rot; 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); CHECK_GL_ERRORS(); if (have_vertex_buffers) { ELglBindBufferARB(GL_ARRAY_BUFFER_ARB, object_id->e3d_data->vertex_vbo); data_ptr = 0; } else { data_ptr = object_id->e3d_data->vertex_data; } vertex_size = get_vertex_size(object_id->e3d_data->vertex_options); // No ground objects glNormalPointer(GL_FLOAT, vertex_size, data_ptr + get_normal_offset(object_id->e3d_data->vertex_options)); #ifdef USE_TANGENT if (use_tangent && has_tangen(object_id->e3d_data->vertex_options)) { EnableVertexAttribArray(tangent_attribut); VertexAttribPointer(tangent_attribut, TANGENT_FLOAT_COUNT, GL_FLOAT, GL_FALSE, vertex_size, data_ptr + get_tangent_offset(vertex_options)); } #endif //USE_TANGENT #ifdef USE_EXTRA_TEXTURE if (use_extra_texture && has_extra_texture(object_id->e3d_data->vertex_options)) { glClientActiveTextureARB(GL_TEXTURE2_ARB); ELglActiveTextureARB(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(EXTRA_TEXTURE_FLOAT_COUNT, GL_FLOAT, vertex_size, data_ptr + get_extra_texture_offset(vertex_options)); ELglActiveTextureARB(GL_TEXTURE0_ARB); glClientActiveTextureARB(GL_TEXTURE0_ARB); } #endif //USE_EXTRA_TEXTURE glTexCoordPointer(TEXTURE_FLOAT_COUNT, GL_FLOAT, vertex_size, data_ptr + get_texture_offset(object_id->e3d_data->vertex_options)); glVertexPointer(VERTEX_FLOAT_COUNT, GL_FLOAT, vertex_size, data_ptr + get_vertex_offset(object_id->e3d_data->vertex_options)); if (have_vertex_buffers) { ELglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object_id->e3d_data->indicies_vbo); } CHECK_GL_ERRORS(); for (i = 0; i < object_id->e3d_data->material_no; i++) { if (material_is_transparent(object_id->e3d_data->materials[i].options)) { //enable alpha filtering, so we have some alpha key glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.05f); glDisable(GL_CULL_FACE); } else { glDisable(GL_ALPHA_TEST); glEnable(GL_CULL_FACE); } texture_id = get_texture_id(object_id->e3d_data->materials[i].diffuse_map); if (last_texture != texture_id) { glBindTexture(GL_TEXTURE_2D, texture_id); last_texture = texture_id; } ELglDrawRangeElementsEXT(GL_TRIANGLES, object_id->e3d_data->materials[i].triangles_indicies_min, object_id->e3d_data->materials[i].triangles_indicies_max, object_id->e3d_data->materials[i].triangles_indicies_count, object_id->e3d_data->index_type, object_id->e3d_data->materials[i].triangles_indicies_index); } glPopMatrix();//restore the scene CHECK_GL_ERRORS(); if (have_multitexture && clouds_shadows) { glClientActiveTextureARB(GL_TEXTURE1_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } #ifdef USE_TANGENT if (use_tangent && has_tangen(object_id->e3d_data->vertex_options)) { DisableVertexAttribArray(tangent_attribut); } #endif //USE_TANGENT #ifdef USE_EXTRA_TEXTURE if (use_extra_texture && has_extra_texture(object_id->e3d_data->vertex_options)) { glClientActiveTextureARB(GL_TEXTURE2_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); } #endif //USE_EXTRA_TEXTURE if (object_id->self_lit && (night_shadows_on || dungeon)) glEnable(GL_LIGHTING); if (material_is_transparent(object_id->e3d_data->materials[object_id->e3d_data->material_no-1].options)) { glDisable(GL_ALPHA_TEST); glEnable(GL_CULL_FACE); } CHECK_GL_ERRORS(); } #else //NEW_E3D_FORMAT void draw_3d_reflection(object3d * object_id) { float x_pos,y_pos,z_pos; float x_rot,y_rot,z_rot; int materials_no,texture_id; int i; e3d_array_vertex *array_vertex; e3d_array_normal *array_normal; e3d_array_uv_main *array_uv_main; e3d_array_order *array_order; int is_transparent; CHECK_GL_ERRORS(); is_transparent=object_id->e3d_data->is_transparent; materials_no=object_id->e3d_data->materials_no; array_vertex=object_id->e3d_data->array_vertex; array_normal=object_id->e3d_data->array_normal; array_uv_main=object_id->e3d_data->array_uv_main; array_order=object_id->e3d_data->array_order; if(object_id->self_lit && (night_shadows_on || dungeon)) { glDisable(GL_LIGHTING); glColor3f(object_id->r,object_id->g,object_id->b); } if(is_transparent) { glEnable(GL_ALPHA_TEST);//enable alpha filtering, so we have some alpha key glAlphaFunc(GL_GREATER,0.05f); } CHECK_GL_ERRORS(); 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; if(z_pos<0)z_pos+=-water_deepth_offset*2; glTranslatef (x_pos, y_pos,z_pos); x_rot=object_id->x_rot; y_rot=object_id->y_rot; z_rot=object_id->z_rot; 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); CHECK_GL_ERRORS(); glVertexPointer(3,GL_FLOAT,0,array_vertex); glTexCoordPointer(2,GL_FLOAT,0,array_uv_main); glNormalPointer(GL_FLOAT,0,array_normal); for(i=0;i self_lit && (night_shadows_on || dungeon))glEnable(GL_LIGHTING); if(is_transparent) { glDisable(GL_ALPHA_TEST); } CHECK_GL_ERRORS(); } #endif //NEW_E3D_FORMAT //if there is any reflecting tile, returns 1, otherwise 0 int find_reflection() { int x_start,x_end,y_start,y_end; int x,y; float x_scaled,y_scaled; int found_water=0; //get only the tiles around the camera //we have the axes inverted, btw the go from 0 to -255 if(camera_x<0)x=(int)(camera_x*-1)/3; else x=(int)camera_x/3; if(camera_y<0)y=(int)(camera_y*-1)/3; else y=(int)camera_y/3; x_start=(int)x-4; y_start=(int)y-4; x_end=(int)x+4; y_end=(int)y+4; if(x_start<0)x_start=0; if(x_end>=tile_map_size_x)x_end=tile_map_size_x-1; if(y_start<0)y_start=0; if(y_end>=tile_map_size_y)y_end=tile_map_size_y-1; for(y=y_start;y<=y_end;y++) { y_scaled=y*3.0f; for(x=x_start;x<=x_end;x++) { x_scaled=x*3.0f; if(!check_tile_in_frustrum(x_scaled,y_scaled))continue;//outside of the frustrum if(is_water_tile(tile_map[y*tile_map_size_x+x])) { if(is_reflecting(tile_map[y*tile_map_size_x+x]))return 2; found_water=1; } } } return found_water; } int find_local_reflection(int x_pos,int y_pos,int range) { int x_start,x_end,y_start,y_end; int x,y; int found_water=0; //get only the tiles around the camera //we have the axes inverted, btw the go from 0 to -255 if(x_pos<0)x=(x_pos*-1)/3; else x=x_pos/3; if(y_pos<0)y=(y_pos*-1)/3; else y=y_pos/3; x_start=(int)x-range; y_start=(int)y-range; x_end=(int)x+range; y_end=(int)y+range; if(x_start<0)x_start=0; if(x_end>=tile_map_size_x)x_end=tile_map_size_x-1; if(y_start<0)y_start=0; if(y_end>=tile_map_size_y)y_end=tile_map_size_y-1; for(y=y_start;y<=y_end;y++) { for(x=x_start;x<=x_end;x++) { if(is_water_tile(tile_map[y*tile_map_size_x+x])) { if(is_reflecting(tile_map[y*tile_map_size_x+x]))return 2; found_water=1; } } } return found_water; } void display_3d_reflection() { int i; int x,y; double water_clipping_p[4]={0,0,-1,water_deepth_offset}; x=(int)-camera_x; y=(int)-camera_y; glEnable(GL_CLIP_PLANE0); glClipPlane(GL_CLIP_PLANE0, water_clipping_p); glDisable(GL_CULL_FACE); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); set_material(0.1f,0.2f,0.3f); glPushMatrix(); glScalef(1.0f, 1.0f, -1.0f); for (i = 0; i < MAX_OBJ_3D; i++) { if(objects_list[i] && objects_list[i]->blended!=20) { #ifndef NEW_E3D_FORMAT if(!objects_list[i]->e3d_data->is_ground) #else //NEW_E3D_FORMAT if (!is_ground(objects_list[i]->e3d_data->vertex_options)) #endif //NEW_E3D_FORMAT { int dist1; int dist2; dist1=x-(int)objects_list[i]->x_pos; dist2=y-(int)objects_list[i]->y_pos; if(dist1*dist1+dist2*dist2<=21*21) { #ifdef NEW_E3D_FORMAT draw_3d_reflection(objects_list[i]); #else //NEW_E3D_FORMAT float x_len, y_len, z_len; float radius; z_len=objects_list[i]->e3d_data->max_z-objects_list[i]->e3d_data->min_z; x_len=objects_list[i]->e3d_data->max_x-objects_list[i]->e3d_data->min_x; y_len=objects_list[i]->e3d_data->max_y-objects_list[i]->e3d_data->min_y; //do some checks, to see if we really have to display this object if(x_len<5 && y_len<5 && z_len<4 && !find_local_reflection((int)objects_list[i]->x_pos,(int)objects_list[i]->y_pos,1))continue; radius=x_len/2; if(radius x_pos,objects_list[i]->y_pos, objects_list[i]->z_pos,radius)) draw_3d_reflection(objects_list[i]); #endif //NEW_E3D_FORMAT } } } } glPopMatrix(); reset_material(); glDisable(GL_CLIP_PLANE0); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void make_lake_water_noise() { int x,y; float noise_u,noise_v; for(x=0;x<16;x++) for(y=0;y<16;y++) { noise_u=mrandom(0.001f); noise_v=mrandom(0.001f); noise_array[y*16+x].u=noise_u; noise_array[y*16+x].v=noise_v; } } void draw_lake_water_tile(float x_pos, float y_pos) { int x,y; float fx,fy; float x_step,y_step; float u_step,v_step; float uv_tile=50; x_step=3.0f/16.0f; y_step=3.0f/16.0f; u_step=3.0f/uv_tile; v_step=3.0f/uv_tile; glBegin(GL_QUADS); for(y=0,fy=y_pos;y<16;fy+=y_step,y++) { for(x=0,fx=x_pos;x<16;fx+=x_step,x++) { glTexCoord2f((fx)*u_step+noise_array[((y+1)&15)*16+x].u+water_movement_u, (fy+y_step)*v_step+noise_array[((y+1)&15)*16+x].v+water_movement_v); glVertex3f(fx,fy+y_step, water_deepth_offset); glTexCoord2f((fx)*u_step+noise_array[y*16+x].u+water_movement_u, (fy)*v_step+noise_array[y*16+x].v+water_movement_v); glVertex3f(fx,fy, water_deepth_offset); glTexCoord2f((fx+x_step)*u_step+noise_array[y*16+((x+1)&15)].u+water_movement_u, (fy)*v_step+noise_array[y*16+((x+1)&15)].v+water_movement_v); glVertex3f(fx+x_step, fy,water_deepth_offset); glTexCoord2f((fx+x_step)*u_step+noise_array[((y+1)&15)*16+((x+1)&15)].u+water_movement_u, (fy+y_step)*v_step+noise_array[((y+1)&15)*16+((x+1)&15)].v+water_movement_v); glVertex3f(fx+x_step, fy+y_step,water_deepth_offset); } } glEnd(); } void draw_lake_tiles() { int x_start,x_end,y_start,y_end; int x,y; float x_scaled,y_scaled; //glDisable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); //get only the tiles around the camera //we have the axes inverted, btw the go from 0 to -255 if(camera_x<0)x=(int)(camera_x*-1)/3; else x=(int)camera_x/3; if(camera_y<0)y=(int)(camera_y*-1)/3; else y=(int)camera_y/3; x_start=x-(int)zoom_level; y_start=y-(int)zoom_level; x_end=x+(int)zoom_level; y_end=y+(int)zoom_level; if(x_start<0)x_start=0; if(x_end>=tile_map_size_x)x_end=tile_map_size_x-1; if(y_start<0)y_start=0; if(y_end>=tile_map_size_y)y_end=tile_map_size_y-1; for(y=y_start;y<=y_end;y++) { y_scaled=y*3.0f; for(x=x_start;x<=x_end;x++) { x_scaled=x*3.0f; if(!check_tile_in_frustrum(x_scaled,y_scaled))continue;//outside of the frustrum if(is_water_tile(tile_map[y*tile_map_size_x+x])) { if(!tile_map[y*tile_map_size_x+x]) { if(dungeon) get_and_set_texture_id(tile_list[231]); else get_and_set_texture_id(tile_list[0]); } else get_and_set_texture_id(tile_list[tile_map[y*tile_map_size_x+x]]); draw_lake_water_tile(x_scaled,y_scaled); } } } glDisable(GL_BLEND); glDisable(GL_CULL_FACE); } void draw_sky_background() { Enter2DMode(); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); //draw the sky background glColor3fv(sky_lights_c1[light_level]); glVertex3i(0,0,0); glColor3fv(sky_lights_c2[light_level]); glVertex3i(0,window_height,0); glColor3fv(sky_lights_c3[light_level]); glVertex3i(window_width,window_height,0); glColor3fv(sky_lights_c4[light_level]); glVertex3i(window_width,0,0); glEnd(); glEnable(GL_TEXTURE_2D); Leave2DMode(); } void draw_dungeon_sky_background() { Enter2DMode(); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); //draw the sky background glColor3f(0,0.21f,0.34f); glVertex3i(0,0,0); glColor3f(0,0.21f,0.34f); glVertex3i(0,window_height,0); glColor3f(0,0.21f,0.34f); glVertex3i(window_width,window_height,0); glColor3f(0,0.21f,0.34f); glVertex3i(window_width,0,0); glEnd(); glEnable(GL_TEXTURE_2D); Leave2DMode(); }