You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							598 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							598 lines
						
					
					
						
							16 KiB
						
					
					
				| #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; | |
| }
 | |
| 
 |