render.c (85385B)
1 #include <arpa/inet.h> 2 #include <netinet/in.h> 3 #include <sys/ipc.h> 4 #include <sys/mman.h> 5 #include <sys/socket.h> 6 #include <sys/shm.h> 7 #include <sys/stat.h> 8 9 #include <X11/Xlib.h> 10 #include <X11/Xutil.h> 11 #include <X11/keysym.h> 12 #include <X11/extensions/XShm.h> 13 14 #include <ctype.h> 15 #include <err.h> 16 #include <fcntl.h> 17 #include <locale.h> 18 #include <math.h> 19 #include <pthread.h> 20 #include <stdio.h> 21 #include <stdint.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <strings.h> 25 #include <time.h> 26 #include <unistd.h> 27 28 #include "skins.h" 29 #include "net.h" 30 31 #define WIDTH 640 32 #define HEIGHT 480 33 #define MAX_CACHE 8192 34 #define NAME_SZ 24 35 #define MAX_DIST 250.0f 36 #define GRID_SZ 64 37 #define MAP_MIN -3000.0f 38 #define MAP_MAX 3000.0f 39 #define MAX_RENDER_TRIS 262144 40 #define TAR_INDEX_SIZE 32768 41 #define CHAT_LINES 6 42 43 #define GRAVITY 9.81f 44 #define TERMINAL_VEL 50.0f 45 #define JUMP_FORCE 6.2f 46 #define STEP_SNAP_DOWN 0.40f 47 48 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 49 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 50 51 struct vec3 { float x, y, z; }; 52 struct mat4 { float m[4][4]; }; 53 54 struct col_triangle { 55 float v0[3]; 56 float v1[3]; 57 float v2[3]; 58 float norm[3]; 59 uint8_t surface; 60 }; 61 62 struct col_cell { 63 const struct col_triangle *tris; 64 uint32_t count; 65 }; 66 67 struct chat_entry { 68 char text[160]; 69 float timer; 70 }; 71 72 struct timecyc_entry { 73 uint8_t amb[3], dir[3], sky_top[3], sky_bot[3], water[4]; 74 float far_clp, fog_st; 75 }; 76 77 struct sys_gfx { 78 Display *dpy; 79 Window win; 80 GC gc; 81 XImage *img; 82 XShmSegmentInfo shm; 83 uint32_t *pixels; 84 float *zbuffer; 85 Atom wm_delete; 86 struct mat4 proj; 87 char keys[512]; 88 float game_time_sec, game_time_hours; 89 struct timecyc_entry weathers[32][8], cur_weather; 90 int num_weathers, game_weather; 91 float far_clip_override; 92 int in_chat, chat_len; 93 char chat_buf[128]; 94 int menu_open; 95 int show_debug; 96 float fps; 97 uint32_t pkts_in, pkts_out; 98 uint32_t pkts_in_sec, pkts_out_sec; 99 float stats_timer; 100 KeyCode key_w, key_a, key_s, key_d, key_t, 101 key_esc, key_space, key_up, key_down, key_left, key_right; 102 XIC ic; 103 XFontSet font_set; 104 }; 105 106 struct vertex { float x, y, z, w, u, v, r, g, b, a, f; }; 107 struct clip_vertex { float x, y, z, w, u, v, r, g, b, a, f; }; 108 109 struct texture { 110 uint32_t *pixels; 111 int w, h, has_alpha; 112 uint32_t *mips[4]; 113 int mip_w[4]; 114 int mip_h[4]; 115 }; 116 117 struct render_triangle { 118 struct vertex v0, v1, v2; 119 const struct texture *tex; 120 int is_water, mip; 121 }; 122 123 struct ply_vertex { 124 float x, y, z; 125 float s, t; 126 uint8_t r, g, b, a; 127 }; 128 129 struct mesh { 130 struct ply_vertex *ply_verts; 131 uint16_t *indices, *mat_ids; 132 uint32_t num_verts, num_tris, num_materials; 133 char (*raw_tex_names)[32]; 134 struct texture **textures; 135 float spr_x, spr_y, spr_z, spr_r, total_area; 136 }; 137 138 struct net_snap { 139 float x, y, z; 140 float yaw; 141 double time; 142 }; 143 144 struct net_player { 145 uint8_t id; 146 uint16_t skin; 147 float cur_x, cur_y, cur_z; 148 float cur_yaw; 149 struct net_snap snaps[4]; 150 int snap_count; 151 int active; 152 }; 153 154 struct transform_array { 155 float *pos_x, *pos_y, *pos_z; 156 float *rot_qx, *rot_qy, *rot_qz, *rot_qw; 157 struct mat4 *world_matrices; 158 float *sphere_cx, *sphere_cy, *sphere_cz, *sphere_r; 159 int16_t *time_on, *time_off; 160 int count; 161 }; 162 163 struct grid_cell { int *ids, count, cap; }; 164 165 struct asset_cache { 166 struct mesh meshes[MAX_CACHE]; 167 struct texture textures[MAX_CACHE]; 168 char mesh_names[MAX_CACHE][NAME_SZ], tex_names[MAX_CACHE][32]; 169 int mesh_count, tex_count, mesh_hash[MAX_CACHE * 2], tex_hash[MAX_CACHE * 2]; 170 }; 171 172 struct draw_item { int id; float dist_sq; }; 173 struct water_face { 174 float x[4], y[4], z[4]; 175 float u[4], v[4], h[4]; 176 int num; 177 }; 178 179 static pthread_barrier_t barrier_start; 180 static pthread_barrier_t barrier_end; 181 182 struct tar_header { 183 char name[100]; 184 char mode[8]; 185 char uid[8]; 186 char gid[8]; 187 char size[12]; 188 char mtime[12]; 189 char chksum[8]; 190 char typeflag; 191 char linkname[100]; 192 char magic[6]; 193 char version[2]; 194 char uname[32]; 195 char gname[32]; 196 char devmajor[8]; 197 char devminor[8]; 198 char prefix[155]; 199 char pad[12]; 200 } __attribute__((packed)); 201 202 struct tga_header { 203 uint8_t id_length; 204 uint8_t color_map_type; 205 uint8_t image_type; 206 uint16_t color_map_first; 207 uint16_t color_map_length; 208 uint8_t color_map_entry_size; 209 uint16_t x_origin; 210 uint16_t y_origin; 211 uint16_t width; 212 uint16_t height; 213 uint8_t pixel_depth; 214 uint8_t image_descriptor; 215 } __attribute__((packed)); 216 217 struct tar_index_entry { 218 char name[128]; 219 const uint8_t *data; 220 size_t size; 221 }; 222 223 static struct col_cell g_col_grid[GRID_SZ][GRID_SZ]; 224 static struct sys_gfx *g_sys; 225 static struct transform_array g_transforms; 226 static struct mesh **scene_meshes = NULL; 227 static int scene_inst_count = 0, scene_inst_capacity = 0; 228 static struct grid_cell scene_grid[GRID_SZ][GRID_SZ]; 229 static struct draw_item *draw_list = NULL; 230 static int draw_cap = 0, draw_count = 0; 231 static struct render_triangle render_list[MAX_RENDER_TRIS]; 232 static int render_count = 0; 233 static struct water_face *water_faces = NULL; 234 static uint32_t water_count = 0; 235 static struct texture *water_tex = NULL, *sand_tex = NULL; 236 static pthread_t *workers = NULL; 237 static int num_threads = 1, threads_running = 1; 238 static struct clip_vertex *v_scratch = NULL; 239 static size_t v_scratch_cap = 0; 240 241 static uint8_t *g_tar_mapped = NULL; 242 static size_t g_tar_size = 0; 243 static struct tar_index_entry tar_idx[TAR_INDEX_SIZE]; 244 static struct asset_cache *g_cache = NULL; 245 static int active_skin_id = 7; 246 247 static int net_fd = -1; 248 static struct sockaddr_in srv_addr; 249 static int my_player_id = -1; 250 static int net_connected = 0; 251 static struct net_player net_players[MAX_PLAYERS]; 252 253 static struct chat_entry chat_log[CHAT_LINES]; 254 static int chat_log_count = 0; 255 static char local_nick[24]; 256 257 static size_t 258 get_tar_size(const char *octal) 259 { 260 size_t size = 0; 261 int i; 262 263 for (i = 0; i < 11; i++) { 264 if (octal[i] < '0' || octal[i] > '7') { 265 break; 266 } 267 size = size * 8 + (octal[i] - '0'); 268 } 269 return (size); 270 } 271 272 static uint32_t 273 tar_hash(const char *str) 274 { 275 uint32_t hash = 5381; 276 int c; 277 278 while ((c = (unsigned char)*str++)) { 279 hash = ((hash << 5) + hash) + tolower(c); 280 } 281 return (hash); 282 } 283 284 static void 285 tar_build_index(void) 286 { 287 size_t offset = 0; 288 struct tar_header *h; 289 size_t file_sz; 290 uint32_t slot; 291 292 memset(tar_idx, 0, sizeof(tar_idx)); 293 294 while (offset < g_tar_size) { 295 h = (struct tar_header *)(g_tar_mapped + offset); 296 if (h->name[0] == '\0') { 297 break; 298 } 299 file_sz = get_tar_size(h->size); 300 const uint8_t *file_data = g_tar_mapped + offset + 512; 301 302 slot = tar_hash(h->name) % TAR_INDEX_SIZE; 303 while (tar_idx[slot].data != NULL) { 304 if (strcasecmp(tar_idx[slot].name, h->name) == 0) { 305 goto next_file; 306 } 307 slot = (slot + 1) % TAR_INDEX_SIZE; 308 } 309 310 strncpy(tar_idx[slot].name, h->name, sizeof(tar_idx[slot].name) - 1); 311 tar_idx[slot].data = file_data; 312 tar_idx[slot].size = file_sz; 313 314 next_file: 315 offset += 512 + ((file_sz + 511) & ~511); 316 } 317 } 318 319 static const uint8_t * 320 tar_lookup(const char *filename, size_t *out_size) 321 { 322 uint32_t slot; 323 324 slot = tar_hash(filename) % TAR_INDEX_SIZE; 325 while (tar_idx[slot].data != NULL) { 326 if (strcasecmp(tar_idx[slot].name, filename) == 0) { 327 *out_size = tar_idx[slot].size; 328 return (tar_idx[slot].data); 329 } 330 slot = (slot + 1) % TAR_INDEX_SIZE; 331 } 332 return (NULL); 333 } 334 335 static inline float 336 edge_func(float ax, float ay, float bx, float by, float cx, float cy) 337 { 338 return ((cx - ax) * (by - ay) - (cy - ay) * (bx - ax)); 339 } 340 341 static void 342 closest_point_triangle(const float p[3], const float a[3], const float b[3], const float c[3], float out[3]) 343 { 344 float ab[3], ac[3], ap[3], bp[3], cp[3]; 345 float d1, d2, d3, d4, d5, d6; 346 float vc, vb, va, denom, v, w, u; 347 348 ab[0] = b[0] - a[0]; 349 ab[1] = b[1] - a[1]; 350 ab[2] = b[2] - a[2]; 351 352 ac[0] = c[0] - a[0]; 353 ac[1] = c[1] - a[1]; 354 ac[2] = c[2] - a[2]; 355 356 ap[0] = p[0] - a[0]; 357 ap[1] = p[1] - a[1]; 358 ap[2] = p[2] - a[2]; 359 360 d1 = ab[0] * ap[0] + ab[1] * ap[1] + ab[2] * ap[2]; 361 d2 = ac[0] * ap[0] + ac[1] * ap[1] + ac[2] * ap[2]; 362 if (d1 <= 0.0f && d2 <= 0.0f) { 363 out[0] = a[0]; 364 out[1] = a[1]; 365 out[2] = a[2]; 366 return; 367 } 368 369 bp[0] = p[0] - b[0]; 370 bp[1] = p[1] - b[1]; 371 bp[2] = p[2] - b[2]; 372 373 d3 = ab[0] * bp[0] + ab[1] * bp[1] + ab[2] * bp[2]; 374 d4 = ac[0] * bp[0] + ac[1] * bp[1] + ac[2] * bp[2]; 375 if (d3 >= 0.0f && d4 <= d3) { 376 out[0] = b[0]; 377 out[1] = b[1]; 378 out[2] = b[2]; 379 return; 380 } 381 382 vc = d1 * d4 - d3 * d2; 383 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { 384 v = d1 / (d1 - d3); 385 out[0] = a[0] + v * ab[0]; 386 out[1] = a[1] + v * ab[1]; 387 out[2] = a[2] + v * ab[2]; 388 return; 389 } 390 391 cp[0] = p[0] - c[0]; 392 cp[1] = p[1] - c[1]; 393 cp[2] = p[2] - c[2]; 394 395 d5 = ab[0] * cp[0] + ab[1] * cp[1] + ab[2] * cp[2]; 396 d6 = ac[0] * cp[0] + ac[1] * cp[1] + ac[2] * cp[2]; 397 if (d6 >= 0.0f && d5 <= d6) { 398 out[0] = c[0]; 399 out[1] = c[1]; 400 out[2] = c[2]; 401 return; 402 } 403 404 vb = d5 * d2 - d1 * d6; 405 if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { 406 w = d2 / (d2 - d6); 407 out[0] = a[0] + w * ac[0]; 408 out[1] = a[1] + w * ac[1]; 409 out[2] = a[2] + w * ac[2]; 410 return; 411 } 412 413 va = d3 * d6 - d5 * d4; 414 if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { 415 w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); 416 out[0] = b[0] + w * (c[0] - b[0]); 417 out[1] = b[1] + w * (c[1] - b[1]); 418 out[2] = b[2] + w * (c[2] - b[2]); 419 return; 420 } 421 422 denom = 1.0f / (va + vb + vc); 423 v = vb * denom; 424 w = vc * denom; 425 u = 1.0f - v - w; 426 out[0] = u * a[0] + v * b[0] + w * c[0]; 427 out[1] = u * a[1] + v * b[1] + w * c[1]; 428 out[2] = u * a[2] + v * b[2] + w * c[2]; 429 } 430 431 static void 432 draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_band) 433 { 434 struct vertex v0, v1, v2, sv0, sv1, sv2, tmp; 435 const struct texture *tex; 436 const uint32_t *pixels; 437 float area, inv_area, dy12, dy20, dx12, dx20, dy01; 438 float p_x_start, p_y_start, w0_start, w1_start; 439 float dw0_dx, dw0_dy, dw1_dx, dw1_dy; 440 float u0_w, u1_w, u2_w, v0_w, v1_w, v2_w, f0_w, f1_w, f2_w; 441 float d_inv_w_dx, d_u_w_dx, d_v_w_dx, d_f_w_dx, d_r_dx, d_g_dx, d_b_dx; 442 float d_r_dx_255, d_g_dx_255, d_b_dx_255; 443 float inv_slope_long, inv_slope_short1, inv_slope_short2; 444 float row_y, x_long, x_short, x_min, x_max; 445 float dx, dy, row_w0, row_w1, row_w2; 446 float inv_w, u_w, v_w, f_w, r, g_val, b, wf, f, inv_f, min_inv_w; 447 uint32_t sky_r, sky_g, sky_b, color, bg, tex_r, tex_g, tex_b; 448 uint8_t tex_a, wa_tc, wr, wg, wb, wa; 449 int min_x, max_x, min_y, max_y, row_min_x, row_max_x; 450 int tw, th, tw_mask, th_mask, py, px, idx, ir, ig, ib, tx, ty, m; 451 452 v0 = tri->v0; 453 v1 = tri->v1; 454 v2 = tri->v2; 455 456 min_y = (int)floorf(MIN(v0.y, MIN(v1.y, v2.y))); 457 max_y = (int)ceilf(MAX(v0.y, MAX(v1.y, v2.y))); 458 if (max_y < min_y_band || min_y > max_y_band) { 459 return; 460 } 461 462 min_x = (int)floorf(MIN(v0.x, MIN(v1.x, v2.x))); 463 max_x = (int)ceilf(MAX(v0.x, MAX(v1.x, v2.x))); 464 if (min_x >= WIDTH || max_x < 0) { 465 return; 466 } 467 468 min_inv_w = MIN(v0.w, MIN(v1.w, v2.w)); 469 if (min_inv_w < 0.0001f) { 470 min_inv_w = 0.0001f; 471 } 472 473 area = edge_func(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); 474 if (fabsf(area) < 1e-5f) { 475 return; 476 } 477 inv_area = 1.0f / area; 478 479 dy12 = v2.y - v1.y; 480 dy20 = v0.y - v2.y; 481 dx12 = v2.x - v1.x; 482 dx20 = v0.x - v2.x; 483 dy01 = v1.y - v0.y; 484 485 if (min_x < 0) min_x = 0; 486 if (max_x >= WIDTH) max_x = WIDTH - 1; 487 if (min_y < min_y_band) min_y = min_y_band; 488 if (max_y > max_y_band) max_y = max_y_band; 489 if (min_y > max_y || min_x > max_x) { 490 return; 491 } 492 493 p_x_start = min_x + 0.5f; 494 p_y_start = min_y + 0.5f; 495 w0_start = ((p_x_start - v1.x) * dy12 - (p_y_start - v1.y) * dx12) * inv_area; 496 w1_start = ((p_x_start - v2.x) * dy20 - (p_y_start - v2.y) * dx20) * inv_area; 497 498 dw0_dx = dy12 * inv_area; 499 dw0_dy = -dx12 * inv_area; 500 dw1_dx = dy20 * inv_area; 501 dw1_dy = -dx20 * inv_area; 502 503 u0_w = v0.u * v0.w; u1_w = v1.u * v1.w; u2_w = v2.u * v2.w; 504 v0_w = v0.v * v0.w; v1_w = v1.v * v1.w; v2_w = v2.v * v2.w; 505 f0_w = v0.f * v0.w; f1_w = v1.f * v1.w; f2_w = v2.f * v2.w; 506 507 d_inv_w_dx = (dy12 * v0.w + dy20 * v1.w + dy01 * v2.w) * inv_area; 508 d_u_w_dx = (dy12 * u0_w + dy20 * u1_w + dy01 * u2_w) * inv_area; 509 d_v_w_dx = (dy12 * v0_w + dy20 * v1_w + dy01 * v2_w) * inv_area; 510 d_f_w_dx = (dy12 * f0_w + dy20 * f1_w + dy01 * f2_w) * inv_area; 511 d_r_dx = (dy12 * v0.r + dy20 * v1.r + dy01 * v2.r) * inv_area; 512 d_g_dx = (dy12 * v0.g + dy20 * v1.g + dy01 * v2.g) * inv_area; 513 d_b_dx = (dy12 * v0.b + dy20 * v1.b + dy01 * v2.b) * inv_area; 514 515 d_r_dx_255 = d_r_dx * 255.0f; 516 d_g_dx_255 = d_g_dx * 255.0f; 517 d_b_dx_255 = d_b_dx * 255.0f; 518 519 sky_r = g_sys->cur_weather.sky_bot[0]; 520 sky_g = g_sys->cur_weather.sky_bot[1]; 521 sky_b = g_sys->cur_weather.sky_bot[2]; 522 523 sv0 = v0; sv1 = v1; sv2 = v2; 524 if (sv0.y > sv1.y) { tmp = sv0; sv0 = sv1; sv1 = tmp; } 525 if (sv0.y > sv2.y) { tmp = sv0; sv0 = sv2; sv2 = tmp; } 526 if (sv1.y > sv2.y) { tmp = sv1; sv1 = sv2; sv2 = tmp; } 527 528 inv_slope_long = (sv2.y != sv0.y) ? (sv2.x - sv0.x) / (sv2.y - sv0.y) : 0.0f; 529 inv_slope_short1 = (sv1.y != sv0.y) ? (sv1.x - sv0.x) / (sv1.y - sv0.y) : 0.0f; 530 inv_slope_short2 = (sv2.y != sv1.y) ? (sv2.x - sv1.x) / (sv2.y - sv1.y) : 0.0f; 531 532 if (tri->tex && (uintptr_t)tri->tex != (uintptr_t)-1 && !tri->is_water) { 533 tex = tri->tex; 534 m = tri->mip; 535 if (m < 0) m = 0; 536 if (m > 3) m = 3; 537 pixels = tex->mips[m]; 538 tw = tex->mip_w[m]; 539 th = tex->mip_h[m]; 540 tw_mask = tw - 1; 541 th_mask = th - 1; 542 543 for (py = min_y; py <= max_y; py++) { 544 row_y = (float)py + 0.5f; 545 x_long = sv0.x + (row_y - sv0.y) * inv_slope_long; 546 x_short = (row_y < sv1.y) ? 547 sv0.x + (row_y - sv0.y) * inv_slope_short1 : 548 sv1.x + (row_y - sv1.y) * inv_slope_short2; 549 550 x_min = (x_long < x_short) ? x_long : x_short; 551 x_max = (x_long < x_short) ? x_short : x_long; 552 553 row_min_x = (int)floorf(x_min); 554 row_max_x = (int)ceilf(x_max); 555 556 if (row_min_x < min_x) row_min_x = min_x; 557 if (row_max_x > max_x) row_max_x = max_x; 558 if (row_min_x > row_max_x) continue; 559 560 dx = (row_min_x + 0.5f) - p_x_start; 561 dy = row_y - p_y_start; 562 row_w0 = w0_start + dw0_dx * dx + dw0_dy * dy; 563 row_w1 = w1_start + dw1_dx * dx + dw1_dy * dy; 564 row_w2 = 1.0f - row_w0 - row_w1; 565 566 inv_w = row_w0 * v0.w + row_w1 * v1.w + row_w2 * v2.w; 567 u_w = row_w0 * u0_w + row_w1 * u1_w + row_w2 * u2_w; 568 v_w = row_w0 * v0_w + row_w1 * v1_w + row_w2 * v2_w; 569 f_w = row_w0 * f0_w + row_w1 * f1_w + row_w2 * f2_w; 570 r = (row_w0 * v0.r + row_w1 * v1.r + row_w2 * v2.r) * 255.0f; 571 g_val = (row_w0 * v0.g + row_w1 * v1.g + row_w2 * v2.g) * 255.0f; 572 b = (row_w0 * v0.b + row_w1 * v1.b + row_w2 * v2.b) * 255.0f; 573 574 for (px = row_min_x; px <= row_max_x; px++) { 575 if (row_w0 >= -1e-4f && row_w1 >= -1e-4f && row_w2 >= -1e-4f) { 576 idx = py * WIDTH + px; 577 if (inv_w >= g_sys->zbuffer[idx] - 1e-6f && inv_w >= min_inv_w * 0.99f) { 578 wf = 1.0f / inv_w; 579 tx = (int)(u_w * wf * tw) & tw_mask; 580 ty = (int)(v_w * wf * th) & th_mask; 581 color = pixels[ty * tw + tx]; 582 tex_a = (color >> 24) & 0xFF; 583 if (tex_a > 127) { 584 ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0; 585 ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0; 586 ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0; 587 588 tex_r = ((color >> 16) & 0xFF) * ir >> 8; 589 tex_g = ((color >> 8) & 0xFF) * ig >> 8; 590 tex_b = (color & 0xFF) * ib >> 8; 591 592 f = f_w * wf; 593 if (f > 0.001f) { 594 if (f > 1.0f) f = 1.0f; 595 inv_f = 1.0f - f; 596 tex_r = (uint32_t)(tex_r * inv_f + sky_r * f); 597 tex_g = (uint32_t)(tex_g * inv_f + sky_g * f); 598 tex_b = (uint32_t)(tex_b * inv_f + sky_b * f); 599 } 600 601 g_sys->pixels[idx] = (tex_a << 24) | 602 (tex_r << 16) | (tex_g << 8) | tex_b; 603 g_sys->zbuffer[idx] = inv_w; 604 } 605 } 606 } 607 row_w0 += dw0_dx; row_w1 += dw1_dx; row_w2 -= (dw0_dx + dw1_dx); 608 inv_w += d_inv_w_dx; u_w += d_u_w_dx; v_w += d_v_w_dx; f_w += d_f_w_dx; 609 r += d_r_dx_255; g_val += d_g_dx_255; b += d_b_dx_255; 610 } 611 } 612 } else if (tri->is_water && tri->tex && (uintptr_t)tri->tex != (uintptr_t)-1) { 613 tex = tri->tex; 614 pixels = tex->pixels; 615 tw = tex->w; 616 th = tex->h; 617 tw_mask = tw - 1; 618 th_mask = th - 1; 619 wa_tc = g_sys->cur_weather.water[3]; 620 wr = g_sys->cur_weather.water[0]; 621 wg = g_sys->cur_weather.water[1]; 622 wb = g_sys->cur_weather.water[2]; 623 624 for (py = min_y; py <= max_y; py++) { 625 row_y = (float)py + 0.5f; 626 x_long = sv0.x + (row_y - sv0.y) * inv_slope_long; 627 x_short = (row_y < sv1.y) ? 628 sv0.x + (row_y - sv0.y) * inv_slope_short1 : 629 sv1.x + (row_y - sv1.y) * inv_slope_short2; 630 631 x_min = (x_long < x_short) ? x_long : x_short; 632 x_max = (x_long < x_short) ? x_short : x_long; 633 634 row_min_x = (int)floorf(x_min); 635 row_max_x = (int)ceilf(x_max); 636 637 if (row_min_x < min_x) row_min_x = min_x; 638 if (row_max_x > max_x) row_max_x = max_x; 639 if (row_min_x > row_max_x) continue; 640 641 dx = (row_min_x + 0.5f) - p_x_start; 642 dy = row_y - p_y_start; 643 row_w0 = w0_start + dw0_dx * dx + dw0_dy * dy; 644 row_w1 = w1_start + dw1_dx * dx + dw1_dy * dy; 645 row_w2 = 1.0f - row_w0 - row_w1; 646 647 inv_w = row_w0 * v0.w + row_w1 * v1.w + row_w2 * v2.w; 648 u_w = row_w0 * u0_w + row_w1 * u1_w + row_w2 * u2_w; 649 v_w = row_w0 * v0_w + row_w1 * v1_w + row_w2 * v2_w; 650 f_w = row_w0 * f0_w + row_w1 * f1_w + row_w2 * f2_w; 651 r = (row_w0 * v0.r + row_w1 * v1.r + row_w2 * v2.r) * 255.0f; 652 g_val = (row_w0 * v0.g + row_w1 * v1.g + row_w2 * v2.g) * 255.0f; 653 b = (row_w0 * v0.b + row_w1 * v1.b + row_w2 * v2.b) * 255.0f; 654 655 for (px = row_min_x; px <= row_max_x; px++) { 656 if (row_w0 >= -1e-4f && row_w1 >= -1e-4f && row_w2 >= -1e-4f) { 657 idx = py * WIDTH + px; 658 if (inv_w >= g_sys->zbuffer[idx] - 1e-6f && inv_w >= min_inv_w * 0.99f) { 659 ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0; 660 ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0; 661 ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0; 662 wf = 1.0f / inv_w; 663 664 tx = (int)(u_w * wf * tw) & tw_mask; 665 ty = (int)(v_w * wf * th) & th_mask; 666 color = pixels[ty * tw + tx]; 667 668 wa = (wa_tc * ((color >> 24) & 0xFF)) >> 8; 669 tex_r = ((((color >> 16) & 0xFF) * ir >> 8) * wr) >> 8; 670 tex_g = ((((color >> 8) & 0xFF) * ig >> 8) * wg) >> 8; 671 tex_b = ((color & 0xFF) * ib >> 8) * wb >> 8; 672 673 f = f_w * wf; 674 if (f > 0.001f) { 675 if (f > 1.0f) f = 1.0f; 676 inv_f = 1.0f - f; 677 tex_r = (uint32_t)(tex_r * inv_f + sky_r * f); 678 tex_g = (uint32_t)(tex_g * inv_f + sky_g * f); 679 tex_b = (uint32_t)(tex_b * inv_f + sky_b * f); 680 } 681 682 bg = g_sys->pixels[idx]; 683 g_sys->pixels[idx] = (0xFF << 24) | 684 (((tex_r * wa + ((bg >> 16) & 0xFF) * (255 - wa)) >> 8) << 16) | 685 (((tex_g * wa + ((bg >> 8) & 0xFF) * (255 - wa)) >> 8) << 8) | 686 ((tex_b * wa + (bg & 0xFF) * (255 - wa)) >> 8); 687 } 688 } 689 row_w0 += dw0_dx; row_w1 += dw1_dx; row_w2 -= (dw0_dx + dw1_dx); 690 inv_w += d_inv_w_dx; u_w += d_u_w_dx; v_w += d_v_w_dx; f_w += d_f_w_dx; 691 r += d_r_dx_255; g_val += d_g_dx_255; b += d_b_dx_255; 692 } 693 } 694 } 695 } 696 697 static void * 698 render_worker(void *arg) 699 { 700 int id, start_y, end_y, i; 701 702 id = (int)(intptr_t)arg; 703 start_y = id * HEIGHT / num_threads; 704 end_y = (id == num_threads - 1) ? HEIGHT - 1 : (id + 1) * HEIGHT / num_threads - 1; 705 706 while (1) { 707 pthread_barrier_wait(&barrier_start); 708 if (!threads_running) { 709 break; 710 } 711 for (i = 0; i < render_count; i++) { 712 draw_triangle_band(&render_list[i], start_y, end_y); 713 } 714 pthread_barrier_wait(&barrier_end); 715 } 716 return (NULL); 717 } 718 719 static void 720 chat_add_message(const char *name, const char *msg) 721 { 722 int i; 723 724 if (chat_log_count < CHAT_LINES) { 725 snprintf(chat_log[chat_log_count].text, 726 sizeof(chat_log[chat_log_count].text), "[%s]: %s", name, msg); 727 chat_log[chat_log_count].timer = 8.0f; 728 chat_log_count++; 729 } else { 730 for (i = 0; i < CHAT_LINES - 1; i++) { 731 chat_log[i] = chat_log[i + 1]; 732 } 733 snprintf(chat_log[CHAT_LINES - 1].text, 734 sizeof(chat_log[CHAT_LINES - 1].text), "[%s]: %s", name, msg); 735 chat_log[CHAT_LINES - 1].timer = 8.0f; 736 } 737 } 738 739 static void 740 net_init(const char *ip, int port, const char *nick) 741 { 742 struct pkt_join pj; 743 744 strncpy(local_nick, nick, sizeof(local_nick) - 1); 745 local_nick[sizeof(local_nick) - 1] = '\0'; 746 747 net_fd = socket(AF_INET, SOCK_DGRAM, 0); 748 if (net_fd < 0) { 749 return; 750 } 751 fcntl(net_fd, F_SETFL, O_NONBLOCK); 752 753 memset(&srv_addr, 0, sizeof(srv_addr)); 754 srv_addr.sin_family = AF_INET; 755 srv_addr.sin_port = htons(port); 756 inet_pton(AF_INET, ip, &srv_addr.sin_addr); 757 758 memset(&pj, 0, sizeof(pj)); 759 pj.hdr.magic = NET_MAGIC; 760 pj.hdr.type = PKT_JOIN; 761 pj.hdr.player_id = 0; 762 strncpy(pj.name, local_nick, sizeof(pj.name) - 1); 763 pj.skin = (uint16_t)active_skin_id; 764 765 sendto(net_fd, &pj, sizeof(pj), 0, 766 (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 767 } 768 769 static void 770 net_send_sync(float px, float py, float pz, float pyaw) 771 { 772 struct pkt_sync ps; 773 774 if (net_fd < 0 || !net_connected) { 775 return; 776 } 777 memset(&ps, 0, sizeof(ps)); 778 ps.hdr.magic = NET_MAGIC; 779 ps.hdr.type = PKT_SYNC; 780 ps.hdr.player_id = (uint8_t)my_player_id; 781 ps.x = px; 782 ps.y = py; 783 ps.z = pz; 784 ps.yaw = pyaw; 785 ps.skin = (uint16_t)active_skin_id; 786 787 sendto(net_fd, &ps, sizeof(ps), 0, 788 (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 789 if (g_sys) { 790 g_sys->pkts_out++; 791 } 792 } 793 794 static void 795 net_send_chat(const char *msg) 796 { 797 struct pkt_chat pc; 798 799 if (net_fd < 0 || !net_connected) { 800 return; 801 } 802 memset(&pc, 0, sizeof(pc)); 803 pc.hdr.magic = NET_MAGIC; 804 pc.hdr.type = PKT_CHAT; 805 pc.hdr.player_id = (uint8_t)my_player_id; 806 strncpy(pc.name, local_nick, sizeof(pc.name) - 1); 807 strncpy(pc.msg, msg, sizeof(pc.msg) - 1); 808 809 sendto(net_fd, &pc, sizeof(pc), 0, 810 (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 811 if (g_sys) { 812 g_sys->pkts_out++; 813 } 814 } 815 816 static void 817 net_player_add_snap(struct net_player *np, float x, float y, float z, float yaw, double now) 818 { 819 int i; 820 821 if (np->snap_count < 4) { 822 np->snaps[np->snap_count].x = x; 823 np->snaps[np->snap_count].y = y; 824 np->snaps[np->snap_count].z = z; 825 np->snaps[np->snap_count].yaw = yaw; 826 np->snaps[np->snap_count].time = now; 827 np->snap_count++; 828 } else { 829 for (i = 0; i < 3; i++) { 830 np->snaps[i] = np->snaps[i + 1]; 831 } 832 np->snaps[3].x = x; 833 np->snaps[3].y = y; 834 np->snaps[3].z = z; 835 np->snaps[3].yaw = yaw; 836 np->snaps[3].time = now; 837 } 838 } 839 840 static void 841 net_poll(struct sys_gfx *g, double now) 842 { 843 uint8_t buf[2048]; 844 ssize_t n; 845 const struct pkt_header *hdr; 846 const struct pkt_join_ack *ack; 847 const struct pkt_world_state *ws; 848 const struct pkt_chat *pc; 849 int i, id, seen[MAX_PLAYERS]; 850 851 if (net_fd < 0) { 852 return; 853 } 854 855 while ((n = recvfrom(net_fd, buf, sizeof(buf), 0, NULL, NULL)) > 0) { 856 g->pkts_in++; 857 if (n < (ssize_t)sizeof(struct pkt_header)) { 858 continue; 859 } 860 hdr = (const struct pkt_header *)buf; 861 if (hdr->magic != NET_MAGIC) { 862 continue; 863 } 864 865 if (hdr->type == PKT_JOIN_ACK) { 866 if (n >= (ssize_t)sizeof(struct pkt_join_ack)) { 867 ack = (const struct pkt_join_ack *)buf; 868 my_player_id = ack->your_id; 869 net_connected = 1; 870 g->game_weather = ack->game_weather; 871 g->game_time_hours = ack->game_time; 872 } 873 } else if (hdr->type == PKT_WORLD_STATE) { 874 if (n >= (ssize_t)(sizeof(struct pkt_header) + 1)) { 875 ws = (const struct pkt_world_state *)buf; 876 memset(seen, 0, sizeof(seen)); 877 for (i = 0; i < ws->player_count && i < MAX_PLAYERS; i++) { 878 id = ws->players[i].id; 879 if (id >= MAX_PLAYERS) { 880 continue; 881 } 882 seen[id] = 1; 883 if (!net_players[id].active) { 884 net_players[id].id = id; 885 net_players[id].skin = ws->players[i].skin; 886 net_players[id].cur_x = ws->players[i].x; 887 net_players[id].cur_y = ws->players[i].y; 888 net_players[id].cur_z = ws->players[i].z; 889 net_players[id].cur_yaw = ws->players[i].yaw; 890 net_players[id].snap_count = 0; 891 net_players[id].active = 1; 892 } 893 net_players[id].skin = ws->players[i].skin; 894 net_player_add_snap(&net_players[id], 895 ws->players[i].x, ws->players[i].y, ws->players[i].z, 896 ws->players[i].yaw, now); 897 } 898 for (i = 0; i < MAX_PLAYERS; i++) { 899 if (!seen[i]) { 900 net_players[i].active = 0; 901 net_players[i].snap_count = 0; 902 } 903 } 904 } 905 } else if (hdr->type == PKT_CHAT) { 906 if (n >= (ssize_t)sizeof(struct pkt_chat)) { 907 pc = (const struct pkt_chat *)buf; 908 chat_add_message(pc->name, pc->msg); 909 } 910 } 911 } 912 } 913 914 static void 915 net_send_leave(void) 916 { 917 struct pkt_header ph; 918 919 if (net_fd < 0 || !net_connected) { 920 return; 921 } 922 ph.magic = NET_MAGIC; 923 ph.type = PKT_LEAVE; 924 ph.player_id = (uint8_t)my_player_id; 925 926 sendto(net_fd, &ph, sizeof(ph), 0, 927 (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 928 close(net_fd); 929 net_fd = -1; 930 } 931 932 static void 933 net_interpolate(double now) 934 { 935 double render_time, dt_snap, t; 936 float dyaw; 937 int i, k; 938 struct net_player *np; 939 struct net_snap *s0, *s1; 940 941 render_time = now - 0.066; 942 943 for (i = 0; i < MAX_PLAYERS; i++) { 944 np = &net_players[i]; 945 if (!np->active || i == my_player_id || np->snap_count < 2) { 946 continue; 947 } 948 949 s0 = NULL; 950 s1 = NULL; 951 952 for (k = 0; k < np->snap_count - 1; k++) { 953 if (render_time >= np->snaps[k].time && 954 render_time <= np->snaps[k + 1].time) { 955 s0 = &np->snaps[k]; 956 s1 = &np->snaps[k + 1]; 957 break; 958 } 959 } 960 961 if (s0 && s1) { 962 dt_snap = s1->time - s0->time; 963 t = (dt_snap > 1e-5) ? (render_time - s0->time) / dt_snap : 0.0; 964 if (t < 0.0) t = 0.0; 965 if (t > 1.0) t = 1.0; 966 967 np->cur_x = s0->x + (s1->x - s0->x) * t; 968 np->cur_y = s0->y + (s1->y - s0->y) * t; 969 np->cur_z = s0->z + (s1->z - s0->z) * t; 970 971 dyaw = s1->yaw - s0->yaw; 972 while (dyaw > 3.14159265f) dyaw -= 6.2831853f; 973 while (dyaw < -3.14159265f) dyaw += 6.2831853f; 974 np->cur_yaw = s0->yaw + dyaw * t; 975 } else if (render_time > np->snaps[np->snap_count - 1].time) { 976 s0 = &np->snaps[np->snap_count - 2]; 977 s1 = &np->snaps[np->snap_count - 1]; 978 dt_snap = s1->time - s0->time; 979 t = (dt_snap > 1e-5) ? (render_time - s1->time) / dt_snap : 0.0; 980 if (t > 2.0) { 981 t = 2.0; 982 } 983 984 np->cur_x = s1->x + (s1->x - s0->x) * t; 985 np->cur_y = s1->y + (s1->y - s0->y) * t; 986 np->cur_z = s1->z + (s1->z - s0->z) * t; 987 np->cur_yaw = s1->yaw; 988 } 989 } 990 } 991 992 static void 993 gfx_init(struct sys_gfx *g) 994 { 995 XIM im; 996 int scr; 997 XColor black; 998 Pixmap bm_no; 999 Cursor no_ptr; 1000 char no_data[] = { 0,0,0,0,0,0,0,0 }; 1001 int i; 1002 char **missing_charsets; 1003 int missing_count; 1004 char *def_string; 1005 1006 memset(g, 0, sizeof(*g)); 1007 1008 setlocale(LC_ALL, ""); 1009 setlocale(LC_NUMERIC, "C"); 1010 XSetLocaleModifiers(""); 1011 1012 g->dpy = XOpenDisplay(NULL); 1013 if (g->dpy == NULL) { 1014 errx(1, "xopendisplay failed"); 1015 } 1016 if (!XShmQueryExtension(g->dpy)) { 1017 errx(1, "xshm extension not supported"); 1018 } 1019 scr = DefaultScreen(g->dpy); 1020 g->win = XCreateSimpleWindow(g->dpy, DefaultRootWindow(g->dpy), 0, 0, 1021 WIDTH, HEIGHT, 0, 0, 0); 1022 XSelectInput(g->dpy, g->win, KeyPressMask | KeyReleaseMask | 1023 StructureNotifyMask | FocusChangeMask | PointerMotionMask); 1024 1025 im = XOpenIM(g->dpy, NULL, NULL, NULL); 1026 g->ic = NULL; 1027 if (im) { 1028 g->ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, g->win, NULL); 1029 } 1030 1031 g->gc = XCreateGC(g->dpy, g->win, 0, NULL); 1032 g->img = XShmCreateImage(g->dpy, DefaultVisual(g->dpy, scr), 1033 DefaultDepth(g->dpy, scr), ZPixmap, NULL, &g->shm, WIDTH, HEIGHT); 1034 g->shm.shmid = shmget(IPC_PRIVATE, g->img->bytes_per_line * g->img->height, 1035 IPC_CREAT | 0777); 1036 g->shm.shmaddr = shmat(g->shm.shmid, 0, 0); 1037 g->img->data = g->shm.shmaddr; 1038 g->pixels = (uint32_t *)g->img->data; 1039 g->shm.readOnly = False; 1040 XShmAttach(g->dpy, &g->shm); 1041 shmctl(g->shm.shmid, IPC_RMID, 0); 1042 g->zbuffer = malloc(WIDTH * HEIGHT * sizeof(float)); 1043 g->wm_delete = XInternAtom(g->dpy, "WM_DELETE_WINDOW", False); 1044 XSetWMProtocols(g->dpy, g->win, &g->wm_delete, 1); 1045 1046 memset(&black, 0, sizeof(black)); 1047 bm_no = XCreateBitmapFromData(g->dpy, g->win, no_data, 8, 8); 1048 no_ptr = XCreatePixmapCursor(g->dpy, bm_no, bm_no, &black, &black, 0, 0); 1049 XDefineCursor(g->dpy, g->win, no_ptr); 1050 XFreeCursor(g->dpy, no_ptr); 1051 XFreePixmap(g->dpy, bm_no); 1052 1053 g->font_set = XCreateFontSet(g->dpy, "-*-*-medium-r-normal-*-14-*-*-*-*-*-iso10646-1", 1054 &missing_charsets, &missing_count, &def_string); 1055 if (!g->font_set) { 1056 g->font_set = XCreateFontSet(g->dpy, "fixed", 1057 &missing_charsets, &missing_count, &def_string); 1058 } 1059 if (missing_count > 0) { 1060 XFreeStringList(missing_charsets); 1061 } 1062 1063 g->key_w = XKeysymToKeycode(g->dpy, XK_w); 1064 g->key_a = XKeysymToKeycode(g->dpy, XK_a); 1065 g->key_s = XKeysymToKeycode(g->dpy, XK_s); 1066 g->key_d = XKeysymToKeycode(g->dpy, XK_d); 1067 g->key_t = XKeysymToKeycode(g->dpy, XK_t); 1068 g->key_esc = XKeysymToKeycode(g->dpy, XK_Escape); 1069 g->key_up = XKeysymToKeycode(g->dpy, XK_Up); 1070 g->key_down = XKeysymToKeycode(g->dpy, XK_Down); 1071 g->key_left = XKeysymToKeycode(g->dpy, XK_Left); 1072 g->key_right = XKeysymToKeycode(g->dpy, XK_Right); 1073 1074 num_threads = sysconf(_SC_NPROCESSORS_ONLN); 1075 if (num_threads < 1) { 1076 num_threads = 4; 1077 } 1078 pthread_barrier_init(&barrier_start, NULL, num_threads + 1); 1079 pthread_barrier_init(&barrier_end, NULL, num_threads + 1); 1080 workers = malloc(num_threads * sizeof(pthread_t)); 1081 for (i = 0; i < num_threads; i++) { 1082 pthread_create(&workers[i], NULL, render_worker, (void *)(intptr_t)i); 1083 } 1084 1085 v_scratch_cap = 16384; 1086 v_scratch = malloc(v_scratch_cap * sizeof(struct clip_vertex)); 1087 } 1088 1089 static void 1090 gfx_cleanup(struct sys_gfx *g) 1091 { 1092 int i; 1093 1094 threads_running = 0; 1095 pthread_barrier_wait(&barrier_start); 1096 for (i = 0; i < num_threads; i++) { 1097 pthread_join(workers[i], NULL); 1098 } 1099 pthread_barrier_destroy(&barrier_start); 1100 pthread_barrier_destroy(&barrier_end); 1101 free(workers); 1102 free(v_scratch); 1103 XUngrabPointer(g->dpy, CurrentTime); 1104 XShmDetach(g->dpy, &g->shm); 1105 XDestroyImage(g->img); 1106 shmdt(g->shm.shmaddr); 1107 free(g->zbuffer); 1108 if (g->font_set) { 1109 XFreeFontSet(g->dpy, g->font_set); 1110 } 1111 XFreeGC(g->dpy, g->gc); 1112 XDestroyWindow(g->dpy, g->win); 1113 XCloseDisplay(g->dpy); 1114 } 1115 1116 static void 1117 gfx_present(struct sys_gfx *g, float px, float py, float pz) 1118 { 1119 char txt[256]; 1120 int i, y_offset, active_count; 1121 1122 if (g->menu_open) { 1123 for (i = 0; i < WIDTH * HEIGHT; i++) { 1124 g->pixels[i] = (g->pixels[i] >> 1) & 0x7F7F7F; 1125 } 1126 } 1127 1128 XShmPutImage(g->dpy, g->win, g->gc, g->img, 0, 0, 0, 0, WIDTH, HEIGHT, False); 1129 1130 XSetForeground(g->dpy, g->gc, 0xFFFFFF); 1131 XSetBackground(g->dpy, g->gc, 0x000000); 1132 1133 for (i = 0; i < chat_log_count; i++) { 1134 if (chat_log[i].timer > 0.0f || g->in_chat) { 1135 y_offset = HEIGHT - 45 - (chat_log_count - 1 - i) * 16; 1136 if (g->font_set) { 1137 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 1138 10, y_offset, chat_log[i].text, strlen(chat_log[i].text)); 1139 } else { 1140 XDrawImageString(g->dpy, g->win, g->gc, 1141 10, y_offset, chat_log[i].text, strlen(chat_log[i].text)); 1142 } 1143 } 1144 } 1145 1146 if (g->show_debug) { 1147 active_count = 0; 1148 for (i = 0; i < MAX_PLAYERS; i++) { 1149 if (net_players[i].active) { 1150 active_count++; 1151 } 1152 } 1153 1154 XSetForeground(g->dpy, g->gc, 0x00FF00); 1155 XSetBackground(g->dpy, g->gc, 0x000000); 1156 1157 snprintf(txt, sizeof(txt), "FPS: %.1f | PLAYERS: %d/%d | ID: %d", 1158 g->fps, active_count, MAX_PLAYERS, my_player_id); 1159 if (g->font_set) { 1160 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 10, 20, txt, strlen(txt)); 1161 } else { 1162 XDrawImageString(g->dpy, g->win, g->gc, 10, 20, txt, strlen(txt)); 1163 } 1164 1165 snprintf(txt, sizeof(txt), "POS: X=%.2f Y=%.2f Z=%.2f", px, py, pz); 1166 if (g->font_set) { 1167 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 10, 36, txt, strlen(txt)); 1168 } else { 1169 XDrawImageString(g->dpy, g->win, g->gc, 10, 36, txt, strlen(txt)); 1170 } 1171 1172 snprintf(txt, sizeof(txt), "NET: IN=%u pkts/s | OUT=%u pkts/s", 1173 g->pkts_in_sec, g->pkts_out_sec); 1174 if (g->font_set) { 1175 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 10, 52, txt, strlen(txt)); 1176 } else { 1177 XDrawImageString(g->dpy, g->win, g->gc, 10, 52, txt, strlen(txt)); 1178 } 1179 } 1180 1181 if (g->menu_open) { 1182 snprintf(txt, sizeof(txt), "[ PAUSED - PRESS ESC TO RESUME ]"); 1183 XSetForeground(g->dpy, g->gc, 0xFFFFFF); 1184 XSetBackground(g->dpy, g->gc, 0x000000); 1185 if (g->font_set) { 1186 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 1187 WIDTH / 2 - 110, HEIGHT / 2, txt, strlen(txt)); 1188 } else { 1189 XDrawImageString(g->dpy, g->win, g->gc, 1190 WIDTH / 2 - 110, HEIGHT / 2, txt, strlen(txt)); 1191 } 1192 } else if (g->in_chat) { 1193 snprintf(txt, sizeof(txt), "> %s_", g->chat_buf); 1194 XSetForeground(g->dpy, g->gc, 0x00FF00); 1195 XSetBackground(g->dpy, g->gc, 0x000000); 1196 if (g->font_set) { 1197 Xutf8DrawImageString(g->dpy, g->win, g->font_set, g->gc, 1198 10, HEIGHT - 20, txt, strlen(txt)); 1199 } else { 1200 XDrawImageString(g->dpy, g->win, g->gc, 1201 10, HEIGHT - 20, txt, strlen(txt)); 1202 } 1203 } 1204 XSync(g->dpy, False); 1205 } 1206 1207 static int 1208 ray_tri_intersect_y(const struct col_triangle *t, float x, float z, float *out_y) 1209 { 1210 float x0, z0, x1, z1, x2, z2; 1211 float det, inv_det, w0, w1, w2; 1212 1213 x0 = t->v0[0]; 1214 z0 = t->v0[2]; 1215 x1 = t->v1[0]; 1216 z1 = t->v1[2]; 1217 x2 = t->v2[0]; 1218 z2 = t->v2[2]; 1219 1220 det = (z1 - z2) * (x0 - x2) + (x2 - x1) * (z0 - z2); 1221 if (fabsf(det) < 1e-6f) { 1222 return (0); 1223 } 1224 inv_det = 1.0f / det; 1225 1226 w0 = ((z1 - z2) * (x - x2) + (x2 - x1) * (z - z2)) * inv_det; 1227 w1 = ((z2 - z0) * (x - x2) + (x0 - x2) * (z - z2)) * inv_det; 1228 w2 = 1.0f - w0 - w1; 1229 1230 if (w0 >= 0.0f && w1 >= 0.0f && w2 >= 0.0f) { 1231 *out_y = w0 * t->v0[1] + w1 * t->v1[1] + w2 * t->v2[1]; 1232 return (1); 1233 } 1234 return (0); 1235 } 1236 1237 static float 1238 get_ground_height(float px, float pz, float cur_y) 1239 { 1240 const struct col_cell *c; 1241 const struct col_triangle *t; 1242 float best_below, hit_y, min_x, max_x, min_z, max_z, sx, sz; 1243 uint32_t i; 1244 int gx, gz, k; 1245 static const float offsets[5][2] = { 1246 { 0.0f, 0.0f }, 1247 { 0.18f, 0.0f }, 1248 {-0.18f, 0.0f }, 1249 { 0.0f, 0.18f }, 1250 { 0.0f, -0.18f } 1251 }; 1252 1253 gx = (int)((px - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1254 gz = (int)((pz - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1255 if (gx < 0 || gx >= GRID_SZ || gz < 0 || gz >= GRID_SZ) { 1256 return (-1000.0f); 1257 } 1258 1259 best_below = -1000.0f; 1260 c = &g_col_grid[gx][gz]; 1261 1262 for (i = 0; i < c->count; i++) { 1263 t = &c->tris[i]; 1264 if (t->norm[1] < 0.45f) { 1265 continue; 1266 } 1267 1268 min_x = fminf(t->v0[0], fminf(t->v1[0], t->v2[0])); 1269 max_x = fmaxf(t->v0[0], fmaxf(t->v1[0], t->v2[0])); 1270 if (px + 0.20f < min_x || px - 0.20f > max_x) { 1271 continue; 1272 } 1273 1274 min_z = fminf(t->v0[2], fminf(t->v1[2], t->v2[2])); 1275 max_z = fmaxf(t->v0[2], fmaxf(t->v1[2], t->v2[2])); 1276 if (pz + 0.20f < min_z || pz - 0.20f > max_z) { 1277 continue; 1278 } 1279 1280 for (k = 0; k < 5; k++) { 1281 sx = px + offsets[k][0]; 1282 sz = pz + offsets[k][1]; 1283 if (ray_tri_intersect_y(t, sx, sz, &hit_y)) { 1284 if (hit_y <= cur_y + 0.60f && hit_y > best_below) { 1285 best_below = hit_y; 1286 } 1287 } 1288 } 1289 } 1290 return (best_below); 1291 } 1292 1293 static float 1294 get_ceiling_height(float px, float pz, float cur_y) 1295 { 1296 const struct col_cell *c; 1297 const struct col_triangle *t; 1298 float best_above, hit_y, min_x, max_x, min_z, max_z; 1299 uint32_t i; 1300 int gx, gz; 1301 1302 gx = (int)((px - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1303 gz = (int)((pz - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1304 if (gx < 0 || gx >= GRID_SZ || gz < 0 || gz >= GRID_SZ) { 1305 return (1000.0f); 1306 } 1307 1308 best_above = 1000.0f; 1309 c = &g_col_grid[gx][gz]; 1310 1311 for (i = 0; i < c->count; i++) { 1312 t = &c->tris[i]; 1313 if (t->norm[1] > -0.2f && t->norm[1] < 0.2f) { 1314 continue; 1315 } 1316 1317 min_x = fminf(t->v0[0], fminf(t->v1[0], t->v2[0])); 1318 max_x = fmaxf(t->v0[0], fmaxf(t->v1[0], t->v2[0])); 1319 if (px < min_x || px > max_x) { 1320 continue; 1321 } 1322 1323 min_z = fminf(t->v0[2], fminf(t->v1[2], t->v2[2])); 1324 max_z = fmaxf(t->v0[2], fmaxf(t->v1[2], t->v2[2])); 1325 if (pz < min_z || pz > max_z) { 1326 continue; 1327 } 1328 1329 if (ray_tri_intersect_y(t, px, pz, &hit_y)) { 1330 if (hit_y >= cur_y + 1.0f && hit_y < best_above) { 1331 best_above = hit_y; 1332 } 1333 } 1334 } 1335 return (best_above); 1336 } 1337 1338 static void 1339 move_and_slide(float *px, float py, float *pz, float vx, float vz, float dt) 1340 { 1341 const struct col_cell *c; 1342 const struct col_triangle *t; 1343 float sphere[3][3]; 1344 float closest[3], diff[3]; 1345 float rad, dist_sq, dist, h_len, dot, step_x, step_z, push; 1346 float min_x, max_x, min_y, max_y, min_z, max_z; 1347 float prev_x, prev_z, accum_nx, accum_nz, n_len; 1348 int sub, iter, s, i, gx, gz, gx0, gx1, gz0, gz1, contacts; 1349 1350 rad = 0.35f; 1351 step_x = (vx * dt) * 0.25f; 1352 step_z = (vz * dt) * 0.25f; 1353 1354 for (sub = 0; sub < 4; sub++) { 1355 prev_x = *px; 1356 prev_z = *pz; 1357 1358 *px += step_x; 1359 *pz += step_z; 1360 1361 accum_nx = 0.0f; 1362 accum_nz = 0.0f; 1363 contacts = 0; 1364 1365 gx0 = (int)((*px - rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1366 gx1 = (int)((*px + rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1367 gz0 = (int)((*pz - rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1368 gz1 = (int)((*pz + rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 1369 1370 if (gx0 < 0) gx0 = 0; 1371 if (gx1 >= GRID_SZ) gx1 = GRID_SZ - 1; 1372 if (gz0 < 0) gz0 = 0; 1373 if (gz1 >= GRID_SZ) gz1 = GRID_SZ - 1; 1374 1375 for (iter = 0; iter < 2; iter++) { 1376 sphere[0][0] = *px; 1377 sphere[0][1] = py + 0.35f; 1378 sphere[0][2] = *pz; 1379 1380 sphere[1][0] = *px; 1381 sphere[1][1] = py + 0.95f; 1382 sphere[1][2] = *pz; 1383 1384 sphere[2][0] = *px; 1385 sphere[2][1] = py + 1.55f; 1386 sphere[2][2] = *pz; 1387 1388 for (gz = gz0; gz <= gz1; gz++) { 1389 for (gx = gx0; gx <= gx1; gx++) { 1390 c = &g_col_grid[gx][gz]; 1391 1392 for (i = 0; i < (int)c->count; i++) { 1393 t = &c->tris[i]; 1394 if (t->norm[1] > 0.6f) { 1395 continue; 1396 } 1397 1398 min_y = fminf(t->v0[1], fminf(t->v1[1], t->v2[1])); 1399 max_y = fmaxf(t->v0[1], fmaxf(t->v1[1], t->v2[1])); 1400 if (py + 1.9f < min_y || py > max_y) { 1401 continue; 1402 } 1403 1404 min_x = fminf(t->v0[0], fminf(t->v1[0], t->v2[0])); 1405 max_x = fmaxf(t->v0[0], fmaxf(t->v1[0], t->v2[0])); 1406 if (*px + rad < min_x || *px - rad > max_x) { 1407 continue; 1408 } 1409 1410 min_z = fminf(t->v0[2], fminf(t->v1[2], t->v2[2])); 1411 max_z = fmaxf(t->v0[2], fmaxf(t->v1[2], t->v2[2])); 1412 if (*pz + rad < min_z || *pz - rad > max_z) { 1413 continue; 1414 } 1415 1416 for (s = 0; s < 3; s++) { 1417 closest_point_triangle(sphere[s], 1418 t->v0, t->v1, t->v2, closest); 1419 1420 diff[0] = sphere[s][0] - closest[0]; 1421 diff[1] = sphere[s][1] - closest[1]; 1422 diff[2] = sphere[s][2] - closest[2]; 1423 1424 dist_sq = diff[0] * diff[0] + 1425 diff[1] * diff[1] + 1426 diff[2] * diff[2]; 1427 1428 if (dist_sq < rad * rad) { 1429 dist = sqrtf(dist_sq); 1430 h_len = sqrtf(diff[0] * diff[0] + diff[2] * diff[2]); 1431 1432 if (h_len > 1e-4f) { 1433 diff[0] /= h_len; 1434 diff[2] /= h_len; 1435 } else { 1436 diff[0] = prev_x - closest[0]; 1437 diff[2] = prev_z - closest[2]; 1438 h_len = sqrtf(diff[0] * diff[0] + diff[2] * diff[2]); 1439 if (h_len > 1e-4f) { 1440 diff[0] /= h_len; 1441 diff[2] /= h_len; 1442 } else { 1443 diff[0] = 1.0f; 1444 diff[2] = 0.0f; 1445 } 1446 } 1447 1448 push = rad - dist; 1449 *px += diff[0] * push; 1450 *pz += diff[2] * push; 1451 1452 accum_nx += diff[0]; 1453 accum_nz += diff[2]; 1454 contacts++; 1455 1456 sphere[0][0] = *px; 1457 sphere[0][2] = *pz; 1458 sphere[1][0] = *px; 1459 sphere[1][2] = *pz; 1460 sphere[2][0] = *px; 1461 sphere[2][2] = *pz; 1462 } 1463 } 1464 } 1465 } 1466 } 1467 } 1468 1469 if (contacts > 0) { 1470 n_len = sqrtf(accum_nx * accum_nx + accum_nz * accum_nz); 1471 if (n_len > 1e-4f) { 1472 accum_nx /= n_len; 1473 accum_nz /= n_len; 1474 dot = vx * accum_nx + vz * accum_nz; 1475 if (dot < 0.0f) { 1476 vx -= dot * accum_nx; 1477 vz -= dot * accum_nz; 1478 } 1479 } 1480 } 1481 } 1482 } 1483 1484 static unsigned int 1485 hash_str(const char *str) 1486 { 1487 unsigned int hash = 5381; 1488 int c; 1489 1490 while ((c = (unsigned char)*str++)) { 1491 hash = ((hash << 5) + hash) + c; 1492 } 1493 return (hash); 1494 } 1495 1496 static void 1497 mesh_load_ply(struct mesh *m, const uint8_t *data, size_t sz) 1498 { 1499 const char *header_end; 1500 const char *p; 1501 const uint8_t *bin; 1502 int temp_materials, idx, k; 1503 char *dst; 1504 const char *src; 1505 uint16_t *mat; 1506 int32_t *idx_ptr; 1507 uint32_t i; 1508 1509 (void)sz; 1510 header_end = strstr((const char *)data, "end_header\n"); 1511 if (!header_end) { 1512 return; 1513 } 1514 header_end += 11; 1515 1516 memset(m, 0, sizeof(*m)); 1517 1518 p = (const char *)data; 1519 temp_materials = 0; 1520 while (p < header_end) { 1521 if (strncmp(p, "comment spr_cx", 14) == 0) m->spr_x = strtof(p + 14, NULL); 1522 else if (strncmp(p, "comment spr_cy", 14) == 0) m->spr_y = strtof(p + 14, NULL); 1523 else if (strncmp(p, "comment spr_cz", 14) == 0) m->spr_z = strtof(p + 14, NULL); 1524 else if (strncmp(p, "comment spr_r", 13) == 0) m->spr_r = strtof(p + 13, NULL); 1525 else if (strncmp(p, "element vertex", 14) == 0) m->num_verts = strtoul(p + 14, NULL, 10); 1526 else if (strncmp(p, "element face", 12) == 0) m->num_tris = strtoul(p + 12, NULL, 10); 1527 else if (strncmp(p, "comment texture", 15) == 0) temp_materials++; 1528 p = strchr(p, '\n'); 1529 if (!p) break; 1530 p++; 1531 } 1532 1533 m->num_materials = temp_materials; 1534 if (m->num_materials > 0) { 1535 m->raw_tex_names = malloc(m->num_materials * 32); 1536 p = (const char *)data; 1537 idx = 0; 1538 while (p < header_end) { 1539 if (strncmp(p, "comment texture", 15) == 0) { 1540 src = p + 16; 1541 dst = m->raw_tex_names[idx]; 1542 k = 0; 1543 while (src[k] != '\n' && src[k] != '\r' && k < 31) { 1544 dst[k] = src[k]; 1545 k++; 1546 } 1547 dst[k] = '\0'; 1548 idx++; 1549 } 1550 p = strchr(p, '\n'); 1551 if (!p) break; 1552 p++; 1553 } 1554 } 1555 1556 m->ply_verts = malloc(m->num_verts * sizeof(struct ply_vertex)); 1557 m->indices = malloc(m->num_tris * 3 * sizeof(uint16_t)); 1558 m->mat_ids = malloc(m->num_tris * sizeof(uint16_t)); 1559 1560 bin = (const uint8_t *)header_end; 1561 1562 memcpy(m->ply_verts, bin, m->num_verts * sizeof(struct ply_vertex)); 1563 bin += m->num_verts * sizeof(struct ply_vertex); 1564 1565 for (i = 0; i < m->num_tris; i++) { 1566 bin += 1; 1567 idx_ptr = (int32_t *)bin; 1568 m->indices[i*3+0] = idx_ptr[0]; 1569 m->indices[i*3+1] = idx_ptr[1]; 1570 m->indices[i*3+2] = idx_ptr[2]; 1571 bin += 12; 1572 1573 mat = (uint16_t *)bin; 1574 m->mat_ids[i] = *mat; 1575 bin += 2; 1576 } 1577 1578 m->total_area = 0.0f; 1579 for (i = 0; i < m->num_tris; i++) { 1580 uint16_t i0 = m->indices[i*3], i1 = m->indices[i*3+1], i2 = m->indices[i*3+2]; 1581 float ux = m->ply_verts[i1].x - m->ply_verts[i0].x; 1582 float uy = m->ply_verts[i1].y - m->ply_verts[i0].y; 1583 float uz = m->ply_verts[i1].z - m->ply_verts[i0].z; 1584 float vx = m->ply_verts[i2].x - m->ply_verts[i0].x; 1585 float vy = m->ply_verts[i2].y - m->ply_verts[i0].y; 1586 float vz = m->ply_verts[i2].z - m->ply_verts[i0].z; 1587 float cx = uy * vz - uz * vy, cy = uz * vx - ux * vz, cz = ux * vy - uy * vx; 1588 m->total_area += 0.5f * sqrtf(cx*cx + cy*cy + cz*cz); 1589 } 1590 } 1591 1592 static void 1593 tex_load_tga(struct texture *t, const uint8_t *data, size_t sz) 1594 { 1595 struct tga_header *hdr; 1596 const uint8_t *src_pixels; 1597 uint32_t *dst, *curr_offset, *src; 1598 int w, h, mw, mh, total_pixels, i, level; 1599 int prev_w, prev_h, next_w, next_h, x, y; 1600 uint32_t c00, c10, c01, c11, r, g, b, a; 1601 1602 memset(t, 0, sizeof(*t)); 1603 if (data == NULL || sz < sizeof(struct tga_header)) { 1604 w = 2; 1605 h = 2; 1606 t->w = w; 1607 t->h = h; 1608 t->has_alpha = 0; 1609 t->pixels = malloc((4 + 1 + 1 + 1) * sizeof(uint32_t)); 1610 if (t->pixels == NULL) { 1611 return; 1612 } 1613 t->pixels[0] = 0xffa0a0a0; 1614 t->pixels[1] = 0xff808080; 1615 t->pixels[2] = 0xff808080; 1616 t->pixels[3] = 0xffa0a0a0; 1617 1618 t->mips[0] = t->pixels; 1619 t->mip_w[0] = 2; 1620 t->mip_h[0] = 2; 1621 1622 for (i = 1; i < 4; i++) { 1623 t->mips[i] = t->pixels + 4; 1624 t->mip_w[i] = 1; 1625 t->mip_h[i] = 1; 1626 } 1627 t->mips[1][0] = 0xff909090; 1628 return; 1629 } 1630 1631 hdr = (struct tga_header *)data; 1632 w = hdr->width; 1633 h = hdr->height; 1634 t->w = w; 1635 t->h = h; 1636 1637 mw = w; 1638 mh = h; 1639 total_pixels = 0; 1640 for (i = 0; i < 4; i++) { 1641 total_pixels += mw * mh; 1642 mw = mw > 1 ? mw / 2 : 1; 1643 mh = mh > 1 ? mh / 2 : 1; 1644 } 1645 1646 t->pixels = malloc(total_pixels * sizeof(uint32_t)); 1647 if (t->pixels == NULL) { 1648 return; 1649 } 1650 src_pixels = data + sizeof(struct tga_header) + hdr->id_length; 1651 1652 if (hdr->pixel_depth == 32) { 1653 memcpy(t->pixels, src_pixels, w * h * 4); 1654 t->has_alpha = 0; 1655 for (i = 0; i < w * h; i++) { 1656 a = (t->pixels[i] >> 24) & 0xFF; 1657 if (a < 250) { 1658 t->has_alpha = 1; 1659 break; 1660 } 1661 } 1662 } else if (hdr->pixel_depth == 24) { 1663 t->has_alpha = 0; 1664 dst = t->pixels; 1665 for (i = 0; i < w * h; i++) { 1666 dst[i] = (255U << 24) | (src_pixels[i*3+2] << 16) | 1667 (src_pixels[i*3+1] << 8) | src_pixels[i*3+0]; 1668 } 1669 } 1670 1671 t->mips[0] = t->pixels; 1672 t->mip_w[0] = w; 1673 t->mip_h[0] = h; 1674 1675 curr_offset = t->pixels + (w * h); 1676 for (level = 1; level < 4; level++) { 1677 prev_w = t->mips[level-1] ? t->mip_w[level-1] : 1; 1678 prev_h = t->mips[level-1] ? t->mip_h[level-1] : 1; 1679 next_w = prev_w > 1 ? prev_w / 2 : 1; 1680 next_h = prev_h > 1 ? prev_h / 2 : 1; 1681 1682 t->mips[level] = curr_offset; 1683 t->mip_w[level] = next_w; 1684 t->mip_h[level] = next_h; 1685 1686 src = t->mips[level-1]; 1687 dst = t->mips[level]; 1688 1689 if (prev_w > 1 && prev_h > 1) { 1690 for (y = 0; y < next_h; y++) { 1691 for (x = 0; x < next_w; x++) { 1692 c00 = src[(y*2)*prev_w + (x*2)]; 1693 c10 = src[(y*2)*prev_w + (x*2+1)]; 1694 c01 = src[(y*2+1)*prev_w + (x*2)]; 1695 c11 = src[(y*2+1)*prev_w + (x*2+1)]; 1696 1697 r = (((c00 >> 16) & 0xFF) + ((c10 >> 16) & 0xFF) + 1698 ((c01 >> 16) & 0xFF) + ((c11 >> 16) & 0xFF)) / 4; 1699 g = (((c00 >> 8) & 0xFF) + ((c10 >> 8) & 0xFF) + 1700 ((c01 >> 8) & 0xFF) + ((c11 >> 8) & 0xFF)) / 4; 1701 b = ((c00 & 0xFF) + (c10 & 0xFF) + 1702 (c01 & 0xFF) + (c11 & 0xFF)) / 4; 1703 a = (((c00 >> 24) & 0xFF) + ((c10 >> 24) & 0xFF) + 1704 ((c01 >> 24) & 0xFF) + ((c11 >> 24) & 0xFF)) / 4; 1705 1706 dst[y * next_w + x] = (a << 24) | (r << 16) | 1707 (g << 8) | b; 1708 } 1709 } 1710 } else { 1711 for (i = 0; i < next_w * next_h; i++) { 1712 dst[i] = src[0]; 1713 } 1714 } 1715 curr_offset += next_w * next_h; 1716 } 1717 } 1718 1719 static struct texture * 1720 cache_get_tex(struct asset_cache *c, const char *name) 1721 { 1722 unsigned int h; 1723 int idx; 1724 char tar_path[1024]; 1725 size_t sz = 0; 1726 const uint8_t *data; 1727 1728 if (!name || name[0] == '\0') { 1729 name = "missing"; 1730 } 1731 h = hash_str(name) % (MAX_CACHE * 2); 1732 while (c->tex_hash[h] != 0) { 1733 idx = c->tex_hash[h] - 1; 1734 if (strcasecmp(c->tex_names[idx], name) == 0) { 1735 return (&c->textures[idx]); 1736 } 1737 h = (h + 1) % (MAX_CACHE * 2); 1738 } 1739 if (c->tex_count >= MAX_CACHE) { 1740 return (NULL); 1741 } 1742 idx = c->tex_count++; 1743 snprintf(c->tex_names[idx], 32, "%s", name); 1744 c->tex_hash[h] = idx + 1; 1745 1746 snprintf(tar_path, sizeof(tar_path), "assets/textures/%s.tga", name); 1747 1748 data = tar_lookup(tar_path, &sz); 1749 tex_load_tga(&c->textures[idx], data, sz); 1750 return (&c->textures[idx]); 1751 } 1752 1753 static struct mesh * 1754 cache_get_mesh(struct asset_cache *c, const char *name) 1755 { 1756 unsigned int h; 1757 int idx; 1758 char tar_path[1024]; 1759 size_t sz = 0; 1760 const uint8_t *data; 1761 uint32_t i; 1762 1763 h = hash_str(name) % (MAX_CACHE * 2); 1764 while (c->mesh_hash[h] != 0) { 1765 idx = c->mesh_hash[h] - 1; 1766 if (strcasecmp(c->mesh_names[idx], name) == 0) { 1767 return (&c->meshes[idx]); 1768 } 1769 h = (h + 1) % (MAX_CACHE * 2); 1770 } 1771 if (c->mesh_count >= MAX_CACHE) { 1772 return (NULL); 1773 } 1774 idx = c->mesh_count++; 1775 snprintf(c->mesh_names[idx], NAME_SZ, "%s", name); 1776 c->mesh_hash[h] = idx + 1; 1777 1778 snprintf(tar_path, sizeof(tar_path), "assets/models/%s.ply", name); 1779 1780 data = tar_lookup(tar_path, &sz); 1781 if (data) { 1782 mesh_load_ply(&c->meshes[idx], data, sz); 1783 if (c->meshes[idx].num_materials > 0) { 1784 c->meshes[idx].textures = malloc(c->meshes[idx].num_materials * sizeof(struct texture *)); 1785 for (i = 0; i < c->meshes[idx].num_materials; i++) { 1786 c->meshes[idx].textures[i] = cache_get_tex(c, c->meshes[idx].raw_tex_names[i]); 1787 } 1788 } 1789 } 1790 return (&c->meshes[idx]); 1791 } 1792 1793 static void 1794 mat_identity(struct mat4 *m) 1795 { 1796 memset(m, 0, sizeof(*m)); 1797 m->m[0][0] = m->m[1][1] = m->m[2][2] = m->m[3][3] = 1.0f; 1798 } 1799 1800 static inline void 1801 mat_mul(struct mat4 *dst, const struct mat4 *a, const struct mat4 *b) 1802 { 1803 struct mat4 r; 1804 int i; 1805 1806 for (i = 0; i < 4; i++) { 1807 r.m[i][0] = a->m[i][0]*b->m[0][0] + a->m[i][1]*b->m[1][0] + a->m[i][2]*b->m[2][0] + a->m[i][3]*b->m[3][0]; 1808 r.m[i][1] = a->m[i][0]*b->m[0][1] + a->m[i][1]*b->m[1][1] + a->m[i][2]*b->m[2][1] + a->m[i][3]*b->m[3][1]; 1809 r.m[i][2] = a->m[i][0]*b->m[0][2] + a->m[i][1]*b->m[1][2] + a->m[i][2]*b->m[2][2] + a->m[i][3]*b->m[3][2]; 1810 r.m[i][3] = a->m[i][0]*b->m[0][3] + a->m[i][1]*b->m[1][3] + a->m[i][2]*b->m[2][3] + a->m[i][3]*b->m[3][3]; 1811 } 1812 *dst = r; 1813 } 1814 1815 static void 1816 mat_translate(struct mat4 *m, float x, float y, float z) 1817 { 1818 mat_identity(m); 1819 m->m[0][3] = x; 1820 m->m[1][3] = y; 1821 m->m[2][3] = z; 1822 } 1823 1824 static void 1825 mat_from_quat(struct mat4 *m, float qx, float qy, float qz, float qw) 1826 { 1827 float len; 1828 1829 qw = -qw; 1830 len = sqrtf(qx * qx + qy * qy + qz * qz + qw * qw); 1831 if (len > 0.0f) { 1832 qx /= len; qy /= len; qz /= len; qw /= len; 1833 } 1834 mat_identity(m); 1835 m->m[0][0] = 1.0f - 2.0f * (qy * qy + qz * qz); 1836 m->m[0][1] = 2.0f * (qx * qy - qz * qw); 1837 m->m[0][2] = 2.0f * (qx * qz + qy * qw); 1838 m->m[1][0] = 2.0f * (qx * qy + qz * qw); 1839 m->m[1][1] = 1.0f - 2.0f * (qx * qx + qz * qz); 1840 m->m[1][2] = 2.0f * (qy * qz - qx * qw); 1841 m->m[2][0] = 2.0f * (qx * qz - qy * qw); 1842 m->m[2][1] = 2.0f * (qy * qz + qx * qw); 1843 m->m[2][2] = 1.0f - 2.0f * (qx * qx + qy * qy); 1844 } 1845 1846 static void 1847 mat_projection(struct mat4 *m, float fov, float aspect, float near, float far) 1848 { 1849 float f; 1850 1851 f = 1.0f / tanf(fov * 0.5f * 3.14159265f / 180.0f); 1852 memset(m, 0, sizeof(*m)); 1853 m->m[0][0] = f / aspect; 1854 m->m[1][1] = f; 1855 m->m[2][2] = (far + near) / (far - near); 1856 m->m[2][3] = -(2.0f * far * near) / (far - near); 1857 m->m[3][2] = 1.0f; 1858 } 1859 1860 static void 1861 mat_view(struct mat4 *m, float cx, float cy, float cz, float cyaw, float cpitch) 1862 { 1863 struct mat4 trans, rot_y, rot_x, rot; 1864 1865 mat_translate(&trans, -cx, -cy, -cz); 1866 mat_identity(&rot_y); 1867 rot_y.m[0][0] = cosf(-cyaw); 1868 rot_y.m[0][2] = sinf(-cyaw); 1869 rot_y.m[2][0] = -sinf(-cyaw); 1870 rot_y.m[2][2] = cosf(-cyaw); 1871 mat_identity(&rot_x); 1872 rot_x.m[1][1] = cosf(cpitch); 1873 rot_x.m[1][2] = -sinf(cpitch); 1874 rot_x.m[2][1] = sinf(cpitch); 1875 rot_x.m[2][2] = cosf(cpitch); 1876 mat_mul(&rot, &rot_x, &rot_y); 1877 mat_mul(m, &rot, &trans); 1878 } 1879 1880 static inline void 1881 mat_transform(struct vec3 *dst, float *w_out, const struct mat4 *m, const struct vec3 *v) 1882 { 1883 dst->x = m->m[0][0] * v->x + m->m[0][1] * v->y + m->m[0][2] * v->z + m->m[0][3]; 1884 dst->y = m->m[1][0] * v->x + m->m[1][1] * v->y + m->m[1][2] * v->z + m->m[1][3]; 1885 dst->z = m->m[2][0] * v->x + m->m[2][1] * v->y + m->m[2][2] * v->z + m->m[2][3]; 1886 *w_out = m->m[3][0] * v->x + m->m[3][1] * v->y + m->m[3][2] * v->z + m->m[3][3]; 1887 } 1888 1889 static void 1890 flush_render_list(void) 1891 { 1892 if (render_count == 0) { 1893 return; 1894 } 1895 pthread_barrier_wait(&barrier_start); 1896 pthread_barrier_wait(&barrier_end); 1897 render_count = 0; 1898 } 1899 1900 static void 1901 project_and_push(const struct clip_vertex *c0, const struct clip_vertex *c1, const struct clip_vertex *c2, const struct texture *tex, int is_water, int mip) 1902 { 1903 struct vertex v0, v1, v2; 1904 float area; 1905 int double_sided; 1906 struct vertex tmp; 1907 1908 v0.w = 1.0f / c0->w; v0.x = (c0->x * v0.w + 1.0f) * WIDTH * 0.5f; v0.y = (1.0f - c0->y * v0.w) * HEIGHT * 0.5f; 1909 v0.z = c0->w; v0.u = c0->u; v0.v = c0->v; v0.r = c0->r; v0.g = c0->g; v0.b = c0->b; v0.a = c0->a; v0.f = c0->f; 1910 v1.w = 1.0f / c1->w; v1.x = (c1->x * v1.w + 1.0f) * WIDTH * 0.5f; v1.y = (1.0f - c1->y * v1.w) * HEIGHT * 0.5f; 1911 v1.z = c1->w; v1.u = c1->u; v1.v = c1->v; v1.r = c1->r; v1.g = c1->g; v1.b = c1->b; v1.a = c1->a; v1.f = c1->f; 1912 v2.w = 1.0f / c2->w; v2.x = (c2->x * v2.w + 1.0f) * WIDTH * 0.5f; v2.y = (1.0f - c2->y * v2.w) * HEIGHT * 0.5f; 1913 v2.z = c2->w; v2.u = c2->u; v2.v = c2->v; v2.r = c2->r; v2.g = c2->g; v2.b = c2->b; v2.a = c2->a; v2.f = c2->f; 1914 1915 area = edge_func(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); 1916 double_sided = (tex && tex->has_alpha) || is_water; 1917 if (area >= 0.0f) { 1918 if (double_sided) { 1919 tmp = v1; 1920 v1 = v2; 1921 v2 = tmp; 1922 } else { 1923 return; 1924 } 1925 } 1926 1927 if (render_count >= MAX_RENDER_TRIS) { 1928 flush_render_list(); 1929 } 1930 render_list[render_count].v0 = v0; 1931 render_list[render_count].v1 = v1; 1932 render_list[render_count].v2 = v2; 1933 render_list[render_count].tex = tex; 1934 render_list[render_count].is_water = is_water; 1935 render_list[render_count].mip = mip; 1936 render_count++; 1937 } 1938 1939 static struct clip_vertex 1940 clip_intersect(const struct clip_vertex *a, const struct clip_vertex *b, float w_clip) 1941 { 1942 struct clip_vertex out; 1943 float t; 1944 1945 t = (w_clip - a->w) / (b->w - a->w); 1946 out.x = a->x + t * (b->x - a->x); 1947 out.y = a->y + t * (b->y - a->y); 1948 out.z = a->z + t * (b->z - a->z); 1949 out.w = w_clip; 1950 out.u = a->u + t * (b->u - a->u); 1951 out.v = a->v + t * (b->v - a->v); 1952 out.r = a->r + t * (b->r - a->r); 1953 out.g = a->g + t * (b->g - a->g); 1954 out.b = a->b + t * (b->b - a->b); 1955 out.a = a->a + t * (b->a - a->a); 1956 out.f = a->f + t * (b->f - a->f); 1957 return (out); 1958 } 1959 1960 static void 1961 clip_and_push_triangle(const struct clip_vertex *c0, const struct clip_vertex *c1, const struct clip_vertex *c2, const struct texture *tex, int is_water, int mip) 1962 { 1963 struct clip_vertex p[4]; 1964 const struct clip_vertex *v[3]; 1965 const struct clip_vertex *c, *n; 1966 int len = 0; 1967 int i; 1968 1969 v[0] = c0; 1970 v[1] = c1; 1971 v[2] = c2; 1972 1973 for (i = 0; i < 3; i++) { 1974 c = v[i]; 1975 n = v[(i + 1) % 3]; 1976 if (c->w >= 0.1f) { 1977 p[len++] = *c; 1978 } 1979 if ((c->w >= 0.1f) != (n->w >= 0.1f)) { 1980 p[len++] = clip_intersect(c, n, 0.1f); 1981 } 1982 } 1983 if (len == 3) { 1984 project_and_push(&p[0], &p[1], &p[2], tex, is_water, mip); 1985 } else if (len == 4) { 1986 project_and_push(&p[0], &p[1], &p[2], tex, is_water, mip); 1987 project_and_push(&p[0], &p[2], &p[3], tex, is_water, mip); 1988 } 1989 } 1990 1991 static void 1992 draw_mesh(const struct mesh *m, const struct mat4 *mvp, int is_seabed) 1993 { 1994 struct clip_vertex *cv; 1995 float ar, ag, ab, far_clp, fog_st, min_dist; 1996 int mip; 1997 float scale; 1998 uint32_t i; 1999 struct vec3 in, out; 2000 float w, fog, d; 2001 2002 if (m->ply_verts == NULL || m->num_verts == 0) { 2003 return; 2004 } 2005 if (m->num_verts > v_scratch_cap) { 2006 v_scratch_cap = m->num_verts * 2; 2007 v_scratch = realloc(v_scratch, v_scratch_cap * sizeof(struct clip_vertex)); 2008 } 2009 cv = v_scratch; 2010 ar = g_sys->cur_weather.amb[0] / 255.0f * 1.2f; 2011 ag = g_sys->cur_weather.amb[1] / 255.0f * 1.2f; 2012 ab = g_sys->cur_weather.amb[2] / 255.0f * 1.2f; 2013 far_clp = g_sys->cur_weather.far_clp; 2014 fog_st = g_sys->cur_weather.fog_st; 2015 if (far_clp <= fog_st) { 2016 far_clp = fog_st + 1.0f; 2017 } 2018 min_dist = 1e9f; 2019 2020 for (i = 0; i < m->num_verts; i++) { 2021 in.x = m->ply_verts[i].x; 2022 in.y = m->ply_verts[i].y; 2023 in.z = m->ply_verts[i].z; 2024 mat_transform(&out, &w, mvp, &in); 2025 cv[i].x = out.x; 2026 cv[i].y = out.y; 2027 cv[i].z = out.z; 2028 cv[i].w = w; 2029 cv[i].u = m->ply_verts[i].s; 2030 cv[i].v = m->ply_verts[i].t; 2031 fog = (out.z - fog_st) / (far_clp - fog_st); 2032 if (fog < 0.0f) { 2033 fog = 0.0f; 2034 } else if (fog > 1.0f) { 2035 fog = 1.0f; 2036 } 2037 cv[i].f = fog; 2038 2039 if (is_seabed) { 2040 cv[i].r = 0.25f * ar; 2041 cv[i].g = 0.28f * ag; 2042 cv[i].b = 0.30f * ab; 2043 } else { 2044 cv[i].r = (m->ply_verts[i].r / 255.0f) * ar; 2045 cv[i].g = (m->ply_verts[i].g / 255.0f) * ag; 2046 cv[i].b = (m->ply_verts[i].b / 255.0f) * ab; 2047 } 2048 cv[i].a = 1.0f; 2049 2050 d = sqrtf(out.x*out.x + out.y*out.y + out.z*out.z); 2051 if (d < min_dist) { 2052 min_dist = d; 2053 } 2054 } 2055 mip = 0; 2056 scale = sqrtf(m->total_area) * 0.05f; 2057 if (scale < 0.2f) { 2058 scale = 0.2f; 2059 } 2060 if (scale > 5.0f) { 2061 scale = 5.0f; 2062 } 2063 if (min_dist > 150.0f * scale) { 2064 mip = 3; 2065 } else if (min_dist > 80.0f * scale) { 2066 mip = 2; 2067 } else if (min_dist > 30.0f * scale) { 2068 mip = 1; 2069 } 2070 2071 for (i = 0; i < m->num_tris; i++) { 2072 uint16_t i0 = m->indices[i*3], i1 = m->indices[i*3+1], i2 = m->indices[i*3+2]; 2073 struct texture *tex; 2074 2075 if (cv[i0].w < 0.1f && cv[i1].w < 0.1f && cv[i2].w < 0.1f) { 2076 continue; 2077 } 2078 if (cv[i0].w > far_clp && cv[i1].w > far_clp && cv[i2].w > far_clp) { 2079 continue; 2080 } 2081 tex = (m->num_materials > 0 && m->textures) ? m->textures[m->mat_ids[i] < m->num_materials ? m->mat_ids[i] : 0] : NULL; 2082 clip_and_push_triangle(&cv[i0], &cv[i1], &cv[i2], tex, 0, mip); 2083 } 2084 } 2085 2086 static int 2087 is_occluded(struct sys_gfx *g, float cx, float cy, float cz, float r) 2088 { 2089 (void)g; (void)cx; (void)cy; (void)cz; (void)r; 2090 return (0); 2091 } 2092 2093 static int 2094 cmp_draw_item(const void *a, const void *b) 2095 { 2096 float da = ((const struct draw_item *)a)->dist_sq; 2097 float db = ((const struct draw_item *)b)->dist_sq; 2098 2099 if (da < db) 2100 return (-1); 2101 if (da > db) 2102 return (1); 2103 return (0); 2104 } 2105 2106 static const char * 2107 ped_lookup_model(int id) 2108 { 2109 if (id < 0 || id >= 313) { 2110 return (NULL); 2111 } 2112 return (skin_names[id][0] != '\0' ? skin_names[id] : NULL); 2113 } 2114 2115 static void 2116 draw_scene(struct sys_gfx *g, const struct mat4 *proj, const struct mat4 *view, 2117 float cam_x, float cam_y, float cam_z, 2118 float player_x, float player_y, float player_z, float player_yaw) 2119 { 2120 float val, pitch, fov_y, fov_x, far_clp, dx, dy, dz, dist_sq, w, r; 2121 float obj_max_dist; 2122 int y_horiz, min_gx, max_gx, min_gz, max_gz, id, x, y, gx, gz, i; 2123 uint8_t sr, sg, sb, hr, hg, hb; 2124 uint32_t c; 2125 struct mesh *m; 2126 struct vec3 mc, cv; 2127 struct mat4 mvp; 2128 2129 val = view->m[1][2]; 2130 if (val > 1.0f) { 2131 val = 1.0f; 2132 } else if (val < -1.0f) { 2133 val = -1.0f; 2134 } 2135 pitch = asin(val); 2136 y_horiz = HEIGHT / 2 + (int)(pitch * 400.0f); 2137 sr = g->cur_weather.sky_top[0]; 2138 sg = g->cur_weather.sky_top[1]; 2139 sb = g->cur_weather.sky_top[2]; 2140 hr = g->cur_weather.sky_bot[0]; 2141 hg = g->cur_weather.sky_bot[1]; 2142 hb = g->cur_weather.sky_bot[2]; 2143 2144 for (y = 0; y < HEIGHT; y++) { 2145 c = (hr << 16) | (hg << 8) | hb; 2146 if (y < y_horiz) { 2147 float f = (float)y / (float)(y_horiz > 0 ? y_horiz : 1); 2148 c = ((sr + (uint8_t)(f * (hr - sr))) << 16) | 2149 ((sg + (uint8_t)(f * (hg - sg))) << 8) | 2150 (sb + (uint8_t)(f * (hb - sb))); 2151 } 2152 for (x = 0; x < WIDTH; x++) { 2153 g->pixels[y * WIDTH + x] = c; 2154 } 2155 } 2156 2157 far_clp = g->cur_weather.far_clp; 2158 fov_y = tanf(60.0f * 0.5f * 3.14159f / 180.0f); 2159 fov_x = fov_y * ((float)WIDTH / HEIGHT); 2160 2161 min_gx = (int)((cam_x - far_clp - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2162 max_gx = (int)((cam_x + far_clp - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2163 min_gz = (int)((cam_z - far_clp - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2164 max_gz = (int)((cam_z + far_clp - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2165 2166 if (min_gx < 0) min_gx = 0; 2167 if (max_gx >= GRID_SZ) max_gx = GRID_SZ - 1; 2168 if (min_gz < 0) min_gz = 0; 2169 if (max_gz >= GRID_SZ) max_gz = GRID_SZ - 1; 2170 2171 draw_count = 0; 2172 for (gz = min_gz; gz <= max_gz; gz++) { 2173 for (gx = min_gx; gx <= max_gx; gx++) { 2174 for (i = 0; i < scene_grid[gx][gz].count; i++) { 2175 id = scene_grid[gx][gz].ids[i]; 2176 2177 int16_t t_on = g_transforms.time_on[id]; 2178 int16_t t_off = g_transforms.time_off[id]; 2179 if (t_on != t_off) { 2180 float cur_h = g->game_time_hours; 2181 int visible = 0; 2182 if (t_on > t_off) { 2183 if (cur_h >= t_on || cur_h < t_off) { 2184 visible = 1; 2185 } 2186 } else { 2187 if (cur_h >= t_on && cur_h < t_off) { 2188 visible = 1; 2189 } 2190 } 2191 if (!visible) { 2192 continue; 2193 } 2194 } 2195 2196 dx = g_transforms.sphere_cx[id] - cam_x; 2197 dy = g_transforms.sphere_cy[id] - cam_y; 2198 dz = g_transforms.sphere_cz[id] - cam_z; 2199 dist_sq = dx * dx + dy * dy + dz * dz; 2200 2201 obj_max_dist = g_transforms.sphere_r[id] * 35.0f; 2202 if (obj_max_dist < 40.0f) { 2203 obj_max_dist = 40.0f; 2204 } 2205 if (obj_max_dist > far_clp) { 2206 obj_max_dist = far_clp; 2207 } 2208 2209 if (dist_sq > (obj_max_dist + g_transforms.sphere_r[id]) * 2210 (obj_max_dist + g_transforms.sphere_r[id])) { 2211 continue; 2212 } 2213 2214 if (draw_count >= draw_cap) { 2215 draw_cap = draw_cap == 0 ? 1024 : draw_cap * 2; 2216 draw_list = realloc(draw_list, draw_cap * sizeof(struct draw_item)); 2217 } 2218 draw_list[draw_count].id = id; 2219 draw_list[draw_count].dist_sq = dist_sq; 2220 draw_count++; 2221 } 2222 } 2223 } 2224 qsort(draw_list, draw_count, sizeof(struct draw_item), cmp_draw_item); 2225 2226 for (i = 0; i < draw_count; i++) { 2227 id = draw_list[i].id; 2228 m = scene_meshes[id]; 2229 if (!m || !m->ply_verts) { 2230 continue; 2231 } 2232 mc.x = g_transforms.sphere_cx[id]; 2233 mc.y = g_transforms.sphere_cy[id]; 2234 mc.z = g_transforms.sphere_cz[id]; 2235 r = g_transforms.sphere_r[id] * 1.05f; 2236 2237 dx = mc.x - cam_x; 2238 dy = mc.y - cam_y; 2239 dz = mc.z - cam_z; 2240 dist_sq = dx * dx + dy * dy + dz * dz; 2241 2242 if (dist_sq > r * r) { 2243 mat_transform(&cv, &w, view, &mc); 2244 2245 if (cv.z + r < 0.1f || cv.z - r > far_clp) { 2246 continue; 2247 } 2248 if (cv.z > 0.0f) { 2249 if (fabsf(cv.x) - r > cv.z * fov_x || 2250 fabsf(cv.y) - r > cv.z * fov_y) { 2251 continue; 2252 } 2253 } 2254 } else { 2255 mat_transform(&cv, &w, view, &mc); 2256 } 2257 2258 if (is_occluded(g, cv.x, cv.y, cv.z, r)) { 2259 continue; 2260 } 2261 mat_mul(&mvp, view, &g_transforms.world_matrices[id]); 2262 mat_mul(&mvp, proj, &mvp); 2263 draw_mesh(m, &mvp, 0); 2264 } 2265 2266 if (active_skin_id >= 0) { 2267 const char *skin_model_name; 2268 2269 skin_model_name = ped_lookup_model(active_skin_id); 2270 if (skin_model_name) { 2271 struct mesh *skin_mesh; 2272 2273 skin_mesh = cache_get_mesh(g_cache, skin_model_name); 2274 if (skin_mesh && skin_mesh->ply_verts) { 2275 struct mat4 rot_y, trans, world; 2276 2277 mat_identity(&rot_y); 2278 rot_y.m[0][0] = cosf(player_yaw); 2279 rot_y.m[0][2] = sinf(player_yaw); 2280 rot_y.m[2][0] = -sinf(player_yaw); 2281 rot_y.m[2][2] = cosf(player_yaw); 2282 2283 mat_translate(&trans, player_x, player_y + 1.0f, player_z); 2284 mat_mul(&world, &trans, &rot_y); 2285 2286 mat_mul(&mvp, view, &world); 2287 mat_mul(&mvp, proj, &mvp); 2288 draw_mesh(skin_mesh, &mvp, 0); 2289 } 2290 } 2291 } 2292 2293 for (i = 0; i < MAX_PLAYERS; i++) { 2294 const char *rem_skin_name; 2295 2296 if (!net_players[i].active || i == my_player_id) { 2297 continue; 2298 } 2299 2300 rem_skin_name = ped_lookup_model(net_players[i].skin); 2301 if (rem_skin_name) { 2302 struct mesh *rem_mesh; 2303 2304 rem_mesh = cache_get_mesh(g_cache, rem_skin_name); 2305 if (rem_mesh && rem_mesh->ply_verts) { 2306 struct mat4 rot_y, trans, world; 2307 2308 mat_identity(&rot_y); 2309 rot_y.m[0][0] = cosf(net_players[i].cur_yaw); 2310 rot_y.m[0][2] = sinf(net_players[i].cur_yaw); 2311 rot_y.m[2][0] = -sinf(net_players[i].cur_yaw); 2312 rot_y.m[2][2] = cosf(net_players[i].cur_yaw); 2313 2314 mat_translate(&trans, net_players[i].cur_x, 2315 net_players[i].cur_y + 1.0f, net_players[i].cur_z); 2316 mat_mul(&world, &trans, &rot_y); 2317 2318 mat_mul(&mvp, view, &world); 2319 mat_mul(&mvp, proj, &mvp); 2320 draw_mesh(rem_mesh, &mvp, 0); 2321 } 2322 } 2323 } 2324 2325 flush_render_list(); 2326 } 2327 2328 static void 2329 update_weather(struct sys_gfx *g) 2330 { 2331 float t, snaps[8] = {0.0f, 5.0f, 6.0f, 7.0f, 12.0f, 19.0f, 20.0f, 22.0f}; 2332 int i0, i1, i; 2333 float f; 2334 struct timecyc_entry *w0, *w1; 2335 2336 if (g->num_weathers == 0) { 2337 return; 2338 } 2339 if (g->game_weather >= g->num_weathers) { 2340 g->game_weather = 0; 2341 } 2342 t = g->game_time_hours; 2343 i0 = 7; 2344 i1 = 0; 2345 f = 0.0f; 2346 if (t >= snaps[7] || t < snaps[0]) { 2347 float wt = t; 2348 if (wt < snaps[0]) { 2349 wt += 24.0f; 2350 } 2351 f = (wt - snaps[7]) / (24.0f - snaps[7] + snaps[0]); 2352 } else { 2353 for (i = 0; i < 7; i++) { 2354 if (t >= snaps[i] && t < snaps[i + 1]) { 2355 i0 = i; 2356 i1 = i + 1; 2357 f = (t - snaps[i]) / (snaps[i + 1] - snaps[i]); 2358 break; 2359 } 2360 } 2361 } 2362 w0 = &g->weathers[g->game_weather][i0]; 2363 w1 = &g->weathers[g->game_weather][i1]; 2364 #define LERP(c) g->cur_weather.c = w0->c + f * (w1->c - w0->c) 2365 LERP(amb[0]); LERP(amb[1]); LERP(amb[2]); 2366 LERP(sky_top[0]); LERP(sky_top[1]); LERP(sky_top[2]); 2367 LERP(sky_bot[0]); LERP(sky_bot[1]); LERP(sky_bot[2]); 2368 LERP(water[0]); LERP(water[1]); LERP(water[2]); LERP(water[3]); 2369 LERP(far_clp); LERP(fog_st); 2370 #undef LERP 2371 2372 if (g->far_clip_override > 10.0f) { 2373 g->cur_weather.far_clp = g->far_clip_override; 2374 } else if (g->cur_weather.far_clp > 220.0f) { 2375 g->cur_weather.far_clp = 220.0f; 2376 } 2377 } 2378 2379 static void 2380 draw_water(const struct mat4 *proj, const struct mat4 *view) 2381 { 2382 struct clip_vertex cv[4]; 2383 struct mat4 mvp; 2384 struct vec3 in, out; 2385 float t, far_clp, fog_st, ar, ag, ab, w, fog, u_tex, v_tex; 2386 float wave_height, wave_factor, dy, flow_u, flow_v; 2387 uint32_t i; 2388 int j; 2389 2390 mat_mul(&mvp, proj, view); 2391 t = g_sys->game_time_sec; 2392 far_clp = g_sys->cur_weather.far_clp; 2393 fog_st = g_sys->cur_weather.fog_st; 2394 if (far_clp <= fog_st) { 2395 far_clp = fog_st + 1.0f; 2396 } 2397 ar = g_sys->cur_weather.amb[0] / 255.0f * 1.2f; 2398 ag = g_sys->cur_weather.amb[1] / 255.0f * 1.2f; 2399 ab = g_sys->cur_weather.amb[2] / 255.0f * 1.2f; 2400 2401 for (i = 0; i < water_count; i++) { 2402 for (j = 0; j < water_faces[i].num; j++) { 2403 in.x = water_faces[i].x[j]; 2404 2405 wave_height = water_faces[i].h[j]; 2406 wave_factor = sinf(t * 1.5f + water_faces[i].x[j] * 0.05f + water_faces[i].y[j] * 0.05f); 2407 dy = wave_factor * wave_height; 2408 2409 in.y = water_faces[i].z[j] + dy; 2410 in.z = water_faces[i].y[j]; 2411 2412 mat_transform(&out, &w, &mvp, &in); 2413 fog = (out.z - fog_st) / (far_clp - fog_st); 2414 if (fog < 0.0f) { 2415 fog = 0.0f; 2416 } else if (fog > 1.0f) { 2417 fog = 1.0f; 2418 } 2419 2420 flow_u = water_faces[i].u[j]; 2421 flow_v = water_faces[i].v[j]; 2422 2423 u_tex = (water_faces[i].x[j] - water_faces[i].x[0]) * 0.01f + t * (flow_u - 0.015f) + dy * 0.05f; 2424 v_tex = (water_faces[i].y[j] - water_faces[i].y[0]) * 0.01f + t * (flow_v - 0.015f) + dy * 0.05f; 2425 2426 cv[j].x = out.x; 2427 cv[j].y = out.y; 2428 cv[j].z = out.z; 2429 cv[j].w = w; 2430 cv[j].u = u_tex; 2431 cv[j].v = v_tex; 2432 cv[j].r = ar; 2433 cv[j].g = ag; 2434 cv[j].b = ab; 2435 cv[j].a = 1.0f; 2436 cv[j].f = fog; 2437 } 2438 if (water_faces[i].num == 4) { 2439 if (!(cv[0].w < 0.1f && cv[2].w < 0.1f && cv[1].w < 0.1f) && !(cv[0].w > far_clp && cv[2].w > far_clp && cv[1].w > far_clp)) { 2440 clip_and_push_triangle(&cv[0], &cv[2], &cv[1], water_tex, 1, 0); 2441 } 2442 if (!(cv[2].w < 0.1f && cv[3].w < 0.1f && cv[1].w < 0.1f) && !(cv[2].w > far_clp && cv[3].w > far_clp && cv[1].w > far_clp)) { 2443 clip_and_push_triangle(&cv[2], &cv[3], &cv[1], water_tex, 1, 0); 2444 } 2445 } else if (water_faces[i].num == 3) { 2446 if (!(cv[0].w < 0.1f && cv[2].w < 0.1f && cv[1].w < 0.1f) && !(cv[0].w > far_clp && cv[2].w > far_clp && cv[1].w > far_clp)) { 2447 clip_and_push_triangle(&cv[0], &cv[2], &cv[1], water_tex, 1, 0); 2448 } 2449 } 2450 } 2451 flush_render_list(); 2452 } 2453 2454 static void 2455 draw_ocean_sector(const struct mat4 *mvp, float x0, float x1, float z0, float z1, float height, float t, const struct texture *tex, int is_water) 2456 { 2457 struct clip_vertex cv[4]; 2458 struct vec3 in, out; 2459 float far_clp, fog_st, ar, ag, ab, w, fog, u_tex, v_tex; 2460 float prelight_r, prelight_g, prelight_b; 2461 float step = 500.0f; 2462 float tx, tz, next_tx, next_tz; 2463 float xs[4], zs[4]; 2464 int i; 2465 2466 far_clp = g_sys->cur_weather.far_clp; 2467 fog_st = g_sys->cur_weather.fog_st; 2468 if (far_clp <= fog_st) { 2469 far_clp = fog_st + 1.0f; 2470 } 2471 ar = g_sys->cur_weather.amb[0] / 255.0f * 1.2f; 2472 ag = g_sys->cur_weather.amb[1] / 255.0f * 1.2f; 2473 ab = g_sys->cur_weather.amb[2] / 255.0f * 1.2f; 2474 2475 prelight_r = is_water ? 1.0f : 0.35f; 2476 prelight_g = is_water ? 1.0f : 0.38f; 2477 prelight_b = is_water ? 1.0f : 0.40f; 2478 2479 for (tx = floorf(x0 / step) * step; tx < x1; tx += step) { 2480 next_tx = tx + step; 2481 if (next_tx > x1) { 2482 next_tx = x1; 2483 } 2484 for (tz = floorf(z0 / step) * step; tz < z1; tz += step) { 2485 next_tz = tz + step; 2486 if (next_tz > z1) { 2487 next_tz = z1; 2488 } 2489 2490 xs[0] = tx; xs[1] = next_tx; xs[2] = next_tx; xs[3] = tx; 2491 zs[0] = tz; zs[1] = tz; zs[2] = next_tz; zs[3] = next_tz; 2492 2493 for (i = 0; i < 4; i++) { 2494 in.x = xs[i]; 2495 in.y = height; 2496 in.z = zs[i]; 2497 mat_transform(&out, &w, mvp, &in); 2498 fog = (out.z - fog_st) / (far_clp - fog_st); 2499 if (fog < 0.0f) { 2500 fog = 0.0f; 2501 } else if (fog > 1.0f) { 2502 fog = 1.0f; 2503 } 2504 u_tex = xs[i] * 0.01f; 2505 v_tex = zs[i] * 0.01f; 2506 if (is_water) { 2507 u_tex -= t * 0.02f; 2508 v_tex -= t * 0.02f; 2509 } 2510 cv[i] = (struct clip_vertex){ 2511 out.x, out.y, out.z, w, u_tex, v_tex, 2512 ar * prelight_r, ag * prelight_g, ab * prelight_b, 2513 1.0f, fog 2514 }; 2515 } 2516 if (!(cv[0].w < 0.1f && cv[2].w < 0.1f && cv[1].w < 0.1f) && !(cv[0].w > far_clp && cv[2].w > far_clp && cv[1].w > far_clp)) { 2517 clip_and_push_triangle(&cv[0], &cv[2], &cv[1], tex, is_water, 0); 2518 } 2519 if (!(cv[0].w < 0.1f && cv[3].w < 0.1f && cv[2].w < 0.1f) && !(cv[0].w > far_clp && cv[3].w > far_clp && cv[2].w > far_clp)) { 2520 clip_and_push_triangle(&cv[0], &cv[3], &cv[2], tex, is_water, 0); 2521 } 2522 } 2523 } 2524 } 2525 2526 static void 2527 draw_infinite_ocean(const struct mat4 *proj, const struct mat4 *view, float cam_x, float cam_z, float t) 2528 { 2529 struct mat4 mvp; 2530 float far_clp, b; 2531 float n_x0, n_x1, n_z0, n_z1; 2532 float s_x0, s_x1, s_z0, s_z1; 2533 float w_x0, w_x1, w_z0, w_z1; 2534 float e_x0, e_x1, e_z0, e_z1; 2535 2536 mat_mul(&mvp, proj, view); 2537 far_clp = g_sys->cur_weather.far_clp; 2538 b = 2970.0f; 2539 2540 n_x0 = cam_x - far_clp * 1.5f; 2541 n_x1 = cam_x + far_clp * 1.5f; 2542 n_z0 = fmaxf(b, cam_z - far_clp * 1.5f); 2543 n_z1 = cam_z + far_clp * 1.5f; 2544 if (n_z1 > n_z0) { 2545 draw_ocean_sector(&mvp, n_x0, n_x1, n_z0, n_z1, -65.0f, t, sand_tex, 0); 2546 draw_ocean_sector(&mvp, n_x0, n_x1, n_z0, n_z1, 0.0f, t, water_tex, 1); 2547 } 2548 2549 s_x0 = cam_x - far_clp * 1.5f; 2550 s_x1 = cam_x + far_clp * 1.5f; 2551 s_z0 = cam_z - far_clp * 1.5f; 2552 s_z1 = fminf(-b, cam_z + far_clp * 1.5f); 2553 if (s_z1 > s_z0) { 2554 draw_ocean_sector(&mvp, s_x0, s_x1, s_z0, s_z1, -65.0f, t, sand_tex, 0); 2555 draw_ocean_sector(&mvp, s_x0, s_x1, s_z0, s_z1, 0.0f, t, water_tex, 1); 2556 } 2557 2558 w_x0 = cam_x - far_clp * 1.5f; 2559 w_x1 = fminf(-b, cam_x + far_clp * 1.5f); 2560 w_z0 = fmaxf(-b, cam_z - far_clp * 1.5f); 2561 w_z1 = fminf(b, cam_z + far_clp * 1.5f); 2562 if (w_x1 > w_x0 && w_z1 > w_z0) { 2563 draw_ocean_sector(&mvp, w_x0, w_x1, w_z0, w_z1, -65.0f, t, sand_tex, 0); 2564 draw_ocean_sector(&mvp, w_x0, w_x1, w_z0, w_z1, 0.0f, t, water_tex, 1); 2565 } 2566 2567 e_x0 = fmaxf(b, cam_x - far_clp * 1.5f); 2568 e_x1 = cam_x + far_clp * 1.5f; 2569 e_z0 = fmaxf(-b, cam_z - far_clp * 1.5f); 2570 e_z1 = fminf(b, cam_z + far_clp * 1.5f); 2571 if (e_x1 > e_x0 && e_z1 > e_z0) { 2572 draw_ocean_sector(&mvp, e_x0, e_x1, e_z0, e_z1, -65.0f, t, sand_tex, 0); 2573 draw_ocean_sector(&mvp, e_x0, e_x1, e_z0, e_z1, 0.0f, t, water_tex, 1); 2574 } 2575 flush_render_list(); 2576 } 2577 2578 static void 2579 scene_load(struct asset_cache *cache, const uint8_t *data, size_t sz) 2580 { 2581 char *buf, *line, *next_line, *p; 2582 int in_inst, id, interior, idx, gx, gz; 2583 char name[NAME_SZ]; 2584 float px, py, pz, qx, qy, qz, qw, w; 2585 struct mesh *m; 2586 struct mat4 rot, trans, sa2gl; 2587 struct vec3 wc; 2588 struct grid_cell *c; 2589 int lod, time_on, time_off; 2590 2591 buf = malloc(sz + 1); 2592 if (buf == NULL) { 2593 return; 2594 } 2595 memcpy(buf, data, sz); 2596 buf[sz] = '\0'; 2597 2598 line = buf; 2599 in_inst = 0; 2600 while (line && *line) { 2601 next_line = strchr(line, '\n'); 2602 if (next_line) { 2603 *next_line = '\0'; 2604 next_line++; 2605 } 2606 p = line; 2607 while (*p == ' ' || *p == '\t') { 2608 p++; 2609 } 2610 if (*p == '\0' || *p == '#') { 2611 line = next_line; 2612 continue; 2613 } 2614 if (strncasecmp(p, "inst", 4) == 0 || strncasecmp(p, "tobj", 4) == 0) { 2615 in_inst = 1; 2616 line = next_line; 2617 continue; 2618 } 2619 if (strncasecmp(p, "end", 3) == 0) { 2620 in_inst = 0; 2621 line = next_line; 2622 continue; 2623 } 2624 if (in_inst) { 2625 lod = -1; 2626 time_on = 0; 2627 time_off = 0; 2628 2629 if (sscanf(p, "%d, %23[^,], %d, %f, %f, %f, %f, %f, %f, %f, %d, %d, %d", 2630 &id, name, &interior, &px, &py, &pz, &qx, &qy, &qz, &qw, &lod, &time_on, &time_off) >= 10) { 2631 char *end_ptr = name + strlen(name) - 1; 2632 while (end_ptr > name && (*end_ptr == ' ' || *end_ptr == '\t')) { 2633 *end_ptr = '\0'; 2634 end_ptr--; 2635 } 2636 for (p = name; *p; p++) { 2637 *p = tolower((unsigned char)*p); 2638 } 2639 2640 if (scene_inst_count >= scene_inst_capacity) { 2641 scene_inst_capacity = scene_inst_capacity == 0 ? 512 : scene_inst_capacity * 2; 2642 scene_meshes = realloc(scene_meshes, scene_inst_capacity * sizeof(struct mesh *)); 2643 g_transforms.pos_x = realloc(g_transforms.pos_x, scene_inst_capacity * sizeof(float)); 2644 g_transforms.pos_y = realloc(g_transforms.pos_y, scene_inst_capacity * sizeof(float)); 2645 g_transforms.pos_z = realloc(g_transforms.pos_z, scene_inst_capacity * sizeof(float)); 2646 g_transforms.rot_qx = realloc(g_transforms.rot_qx, scene_inst_capacity * sizeof(float)); 2647 g_transforms.rot_qy = realloc(g_transforms.rot_qy, scene_inst_capacity * sizeof(float)); 2648 g_transforms.rot_qz = realloc(g_transforms.rot_qz, scene_inst_capacity * sizeof(float)); 2649 g_transforms.rot_qw = realloc(g_transforms.rot_qw, scene_inst_capacity * sizeof(float)); 2650 g_transforms.world_matrices = realloc(g_transforms.world_matrices, scene_inst_capacity * sizeof(struct mat4)); 2651 g_transforms.sphere_cx = realloc(g_transforms.sphere_cx, scene_inst_capacity * sizeof(float)); 2652 g_transforms.sphere_cy = realloc(g_transforms.sphere_cy, scene_inst_capacity * sizeof(float)); 2653 g_transforms.sphere_cz = realloc(g_transforms.sphere_cz, scene_inst_capacity * sizeof(float)); 2654 g_transforms.sphere_r = realloc(g_transforms.sphere_r, scene_inst_capacity * sizeof(float)); 2655 g_transforms.time_on = realloc(g_transforms.time_on, scene_inst_capacity * sizeof(int16_t)); 2656 g_transforms.time_off = realloc(g_transforms.time_off, scene_inst_capacity * sizeof(int16_t)); 2657 } 2658 2659 m = cache_get_mesh(cache, name); 2660 if (m) { 2661 idx = scene_inst_count++; 2662 scene_meshes[idx] = m; 2663 g_transforms.pos_x[idx] = px; 2664 g_transforms.pos_y[idx] = py; 2665 g_transforms.pos_z[idx] = pz; 2666 g_transforms.rot_qx[idx] = qx; 2667 g_transforms.rot_qy[idx] = qy; 2668 g_transforms.rot_qz[idx] = qz; 2669 g_transforms.rot_qw[idx] = qw; 2670 2671 g_transforms.time_on[idx] = (time_on >= 0) ? time_on : 0; 2672 g_transforms.time_off[idx] = (time_off >= 0) ? time_off : 0; 2673 2674 mat_from_quat(&rot, qx, qy, qz, qw); 2675 mat_translate(&trans, px, py, pz); 2676 mat_mul(&g_transforms.world_matrices[idx], &trans, &rot); 2677 2678 memset(&sa2gl, 0, sizeof(sa2gl)); 2679 sa2gl.m[0][0] = sa2gl.m[1][2] = sa2gl.m[2][1] = sa2gl.m[3][3] = 1.0f; 2680 mat_mul(&g_transforms.world_matrices[idx], &sa2gl, &g_transforms.world_matrices[idx]); 2681 2682 mat_transform(&wc, &w, &g_transforms.world_matrices[idx], &(struct vec3){m->spr_x, m->spr_y, m->spr_z}); 2683 g_transforms.sphere_cx[idx] = wc.x; 2684 g_transforms.sphere_cy[idx] = wc.y; 2685 g_transforms.sphere_cz[idx] = wc.z; 2686 g_transforms.sphere_r[idx] = m->spr_r; 2687 2688 gx = (int)((wc.x - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2689 gz = (int)((wc.z - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2690 if (gx < 0) gx = 0; if (gx >= GRID_SZ) gx = GRID_SZ - 1; 2691 if (gz < 0) gz = 0; if (gz >= GRID_SZ) gz = GRID_SZ - 1; 2692 2693 c = &scene_grid[gx][gz]; 2694 if (c->count >= c->cap) { 2695 c->cap = c->cap == 0 ? 16 : c->cap * 2; 2696 c->ids = realloc(c->ids, c->cap * sizeof(int)); 2697 } 2698 c->ids[c->count++] = idx; 2699 } 2700 } 2701 } 2702 line = next_line; 2703 } 2704 free(buf); 2705 } 2706 2707 int 2708 main(int argc, char *argv[]) 2709 { 2710 struct sys_gfx g; 2711 struct mat4 view; 2712 struct timespec ts, t_start, t_end; 2713 XEvent sa_event; 2714 KeySym sym; 2715 float player_x = 2490.0f, player_y = 13.5f, player_z = -1660.0f; 2716 float player_vy = 0.0f; 2717 float player_yaw = 0.0f; 2718 float cam_x, cam_y, cam_z; 2719 float cam_yaw = -1.57f, cam_pitch = 0.2f, cam_dist = 3.5f; 2720 float move_forward, move_strafe, move_x, move_z, move_len; 2721 float speed, ground_y, dt, net_timer = 0.0f; 2722 int running, tar_fd, m_dx, m_dy, gz, gx, last_mx, last_my, i; 2723 int is_grounded = 0; 2724 struct stat st; 2725 size_t ipl_sz = 0, water_sz = 0, tc_sz = 0, col_sz = 0; 2726 const uint8_t *ipl_data, *water_data, *tc_data, *col_data; 2727 char srv_ip[64] = "127.0.0.1"; 2728 int srv_port = NET_PORT; 2729 char nick[24] = "player"; 2730 char *colon; 2731 KeyCode code; 2732 2733 if (argc < 3) { 2734 fprintf(stderr, "usage: %s <ip:port> <nick>\n", argv[0]); 2735 return (1); 2736 } 2737 2738 strncpy(srv_ip, argv[1], sizeof(srv_ip) - 1); 2739 srv_ip[sizeof(srv_ip) - 1] = '\0'; 2740 colon = strchr(srv_ip, ':'); 2741 if (colon) { 2742 *colon = '\0'; 2743 srv_port = atoi(colon + 1); 2744 } 2745 2746 strncpy(nick, argv[2], sizeof(nick) - 1); 2747 nick[sizeof(nick) - 1] = '\0'; 2748 2749 g_sys = &g; 2750 gfx_init(&g); 2751 g_cache = calloc(1, sizeof(struct asset_cache)); 2752 g.game_time_sec = 0.0f; 2753 g.game_time_hours = 12.0f; 2754 ts.tv_sec = 0; 2755 ts.tv_nsec = 16666666; 2756 2757 tar_fd = open("assets.tar", O_RDONLY); 2758 if (tar_fd < 0) { 2759 err(1, "failed to open assets.tar"); 2760 } 2761 fstat(tar_fd, &st); 2762 g_tar_size = st.st_size; 2763 g_tar_mapped = mmap(NULL, g_tar_size, PROT_READ, MAP_PRIVATE, tar_fd, 0); 2764 if (g_tar_mapped == MAP_FAILED) { 2765 err(1, "failed to mmap assets.tar"); 2766 } 2767 2768 tar_build_index(); 2769 2770 ipl_data = tar_lookup("assets/map.ipl", &ipl_sz); 2771 if (ipl_data) { 2772 scene_load(g_cache, ipl_data, ipl_sz); 2773 } 2774 2775 water_data = tar_lookup("assets/water.bin", &water_sz); 2776 if (water_data && water_sz > 0) { 2777 memcpy(&water_count, water_data, 4); 2778 water_faces = malloc(water_count * sizeof(struct water_face)); 2779 memcpy(water_faces, water_data + 4, water_count * sizeof(struct water_face)); 2780 } 2781 2782 tc_data = tar_lookup("assets/timecyc.bin", &tc_sz); 2783 if (tc_data && tc_sz > 0) { 2784 memcpy(&g.num_weathers, tc_data, 4); 2785 if (g.num_weathers > 32) { 2786 g.num_weathers = 32; 2787 } 2788 memcpy(g.weathers, tc_data + 4, g.num_weathers * 8 * sizeof(struct timecyc_entry)); 2789 } 2790 2791 col_data = tar_lookup("assets/collision.bin", &col_sz); 2792 if (col_data && col_sz > 0) { 2793 const uint8_t *ptr = col_data; 2794 for (gz = 0; gz < GRID_SZ; gz++) { 2795 for (gx = 0; gx < GRID_SZ; gx++) { 2796 uint32_t cnt; 2797 memcpy(&cnt, ptr, sizeof(uint32_t)); 2798 ptr += sizeof(uint32_t); 2799 g_col_grid[gx][gz].count = cnt; 2800 if (cnt > 0) { 2801 g_col_grid[gx][gz].tris = (const struct col_triangle *)ptr; 2802 ptr += cnt * sizeof(struct col_triangle); 2803 } else { 2804 g_col_grid[gx][gz].tris = NULL; 2805 } 2806 } 2807 } 2808 } 2809 2810 water_tex = cache_get_tex(g_cache, "waterclear256"); 2811 sand_tex = cache_get_tex(g_cache, "sand256"); 2812 2813 net_init(srv_ip, srv_port, nick); 2814 2815 XMapWindow(g.dpy, g.win); 2816 clock_gettime(CLOCK_MONOTONIC, &t_start); 2817 XWarpPointer(g.dpy, None, g.win, 0, 0, 0, 0, WIDTH / 2, HEIGHT / 2); 2818 XGrabPointer(g.dpy, g.win, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 2819 GrabModeAsync, GrabModeAsync, g.win, None, CurrentTime); 2820 XSync(g.dpy, False); 2821 2822 running = 1; 2823 while (running) { 2824 last_mx = WIDTH / 2; 2825 last_my = HEIGHT / 2; 2826 m_dx = 0; 2827 m_dy = 0; 2828 2829 while (XPending(g.dpy)) { 2830 XNextEvent(g.dpy, &sa_event); 2831 if (XFilterEvent(&sa_event, None)) { 2832 continue; 2833 } 2834 if (sa_event.type == ClientMessage && 2835 (Atom)sa_event.xclient.data.l[0] == g.wm_delete) { 2836 running = 0; 2837 } 2838 if (sa_event.type == FocusIn && !g.in_chat && !g.menu_open) { 2839 XGrabPointer(g.dpy, g.win, True, 2840 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 2841 GrabModeAsync, GrabModeAsync, g.win, None, CurrentTime); 2842 } 2843 if (sa_event.type == FocusOut) { 2844 memset(g.keys, 0, sizeof(g.keys)); 2845 } 2846 if (sa_event.type == MotionNotify && !g.menu_open) { 2847 last_mx = sa_event.xmotion.x; 2848 last_my = sa_event.xmotion.y; 2849 } 2850 if (sa_event.type == KeyPress) { 2851 code = sa_event.xkey.keycode; 2852 sym = XLookupKeysym(&sa_event.xkey, 0); 2853 2854 if (code == g.key_esc || sym == XK_Escape) { 2855 if (g.in_chat) { 2856 g.in_chat = 0; 2857 XGrabPointer(g.dpy, g.win, True, 2858 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 2859 GrabModeAsync, GrabModeAsync, g.win, None, CurrentTime); 2860 } else { 2861 g.menu_open = !g.menu_open; 2862 if (g.menu_open) { 2863 XUngrabPointer(g.dpy, CurrentTime); 2864 memset(g.keys, 0, sizeof(g.keys)); 2865 } else { 2866 XWarpPointer(g.dpy, None, g.win, 0, 0, 0, 0, 2867 WIDTH / 2, HEIGHT / 2); 2868 XGrabPointer(g.dpy, g.win, True, 2869 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 2870 GrabModeAsync, GrabModeAsync, g.win, None, CurrentTime); 2871 } 2872 } 2873 } else if (sym == XK_F5) { 2874 g.show_debug = !g.show_debug; 2875 } 2876 2877 if (g.in_chat) { 2878 char str[32]; 2879 Status status; 2880 int n = 0; 2881 2882 if (g_sys->ic) { 2883 n = Xutf8LookupString(g_sys->ic, &sa_event.xkey, str, 2884 sizeof(str), &sym, &status); 2885 } else { 2886 n = XLookupString(&sa_event.xkey, str, sizeof(str), &sym, NULL); 2887 } 2888 2889 if (sym == XK_Return) { 2890 if (strcmp(g.chat_buf, "/q") == 0 || 2891 strcmp(g.chat_buf, "/quit") == 0) { 2892 running = 0; 2893 } else if (strncmp(g.chat_buf, "/st ", 4) == 0) { 2894 g.game_time_hours = atof(g.chat_buf + 4); 2895 } else if (strncmp(g.chat_buf, "/sw ", 4) == 0) { 2896 g.game_weather = atoi(g.chat_buf + 4); 2897 } else if (strncmp(g.chat_buf, "/sd ", 4) == 0) { 2898 g.far_clip_override = atof(g.chat_buf + 4); 2899 } else if (strncmp(g.chat_buf, "/skin ", 6) == 0) { 2900 int new_id = atoi(g.chat_buf + 6); 2901 if (ped_lookup_model(new_id) != NULL) { 2902 active_skin_id = new_id; 2903 } 2904 } else if (g.chat_buf[0] != '/' && g.chat_len > 0) { 2905 net_send_chat(g.chat_buf); 2906 } 2907 g.in_chat = 0; 2908 XGrabPointer(g.dpy, g.win, True, 2909 PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 2910 GrabModeAsync, GrabModeAsync, g.win, None, CurrentTime); 2911 } else if (sym == XK_BackSpace) { 2912 if (g.chat_len > 0) { 2913 while (g.chat_len > 0) { 2914 g.chat_len--; 2915 if ((g.chat_buf[g.chat_len] & 0xC0) != 0x80) { 2916 break; 2917 } 2918 } 2919 g.chat_buf[g.chat_len] = '\0'; 2920 } 2921 } else if (n > 0 && (unsigned char)str[0] >= 32 && 2922 str[0] != 127 && g.chat_len + n < 127) { 2923 memcpy(&g.chat_buf[g.chat_len], str, n); 2924 g.chat_len += n; 2925 g.chat_buf[g.chat_len] = '\0'; 2926 } 2927 } else if (!g.menu_open) { 2928 if (code == g.key_w || sym == XK_w || sym == XK_W) g.keys['w'] = 1; 2929 else if (code == g.key_a || sym == XK_a || sym == XK_A) g.keys['a'] = 1; 2930 else if (code == g.key_s || sym == XK_s || sym == XK_S) g.keys['s'] = 1; 2931 else if (code == g.key_d || sym == XK_d || sym == XK_D) g.keys['d'] = 1; 2932 else if (code == g.key_space || sym == XK_space) g.keys[' '] = 1; 2933 else if (code == g.key_t || sym == XK_t || sym == XK_T) { 2934 g.in_chat = 1; 2935 g.chat_len = 0; 2936 g.chat_buf[0] = '\0'; 2937 XUngrabPointer(g.dpy, CurrentTime); 2938 } 2939 } 2940 } 2941 if (sa_event.type == KeyRelease && !g.menu_open) { 2942 code = sa_event.xkey.keycode; 2943 sym = XLookupKeysym(&sa_event.xkey, 0); 2944 2945 if (code == g.key_w || sym == XK_w || sym == XK_W) g.keys['w'] = 0; 2946 else if (code == g.key_a || sym == XK_a || sym == XK_A) g.keys['a'] = 0; 2947 else if (code == g.key_s || sym == XK_s || sym == XK_S) g.keys['s'] = 0; 2948 else if (code == g.key_d || sym == XK_d || sym == XK_D) g.keys['d'] = 0; 2949 else if (code == g.key_space || sym == XK_space) g.keys[' '] = 0; 2950 } 2951 } 2952 2953 clock_gettime(CLOCK_MONOTONIC, &t_end); 2954 dt = (t_end.tv_sec - t_start.tv_sec) + (t_end.tv_nsec - t_start.tv_nsec) * 1e-9f; 2955 t_start = t_end; 2956 if (dt > 0.1f) dt = 0.1f; 2957 if (dt < 0.001f) dt = 0.001f; 2958 2959 double cur_time = t_end.tv_sec + t_end.tv_nsec * 1e-9; 2960 2961 g.game_time_sec += dt; 2962 g.game_time_hours += dt * (24.0f / 1440.0f); 2963 if (g.game_time_hours >= 24.0f) { 2964 g.game_time_hours -= 24.0f; 2965 } 2966 2967 for (i = 0; i < chat_log_count; i++) { 2968 if (chat_log[i].timer > 0.0f) { 2969 chat_log[i].timer -= dt; 2970 } 2971 } 2972 2973 net_poll(&g, cur_time); 2974 net_interpolate(cur_time); 2975 2976 net_timer += dt; 2977 if (net_timer >= 0.033f) { 2978 net_send_sync(player_x, player_y, player_z, player_yaw); 2979 net_timer = 0.0f; 2980 } 2981 2982 g.stats_timer += dt; 2983 if (g.stats_timer >= 1.0f) { 2984 g.pkts_in_sec = g.pkts_in; 2985 g.pkts_out_sec = g.pkts_out; 2986 g.pkts_in = 0; 2987 g.pkts_out = 0; 2988 g.stats_timer = 0.0f; 2989 } 2990 g.fps = g.fps * 0.90f + (1.0f / dt) * 0.10f; 2991 2992 move_forward = 0.0f; 2993 move_strafe = 0.0f; 2994 2995 if (!g.in_chat && !g.menu_open) { 2996 m_dx = last_mx - WIDTH / 2; 2997 m_dy = last_my - HEIGHT / 2; 2998 if (m_dx != 0 || m_dy != 0) { 2999 XWarpPointer(g.dpy, None, g.win, 0, 0, 0, 0, WIDTH / 2, HEIGHT / 2); 3000 XFlush(g.dpy); 3001 } 3002 3003 cam_yaw += m_dx * 0.003f; 3004 cam_pitch -= m_dy * 0.003f; 3005 if (cam_pitch > 1.2f) { 3006 cam_pitch = 1.2f; 3007 } 3008 if (cam_pitch < -1.2f) { 3009 cam_pitch = -1.2f; 3010 } 3011 3012 if (g.keys['w']) move_forward += 1.0f; 3013 if (g.keys['s']) move_forward -= 1.0f; 3014 if (g.keys['d']) move_strafe += 1.0f; 3015 if (g.keys['a']) move_strafe -= 1.0f; 3016 } 3017 3018 move_x = sinf(cam_yaw) * move_forward + cosf(cam_yaw) * move_strafe; 3019 move_z = cosf(cam_yaw) * move_forward - sinf(cam_yaw) * move_strafe; 3020 move_len = sqrtf(move_x * move_x + move_z * move_z); 3021 3022 if (move_len > 0.001f) { 3023 move_x /= move_len; 3024 move_z /= move_len; 3025 player_yaw = atan2f(move_x, move_z); 3026 speed = 6.0f; 3027 move_and_slide(&player_x, player_y, &player_z, 3028 move_x * speed, move_z * speed, dt); 3029 } 3030 3031 ground_y = get_ground_height(player_x, player_z, player_y); 3032 3033 if (ground_y > -900.0f && player_y <= ground_y + 0.1f && player_vy <= 0.0f) { 3034 player_y = ground_y; 3035 player_vy = 0.0f; 3036 is_grounded = 1; 3037 } else { 3038 is_grounded = 0; 3039 } 3040 3041 if (g.keys[' '] && is_grounded && !g.in_chat && !g.menu_open) { 3042 player_vy = JUMP_FORCE; 3043 player_y += 0.05f; 3044 is_grounded = 0; 3045 } 3046 3047 if (!is_grounded) { 3048 player_vy -= GRAVITY * dt; 3049 if (player_vy < -TERMINAL_VEL) { 3050 player_vy = -TERMINAL_VEL; 3051 } 3052 3053 if (player_vy > 0.0f) { 3054 float ceil_y = get_ceiling_height(player_x, player_z, player_y); 3055 if (ceil_y < 900.0f && (player_y + 1.85f + player_vy * dt) >= ceil_y) { 3056 player_y = ceil_y - 1.85f; 3057 player_vy = 0.0f; 3058 } else { 3059 player_y += player_vy * dt; 3060 } 3061 } else { 3062 player_y += player_vy * dt; 3063 } 3064 3065 if (player_vy <= 0.0f && ground_y > -900.0f && player_y <= ground_y) { 3066 player_y = ground_y; 3067 player_vy = 0.0f; 3068 is_grounded = 1; 3069 } 3070 } 3071 3072 cam_x = player_x - sinf(cam_yaw) * cosf(cam_pitch) * cam_dist; 3073 cam_y = player_y + 1.2f - sinf(cam_pitch) * cam_dist; 3074 cam_z = player_z - cosf(cam_yaw) * cosf(cam_pitch) * cam_dist; 3075 3076 update_weather(&g); 3077 mat_projection(&g.proj, 60.0f, (float)WIDTH / HEIGHT, 0.1f, g.cur_weather.far_clp); 3078 memset(g.zbuffer, 0, WIDTH * HEIGHT * sizeof(float)); 3079 3080 mat_view(&view, cam_x, cam_y, cam_z, cam_yaw, cam_pitch); 3081 draw_scene(&g, &g.proj, &view, cam_x, cam_y, cam_z, 3082 player_x, player_y, player_z, player_yaw); 3083 draw_water(&g.proj, &view); 3084 draw_infinite_ocean(&g.proj, &view, cam_x, cam_z, g.game_time_sec); 3085 gfx_present(&g, player_x, player_y, player_z); 3086 } 3087 3088 net_send_leave(); 3089 munmap(g_tar_mapped, g_tar_size); 3090 close(tar_fd); 3091 gfx_cleanup(&g); 3092 return (0); 3093 }