static void _apply_kernel (cairo_surface_t *surface, const int *kernel, int kernel_size) { ol_assert (kernel_size > 0 && kernel_size % 2 == 1); ol_assert (kernel != NULL); static const int DIR[2][2] = {{0, 1}, {1, 0}}; guint32 *pixels = (guint32*) cairo_image_surface_get_data (surface); int width = cairo_image_surface_get_width (surface); int height = cairo_image_surface_get_height (surface); if (pixels == NULL || width <= 0 || height <= 0) { ol_errorf ("Invalid image surface"); return; } int kernel_orig = kernel_size / 2; int d, i, x, y; for (d = 0; d < 2; d++) { guint32 *old_pixels = g_new (guint32, width * height); memcpy (old_pixels, pixels, sizeof (guint32) * width * height); for (x = 0; x < width; x++) for (y = 0; y < height; y++) { struct _pixel final_value = {0}; int sum = 0; for (i = 0; i < kernel_size; i++) { int x1 = x + (i - kernel_orig) * DIR[d][0]; int y1 = y + (i - kernel_orig) * DIR[d][1]; int index1 = _pos_to_index (x1, y1, width, height); if (index1 > 0) { sum += kernel[i]; struct _pixel value = _num_to_pixel_with_factor (old_pixels[index1], kernel[i]); _pixel_plus (&final_value, &value); } } int index = _pos_to_index (x, y, width, height); pixels[index] = _pixel_to_num_with_divisor (&final_value, sum); } g_free (old_pixels); } }
void GPathFinder::_alg_astarmod_3d(const g_ivec3 &st_pos, const g_ivec3 &end_pos) { g_double ticks = GetTicks(); priority_queue <G_WP*, vector<G_WP*>, G_WP> WPQueue; G_WP_TREE WPTree; WPQueue.push(WPTree.add_wp(st_pos, 0, 0, NULL)); g_ivec3 min = st_pos - _init_params.search_radius; g_ivec3 max = st_pos + _init_params.search_radius; g_float end_dist = g_float((end_pos - st_pos).Length()); g_float max_dist = end_dist*1.3f; if (max_dist < 25) max_dist += 10.0f; memset(_cached_cells, 0, _cache_buff_size*sizeof(G_CELL_INFO)); G_WP *curr_wp; _last_path.state = psNotFound; while (WPQueue.size() > 0) { curr_wp = WPQueue.top(); WPQueue.pop(); //Проверяем является ли точка конечной g_ivec3 curr_pos = curr_wp->pos; if (curr_pos == end_pos) { _last_path.state = psFound; break; } //Проверяем максимальную длинну пути /*if (curr_wp->total_length > g_max_length) { _last_path.state = psTooLong; break; }*/ //Проверяем возможность прыжка g_int32 curr_jump = -2; for (g_uint32 i = 0; i < _init_params.jump_power + 2; i++) { g_ivec3 new_pos = curr_pos + g_ivec3(0,i,0); if (!_pos_in_range(min,max,new_pos)) break; g_int32 index = _pos_to_index(new_pos - min, _cache_area_size); _get_info_at_pos(new_pos, _cached_cells[index]); _cached_cells[index].state = csDenyMove; if (_cached_cells[index].move_resist == 255) break; curr_jump++; } //Проверяем точки по осям for (g_int32 curr_dir = 0; curr_dir < 8; curr_dir++) { g_int32 diag = curr_dir%2; g_ivec3 targ_pos = curr_pos + move_dir[curr_dir]; if (!_pos_in_range(min,max,targ_pos)) continue; G_CELL_INFO *up_cell_info[3], *down_cell_info[3]; //Получаем инфу о соседних ячейках (сверху и снизу) for (g_int32 i = 0; i < 3; i++) { g_ivec3 new_pos = targ_pos + g_ivec3(0,i-1,0); g_int32 index = _pos_to_index(new_pos - min, _cache_area_size); _get_info_at_pos(new_pos, _cached_cells[index]); up_cell_info[i] = down_cell_info[i] = &_cached_cells[index]; } g_bool check_way_down = true; // Проверяем перемещение вверх for (g_int32 i = 0; i < curr_jump + 1; i++) { if (up_cell_info[0]->move_resist == 255) { g_bool no_wall = true; if (i < 3) check_way_down = false; if (diag == 1) { g_ivec3 new_pos[2] = {curr_pos + g_ivec3(0,i,0), curr_pos + g_ivec3(0,i,0)}; new_pos[0].x += move_dir[curr_dir].x; new_pos[1].z += move_dir[curr_dir].z; for (g_int32 j = 0; j < 4; j++) { g_int32 index = _pos_to_index(new_pos[j%2] - min, _cache_area_size); _get_info_at_pos(new_pos[j%2], _cached_cells[index]); if (_cached_cells[index].move_resist == 255) { no_wall = false; break; } new_pos[j%2].y++; } } if (no_wall) if ((up_cell_info[1]->state != csDenyMove) && (up_cell_info[2]->state != csDenyMove) && (up_cell_info[1]->move_resist < 255) && (up_cell_info[2]->move_resist < 255)) { g_ivec3 new_pos = targ_pos + g_ivec3(0,i,0); if (i < 2) up_cell_info[1]->state = csDenyMove; g_float dist = g_float((end_pos - new_pos).Length()); if (dist < max_dist) { G_WP *temp_wp = curr_wp; if (i > 0) //Если движемся вверх temp_wp = WPTree.add_wp(curr_pos + g_ivec3(0,i,0), move_weight[2]*i, dist, curr_wp); WPQueue.push(WPTree.add_wp(new_pos, move_weight[diag], dist, temp_wp)); } } } up_cell_info[0] = up_cell_info[1]; up_cell_info[1] = up_cell_info[2]; g_ivec3 new_pos = targ_pos + g_ivec3(0,2+i,0); g_int32 index = _pos_to_index(new_pos - min, _cache_area_size); _get_info_at_pos(new_pos, _cached_cells[index]); up_cell_info[2] = &_cached_cells[index]; } // Проверяем перемещение вниз if (check_way_down) for (g_int32 i = 0; i <= g_int32(_init_params.jump_power); i++) { if ((down_cell_info[0]->move_resist == 255) || (down_cell_info[1]->move_resist == 255) || (down_cell_info[2]->move_resist == 255)) { if ((down_cell_info[1]->state != csDenyMove) && (down_cell_info[2]->state != csDenyMove) && (down_cell_info[1]->move_resist < 255) && (down_cell_info[2]->move_resist < 255)) { g_ivec3 new_pos = targ_pos + g_ivec3(0,-i,0); if (i < 2) down_cell_info[1]->state = csDenyMove; g_float dist = g_float((end_pos - new_pos).Length()); if (dist < max_dist) { if (i > 0) //Если движемся вниз { G_WP *temp_wp = WPTree.add_wp(targ_pos, move_weight[diag], dist, curr_wp); WPQueue.push(WPTree.add_wp(new_pos, move_weight[3]*i, dist, temp_wp)); } else WPQueue.push(WPTree.add_wp(new_pos, move_weight[diag], dist, curr_wp)); } } break; } down_cell_info[2] = down_cell_info[1]; down_cell_info[1] = down_cell_info[0]; g_ivec3 new_pos = targ_pos + g_ivec3(0,-2-i,0); g_int32 index = _pos_to_index(new_pos - min, _cache_area_size); _get_info_at_pos(new_pos, _cached_cells[index]); down_cell_info[0] = &_cached_cells[index]; } } } if (_last_path.state == psFound) { _last_path.path.total_length = 0; G_WAYPOINT new_wp; while (curr_wp->prev_wp != NULL) { new_wp.move_pos = curr_wp->pos; new_wp.length = curr_wp->total_length - curr_wp->prev_wp->total_length; _last_path.path.add_front_wp(new_wp); curr_wp = curr_wp->prev_wp; } new_wp.move_pos = curr_wp->pos; new_wp.length = 0; _last_path.path.add_front_wp(new_wp); } WPTree.clear(); g_char res_str[100]; sprintf_s(res_str,100,"wp: %d st: %d dist: %.3f", WPTree.way_points.size(), _last_path.state, max_dist); CheckTimeAndWriteToFile(ticks, res_str); }