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