2144 ALLEGRO_BITMAP** overlay_bitmaps,
2145 int num_overlay_tiles,
2157 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2162 float phw = hw0 * zoom;
2163 float phh = hh0 * zoom;
2164 float lift = tl0 * zoom;
2165 float tile_draw_w = 2.0f * phw;
2166 float tile_draw_h = 2.0f * phh;
2182 double _iso_t_setup = al_get_time();
2214 int nobj = (objects && num_objects > 0) ? num_objects : 0;
2215 static int* obj_order = NULL;
2216 static float* obj_sx_arr = NULL;
2217 static float* obj_sy_arr = NULL;
2218 static int obj_buf_cap = 0;
2219 if (nobj > obj_buf_cap) {
2220 int new_cap = obj_buf_cap > 0 ? obj_buf_cap : 64;
2221 while (new_cap < nobj) new_cap *= 2;
2222 int* g1 = (
int*)realloc(obj_order, (
size_t)new_cap *
sizeof(
int));
2223 float* g2 = (
float*)realloc(obj_sx_arr, (
size_t)new_cap *
sizeof(
float));
2224 float* g3 = (
float*)realloc(obj_sy_arr, (
size_t)new_cap *
sizeof(
float));
2225 if (!g1 || !g2 || !g3) {
2226 n_log(
LOG_ERR,
"iso_map_draw: object buffer realloc failed");
2229 if (g1) obj_order = g1;
2230 if (g2) obj_sx_arr = g2;
2231 if (g3) obj_sy_arr = g3;
2237 obj_buf_cap = new_cap;
2242 for (
int i = 0; i < nobj; i++) {
2248 obj_sx_arr[i] = wsx * zoom + cam_px;
2249 obj_sy_arr[i] = wsy * zoom + cam_py;
2253 for (
int i = 1; i < nobj; i++) {
2254 int key = obj_order[i];
2255 int key_fz = (int)floorf(objects[
key].fz);
2256 int key_my = (int)floorf(objects[
key].fy);
2257 int key_mx = (int)floorf(objects[
key].fx);
2258 int key_depth = key_my + key_mx;
2261 int cj = obj_order[j];
2262 int cj_fz = (int)floorf(objects[cj].fz);
2263 int cj_my = (int)floorf(objects[cj].fy);
2264 int cj_mx = (int)floorf(objects[cj].fx);
2265 int cj_depth = cj_my + cj_mx;
2266 if (cj_depth > key_depth ||
2267 (cj_depth == key_depth && cj_fz > key_fz) ||
2268 (cj_depth == key_depth && cj_fz == key_fz && cj_my > key_my) ||
2269 (cj_depth == key_depth && cj_fz == key_fz && cj_my == key_my && cj_mx > key_mx)) {
2270 obj_order[j + 1] = obj_order[j];
2276 obj_order[j + 1] =
key;
2280 double _iso_t_pass1 = al_get_time();
2303 int blender_is_one = 1;
2311 static int s_hold_pass1 = -1;
2312 static int s_hold_per_tile = -1;
2313 static int s_no_transitions = -1;
2314 static int s_no_overlay = -1;
2315 static int s_no_height_borders = -1;
2316 static int s_no_hover_grid = -1;
2317 static int s_tile_limit = -1;
2318 static int s_force_alpha = -1;
2319 if (s_hold_pass1 < 0) {
2321 const char* e = getenv(
"NILOREA_PASS1_HOLD");
2322 s_hold_pass1 = (e && e[0] ==
'0') ? 0 : 1;
2351 if (s_hold_per_tile < 0) {
2352 const char* e = getenv(
"NILOREA_PASS1_HOLD_PER_TILE");
2353 s_hold_per_tile = (e && e[0] ==
'1') ? 1 : 0;
2355 if (s_no_transitions < 0) {
2356 const char* e = getenv(
"NILOREA_PASS1_NO_TRANSITIONS");
2357 s_no_transitions = (e && e[0] ==
'1') ? 1 : 0;
2359 if (s_no_overlay < 0) {
2360 const char* e = getenv(
"NILOREA_PASS1_NO_OVERLAY");
2361 s_no_overlay = (e && e[0] ==
'1') ? 1 : 0;
2363 if (s_no_height_borders < 0) {
2364 const char* e = getenv(
"NILOREA_PASS1_NO_HEIGHT_BORDERS");
2365 s_no_height_borders = (e && e[0] ==
'1') ? 1 : 0;
2367 if (s_no_hover_grid < 0) {
2368 const char* e = getenv(
"NILOREA_PASS1_NO_HOVER_GRID");
2369 s_no_hover_grid = (e && e[0] ==
'1') ? 1 : 0;
2371 if (s_tile_limit < 0) {
2372 const char* e = getenv(
"NILOREA_PASS1_TILE_LIMIT");
2373 s_tile_limit = (e && e[0] >=
'0' && e[0] <=
'9') ? atoi(e) : 0;
2375 if (s_force_alpha < 0) {
2376 const char* e = getenv(
"NILOREA_PASS1_FORCE_ALPHA");
2377 s_force_alpha = (e && e[0] ==
'1') ? 1 : 0;
2381 int effective_hold_pass = s_hold_pass1 && !s_hold_per_tile;
2382 if (effective_hold_pass) {
2383 al_hold_bitmap_drawing(
true);
2398 al_map_rgba(0, 0, 0, 0),
2400 -100, -100, 1, 1, 0);
2403 int _p1_tiles_drawn = 0;
2404 for (
int di = 0; di < num_entries; di++) {
2405 if (draw_order[di].bottom > 0)
continue;
2408 if (s_tile_limit > 0 && _p1_tiles_drawn >= s_tile_limit)
break;
2413 if (s_hold_per_tile) al_hold_bitmap_drawing(
true);
2415 int mx = draw_order[di].
mx;
2416 int my = draw_order[di].
my;
2417 int seg_top = draw_order[di].
top;
2454 float h_n = (float)
h, h_e = (
float)
h, h_s = (float)
h, h_w = (
float)
h;
2455 int tile_is_flat = 1;
2458 tile_is_flat = (h_n == h_e && h_e == h_s && h_s == h_w);
2460 int tile_needs_primitives = (seg_top > 0) ||
2464 int unbatched_tile = effective_hold_pass && tile_needs_primitives;
2465 if (unbatched_tile) {
2466 al_hold_bitmap_drawing(
false);
2470 int top_terrain = base;
2471 int wall_terrain = base;
2473 int si = draw_order[di].
seg_idx;
2474 int tidx = my * map->
width + mx;
2475 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2476 si >= 0 && si < map->segments[tidx].count) {
2479 if (ut >= 0 && ut < map->num_terrains) top_terrain = ut;
2480 if (lt >= 0 && lt < map->num_terrains) wall_terrain = lt;
2485 float base_dx, base_dy;
2489 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, h_n, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2490 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, h_e, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2491 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, h_s, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2492 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, h_w, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2496 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)
h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2497 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)
h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2498 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)
h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2499 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)
h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2505 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2506 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2507 float max_side = fmaxf((
float)
h, (
float)map->
max_height) * lift;
2508 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2509 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2515 float dyn_r = 0.0f, dyn_g = 0.0f, dyn_b = 0.0f;
2517 int lidx = (my * map->
width + mx) * 3;
2524 amb_r, amb_g, amb_b,
2525 dyn_r, dyn_g, dyn_b);
2526 float seg_brightness = 1.0f;
2528 float ratio = (float)seg_top / (
float)map->
max_height;
2532 seg_brightness *= (amb_r + amb_g + amb_b) / 3.0f;
2533 float wall_dyn = (dyn_r + dyn_g + dyn_b) / 3.0f;
2534 seg_brightness += wall_dyn;
2535 if (seg_brightness > 1.0f) seg_brightness = 1.0f;
2553 if (s_force_alpha) {
2554 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2557 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2570 al_draw_tinted_scaled_bitmap(
tile_bitmaps[top_terrain], seg_tint,
2571 0, 0, (
float)tile_w, (
float)tile_h,
2572 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2584 float ce_x, ce_y, cs_x, cs_y, cw_x, cw_y;
2585 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)
h, cam_px, cam_py, zoom, &ce_x, &ce_y);
2586 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)
h, cam_px, cam_py, zoom, &cs_x, &cs_y);
2587 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)
h, cam_px, cam_py, zoom, &cw_x, &cw_y);
2589 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2594 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2601 int edge_bits_arr[16];
2602 int corner_bits_arr[16];
2604 memset(edge_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2605 memset(corner_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2608 for (
int t = base + 1; t < nt; t++) {
2611 if (!blender_is_one && !s_force_alpha) {
2612 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2617 vx, vy, tile_w, tile_h, seg_tint);
2621 0, 0, (
float)tile_w, (
float)tile_h,
2622 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2626 int cidx = num_edge_masks + corner_bits_arr[t];
2627 if (corner_bits_arr[t] != 0 && cidx < num_masks &&
2629 if (!blender_is_one && !s_force_alpha) {
2630 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2635 vx, vy, tile_w, tile_h, seg_tint);
2639 0, 0, (
float)tile_w, (
float)tile_h,
2640 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2657 if (overlay_bitmaps && map->
overlay && num_overlay_tiles > 0 && !s_no_overlay) {
2658 int ov_idx = my * map->
width + mx;
2659 int ov_tile = map->
overlay[ov_idx];
2660 if (ov_tile > 0 && ov_tile < num_overlay_tiles && overlay_bitmaps[ov_tile]) {
2661 if (!blender_is_one) {
2662 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2668 al_draw_tinted_scaled_bitmap(overlay_bitmaps[ov_tile], seg_tint,
2669 0, 0, (
float)tile_w, (
float)tile_h,
2670 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2676 if (seg_top > 0 && !s_no_height_borders) {
2677 if (!blender_is_one) {
2678 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2683 draw_order[di].underside,
2689 if (!blender_is_one) {
2690 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2695 ? al_map_rgba(100 * 120 / 255, 255 * 120 / 255, 100 * 120 / 255, 120)
2696 : al_map_rgba(255 * 120 / 255, 255 * 120 / 255, 100 * 120 / 255, 120);
2697 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2698 vx[2], vy[2], vx[3], vy[3]};
2699 al_draw_filled_polygon(verts, 4, hc);
2701 ? al_map_rgba(100 * 200 / 255, 255 * 200 / 255, 100 * 200 / 255, 200)
2702 : al_map_rgba(255 * 200 / 255, 255 * 200 / 255, 100 * 200 / 255, 200);
2703 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2704 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2705 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2706 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2713 if (map->
show_grid && !s_no_hover_grid) {
2714 if (!blender_is_one) {
2715 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2718 ALLEGRO_COLOR gc = al_map_rgba(60, 60, 60, 60);
2719 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2720 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2721 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2722 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2725 unsigned char a2 = (
unsigned char)(60 +
h * 35);
2727 ALLEGRO_COLOR hc2 = al_map_rgba(a2,
2728 (
unsigned char)(200 * a2 / 255),
2729 (
unsigned char)(100 * a2 / 255),
2731 float dot_x = (vx[0] + vx[2]) / 2.0f;
2732 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2733 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2739 if (s_hold_per_tile) al_hold_bitmap_drawing(
false);
2747 if (unbatched_tile) {
2748 al_hold_bitmap_drawing(
true);
2749 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2753 if (effective_hold_pass) al_hold_bitmap_drawing(
false);
2755 double _iso_t_pass2 = al_get_time();
2762 for (
int di = 0; di < num_entries; di++) {
2763 int mx = draw_order[di].
mx;
2764 int my = draw_order[di].
my;
2765 int seg_bottom = draw_order[di].
bottom;
2771 int seg_depth = my + mx;
2772 while (obj_cursor < nobj) {
2773 int oi = obj_order[obj_cursor];
2774 int obj_fz = (int)floorf(objects[oi].fz);
2775 int obj_my = (int)floorf(objects[oi].fy);
2776 int obj_mx = (int)floorf(objects[oi].fx);
2777 int obj_depth = obj_my + obj_mx;
2778 if (obj_depth > seg_depth ||
2779 (obj_depth == seg_depth && obj_fz > seg_bottom) ||
2780 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my > my) ||
2781 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my == my && obj_mx >= mx))
2783 if (objects[oi].
draw) {
2784 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2785 zoom, 1.0f, objects[oi].user_data);
2792 if (seg_bottom == 0)
continue;
2795 int seg_top = draw_order[di].
top;
2800 int etop_terrain = base;
2801 int ewall_terrain = base;
2803 int si = draw_order[di].
seg_idx;
2804 int tidx = my * map->
width + mx;
2805 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2806 si >= 0 && si < map->segments[tidx].count) {
2809 if (ut >= 0 && ut < map->num_terrains) etop_terrain = ut;
2810 if (lt >= 0 && lt < map->num_terrains) ewall_terrain = lt;
2815 float base_dx, base_dy;
2816 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)
h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2817 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)
h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2818 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)
h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2819 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)
h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2824 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2825 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2826 float max_side = fmaxf((
float)
h, (
float)map->
max_height) * lift;
2827 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2828 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2831 if (draw_order[di].underside &&
tile_bitmaps[etop_terrain]) {
2832 float under_sx, under_sy;
2834 float under_dx = under_sx * zoom + cam_px;
2835 float under_dy = under_sy * zoom + cam_py;
2837 phw, phh, tile_draw_w, tile_draw_h,
2846 float edyn_r = 0.0f, edyn_g = 0.0f, edyn_b = 0.0f;
2848 int elidx = (my * map->
width + mx) * 3;
2855 eamb_r, eamb_g, eamb_b,
2856 edyn_r, edyn_g, edyn_b);
2857 float eseg_brightness = 1.0f;
2859 float ratio = (float)seg_top / (
float)map->
max_height;
2862 eseg_brightness *= (eamb_r + eamb_g + eamb_b) / 3.0f;
2863 eseg_brightness += (edyn_r + edyn_g + edyn_b) / 3.0f;
2864 if (eseg_brightness > 1.0f) eseg_brightness = 1.0f;
2867 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2868 al_draw_tinted_scaled_bitmap(
tile_bitmaps[etop_terrain], eseg_tint,
2869 0, 0, (
float)tile_w, (
float)tile_h,
2870 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2873 if (seg_top > seg_bottom) {
2875 mx, my, seg_bottom, seg_top, lift, eseg_brightness, ewall_terrain);
2876 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2878 seg_bottom, seg_top,
2879 draw_order[di].underside,
2885 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2887 ? al_map_rgba(100, 255, 100, 120)
2888 : al_map_rgba(255, 255, 100, 120);
2889 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2890 vx[2], vy[2], vx[3], vy[3]};
2891 al_draw_filled_polygon(verts, 4, hc);
2893 ? al_map_rgba(100, 255, 100, 200)
2894 : al_map_rgba(255, 255, 100, 200);
2895 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2896 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2897 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2898 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2903 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2904 ALLEGRO_COLOR gc = al_map_rgba(255, 255, 255, 60);
2905 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2906 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2907 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2908 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2911 ALLEGRO_COLOR hc2 = al_map_rgba(255, 200, 100,
2912 (
unsigned char)(60 +
h * 35));
2913 float dot_x = (vx[0] + vx[2]) / 2.0f;
2914 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2915 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2921 while (obj_cursor < nobj) {
2922 int oi = obj_order[obj_cursor];
2923 if (objects[oi].
draw) {
2924 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2925 zoom, 1.0f, objects[oi].user_data);
2931 double _iso_t_pass3 = al_get_time();
2935 for (
int i = 0; i < nobj; i++) {
2936 int oi = obj_order[i];
2937 if (objects[oi].occluded_alpha <= 0.0f)
continue;
2938 if (!objects[oi].
draw)
continue;
2940 float clip_y = 1e9f;
2942 objects[oi].fx, objects[oi].fy, objects[oi].fz,
2943 obj_sx_arr[oi], obj_sy_arr[oi],
2944 objects[oi].sprite_h,
2945 objects[oi].sprite_half_w,
2946 cam_px, cam_py, zoom,
2962 int prev_cx, prev_cy, prev_cw, prev_ch;
2963 al_get_clipping_rectangle(&prev_cx, &prev_cy, &prev_cw, &prev_ch);
2964 int clip_top = (int)floorf(clip_y);
2965 if (clip_top < prev_cy) clip_top = prev_cy;
2966 al_set_clipping_rectangle(prev_cx, clip_top,
2967 prev_cw, prev_cy + prev_ch - clip_top);
2968 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2969 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2970 zoom, objects[oi].occluded_alpha, objects[oi].user_data);
2971 al_set_clipping_rectangle(prev_cx, prev_cy, prev_cw, prev_ch);