Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

598 lines
16 KiB

  1. #define _WIN32_WINNT 0x400
  2. #include <assert.h>
  3. #include <windows.h>
  4. // stb.h
  5. #define STB_DEFINE
  6. #include "stb.h"
  7. // stb_gl.h
  8. #define STB_GL_IMPLEMENTATION
  9. #define STB_GLEXT_DEFINE "glext_list.h"
  10. #include "stb_gl.h"
  11. // SDL
  12. #include "sdl.h"
  13. #include "SDL_opengl.h"
  14. // stb_glprog.h
  15. #define STB_GLPROG_IMPLEMENTATION
  16. #define STB_GLPROG_ARB_DEFINE_EXTENSIONS
  17. #include "stb_glprog.h"
  18. // stb_image.h
  19. #define STB_IMAGE_IMPLEMENTATION
  20. #include "stb_image.h"
  21. // stb_easy_font.h
  22. #include "stb_easy_font.h" // doesn't require an IMPLEMENTATION
  23. #include "caveview.h"
  24. char *game_name = "caveview";
  25. #define REVERSE_DEPTH
  26. static void print_string(float x, float y, char *text, float r, float g, float b)
  27. {
  28. static char buffer[99999];
  29. int num_quads;
  30. num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer));
  31. glColor3f(r,g,b);
  32. glEnableClientState(GL_VERTEX_ARRAY);
  33. glVertexPointer(2, GL_FLOAT, 16, buffer);
  34. glDrawArrays(GL_QUADS, 0, num_quads*4);
  35. glDisableClientState(GL_VERTEX_ARRAY);
  36. }
  37. static float text_color[3];
  38. static float pos_x = 10;
  39. static float pos_y = 10;
  40. static void print(char *text, ...)
  41. {
  42. char buffer[999];
  43. va_list va;
  44. va_start(va, text);
  45. vsprintf(buffer, text, va);
  46. va_end(va);
  47. print_string(pos_x, pos_y, buffer, text_color[0], text_color[1], text_color[2]);
  48. pos_y += 10;
  49. }
  50. float camang[3], camloc[3] = { 60,22,77 };
  51. float player_zoom = 1.0;
  52. float rotate_view = 0.0;
  53. void camera_to_worldspace(float world[3], float cam_x, float cam_y, float cam_z)
  54. {
  55. float vec[3] = { cam_x, cam_y, cam_z };
  56. float t[3];
  57. float s,c;
  58. s = (float) sin(camang[0]*3.141592/180);
  59. c = (float) cos(camang[0]*3.141592/180);
  60. t[0] = vec[0];
  61. t[1] = c*vec[1] - s*vec[2];
  62. t[2] = s*vec[1] + c*vec[2];
  63. s = (float) sin(camang[2]*3.141592/180);
  64. c = (float) cos(camang[2]*3.141592/180);
  65. world[0] = c*t[0] - s*t[1];
  66. world[1] = s*t[0] + c*t[1];
  67. world[2] = t[2];
  68. }
  69. // camera worldspace velocity
  70. float cam_vel[3];
  71. int controls;
  72. #define MAX_VEL 150.0f // blocks per second
  73. #define ACCEL 6.0f
  74. #define DECEL 3.0f
  75. #define STATIC_FRICTION DECEL
  76. #define EFFECTIVE_ACCEL (ACCEL+DECEL)
  77. // dynamic friction:
  78. //
  79. // if going at MAX_VEL, ACCEL and friction must cancel
  80. // EFFECTIVE_ACCEL = DECEL + DYNAMIC_FRIC*MAX_VEL
  81. #define DYNAMIC_FRICTION (ACCEL/(float)MAX_VEL)
  82. float view_x_vel = 0;
  83. float view_z_vel = 0;
  84. float pending_view_x;
  85. float pending_view_z;
  86. float pending_view_x;
  87. float pending_view_z;
  88. void process_tick_raw(float dt)
  89. {
  90. int i;
  91. float thrust[3] = { 0,0,0 };
  92. float world_thrust[3];
  93. // choose direction to apply thrust
  94. thrust[0] = (controls & 3)== 1 ? EFFECTIVE_ACCEL : (controls & 3)== 2 ? -EFFECTIVE_ACCEL : 0;
  95. thrust[1] = (controls & 12)== 4 ? EFFECTIVE_ACCEL : (controls & 12)== 8 ? -EFFECTIVE_ACCEL : 0;
  96. thrust[2] = (controls & 48)==16 ? EFFECTIVE_ACCEL : (controls & 48)==32 ? -EFFECTIVE_ACCEL : 0;
  97. // @TODO clamp thrust[0] & thrust[1] vector length to EFFECTIVE_ACCEL
  98. camera_to_worldspace(world_thrust, thrust[0], thrust[1], 0);
  99. world_thrust[2] += thrust[2];
  100. for (i=0; i < 3; ++i) {
  101. float acc = world_thrust[i];
  102. cam_vel[i] += acc*dt;
  103. }
  104. if (cam_vel[0] || cam_vel[1] || cam_vel[2])
  105. {
  106. float vel = (float) sqrt(cam_vel[0]*cam_vel[0] + cam_vel[1]*cam_vel[1] + cam_vel[2]*cam_vel[2]);
  107. float newvel = vel;
  108. float dec = STATIC_FRICTION + DYNAMIC_FRICTION*vel;
  109. newvel = vel - dec*dt;
  110. if (newvel < 0)
  111. newvel = 0;
  112. cam_vel[0] *= newvel/vel;
  113. cam_vel[1] *= newvel/vel;
  114. cam_vel[2] *= newvel/vel;
  115. }
  116. camloc[0] += cam_vel[0] * dt;
  117. camloc[1] += cam_vel[1] * dt;
  118. camloc[2] += cam_vel[2] * dt;
  119. view_x_vel *= (float) pow(0.75, dt);
  120. view_z_vel *= (float) pow(0.75, dt);
  121. view_x_vel += (pending_view_x - view_x_vel)*dt*60;
  122. view_z_vel += (pending_view_z - view_z_vel)*dt*60;
  123. pending_view_x -= view_x_vel * dt;
  124. pending_view_z -= view_z_vel * dt;
  125. camang[0] += view_x_vel * dt;
  126. camang[2] += view_z_vel * dt;
  127. camang[0] = stb_clamp(camang[0], -90, 90);
  128. camang[2] = (float) fmod(camang[2], 360);
  129. }
  130. void process_tick(float dt)
  131. {
  132. while (dt > 1.0f/60) {
  133. process_tick_raw(1.0f/60);
  134. dt -= 1.0f/60;
  135. }
  136. process_tick_raw(dt);
  137. }
  138. void update_view(float dx, float dy)
  139. {
  140. // hard-coded mouse sensitivity, not resolution independent?
  141. pending_view_z -= dx*300;
  142. pending_view_x -= dy*700;
  143. }
  144. extern int screen_x, screen_y;
  145. extern int is_synchronous_debug;
  146. float render_time;
  147. extern int chunk_locations, chunks_considered, chunks_in_frustum;
  148. extern int quads_considered, quads_rendered;
  149. extern int chunk_storage_rendered, chunk_storage_considered, chunk_storage_total;
  150. extern int view_dist_in_chunks;
  151. extern int num_threads_active, num_meshes_started, num_meshes_uploaded;
  152. extern float chunk_server_activity;
  153. static Uint64 start_time, end_time; // render time
  154. float chunk_server_status[32];
  155. int chunk_server_pos;
  156. void draw_stats(void)
  157. {
  158. int i;
  159. static Uint64 last_frame_time;
  160. Uint64 cur_time = SDL_GetPerformanceCounter();
  161. float chunk_server=0;
  162. float frame_time = (cur_time - last_frame_time) / (float) SDL_GetPerformanceFrequency();
  163. last_frame_time = cur_time;
  164. chunk_server_status[chunk_server_pos] = chunk_server_activity;
  165. chunk_server_pos = (chunk_server_pos+1) %32;
  166. for (i=0; i < 32; ++i)
  167. chunk_server += chunk_server_status[i] / 32.0f;
  168. stb_easy_font_spacing(-0.75);
  169. pos_y = 10;
  170. text_color[0] = text_color[1] = text_color[2] = 1.0f;
  171. print("Frame time: %6.2fms, CPU frame render time: %5.2fms", frame_time*1000, render_time*1000);
  172. print("Tris: %4.1fM drawn of %4.1fM in range", 2*quads_rendered/1000000.0f, 2*quads_considered/1000000.0f);
  173. print("Vbuf storage: %dMB in frustum of %dMB in range of %dMB in cache", chunk_storage_rendered>>20, chunk_storage_considered>>20, chunk_storage_total>>20);
  174. print("Num mesh builds started this frame: %d; num uploaded this frame: %d\n", num_meshes_started, num_meshes_uploaded);
  175. print("QChunks: %3d in frustum of %3d valid of %3d in range", chunks_in_frustum, chunks_considered, chunk_locations);
  176. print("Mesh worker threads active: %d", num_threads_active);
  177. print("View distance: %d blocks", view_dist_in_chunks*16);
  178. print("%s", glGetString(GL_RENDERER));
  179. if (is_synchronous_debug) {
  180. text_color[0] = 1.0;
  181. text_color[1] = 0.5;
  182. text_color[2] = 0.5;
  183. print("SLOWNESS: Synchronous debug output is enabled!");
  184. }
  185. }
  186. void draw_main(void)
  187. {
  188. glEnable(GL_CULL_FACE);
  189. glDisable(GL_TEXTURE_2D);
  190. glDisable(GL_LIGHTING);
  191. glEnable(GL_DEPTH_TEST);
  192. #ifdef REVERSE_DEPTH
  193. glDepthFunc(GL_GREATER);
  194. glClearDepth(0);
  195. #else
  196. glDepthFunc(GL_LESS);
  197. glClearDepth(1);
  198. #endif
  199. glDepthMask(GL_TRUE);
  200. glDisable(GL_SCISSOR_TEST);
  201. glClearColor(0.6f,0.7f,0.9f,0.0f);
  202. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  203. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  204. glColor3f(1,1,1);
  205. glFrontFace(GL_CW);
  206. glEnable(GL_TEXTURE_2D);
  207. glDisable(GL_BLEND);
  208. glMatrixMode(GL_PROJECTION);
  209. glLoadIdentity();
  210. #ifdef REVERSE_DEPTH
  211. stbgl_Perspective(player_zoom, 90, 70, 3000, 1.0/16);
  212. #else
  213. stbgl_Perspective(player_zoom, 90, 70, 1.0/16, 3000);
  214. #endif
  215. // now compute where the camera should be
  216. glMatrixMode(GL_MODELVIEW);
  217. glLoadIdentity();
  218. stbgl_initCamera_zup_facing_y();
  219. glRotatef(-camang[0],1,0,0);
  220. glRotatef(-camang[2],0,0,1);
  221. glTranslatef(-camloc[0], -camloc[1], -camloc[2]);
  222. start_time = SDL_GetPerformanceCounter();
  223. render_caves(camloc);
  224. end_time = SDL_GetPerformanceCounter();
  225. render_time = (end_time - start_time) / (float) SDL_GetPerformanceFrequency();
  226. glMatrixMode(GL_PROJECTION);
  227. glLoadIdentity();
  228. gluOrtho2D(0,screen_x/2,screen_y/2,0);
  229. glMatrixMode(GL_MODELVIEW);
  230. glLoadIdentity();
  231. glDisable(GL_TEXTURE_2D);
  232. glDisable(GL_BLEND);
  233. glDisable(GL_CULL_FACE);
  234. draw_stats();
  235. }
  236. #pragma warning(disable:4244; disable:4305; disable:4018)
  237. #define SCALE 2
  238. void error(char *s)
  239. {
  240. SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", s, NULL);
  241. exit(0);
  242. }
  243. void ods(char *fmt, ...)
  244. {
  245. char buffer[1000];
  246. va_list va;
  247. va_start(va, fmt);
  248. vsprintf(buffer, fmt, va);
  249. va_end(va);
  250. SDL_Log("%s", buffer);
  251. }
  252. #define TICKS_PER_SECOND 60
  253. static SDL_Window *window;
  254. extern void draw_main(void);
  255. extern void process_tick(float dt);
  256. extern void editor_init(void);
  257. void draw(void)
  258. {
  259. draw_main();
  260. SDL_GL_SwapWindow(window);
  261. }
  262. static int initialized=0;
  263. static float last_dt;
  264. int screen_x,screen_y;
  265. float carried_dt = 0;
  266. #define TICKRATE 60
  267. float tex2_alpha = 1.0;
  268. int raw_level_time;
  269. float global_timer;
  270. int global_hack;
  271. int loopmode(float dt, int real, int in_client)
  272. {
  273. if (!initialized) return 0;
  274. if (!real)
  275. return 0;
  276. // don't allow more than 6 frames to update at a time
  277. if (dt > 0.075) dt = 0.075;
  278. global_timer += dt;
  279. carried_dt += dt;
  280. while (carried_dt > 1.0/TICKRATE) {
  281. if (global_hack) {
  282. tex2_alpha += global_hack / 60.0f;
  283. if (tex2_alpha < 0) tex2_alpha = 0;
  284. if (tex2_alpha > 1) tex2_alpha = 1;
  285. }
  286. //update_input();
  287. // if the player is dead, stop the sim
  288. carried_dt -= 1.0/TICKRATE;
  289. }
  290. process_tick(dt);
  291. draw();
  292. return 0;
  293. }
  294. static int quit;
  295. extern int controls;
  296. void active_control_set(int key)
  297. {
  298. controls |= 1 << key;
  299. }
  300. void active_control_clear(int key)
  301. {
  302. controls &= ~(1 << key);
  303. }
  304. extern void update_view(float dx, float dy);
  305. void process_sdl_mouse(SDL_Event *e)
  306. {
  307. update_view((float) e->motion.xrel / screen_x, (float) e->motion.yrel / screen_y);
  308. }
  309. void process_event(SDL_Event *e)
  310. {
  311. switch (e->type) {
  312. case SDL_MOUSEMOTION:
  313. process_sdl_mouse(e);
  314. break;
  315. case SDL_MOUSEBUTTONDOWN:
  316. case SDL_MOUSEBUTTONUP:
  317. break;
  318. case SDL_QUIT:
  319. quit = 1;
  320. break;
  321. case SDL_WINDOWEVENT:
  322. switch (e->window.event) {
  323. case SDL_WINDOWEVENT_SIZE_CHANGED:
  324. screen_x = e->window.data1;
  325. screen_y = e->window.data2;
  326. loopmode(0,1,0);
  327. break;
  328. }
  329. break;
  330. case SDL_KEYDOWN: {
  331. int k = e->key.keysym.sym;
  332. int s = e->key.keysym.scancode;
  333. SDL_Keymod mod;
  334. mod = SDL_GetModState();
  335. if (k == SDLK_ESCAPE)
  336. quit = 1;
  337. if (s == SDL_SCANCODE_D) active_control_set(0);
  338. if (s == SDL_SCANCODE_A) active_control_set(1);
  339. if (s == SDL_SCANCODE_W) active_control_set(2);
  340. if (s == SDL_SCANCODE_S) active_control_set(3);
  341. if (k == SDLK_SPACE) active_control_set(4);
  342. if (s == SDL_SCANCODE_LCTRL) active_control_set(5);
  343. if (s == SDL_SCANCODE_S) active_control_set(6);
  344. if (s == SDL_SCANCODE_D) active_control_set(7);
  345. if (k == '1') global_hack = !global_hack;
  346. if (k == '2') global_hack = -1;
  347. #if 0
  348. if (game_mode == GAME_editor) {
  349. switch (k) {
  350. case SDLK_RIGHT: editor_key(STBTE_scroll_right); break;
  351. case SDLK_LEFT : editor_key(STBTE_scroll_left ); break;
  352. case SDLK_UP : editor_key(STBTE_scroll_up ); break;
  353. case SDLK_DOWN : editor_key(STBTE_scroll_down ); break;
  354. }
  355. switch (s) {
  356. case SDL_SCANCODE_S: editor_key(STBTE_tool_select); break;
  357. case SDL_SCANCODE_B: editor_key(STBTE_tool_brush ); break;
  358. case SDL_SCANCODE_E: editor_key(STBTE_tool_erase ); break;
  359. case SDL_SCANCODE_R: editor_key(STBTE_tool_rectangle ); break;
  360. case SDL_SCANCODE_I: editor_key(STBTE_tool_eyedropper); break;
  361. case SDL_SCANCODE_L: editor_key(STBTE_tool_link); break;
  362. case SDL_SCANCODE_G: editor_key(STBTE_act_toggle_grid); break;
  363. }
  364. if ((e->key.keysym.mod & KMOD_CTRL) && !(e->key.keysym.mod & ~KMOD_CTRL)) {
  365. switch (s) {
  366. case SDL_SCANCODE_X: editor_key(STBTE_act_cut ); break;
  367. case SDL_SCANCODE_C: editor_key(STBTE_act_copy ); break;
  368. case SDL_SCANCODE_V: editor_key(STBTE_act_paste); break;
  369. case SDL_SCANCODE_Z: editor_key(STBTE_act_undo ); break;
  370. case SDL_SCANCODE_Y: editor_key(STBTE_act_redo ); break;
  371. }
  372. }
  373. }
  374. #endif
  375. break;
  376. }
  377. case SDL_KEYUP: {
  378. int k = e->key.keysym.sym;
  379. int s = e->key.keysym.scancode;
  380. if (s == SDL_SCANCODE_D) active_control_clear(0);
  381. if (s == SDL_SCANCODE_A) active_control_clear(1);
  382. if (s == SDL_SCANCODE_W) active_control_clear(2);
  383. if (s == SDL_SCANCODE_S) active_control_clear(3);
  384. if (k == SDLK_SPACE) active_control_clear(4);
  385. if (s == SDL_SCANCODE_LCTRL) active_control_clear(5);
  386. if (s == SDL_SCANCODE_S) active_control_clear(6);
  387. if (s == SDL_SCANCODE_D) active_control_clear(7);
  388. break;
  389. }
  390. }
  391. }
  392. static SDL_GLContext *context;
  393. static float getTimestep(float minimum_time)
  394. {
  395. float elapsedTime;
  396. double thisTime;
  397. static double lastTime = -1;
  398. if (lastTime == -1)
  399. lastTime = SDL_GetTicks() / 1000.0 - minimum_time;
  400. for(;;) {
  401. thisTime = SDL_GetTicks() / 1000.0;
  402. elapsedTime = (float) (thisTime - lastTime);
  403. if (elapsedTime >= minimum_time) {
  404. lastTime = thisTime;
  405. return elapsedTime;
  406. }
  407. // @TODO: compute correct delay
  408. SDL_Delay(1);
  409. }
  410. }
  411. void APIENTRY gl_debug(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *param)
  412. {
  413. ods("%s\n", message);
  414. }
  415. int is_synchronous_debug;
  416. void enable_synchronous(void)
  417. {
  418. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
  419. is_synchronous_debug = 1;
  420. }
  421. void prepare_threads(void);
  422. //void stbwingraph_main(void)
  423. int SDL_main(int argc, char **argv)
  424. {
  425. SDL_Init(SDL_INIT_VIDEO);
  426. prepare_threads();
  427. SDL_GL_SetAttribute(SDL_GL_RED_SIZE , 8);
  428. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  429. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE , 8);
  430. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  431. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
  432. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  433. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
  434. #ifdef GL_DEBUG
  435. SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
  436. #endif
  437. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
  438. screen_x = 1920;
  439. screen_y = 1080;
  440. window = SDL_CreateWindow("caveview", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  441. screen_x, screen_y,
  442. SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
  443. );
  444. if (!window) error("Couldn't create window");
  445. context = SDL_GL_CreateContext(window);
  446. if (!context) error("Couldn't create context");
  447. SDL_GL_MakeCurrent(window, context); // is this true by default?
  448. SDL_SetRelativeMouseMode(SDL_TRUE);
  449. #if defined(_MSC_VER) && _MSC_VER < 1300
  450. // work around broken behavior in VC6 debugging
  451. if (IsDebuggerPresent())
  452. SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
  453. #endif
  454. stbgl_initExtensions();
  455. #ifdef GL_DEBUG
  456. if (glDebugMessageCallbackARB) {
  457. glDebugMessageCallbackARB(gl_debug, NULL);
  458. enable_synchronous();
  459. }
  460. #endif
  461. SDL_GL_SetSwapInterval(1);
  462. render_init();
  463. mesh_init();
  464. world_init();
  465. initialized = 1;
  466. while (!quit) {
  467. SDL_Event e;
  468. while (SDL_PollEvent(&e))
  469. process_event(&e);
  470. loopmode(getTimestep(0.0166f/8), 1, 1);
  471. }
  472. return 0;
  473. }