2163 ALLEGRO_BITMAP** overlay_bitmaps,
2164 int num_overlay_tiles,
2176 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2181 float phw = hw0 * zoom;
2182 float phh = hh0 * zoom;
2183 float lift = tl0 * zoom;
2184 float tile_draw_w = 2.0f * phw;
2185 float tile_draw_h = 2.0f * phh;
2201 double _iso_t_setup = al_get_time();
2233 int nobj = (objects && num_objects > 0) ? num_objects : 0;
2234 static int* obj_order = NULL;
2235 static float* obj_sx_arr = NULL;
2236 static float* obj_sy_arr = NULL;
2237 static int obj_buf_cap = 0;
2238 if (nobj > obj_buf_cap) {
2239 int new_cap = obj_buf_cap > 0 ? obj_buf_cap : 64;
2240 while (new_cap < nobj) new_cap *= 2;
2241 int* g1 = (
int*)realloc(obj_order, (
size_t)new_cap *
sizeof(int));
2242 float* g2 = (
float*)realloc(obj_sx_arr, (
size_t)new_cap *
sizeof(float));
2243 float* g3 = (
float*)realloc(obj_sy_arr, (
size_t)new_cap *
sizeof(float));
2244 if (!g1 || !g2 || !g3) {
2245 n_log(
LOG_ERR,
"iso_map_draw: object buffer realloc failed");
2248 if (g1) obj_order = g1;
2249 if (g2) obj_sx_arr = g2;
2250 if (g3) obj_sy_arr = g3;
2256 obj_buf_cap = new_cap;
2261 for (
int i = 0; i < nobj; i++) {
2267 obj_sx_arr[i] = wsx * zoom + cam_px;
2268 obj_sy_arr[i] = wsy * zoom + cam_py;
2272 for (
int i = 1; i < nobj; i++) {
2273 int key = obj_order[i];
2274 int key_fz = (int)floorf(objects[
key].fz);
2275 int key_my = (int)floorf(objects[
key].fy);
2276 int key_mx = (int)floorf(objects[
key].fx);
2277 int key_depth = key_my + key_mx;
2280 int cj = obj_order[j];
2281 int cj_fz = (int)floorf(objects[cj].fz);
2282 int cj_my = (int)floorf(objects[cj].fy);
2283 int cj_mx = (int)floorf(objects[cj].fx);
2284 int cj_depth = cj_my + cj_mx;
2285 if (cj_depth > key_depth ||
2286 (cj_depth == key_depth && cj_fz > key_fz) ||
2287 (cj_depth == key_depth && cj_fz == key_fz && cj_my > key_my) ||
2288 (cj_depth == key_depth && cj_fz == key_fz && cj_my == key_my && cj_mx > key_mx)) {
2289 obj_order[j + 1] = obj_order[j];
2295 obj_order[j + 1] =
key;
2299 double _iso_t_pass1 = al_get_time();
2322 int blender_is_one = 1;
2330 static int s_hold_pass1 = -1;
2331 static int s_hold_per_tile = -1;
2332 static int s_no_transitions = -1;
2333 static int s_no_overlay = -1;
2334 static int s_no_height_borders = -1;
2335 static int s_no_hover_grid = -1;
2336 static int s_tile_limit = -1;
2337 static int s_force_alpha = -1;
2338 if (s_hold_pass1 < 0) {
2340 const char* e = getenv(
"NILOREA_PASS1_HOLD");
2341 s_hold_pass1 = (e && e[0] ==
'0') ? 0 : 1;
2370 if (s_hold_per_tile < 0) {
2371 const char* e = getenv(
"NILOREA_PASS1_HOLD_PER_TILE");
2372 s_hold_per_tile = (e && e[0] ==
'1') ? 1 : 0;
2374 if (s_no_transitions < 0) {
2375 const char* e = getenv(
"NILOREA_PASS1_NO_TRANSITIONS");
2376 s_no_transitions = (e && e[0] ==
'1') ? 1 : 0;
2378 if (s_no_overlay < 0) {
2379 const char* e = getenv(
"NILOREA_PASS1_NO_OVERLAY");
2380 s_no_overlay = (e && e[0] ==
'1') ? 1 : 0;
2382 if (s_no_height_borders < 0) {
2383 const char* e = getenv(
"NILOREA_PASS1_NO_HEIGHT_BORDERS");
2384 s_no_height_borders = (e && e[0] ==
'1') ? 1 : 0;
2386 if (s_no_hover_grid < 0) {
2387 const char* e = getenv(
"NILOREA_PASS1_NO_HOVER_GRID");
2388 s_no_hover_grid = (e && e[0] ==
'1') ? 1 : 0;
2390 if (s_tile_limit < 0) {
2391 const char* e = getenv(
"NILOREA_PASS1_TILE_LIMIT");
2392 s_tile_limit = (e && e[0] >=
'0' && e[0] <=
'9') ? atoi(e) : 0;
2394 if (s_force_alpha < 0) {
2395 const char* e = getenv(
"NILOREA_PASS1_FORCE_ALPHA");
2396 s_force_alpha = (e && e[0] ==
'1') ? 1 : 0;
2400 int effective_hold_pass = s_hold_pass1 && !s_hold_per_tile;
2401 if (effective_hold_pass) {
2402 al_hold_bitmap_drawing(
true);
2417 al_map_rgba(0, 0, 0, 0),
2419 -100, -100, 1, 1, 0);
2422 int _p1_tiles_drawn = 0;
2423 for (
int di = 0; di < num_entries; di++) {
2424 if (draw_order[di].bottom > 0)
continue;
2427 if (s_tile_limit > 0 && _p1_tiles_drawn >= s_tile_limit)
break;
2432 if (s_hold_per_tile) al_hold_bitmap_drawing(
true);
2434 int mx = draw_order[di].
mx;
2435 int my = draw_order[di].
my;
2436 int seg_top = draw_order[di].
top;
2473 float h_n = (float)h, h_e = (
float)h, h_s = (float)h, h_w = (
float)h;
2474 int tile_is_flat = 1;
2477 tile_is_flat = (h_n == h_e && h_e == h_s && h_s == h_w);
2479 int tile_needs_primitives = (seg_top > 0) ||
2483 int unbatched_tile = effective_hold_pass && tile_needs_primitives;
2484 if (unbatched_tile) {
2485 al_hold_bitmap_drawing(
false);
2489 int top_terrain = base;
2490 int wall_terrain = base;
2492 int si = draw_order[di].
seg_idx;
2493 int tidx = my * map->
width + mx;
2494 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2495 si >= 0 && si < map->segments[tidx].count) {
2498 if (ut >= 0 && ut < map->num_terrains) top_terrain = ut;
2499 if (lt >= 0 && lt < map->num_terrains) wall_terrain = lt;
2504 float base_dx, base_dy;
2508 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, h_n, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2509 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, h_e, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2510 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, h_s, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2511 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, h_w, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2515 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2516 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2517 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2518 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2524 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2525 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2526 float max_side = fmaxf((
float)h, (
float)map->
max_height) * lift;
2527 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2528 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2534 float dyn_r = 0.0f, dyn_g = 0.0f, dyn_b = 0.0f;
2536 int lidx = (my * map->
width + mx) * 3;
2543 amb_r, amb_g, amb_b,
2544 dyn_r, dyn_g, dyn_b);
2545 float seg_brightness = 1.0f;
2547 float ratio = (float)seg_top / (
float)map->
max_height;
2551 seg_brightness *= (amb_r + amb_g + amb_b) / 3.0f;
2552 float wall_dyn = (dyn_r + dyn_g + dyn_b) / 3.0f;
2553 seg_brightness += wall_dyn;
2554 if (seg_brightness > 1.0f) seg_brightness = 1.0f;
2572 if (s_force_alpha) {
2573 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2576 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2589 al_draw_tinted_scaled_bitmap(
tile_bitmaps[top_terrain], seg_tint,
2590 0, 0, (
float)tile_w, (
float)tile_h,
2591 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2603 float ce_x, ce_y, cs_x, cs_y, cw_x, cw_y;
2604 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &ce_x, &ce_y);
2605 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &cs_x, &cs_y);
2606 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &cw_x, &cw_y);
2608 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2613 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2620 int edge_bits_arr[16];
2621 int corner_bits_arr[16];
2623 memset(edge_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2624 memset(corner_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2627 for (
int t = base + 1; t < nt; t++) {
2630 if (!blender_is_one && !s_force_alpha) {
2631 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2636 vx, vy, tile_w, tile_h, seg_tint);
2640 0, 0, (
float)tile_w, (
float)tile_h,
2641 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2645 int cidx = num_edge_masks + corner_bits_arr[t];
2646 if (corner_bits_arr[t] != 0 && cidx < num_masks &&
2648 if (!blender_is_one && !s_force_alpha) {
2649 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2654 vx, vy, tile_w, tile_h, seg_tint);
2658 0, 0, (
float)tile_w, (
float)tile_h,
2659 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2676 if (overlay_bitmaps && map->
overlay && num_overlay_tiles > 0 && !s_no_overlay) {
2677 int ov_idx = my * map->
width + mx;
2678 int ov_tile = map->
overlay[ov_idx];
2679 if (ov_tile > 0 && ov_tile < num_overlay_tiles && overlay_bitmaps[ov_tile]) {
2680 if (!blender_is_one) {
2681 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2687 al_draw_tinted_scaled_bitmap(overlay_bitmaps[ov_tile], seg_tint,
2688 0, 0, (
float)tile_w, (
float)tile_h,
2689 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2695 if (seg_top > 0 && !s_no_height_borders) {
2696 if (!blender_is_one) {
2697 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2702 draw_order[di].underside,
2708 if (!blender_is_one) {
2709 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2714 ? al_map_rgba(100 * 120 / 255, 255 * 120 / 255, 100 * 120 / 255, 120)
2715 : al_map_rgba(255 * 120 / 255, 255 * 120 / 255, 100 * 120 / 255, 120);
2716 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2717 vx[2], vy[2], vx[3], vy[3]};
2718 al_draw_filled_polygon(verts, 4, hc);
2720 ? al_map_rgba(100 * 200 / 255, 255 * 200 / 255, 100 * 200 / 255, 200)
2721 : al_map_rgba(255 * 200 / 255, 255 * 200 / 255, 100 * 200 / 255, 200);
2722 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2723 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2724 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2725 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2732 if (map->
show_grid && !s_no_hover_grid) {
2733 if (!blender_is_one) {
2734 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2737 ALLEGRO_COLOR gc = al_map_rgba(60, 60, 60, 60);
2738 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2739 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2740 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2741 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2744 unsigned char a2 = (
unsigned char)(60 + h * 35);
2746 ALLEGRO_COLOR hc2 = al_map_rgba(a2,
2747 (
unsigned char)(200 * a2 / 255),
2748 (
unsigned char)(100 * a2 / 255),
2750 float dot_x = (vx[0] + vx[2]) / 2.0f;
2751 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2752 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2758 if (s_hold_per_tile) al_hold_bitmap_drawing(
false);
2766 if (unbatched_tile) {
2767 al_hold_bitmap_drawing(
true);
2768 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2772 if (effective_hold_pass) al_hold_bitmap_drawing(
false);
2774 double _iso_t_pass2 = al_get_time();
2781 for (
int di = 0; di < num_entries; di++) {
2782 int mx = draw_order[di].
mx;
2783 int my = draw_order[di].
my;
2784 int seg_bottom = draw_order[di].
bottom;
2790 int seg_depth = my + mx;
2791 while (obj_cursor < nobj) {
2792 int oi = obj_order[obj_cursor];
2793 int obj_fz = (int)floorf(objects[oi].fz);
2794 int obj_my = (int)floorf(objects[oi].fy);
2795 int obj_mx = (int)floorf(objects[oi].fx);
2796 int obj_depth = obj_my + obj_mx;
2797 if (obj_depth > seg_depth ||
2798 (obj_depth == seg_depth && obj_fz > seg_bottom) ||
2799 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my > my) ||
2800 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my == my && obj_mx >= mx))
2802 if (objects[oi].draw) {
2803 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2804 zoom, 1.0f, objects[oi].user_data);
2811 if (seg_bottom == 0)
continue;
2814 int seg_top = draw_order[di].
top;
2819 int etop_terrain = base;
2820 int ewall_terrain = base;
2822 int si = draw_order[di].
seg_idx;
2823 int tidx = my * map->
width + mx;
2824 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2825 si >= 0 && si < map->segments[tidx].count) {
2828 if (ut >= 0 && ut < map->num_terrains) etop_terrain = ut;
2829 if (lt >= 0 && lt < map->num_terrains) ewall_terrain = lt;
2834 float base_dx, base_dy;
2835 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2836 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2837 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2838 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2843 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2844 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2845 float max_side = fmaxf((
float)h, (
float)map->
max_height) * lift;
2846 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2847 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2850 if (draw_order[di].underside &&
tile_bitmaps[etop_terrain]) {
2851 float under_sx, under_sy;
2853 float under_dx = under_sx * zoom + cam_px;
2854 float under_dy = under_sy * zoom + cam_py;
2856 phw, phh, tile_draw_w, tile_draw_h,
2865 float edyn_r = 0.0f, edyn_g = 0.0f, edyn_b = 0.0f;
2867 int elidx = (my * map->
width + mx) * 3;
2874 eamb_r, eamb_g, eamb_b,
2875 edyn_r, edyn_g, edyn_b);
2876 float eseg_brightness = 1.0f;
2878 float ratio = (float)seg_top / (
float)map->
max_height;
2881 eseg_brightness *= (eamb_r + eamb_g + eamb_b) / 3.0f;
2882 eseg_brightness += (edyn_r + edyn_g + edyn_b) / 3.0f;
2883 if (eseg_brightness > 1.0f) eseg_brightness = 1.0f;
2886 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2887 al_draw_tinted_scaled_bitmap(
tile_bitmaps[etop_terrain], eseg_tint,
2888 0, 0, (
float)tile_w, (
float)tile_h,
2889 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2892 if (seg_top > seg_bottom) {
2894 mx, my, seg_bottom, seg_top, lift, eseg_brightness, ewall_terrain);
2895 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2897 seg_bottom, seg_top,
2898 draw_order[di].underside,
2904 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2906 ? al_map_rgba(100, 255, 100, 120)
2907 : al_map_rgba(255, 255, 100, 120);
2908 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2909 vx[2], vy[2], vx[3], vy[3]};
2910 al_draw_filled_polygon(verts, 4, hc);
2912 ? al_map_rgba(100, 255, 100, 200)
2913 : al_map_rgba(255, 255, 100, 200);
2914 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2915 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2916 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2917 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2922 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2923 ALLEGRO_COLOR gc = al_map_rgba(255, 255, 255, 60);
2924 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2925 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2926 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2927 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2930 ALLEGRO_COLOR hc2 = al_map_rgba(255, 200, 100,
2931 (
unsigned char)(60 + h * 35));
2932 float dot_x = (vx[0] + vx[2]) / 2.0f;
2933 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2934 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2940 while (obj_cursor < nobj) {
2941 int oi = obj_order[obj_cursor];
2942 if (objects[oi].draw) {
2943 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2944 zoom, 1.0f, objects[oi].user_data);
2950 double _iso_t_pass3 = al_get_time();
2954 for (
int i = 0; i < nobj; i++) {
2955 int oi = obj_order[i];
2956 if (objects[oi].occluded_alpha <= 0.0f)
continue;
2957 if (!objects[oi].draw)
continue;
2959 float clip_y = 1e9f;
2961 objects[oi].fx, objects[oi].fy, objects[oi].fz,
2962 obj_sx_arr[oi], obj_sy_arr[oi],
2963 objects[oi].sprite_h,
2964 objects[oi].sprite_half_w,
2965 cam_px, cam_py, zoom,
2981 int prev_cx, prev_cy, prev_cw, prev_ch;
2982 al_get_clipping_rectangle(&prev_cx, &prev_cy, &prev_cw, &prev_ch);
2983 int clip_top = (int)floorf(clip_y);
2984 if (clip_top < prev_cy) clip_top = prev_cy;
2985 al_set_clipping_rectangle(prev_cx, clip_top,
2986 prev_cw, prev_cy + prev_ch - clip_top);
2987 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2988 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2989 zoom, objects[oi].occluded_alpha, objects[oi].user_data);
2990 al_set_clipping_rectangle(prev_cx, prev_cy, prev_cw, prev_ch);