| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- #define _WIN32_WINNT 0x400
- #include <assert.h>
- #include <windows.h>
- // stb.h
- #define STB_DEFINE
- #include "stb.h"
- // stb_gl.h
- #define STB_GL_IMPLEMENTATION
- #define STB_GLEXT_DEFINE "glext_list.h"
- #include "stb_gl.h"
- // SDL
- #include "sdl.h"
- #include "SDL_opengl.h"
- // stb_glprog.h
- #define STB_GLPROG_IMPLEMENTATION
- #define STB_GLPROG_ARB_DEFINE_EXTENSIONS
- #include "stb_glprog.h"
- // stb_image.h
- #define STB_IMAGE_IMPLEMENTATION
- #include "stb_image.h"
- // stb_easy_font.h
- #include "stb_easy_font.h" // doesn't require an IMPLEMENTATION
- #include "caveview.h"
- char *game_name = "caveview";
- #define REVERSE_DEPTH
- static void print_string(float x, float y, char *text, float r, float g, float b)
- {
- static char buffer[99999];
- int num_quads;
-
- num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer));
- glColor3f(r,g,b);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 16, buffer);
- glDrawArrays(GL_QUADS, 0, num_quads*4);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- static float text_color[3];
- static float pos_x = 10;
- static float pos_y = 10;
- static void print(char *text, ...)
- {
- char buffer[999];
- va_list va;
- va_start(va, text);
- vsprintf(buffer, text, va);
- va_end(va);
- print_string(pos_x, pos_y, buffer, text_color[0], text_color[1], text_color[2]);
- pos_y += 10;
- }
- float camang[3], camloc[3] = { 60,22,77 };
- float player_zoom = 1.0;
- float rotate_view = 0.0;
- void camera_to_worldspace(float world[3], float cam_x, float cam_y, float cam_z)
- {
- float vec[3] = { cam_x, cam_y, cam_z };
- float t[3];
- float s,c;
- s = (float) sin(camang[0]*3.141592/180);
- c = (float) cos(camang[0]*3.141592/180);
- t[0] = vec[0];
- t[1] = c*vec[1] - s*vec[2];
- t[2] = s*vec[1] + c*vec[2];
- s = (float) sin(camang[2]*3.141592/180);
- c = (float) cos(camang[2]*3.141592/180);
- world[0] = c*t[0] - s*t[1];
- world[1] = s*t[0] + c*t[1];
- world[2] = t[2];
- }
- // camera worldspace velocity
- float cam_vel[3];
- int controls;
- #define MAX_VEL 150.0f // blocks per second
- #define ACCEL 6.0f
- #define DECEL 3.0f
- #define STATIC_FRICTION DECEL
- #define EFFECTIVE_ACCEL (ACCEL+DECEL)
- // dynamic friction:
- //
- // if going at MAX_VEL, ACCEL and friction must cancel
- // EFFECTIVE_ACCEL = DECEL + DYNAMIC_FRIC*MAX_VEL
- #define DYNAMIC_FRICTION (ACCEL/(float)MAX_VEL)
- float view_x_vel = 0;
- float view_z_vel = 0;
- float pending_view_x;
- float pending_view_z;
- float pending_view_x;
- float pending_view_z;
- void process_tick_raw(float dt)
- {
- int i;
- float thrust[3] = { 0,0,0 };
- float world_thrust[3];
- // choose direction to apply thrust
- thrust[0] = (controls & 3)== 1 ? EFFECTIVE_ACCEL : (controls & 3)== 2 ? -EFFECTIVE_ACCEL : 0;
- thrust[1] = (controls & 12)== 4 ? EFFECTIVE_ACCEL : (controls & 12)== 8 ? -EFFECTIVE_ACCEL : 0;
- thrust[2] = (controls & 48)==16 ? EFFECTIVE_ACCEL : (controls & 48)==32 ? -EFFECTIVE_ACCEL : 0;
- // @TODO clamp thrust[0] & thrust[1] vector length to EFFECTIVE_ACCEL
- camera_to_worldspace(world_thrust, thrust[0], thrust[1], 0);
- world_thrust[2] += thrust[2];
- for (i=0; i < 3; ++i) {
- float acc = world_thrust[i];
- cam_vel[i] += acc*dt;
- }
- if (cam_vel[0] || cam_vel[1] || cam_vel[2])
- {
- float vel = (float) sqrt(cam_vel[0]*cam_vel[0] + cam_vel[1]*cam_vel[1] + cam_vel[2]*cam_vel[2]);
- float newvel = vel;
- float dec = STATIC_FRICTION + DYNAMIC_FRICTION*vel;
- newvel = vel - dec*dt;
- if (newvel < 0)
- newvel = 0;
- cam_vel[0] *= newvel/vel;
- cam_vel[1] *= newvel/vel;
- cam_vel[2] *= newvel/vel;
- }
- camloc[0] += cam_vel[0] * dt;
- camloc[1] += cam_vel[1] * dt;
- camloc[2] += cam_vel[2] * dt;
- view_x_vel *= (float) pow(0.75, dt);
- view_z_vel *= (float) pow(0.75, dt);
- view_x_vel += (pending_view_x - view_x_vel)*dt*60;
- view_z_vel += (pending_view_z - view_z_vel)*dt*60;
- pending_view_x -= view_x_vel * dt;
- pending_view_z -= view_z_vel * dt;
- camang[0] += view_x_vel * dt;
- camang[2] += view_z_vel * dt;
- camang[0] = stb_clamp(camang[0], -90, 90);
- camang[2] = (float) fmod(camang[2], 360);
- }
- void process_tick(float dt)
- {
- while (dt > 1.0f/60) {
- process_tick_raw(1.0f/60);
- dt -= 1.0f/60;
- }
- process_tick_raw(dt);
- }
- void update_view(float dx, float dy)
- {
- // hard-coded mouse sensitivity, not resolution independent?
- pending_view_z -= dx*300;
- pending_view_x -= dy*700;
- }
- extern int screen_x, screen_y;
- extern int is_synchronous_debug;
- float render_time;
- extern int chunk_locations, chunks_considered, chunks_in_frustum;
- extern int quads_considered, quads_rendered;
- extern int chunk_storage_rendered, chunk_storage_considered, chunk_storage_total;
- extern int view_dist_in_chunks;
- extern int num_threads_active, num_meshes_started, num_meshes_uploaded;
- extern float chunk_server_activity;
- static Uint64 start_time, end_time; // render time
- float chunk_server_status[32];
- int chunk_server_pos;
- void draw_stats(void)
- {
- int i;
- static Uint64 last_frame_time;
- Uint64 cur_time = SDL_GetPerformanceCounter();
- float chunk_server=0;
- float frame_time = (cur_time - last_frame_time) / (float) SDL_GetPerformanceFrequency();
- last_frame_time = cur_time;
- chunk_server_status[chunk_server_pos] = chunk_server_activity;
- chunk_server_pos = (chunk_server_pos+1) %32;
- for (i=0; i < 32; ++i)
- chunk_server += chunk_server_status[i] / 32.0f;
- stb_easy_font_spacing(-0.75);
- pos_y = 10;
- text_color[0] = text_color[1] = text_color[2] = 1.0f;
- print("Frame time: %6.2fms, CPU frame render time: %5.2fms", frame_time*1000, render_time*1000);
- print("Tris: %4.1fM drawn of %4.1fM in range", 2*quads_rendered/1000000.0f, 2*quads_considered/1000000.0f);
- 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);
- print("Num mesh builds started this frame: %d; num uploaded this frame: %d\n", num_meshes_started, num_meshes_uploaded);
- print("QChunks: %3d in frustum of %3d valid of %3d in range", chunks_in_frustum, chunks_considered, chunk_locations);
- print("Mesh worker threads active: %d", num_threads_active);
- print("View distance: %d blocks", view_dist_in_chunks*16);
- print("%s", glGetString(GL_RENDERER));
- if (is_synchronous_debug) {
- text_color[0] = 1.0;
- text_color[1] = 0.5;
- text_color[2] = 0.5;
- print("SLOWNESS: Synchronous debug output is enabled!");
- }
- }
- void draw_main(void)
- {
- glEnable(GL_CULL_FACE);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_LIGHTING);
- glEnable(GL_DEPTH_TEST);
- #ifdef REVERSE_DEPTH
- glDepthFunc(GL_GREATER);
- glClearDepth(0);
- #else
- glDepthFunc(GL_LESS);
- glClearDepth(1);
- #endif
- glDepthMask(GL_TRUE);
- glDisable(GL_SCISSOR_TEST);
- glClearColor(0.6f,0.7f,0.9f,0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor3f(1,1,1);
- glFrontFace(GL_CW);
- glEnable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- #ifdef REVERSE_DEPTH
- stbgl_Perspective(player_zoom, 90, 70, 3000, 1.0/16);
- #else
- stbgl_Perspective(player_zoom, 90, 70, 1.0/16, 3000);
- #endif
- // now compute where the camera should be
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- stbgl_initCamera_zup_facing_y();
- glRotatef(-camang[0],1,0,0);
- glRotatef(-camang[2],0,0,1);
- glTranslatef(-camloc[0], -camloc[1], -camloc[2]);
- start_time = SDL_GetPerformanceCounter();
- render_caves(camloc);
- end_time = SDL_GetPerformanceCounter();
- render_time = (end_time - start_time) / (float) SDL_GetPerformanceFrequency();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0,screen_x/2,screen_y/2,0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glDisable(GL_CULL_FACE);
- draw_stats();
- }
- #pragma warning(disable:4244; disable:4305; disable:4018)
- #define SCALE 2
- void error(char *s)
- {
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", s, NULL);
- exit(0);
- }
- void ods(char *fmt, ...)
- {
- char buffer[1000];
- va_list va;
- va_start(va, fmt);
- vsprintf(buffer, fmt, va);
- va_end(va);
- SDL_Log("%s", buffer);
- }
- #define TICKS_PER_SECOND 60
- static SDL_Window *window;
- extern void draw_main(void);
- extern void process_tick(float dt);
- extern void editor_init(void);
- void draw(void)
- {
- draw_main();
- SDL_GL_SwapWindow(window);
- }
- static int initialized=0;
- static float last_dt;
- int screen_x,screen_y;
- float carried_dt = 0;
- #define TICKRATE 60
- float tex2_alpha = 1.0;
- int raw_level_time;
- float global_timer;
- int global_hack;
- int loopmode(float dt, int real, int in_client)
- {
- if (!initialized) return 0;
- if (!real)
- return 0;
- // don't allow more than 6 frames to update at a time
- if (dt > 0.075) dt = 0.075;
- global_timer += dt;
- carried_dt += dt;
- while (carried_dt > 1.0/TICKRATE) {
- if (global_hack) {
- tex2_alpha += global_hack / 60.0f;
- if (tex2_alpha < 0) tex2_alpha = 0;
- if (tex2_alpha > 1) tex2_alpha = 1;
- }
- //update_input();
- // if the player is dead, stop the sim
- carried_dt -= 1.0/TICKRATE;
- }
- process_tick(dt);
- draw();
- return 0;
- }
- static int quit;
- extern int controls;
- void active_control_set(int key)
- {
- controls |= 1 << key;
- }
- void active_control_clear(int key)
- {
- controls &= ~(1 << key);
- }
- extern void update_view(float dx, float dy);
- void process_sdl_mouse(SDL_Event *e)
- {
- update_view((float) e->motion.xrel / screen_x, (float) e->motion.yrel / screen_y);
- }
- void process_event(SDL_Event *e)
- {
- switch (e->type) {
- case SDL_MOUSEMOTION:
- process_sdl_mouse(e);
- break;
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- break;
- case SDL_QUIT:
- quit = 1;
- break;
- case SDL_WINDOWEVENT:
- switch (e->window.event) {
- case SDL_WINDOWEVENT_SIZE_CHANGED:
- screen_x = e->window.data1;
- screen_y = e->window.data2;
- loopmode(0,1,0);
- break;
- }
- break;
- case SDL_KEYDOWN: {
- int k = e->key.keysym.sym;
- int s = e->key.keysym.scancode;
- SDL_Keymod mod;
- mod = SDL_GetModState();
- if (k == SDLK_ESCAPE)
- quit = 1;
- if (s == SDL_SCANCODE_D) active_control_set(0);
- if (s == SDL_SCANCODE_A) active_control_set(1);
- if (s == SDL_SCANCODE_W) active_control_set(2);
- if (s == SDL_SCANCODE_S) active_control_set(3);
- if (k == SDLK_SPACE) active_control_set(4);
- if (s == SDL_SCANCODE_LCTRL) active_control_set(5);
- if (s == SDL_SCANCODE_S) active_control_set(6);
- if (s == SDL_SCANCODE_D) active_control_set(7);
- if (k == '1') global_hack = !global_hack;
- if (k == '2') global_hack = -1;
- #if 0
- if (game_mode == GAME_editor) {
- switch (k) {
- case SDLK_RIGHT: editor_key(STBTE_scroll_right); break;
- case SDLK_LEFT : editor_key(STBTE_scroll_left ); break;
- case SDLK_UP : editor_key(STBTE_scroll_up ); break;
- case SDLK_DOWN : editor_key(STBTE_scroll_down ); break;
- }
- switch (s) {
- case SDL_SCANCODE_S: editor_key(STBTE_tool_select); break;
- case SDL_SCANCODE_B: editor_key(STBTE_tool_brush ); break;
- case SDL_SCANCODE_E: editor_key(STBTE_tool_erase ); break;
- case SDL_SCANCODE_R: editor_key(STBTE_tool_rectangle ); break;
- case SDL_SCANCODE_I: editor_key(STBTE_tool_eyedropper); break;
- case SDL_SCANCODE_L: editor_key(STBTE_tool_link); break;
- case SDL_SCANCODE_G: editor_key(STBTE_act_toggle_grid); break;
- }
- if ((e->key.keysym.mod & KMOD_CTRL) && !(e->key.keysym.mod & ~KMOD_CTRL)) {
- switch (s) {
- case SDL_SCANCODE_X: editor_key(STBTE_act_cut ); break;
- case SDL_SCANCODE_C: editor_key(STBTE_act_copy ); break;
- case SDL_SCANCODE_V: editor_key(STBTE_act_paste); break;
- case SDL_SCANCODE_Z: editor_key(STBTE_act_undo ); break;
- case SDL_SCANCODE_Y: editor_key(STBTE_act_redo ); break;
- }
- }
- }
- #endif
- break;
- }
- case SDL_KEYUP: {
- int k = e->key.keysym.sym;
- int s = e->key.keysym.scancode;
- if (s == SDL_SCANCODE_D) active_control_clear(0);
- if (s == SDL_SCANCODE_A) active_control_clear(1);
- if (s == SDL_SCANCODE_W) active_control_clear(2);
- if (s == SDL_SCANCODE_S) active_control_clear(3);
- if (k == SDLK_SPACE) active_control_clear(4);
- if (s == SDL_SCANCODE_LCTRL) active_control_clear(5);
- if (s == SDL_SCANCODE_S) active_control_clear(6);
- if (s == SDL_SCANCODE_D) active_control_clear(7);
- break;
- }
- }
- }
- static SDL_GLContext *context;
- static float getTimestep(float minimum_time)
- {
- float elapsedTime;
- double thisTime;
- static double lastTime = -1;
-
- if (lastTime == -1)
- lastTime = SDL_GetTicks() / 1000.0 - minimum_time;
- for(;;) {
- thisTime = SDL_GetTicks() / 1000.0;
- elapsedTime = (float) (thisTime - lastTime);
- if (elapsedTime >= minimum_time) {
- lastTime = thisTime;
- return elapsedTime;
- }
- // @TODO: compute correct delay
- SDL_Delay(1);
- }
- }
- void APIENTRY gl_debug(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *param)
- {
- ods("%s\n", message);
- }
- int is_synchronous_debug;
- void enable_synchronous(void)
- {
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
- is_synchronous_debug = 1;
- }
- void prepare_threads(void);
- //void stbwingraph_main(void)
- int SDL_main(int argc, char **argv)
- {
- SDL_Init(SDL_INIT_VIDEO);
- prepare_threads();
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE , 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE , 8);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
- #ifdef GL_DEBUG
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
- #endif
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
- screen_x = 1920;
- screen_y = 1080;
- window = SDL_CreateWindow("caveview", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- screen_x, screen_y,
- SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
- );
- if (!window) error("Couldn't create window");
- context = SDL_GL_CreateContext(window);
- if (!context) error("Couldn't create context");
- SDL_GL_MakeCurrent(window, context); // is this true by default?
- SDL_SetRelativeMouseMode(SDL_TRUE);
- #if defined(_MSC_VER) && _MSC_VER < 1300
- // work around broken behavior in VC6 debugging
- if (IsDebuggerPresent())
- SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
- #endif
- stbgl_initExtensions();
- #ifdef GL_DEBUG
- if (glDebugMessageCallbackARB) {
- glDebugMessageCallbackARB(gl_debug, NULL);
- enable_synchronous();
- }
- #endif
- SDL_GL_SetSwapInterval(1);
- render_init();
- mesh_init();
- world_init();
- initialized = 1;
- while (!quit) {
- SDL_Event e;
- while (SDL_PollEvent(&e))
- process_event(&e);
- loopmode(getTimestep(0.0166f/8), 1, 1);
- }
- return 0;
- }
|