void get_old_world_x_y (short *scene_x, short *scene_y) { AABBOX box; float t, x, y, z, t1, t2, tx, ty, dx, dy, h, len; int i, j, h_max, h_min, h1, h2, h3, h4, sx, sy, zx, zy, i_min, i_max, j_min, j_max; x = click_line.center[X]; y = click_line.center[Y]; z = click_line.center[Z]; dx = click_line.direction[X]; dy = click_line.direction[Y]; t = min2f(4.0f, max2f(-2.2f, z)); if (t != z) { t = (t-z)/click_line.direction[Z]; x += t*dx; y += t*dy; } t = 6.2f / click_line.direction[Z]; len = min2f(max2f(t, -t), click_line.length); len = click_line.length; if (max2f(dx, -dx) < 0.000001f) { zx = 1; sx = 0; } else { zx = 0; if (dx < 0.0f) sx = -1; else sx = 1; } if (max2f(dy, -dy) < 0.000001f) { zy = 1; sy = 0; } else { zy = 0; if (dy < 0.0f) sy = -1; else sy = 1; } i = x*2.0f; j = y*2.0f; i_min = min2f(x, x+dx*len)*2.0f; i_max = max2f(x, x+dx*len)*2.0f; j_min = min2f(y, y+dy*len)*2.0f; j_max = max2f(y, y+dy*len)*2.0f; i_min = max2i(min2i(i_min, tile_map_size_x*6), 0); i_max = max2i(min2i(i_max, tile_map_size_x*6-1), 0); j_min = max2i(min2i(j_min, tile_map_size_y*6), 0); j_max = max2i(min2i(j_max, tile_map_size_y*6-1), 0); i = min2i(max2i(i, i_min), i_max-1); j = min2i(max2i(j, j_min), j_max-1); h = 0.0f; while ((i >= i_min) && (j >= j_min) && (i < i_max) && (j < j_max)) { h1 = height_map[j*tile_map_size_x*6+i]; h2 = height_map[j*tile_map_size_x*6+i+1]; h3 = height_map[(j+1)*tile_map_size_x*6+i]; h4 = height_map[(j+1)*tile_map_size_x*6+i+1]; h_max = max2i(max2i(h1, h2), max2i(h3, h4)); h_min = min2i(min2i(h1, h2), min2i(h3, h4)); tx = i*0.5f; ty = j*0.5f; box.bbmin[X] = tx; box.bbmin[Y] = ty; box.bbmin[Z] = h_min*0.2f-2.2f; box.bbmax[X] = tx+1.0f; box.bbmax[Y] = ty+1.0f; box.bbmax[Z] = h_max*0.2f-2.2f; if (click_line_bbox_intersection(box)) { box.bbmin[X] = tx+0.0f; box.bbmin[Y] = ty+0.0f; box.bbmin[Z] = h1*0.2f-2.2f; box.bbmax[X] = tx+0.5f; box.bbmax[Y] = ty+0.5f; box.bbmax[Z] = h1*0.2f-2.2f; if (click_line_bbox_intersection(box)) { h = h1*0.2f-2.2f; break; } box.bbmin[X] = tx+0.5f; box.bbmin[Y] = ty+0.0f; box.bbmin[Z] = h2*0.2f-2.2f; box.bbmax[X] = tx+1.0f; box.bbmax[Y] = ty+0.5f; box.bbmax[Z] = h2*0.2f-2.2f; if (click_line_bbox_intersection(box)) { h = h2*0.2f-2.2f; break; } box.bbmin[X] = tx+0.0f; box.bbmin[Y] = ty+0.5f; box.bbmin[Z] = h3*0.2f-2.2f; box.bbmax[X] = tx+0.5f; box.bbmax[Y] = ty+1.0f; box.bbmax[Z] = h3*0.2f-2.2f; if (click_line_bbox_intersection(box)) { h = h3*0.2f-2.2f; break; } box.bbmin[X] = tx+0.5f; box.bbmin[Y] = ty+0.5f; box.bbmin[Z] = h4*0.2f-2.2f; box.bbmax[X] = tx+1.0f; box.bbmax[Y] = ty+1.0f; box.bbmax[Z] = h4*0.2f-2.2f; if (click_line_bbox_intersection(box)) { h = h4*0.2f-2.2f; break; } } if ((zx == 1) && (zy == 1)) break; if (zx == 0) t1 = (tx+sx-x)/dx; else t1 = 10e30; if (zx == 0) t2 = (ty+sy-y)/dy; else t2 = -10e30; if (t1 < t2) i += 2*sx; else j += 2*sy; t = min2f(t1, t2); x += dx*t; y += dy*t; } t = (h-click_line.center[Z])/click_line.direction[Z]; *scene_x = (click_line.center[X]+click_line.direction[X]*t) / 0.5; *scene_y = (click_line.center[Y]+click_line.direction[Y]*t) / 0.5; }
static __inline__ int check_shadow_lines_outside(const AABBOX bbox, const FRUSTUM frustum, const FRUSTUM_DATA data, const VECTOR3 light_dir, Uint32 mask, Uint32 point_mask) { VECTOR3 _p; VECTOR4 p; float tmp, vmin, vmax, step, hit[16]; int i, j, k, l, intersect; memset(hit, 0, sizeof(hit)); for (i = 0, k = 1; k <= point_mask; i++, k += k) { if (k & point_mask) { get_point_from_aabbox(_p, bbox, i); VAssign4(p, _p, 1.0f); vmin = 0.0f; vmax = BOUND_HUGE; intersect = 1; for (j = 0, l = 1; l <= mask; j++, l += l) { if (l & mask) { tmp = VDot4(p, frustum[j].plane); if (data[j].zero == 0) { step = tmp/data[j].scale; if (step < 0.0f) { if (tmp < 0.0f) { intersect = 0; } } else { hit[j] = max2f(hit[j], step); if (intersect != 0) { if (data[j].mask) { vmin = max2f(vmin, step); } else { vmax = min2f(vmax, step); } if (vmin > vmax) { intersect = 0; } } } } else { if (tmp < 0.0f) { intersect = 0; } } } } if (intersect != 0) return INTERSECT; } } return check_shadow_line_walk_outside(bbox, frustum, light_dir, mask, hit); }
static e3d_object* do_load_e3d_detail(e3d_object* cur_object) { e3d_header header; e3d_material material; char cur_dir[1024]; int i, idx, l, mem_size, vertex_size, material_size; int file_pos, indices_size, index_size; char text_file_name[1024]; Uint32 tmp; Uint16 tmp_16; Uint8* index_pointer; el_file_ptr file; version_number version; if (cur_object == 0) return 0; memset(cur_dir, 0, sizeof(cur_dir)); //get the current directory l = strlen(cur_object->file_name); //parse the string backwards, until we find a / while (l > 0) { if ((cur_object->file_name[l] == '/') || (cur_object->file_name[l] == '\\')) break; l--; } i = 0; if (l)//prevent invalid dir names { while (l >= 0) { cur_dir[i] = cur_object->file_name[i]; i++; l--; } cur_dir[i+1] = 0; } LOG_DEBUG_OLD("Loading e3d file '%s'.", cur_object->file_name); file = el_open(cur_object->file_name); if (file == 0) { LOG_ERROR_OLD("Can't open file '%s'!", cur_object->file_name); free_e3d_pointer(cur_object); return 0; } if (read_and_check_elc_header(file, EL3D_FILE_MAGIC_NUMBER, &version, cur_object->file_name) != 0) { LOG_ERROR_OLD("File '%s' has wrong header!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } el_read(file, sizeof(e3d_header), &header); cur_object->vertex_no = SDL_SwapLE32(header.vertex_no); cur_object->index_no = SDL_SwapLE32(header.index_no); cur_object->material_no = SDL_SwapLE32(header.material_no); vertex_size = SDL_SwapLE32(header.vertex_size); material_size = SDL_SwapLE32(header.material_size); index_size = SDL_SwapLE32(header.index_size); LOG_DEBUG_OLD("E3d file vertex count %d and size %d.", cur_object->vertex_no, vertex_size); LOG_DEBUG_OLD("E3d file index count %d and size %d.", cur_object->index_no, index_size); LOG_DEBUG_OLD("E3d file material count %d and size %d.", cur_object->material_no, material_size); LOG_DEBUG_OLD("E3d file version %d.%d.%d.%d.", version[0], version[1], version[2], version[3]); if ((version[0] == 1) && (version[1] == 1)) { if ((header.vertex_options & 0xF0) != 0) { LOG_ERROR_OLD("Unknow options (%d) for file %s.", header.vertex_options, cur_object->file_name); } header.vertex_options &= 0x0F; if ((header.vertex_format & 0xE0) != 0) { LOG_ERROR_OLD("Unknow format (%d) for file %s.", header.vertex_format, cur_object->file_name); } header.vertex_format &= 0x1F; } else { if ((version[0] == 1) && (version[1] == 0)) { header.vertex_format = 0; header.vertex_options ^= 0x01; header.vertex_options &= 0x07; } else { LOG_ERROR_OLD("File '%s' has wrong version number!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } } idx = 0; if (has_normal(header.vertex_options)) { idx += 1; } if (has_color(header.vertex_options)) { idx += 2; } cur_object->vertex_layout = &(vertex_layout_array[idx]); // They have at least the size we expected if (check_vertex_size(vertex_size, header.vertex_options, header.vertex_format) == 0) { LOG_ERROR_OLD("File '%s' has wrong vertex size!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } if (material_size != get_material_size(header.vertex_options)) { LOG_ERROR_OLD("File '%s' has wrong material size! Expected size %d, found size %d.", cur_object->file_name, get_material_size(header.vertex_options), material_size); free_e3d_pointer(cur_object); el_close(file); return 0; } if (short_index(header.vertex_format)) { if (index_size != sizeof(Uint16)) { LOG_ERROR_OLD("File '%s' has wrong index size! Expected size %d, found size %d.", cur_object->file_name, sizeof(Uint16), index_size); free_e3d_pointer(cur_object); el_close(file); return 0; } } else { if (index_size != sizeof(Uint32)) { LOG_ERROR_OLD("File '%s' has wrong index size! Expected size %d, found size %d.", cur_object->file_name, sizeof(Uint32), index_size); free_e3d_pointer(cur_object); el_close(file); return 0; } } LOG_DEBUG_OLD("Reading vertices at %d from e3d file '%s'.", SDL_SwapLE32(header.vertex_offset), cur_object->file_name); // Now reading the vertices el_seek(file, SDL_SwapLE32(header.vertex_offset), SEEK_SET); cur_object->vertex_data = malloc(cur_object->vertex_no * cur_object->vertex_layout->size); mem_size = cur_object->vertex_no * cur_object->vertex_layout->size; if (!CHECK_POINTER(cur_object->vertex_data, "vertex data")) return 0; read_vertex_buffer(file, (float*)(cur_object->vertex_data), cur_object->vertex_no, vertex_size, header.vertex_options, header.vertex_format); LOG_DEBUG_OLD("Reading indices at %d from e3d file '%s'.", SDL_SwapLE32(header.index_offset), cur_object->file_name); // Now reading the indices el_seek(file, SDL_SwapLE32(header.index_offset), SEEK_SET); if (cur_object->index_no < 65536) { indices_size = 2; cur_object->index_type = GL_UNSIGNED_SHORT; } else { indices_size = 4; cur_object->index_type = GL_UNSIGNED_INT; } cur_object->indices = malloc(cur_object->index_no * indices_size); index_pointer = 0; for (i = 0; i < cur_object->index_no; i++) { if (index_size == 2) { el_read(file, sizeof(Uint16), &tmp_16); tmp = SDL_SwapLE16(tmp_16); } else { el_read(file, sizeof(Uint32), &tmp); tmp = SDL_SwapLE32(tmp); } if (indices_size == 2) { ((Uint16*)(cur_object->indices))[i] = tmp; } else { ((Uint32*)(cur_object->indices))[i] = tmp; } } // only allocate the materials structure if it doesn't exist (on initial load) if (cur_object->materials == 0) { cur_object->materials = (e3d_draw_list*)malloc(cur_object->material_no*sizeof(e3d_draw_list)); if (!CHECK_POINTER(cur_object->materials, "materials")) return 0; memset(cur_object->materials, 0, cur_object->material_no * sizeof(e3d_draw_list)); } mem_size += cur_object->material_no * sizeof(e3d_draw_list); LOG_DEBUG_OLD("Reading materials at %d from e3d file '%s'.", SDL_SwapLE32(header.material_offset), cur_object->file_name); // Now reading the materials el_seek(file, SDL_SwapLE32(header.material_offset), SEEK_SET); cur_object->min_x = 1e10f; cur_object->min_y = 1e10f; cur_object->min_z = 1e10f; cur_object->max_x = -1e10f; cur_object->max_y = -1e10f; cur_object->max_z = -1e10f; cur_object->max_size = -1e10f; for (i = 0; i < cur_object->material_no; i++) { file_pos = el_tell(file); el_read(file, sizeof(e3d_material), &material); safe_snprintf(text_file_name, sizeof(text_file_name), "%s%s", cur_dir, material.material_name); cur_object->materials[i].options = SDL_SwapLE32(material.options); #ifdef MAP_EDITOR #ifdef NEW_TEXTURES cur_object->materials[i].texture = load_texture_cached(text_file_name, tt_mesh); #else /* NEW_TEXTURES */ cur_object->materials[i].texture = load_texture_cache(text_file_name,0); #endif /* NEW_TEXTURES */ #else //MAP_EDITOR #ifdef NEW_TEXTURES cur_object->materials[i].texture = load_texture_cached(text_file_name, tt_mesh); #else /* NEW_TEXTURES */ #ifdef NEW_ALPHA // prepare to load the textures depending on if it is transparent or not (diff alpha handling) if (material_is_transparent(cur_object->materials[i].options)) { // is this object transparent? cur_object->materials[i].texture= load_texture_cache_deferred(text_file_name, -1); } else { cur_object->materials[i].texture= load_texture_cache_deferred(text_file_name, -1); //255); } #else //NEW_ALPHA // cur_object->materials[i].texture = load_texture_cache_deferred(text_file_name, 255); cur_object->materials[i].texture = load_texture_cache_deferred(text_file_name, 0); #endif //NEW_ALPHA #endif /* NEW_TEXTURES */ #endif //MAP_EDITOR cur_object->materials[i].min_x = SwapLEFloat(material.min_x); cur_object->materials[i].min_y = SwapLEFloat(material.min_y); cur_object->materials[i].min_z = SwapLEFloat(material.min_z); cur_object->materials[i].max_x = SwapLEFloat(material.max_x); cur_object->materials[i].max_y = SwapLEFloat(material.max_y); cur_object->materials[i].max_z = SwapLEFloat(material.max_z); // calculate the max size for cruse LOD processing cur_object->materials[i].max_size= max2f(max2f(cur_object->materials[i].max_x-cur_object->materials[i].min_x, cur_object->materials[i].max_y-cur_object->materials[i].min_y), cur_object->materials[i].max_z-cur_object->materials[i].min_z); cur_object->min_x = min2f(cur_object->min_x, cur_object->materials[i].min_x); cur_object->min_y = min2f(cur_object->min_y, cur_object->materials[i].min_y); cur_object->min_z = min2f(cur_object->min_z, cur_object->materials[i].min_z); cur_object->max_x = max2f(cur_object->max_x, cur_object->materials[i].max_x); cur_object->max_y = max2f(cur_object->max_y, cur_object->materials[i].max_y); cur_object->max_z = max2f(cur_object->max_z, cur_object->materials[i].max_z); cur_object->max_size = max2f(cur_object->max_size, cur_object->materials[i].max_size); cur_object->materials[i].triangles_indices_index = indices_size*SDL_SwapLE32(material.index) + index_pointer; cur_object->materials[i].triangles_indices_count = SDL_SwapLE32(material.count); cur_object->materials[i].triangles_indices_min = SDL_SwapLE32(material.triangles_min_index); cur_object->materials[i].triangles_indices_max = SDL_SwapLE32(material.triangles_max_index); file_pos += SDL_SwapLE32(material_size); el_seek(file, file_pos, SEEK_SET); } el_close(file); LOG_DEBUG_OLD("Building vertex buffers for e3d file '%s'.", cur_object->file_name); //Generate the buffers glGenBuffersARB(1, &cur_object->vertex_vbo); glBindBufferARB(GL_ARRAY_BUFFER_ARB, cur_object->vertex_vbo); glBufferDataARB(GL_ARRAY_BUFFER_ARB, cur_object->vertex_no * cur_object->vertex_layout->size, cur_object->vertex_data, GL_STATIC_DRAW_ARB); #ifndef MAP_EDITOR free(cur_object->vertex_data); cur_object->vertex_data = 0; #endif //MAP_EDITOR glGenBuffersARB(1, &cur_object->indices_vbo); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, cur_object->indices_vbo); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, cur_object->index_no * indices_size, cur_object->indices, GL_STATIC_DRAW_ARB); #ifndef MAP_EDITOR free(cur_object->indices); cur_object->indices = 0; #endif //MAP_EDITOR glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); #ifndef MAP_EDITOR LOG_DEBUG_OLD("Adding e3d file '%s' to cache.", cur_object->file_name); cache_adj_size(cache_e3d, mem_size, cur_object); #endif //MAP_EDITOR return cur_object; }