Example #1
0
void scotland_update() {
  
  camera* cam = entity_get("camera");
  light* sun = entity_get("sun");
  static_object* skydome = entity_get("skydome");
  landscape* world = entity_get("world");
  
  sun_orbit += frame_time() * 0.01;
  
  sun->position.x = 512 + sin(sun_orbit) * 512;
  sun->position.y = cos(sun_orbit) * 512;
  sun->position.z = 512;
  sun->target = vec3_new(512, 0, 512);
  
  if (w_held || s_held) {
    
    vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position));
    float speed = 0.5;
    if (!freecam) speed = 0.05;
    if (w_held) {
      cam->position = vec3_add(cam->position, vec3_mul(cam_dir, speed));
    }
    if (s_held) {
      cam->position = vec3_sub(cam->position, vec3_mul(cam_dir, speed));
    }
    
    if (!freecam) {
      float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z));
      cam->position.y = height + 1;
    }
    
    cam->target = vec3_add(cam->position, cam_dir);
  }
  
  Uint8 keystate = SDL_GetMouseState(NULL, NULL);
  if(keystate & SDL_BUTTON(1)){
  
    float a1 = -(float)mouse_x * 0.005;
    float a2 = (float)mouse_y * 0.005;
    
    vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position));
    
    cam_dir.y += -a2;
    vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0)));
    cam_dir = vec3_add(cam_dir, vec3_mul(side_dir, -a1));
    cam_dir = vec3_normalize(cam_dir);
    
    cam->target = vec3_add(cam->position, cam_dir);
  }
  
  mouse_x = 0;
  mouse_y = 0;
  
  ui_button* framerate = ui_elem_get("framerate");
  ui_button_set_label(framerate, frame_rate_string());
}
Example #2
0
void camera_control_freecam(camera* c, float timestep) {

  const Uint8* kbstate = SDL_GetKeyboardState(NULL);
  
  if (kbstate[SDL_SCANCODE_W] 
  ||  kbstate[SDL_SCANCODE_S] 
  ||  kbstate[SDL_SCANCODE_A] 
  ||  kbstate[SDL_SCANCODE_D]) {
    
    vec3 cam_dir = vec3_normalize(vec3_sub(c->target, c->position));
    vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0)));

    const float speed = 100 * timestep;
    
    if (kbstate[SDL_SCANCODE_W]) {
      c->position = vec3_add(c->position, vec3_mul(cam_dir, speed));
      c->target = vec3_add(c->target, vec3_mul(cam_dir, speed));
    }
    if (kbstate[SDL_SCANCODE_S]) {
      c->position = vec3_sub(c->position, vec3_mul(cam_dir, speed));
      c->target = vec3_sub(c->target, vec3_mul(cam_dir, speed));
    }
    if (kbstate[SDL_SCANCODE_D]) {
      c->position = vec3_add(c->position, vec3_mul(side_dir, speed));
      c->target = vec3_add(c->target, vec3_mul(side_dir, speed));
    }
    if (kbstate[SDL_SCANCODE_A]) {
      c->position = vec3_sub(c->position, vec3_mul(side_dir, speed));
      c->target = vec3_sub(c->target, vec3_mul(side_dir, speed));
    }
    
  }
  
  int mouse_x, mouse_y;
  Uint8 mstate = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
  if (mstate & SDL_BUTTON(1)) {
  
    float a1 = -(float)mouse_x * 0.005;
    float a2 = (float)mouse_y * 0.005;
    
    vec3 cam_dir = vec3_normalize(vec3_sub(c->target, c->position));
    
    cam_dir.y += -a2;
    vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0)));
    cam_dir = vec3_add(cam_dir, vec3_mul(side_dir, -a1));
    cam_dir = vec3_normalize(cam_dir);
    
    c->target = vec3_add(c->position, cam_dir);
  }
}
Example #3
0
static int vec3_mt_mul(lua_State *L)
{
	if (lua_isnumber(L, 1)) {
		lua_Number a = lua_tonumber(L, 1);
		vec3_t *b = (vec3_t *)luaL_checkudata(L, 2, "vec3");
		return vec3_new(L, a * b->x, a * b->y, a * b->z);
	} else if (lua_isnumber(L, 2)) {
		vec3_t *a = (vec3_t *)luaL_checkudata(L, 1, "vec3");
		lua_Number b = lua_tonumber(L, 2);
		return vec3_new(L, a->x * b, a->y * b, a->z * b);
	} else {
		return luaL_error(L, "expected arg #1 or #2 to be `number'");
	}
}
Example #4
0
void camera_control_joyorbit(camera* c, float timestep) {
  
  if (joystick_count() == 0) return;
  
  SDL_Joystick* mainstick = joystick_get(0);
  int x_move = SDL_JoystickGetAxis(mainstick, 0);
  int y_move = SDL_JoystickGetAxis(mainstick, 1);
  
  /* Dead Zone */
  if (abs(x_move) < 10000) { x_move = 0; };
  if (abs(y_move) < 10000) { y_move = 0; };
  
  float a1 = (x_move / 32768.0) * -0.05;
  float a2 = (y_move / 32768.0) * 0.05;
  
  vec3 translation = c->target;
  c->position = vec3_sub(c->position, translation);
  c->target = vec3_sub(c->target, translation);
  
  c->position = mat3_mul_vec3(mat3_rotation_y( a1 ), c->position );
  vec3 axis = vec3_normalize(vec3_cross( vec3_sub(c->position, c->target) , vec3_new(0,1,0) ));
  c->position = mat3_mul_vec3(mat3_rotation_axis_angle(axis, a2 ), c->position );
  
  c->position = vec3_add(c->position, translation);
  c->target = vec3_add(c->target, translation);

}
Example #5
0
vec3 terrain_normal(terrain* ter, vec2 position) {
  
  mat3 axis = terrain_axis(ter, position);
  
  return mat3_mul_vec3(axis, vec3_new(0, 1, 0));
  
}
Example #6
0
void camera_control_orbit(camera* c, SDL_Event e) {
  
  float a1 = 0;
  float a2 = 0;
  vec3 axis;
  
  vec3 translation = c->target;
  c->position = vec3_sub(c->position, translation);
  c->target = vec3_sub(c->target, translation);
  
  switch(e.type) {
    
    case SDL_MOUSEMOTION:
      if (e.motion.state & SDL_BUTTON(1)) {
        a1 = e.motion.xrel * -0.005;
        a2 = e.motion.yrel * 0.005;
        c->position = mat3_mul_vec3(mat3_rotation_y( a1 ), c->position );
        axis = vec3_normalize(vec3_cross( vec3_sub(c->position, c->target) , vec3_new(0,1,0) ));
        c->position = mat3_mul_vec3(mat3_rotation_angle_axis(a2, axis), c->position );
      }
    break;
    
    case SDL_MOUSEWHEEL:
      c->position = vec3_add(c->position, vec3_mul(vec3_normalize(c->position), -e.wheel.y));
    break;

  }
  
  c->position = vec3_add(c->position, translation);
  c->target = vec3_add(c->target, translation);

}
Example #7
0
File: gx.c Project: LWSS/gx
void render_game(struct GameMemory *memory, struct Renderer *renderer, uint32 screen_width, uint32 screen_height)
{
    struct GameState *game_state = (struct GameState *)memory->game_memory;
    struct RenderBuffer *render_buffer = (struct RenderBuffer *)memory->render_memory;

    float aspect_ratio = (float)screen_width / (float)screen_height;
    mat4 projection_matrix = mat4_orthographic(-game_state->camera.zoom/2.0f, game_state->camera.zoom/2.0f,
                                               -game_state->camera.zoom/2.0f / aspect_ratio, game_state->camera.zoom/2.0f / aspect_ratio,
                                               0.0f, 1.0f);
    mat4 view_matrix = mat4_look_at(vec3_new(game_state->camera.position.x, game_state->camera.position.y, 0.0f), vec3_new(game_state->camera.position.x, game_state->camera.position.y, -1.0f), vec3_new(0, 1, 0));
    mat4 view_projection_matrix = mat4_mul(projection_matrix, view_matrix);

    update_ubo(renderer->camera_ubo, sizeof(mat4), &view_projection_matrix);

    bind_program(renderer->line_program);
    draw_world_line_buffer(renderer, render_buffer, renderer->line_program);
    bind_program(0);

    bind_program(renderer->quad_program);
    draw_world_quad_buffer(&renderer->sprite_batch, render_buffer);
    bind_program(0);

    draw_buildings(game_state, renderer);
    draw_ships(game_state, renderer);
    draw_projectiles(game_state, renderer);

    view_projection_matrix = mat4_orthographic(0, screen_width, screen_height, 0, 0, 1);
    update_ubo(renderer->camera_ubo, sizeof(mat4), &view_projection_matrix);

    bind_program(renderer->quad_program);
    draw_screen_quad_buffer(&renderer->sprite_batch, render_buffer);
    bind_program(0);

    draw_frame_text_buffer(renderer, render_buffer);
}
Example #8
0
static int vec3_index_cross(lua_State *L)
{
	vec3_t *a = (vec3_t *)luaL_checkudata(L, 1, "vec3");
	vec3_t *b = (vec3_t *)luaL_checkudata(L, 2, "vec3");
	return vec3_new(L,
		a->y * b->z - a->z * b->y,
		a->z * b->x - a->x * b->z,
		a->x * b->y - a->y * b->x);
}
Example #9
0
mat3 terrain_axis(terrain* ter, vec2 position) {

  float offset   = terrain_height(ter, position);
  float offset_x = terrain_height(ter, vec2_add(position, vec2_new(1,0)));
  float offset_y = terrain_height(ter, vec2_add(position, vec2_new(0,1)));
  
  vec3 pos    = vec3_new(position.x+0, offset,   position.y+0);
  vec3 pos_xv = vec3_new(position.x+1, offset_x, position.y+0);
  vec3 pos_yv = vec3_new(position.x+0, offset_y, position.y+1);
  
  vec3 tangent = vec3_normalize(vec3_sub(pos_xv, pos));
  vec3 binorm  = vec3_normalize(vec3_sub(pos_yv, pos));
  vec3 normal  = vec3_cross(binorm, tangent);

  return mat3_new(
    tangent.x, tangent.y, tangent.z,
    normal.x,  normal.y,  normal.z, 
    binorm.x,  binorm.y,  binorm.z);
  
}
Example #10
0
static int load_resources(void* unused) {
  
  folder_load(P("./resources/terrain/"));
  folder_load(P("./resources/vegetation/"));
  
  static_object* skydome = entity_new("skydome", static_object);
  skydome->renderable = asset_hndl_new_load(P("./resources/terrain/skydome.obj"));
  ((renderable*)asset_hndl_ptr(skydome->renderable))->material = asset_hndl_new_load(P("$CORANGE/shaders/skydome.mat"));
  skydome->position = vec3_new(512, 0, 512);
  skydome->scale = vec3_new(1024, 1024, 1024);
  
  landscape* world = entity_new("world", landscape);
  world->terrain = asset_hndl_new_load(P("./resources/terrain/heightmap.raw"));
  world->normalmap = asset_hndl_new_load(P("./resources/terrain/normalsmap.dds"));
  world->colormap = asset_hndl_new_load(P("./resources/terrain/colormap.dds"));
  world->attributemap = asset_hndl_new_load(P("./resources/terrain/attributemap.dds"));

  landscape_set_textures(world, asset_hndl_new_load(P("./resources/terrain/surface.dds")), 
                                asset_hndl_new_load(P("./resources/terrain/surface_bump.dds")), 
                                asset_hndl_new_load(P("./resources/terrain/surface_far.dds")), 
                                asset_hndl_new_load(P("./resources/terrain/surface_far_bump.dds")));
  
  vegetation_init();
  //vegetation_add_type(asset_get("./resources/terrain/heightmap.raw"), 
  //                    asset_get("./resources/vegetation/grass.obj"), 
  //                    4.0);
  
  ui_button* loading = ui_elem_get("loading");
  ui_spinner* load_spinner = ui_elem_get("load_spinner");
  ui_button* framerate = ui_elem_get("framerate");
  ui_button* wireframe = ui_elem_get("wireframe");
  ui_button* freecam = ui_elem_get("freecam");
  loading->active = false;
  load_spinner->active = false;
  framerate->active = true;
  wireframe->active = true;
  freecam->active = true;
  
  loading_resources = false;
  return 1;
}
Example #11
0
static int vec3_new(lua_State *L)
{
	lua_Number x, y, z;
	if (lua_gettop(L) == 0) {
		x = y = z = 0;
	} else {
		x = luaL_checknumber(L, 1);
		y = luaL_checknumber(L, 2);
		z = luaL_checknumber(L, 3);
	}
	return vec3_new(L, x, y, z);
}
Example #12
0
camera* camera_new() {

  camera* c = malloc(sizeof(camera));
  
  c->position = vec3_new(10, 10, 10);
  c->target = vec3_zero();
  c->fov = 0.785398163;
  c->near_clip = 0.1;
  c->far_clip = 512.0;
  
  return c;
}
Example #13
0
File: gx.c Project: LWSS/gx
static void draw_ships(struct GameState *game_state, struct Renderer *renderer)
{
    bind_program(renderer->quad_program);
    begin_sprite_batch(&renderer->sprite_batch);

    for (uint32 i = 0; i < game_state->ship_count; ++i)
    {
        struct Ship *ship = &game_state->ships[i];
        draw_quad(&renderer->sprite_batch, ship->position, ship->size, vec3_new(0.5f, 0.5f, 0.5f));
    }

    end_sprite_batch(&renderer->sprite_batch);
    bind_program(0);
}
Example #14
0
File: gx.c Project: LWSS/gx
static void draw_projectiles(struct GameState *game_state, struct Renderer *renderer)
{
    bind_program(renderer->quad_program);
    begin_sprite_batch(&renderer->sprite_batch);

    for (uint32 i = 0; i < game_state->projectile_count; ++i)
    {
        struct Projectile *projectile = &game_state->projectiles[i];
        draw_quad(&renderer->sprite_batch, projectile->position, projectile->size, vec3_new(0.0f, 1.0f, 0.0f));
    }

    end_sprite_batch(&renderer->sprite_batch);
    bind_program(0);
}
Example #15
0
File: gx.c Project: LWSS/gx
static void draw_buildings(struct GameState *game_state, struct Renderer *renderer)
{
    bind_program(renderer->quad_program);
    begin_sprite_batch(&renderer->sprite_batch);

    for (uint32 i = 0; i < game_state->building_count; ++i)
    {
        struct Building *building = &game_state->buildings[i];
        draw_quad(&renderer->sprite_batch, building->position, building->size, vec3_new(0.3f, 0.3f, 0.3f));
    }

    end_sprite_batch(&renderer->sprite_batch);
    bind_program(0);
}
Example #16
0
void camera_control_orbit(camera* c, SDL_Event e) {
  
  float a1 = 0;
  float a2 = 0;
  vec3 axis;
  
  vec3 translation = c->target;
  c->position = vec3_sub(c->position, translation);
  c->target = vec3_sub(c->target, translation);
  
  switch(e.type) {
    
    case SDL_MOUSEMOTION:
      if (e.motion.state & SDL_BUTTON(1)) {
        a1 = e.motion.xrel * -0.005;
        a2 = e.motion.yrel * 0.005;
        c->position = mat3_mul_vec3(mat3_rotation_y( a1 ), c->position );
        axis = vec3_normalize(vec3_cross( vec3_sub(c->position, c->target) , vec3_new(0,1,0) ));
        c->position = mat3_mul_vec3(mat3_rotation_axis_angle(axis, a2 ), c->position );
      }
    break;
    
    case SDL_MOUSEBUTTONDOWN:
      if (e.button.button == SDL_BUTTON_WHEELUP) {
        c->position = vec3_sub(c->position, vec3_normalize(c->position));
      }
      if (e.button.button == SDL_BUTTON_WHEELDOWN) {
        c->position = vec3_add(c->position, vec3_normalize(c->position));
      }
    break;

  }
  
  c->position = vec3_add(c->position, translation);
  c->target = vec3_add(c->target, translation);

}
Example #17
0
vec3 vec3_gravity() {
  return vec3_new(0, -9.81, 0);
}
Example #18
0
void scotland_init() {
  
  graphics_viewport_set_dimensions(1280, 720);
  graphics_viewport_set_title("Scotland");
  
  ui_button* loading = ui_elem_new("loading", ui_button);
  ui_button_move(loading, vec2_new(graphics_viewport_width() / 2 - 40,graphics_viewport_height() / 2 - 13));
  ui_button_resize(loading, vec2_new(80,25));
  ui_button_set_label(loading, "Loading...");
  ui_button_disable(loading);
  
  ui_spinner* load_spinner = ui_elem_new("load_spinner", ui_spinner);
  load_spinner->color = vec4_white();
  load_spinner->top_left = vec2_new(graphics_viewport_width() / 2 + 50, graphics_viewport_height() / 2 - 13);
  load_spinner->bottom_right = vec2_add(load_spinner->top_left, vec2_new(24,24));
  
  ui_button* framerate = ui_elem_new("framerate", ui_button);
  ui_button_move(framerate, vec2_new(10,10));
  ui_button_resize(framerate, vec2_new(30,25));
  ui_button_set_label(framerate, "FRAMERATE");
  ui_button_disable(framerate);
  framerate->active = false;
  
  ui_button* wireframe = ui_elem_new("wireframe", ui_button);
  ui_button_move(wireframe, vec2_new(50,10));
  ui_button_resize(wireframe, vec2_new(80,25));
  ui_button_set_label(wireframe, "wireframe");
  wireframe->active = false;
  
  ui_elem_add_event("wireframe", toggle_wireframe);
  
  ui_button* freecam = ui_elem_new("freecam", ui_button);
  ui_button_move(freecam, vec2_new(140,10));
  ui_button_resize(freecam, vec2_new(65,25));
  ui_button_set_label(freecam, "freecam");
  freecam->active = false;
  
  ui_elem_add_event("freecam", toggle_freecam);
  
  loading_resources = true;
  SDL_Thread* load_thread = SDL_GL_CreateThread(load_resources, NULL);
  
  /* New Camera and light */
  
  camera* cam = entity_new("camera", camera);
  cam->position = vec3_new(512.0, 200.0, 512.0);
  cam->target =  vec3_new(0.0, 0.0, 0.0);
  
  light* sun = entity_new("sun", light);
  light_set_type(sun, light_type_sun);
  sun->position = vec3_new(0, 512, 0);
  sun->target = vec3_new(512, 0, 512);
  
  /* Renderer Setup */
  
  shadow_mapper_init(sun);
  
  forward_renderer_init();
  forward_renderer_set_camera(cam);
  forward_renderer_set_shadow_light(sun);
  forward_renderer_set_shadow_texture( shadow_mapper_depth_texture() );
  forward_renderer_add_light(sun);
  
}
Example #19
0
File: vector.c Project: Murii/CLove
void m4x4_scale(mat4x4 *inout,float angle, float r_x, float r_y, float r_z, float x, float y, float z) {
    m4x4_newRotationScale(inout, angle, vec3_new(r_x, r_y, r_z), x, y, z);
}
Example #20
0
int main(int argc, char **argv) {
  
  #ifdef _WIN32
    FILE* ctt = fopen("CON", "w" );
    FILE* fout = freopen( "CON", "w", stdout );
    FILE* ferr = freopen( "CON", "w", stderr );
  #endif
  
  corange_init("../../assets_core");
  
  graphics_viewport_set_title("Teapot");
  graphics_viewport_set_size(1280, 720);
  
  camera* cam = entity_new("camera", camera);
  cam->position = vec3_new(5, 5, 5);
  cam->target =  vec3_new(0, 0, 0);
  
  teapot_shader = asset_hndl_new_load(P("./assets/teapot.mat"));
  teapot_object = asset_hndl_new_load(P("./assets/teapot.obj"));
  
  int running = 1;
  SDL_Event e = {0};
  
  while(running) {
    
    frame_begin();
    
    camera* cam = entity_get("camera");
    
    while(SDL_PollEvent(&e)) {
      switch(e.type){
      case SDL_KEYDOWN:
      case SDL_KEYUP:
        if (e.key.keysym.sym == SDLK_ESCAPE) { running = 0; }
        if (e.key.keysym.sym == SDLK_PRINTSCREEN) { graphics_viewport_screenshot(); }
        if (e.key.keysym.sym == SDLK_r &&
            e.key.keysym.mod == KMOD_LCTRL) {
            asset_reload_all();
        }
        break;
      case SDL_QUIT:
        running = 0;
        break;
      }
      camera_control_orbit(cam, e);
      ui_event(e);
    }
    
    ui_update();
    
    glClearColor(0.25, 0.25, 0.25, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    
    shader_program* shader = material_first_program(asset_hndl_ptr(&teapot_shader));
    shader_program_enable(shader);
    shader_program_set_mat4(shader, "world", mat4_id());
    shader_program_set_mat4(shader, "view", camera_view_matrix(cam));
    shader_program_set_mat4(shader, "proj", camera_proj_matrix(cam));
      
    shader_program_set_texture(shader, "cube_beach", 0, asset_hndl_new_load(P("$CORANGE/water/cube_sea.dds")));
    shader_program_set_vec3(shader, "camera_direction", camera_direction(cam));
    
    renderable* r = asset_hndl_ptr(&teapot_object);
    
    for(int i=0; i < r->num_surfaces; i++) {
      
      renderable_surface* s = r->surfaces[i];
      
      int mentry_id = min(i, ((material*)asset_hndl_ptr(&r->material))->num_entries-1);
      material_entry* me = material_get_entry(asset_hndl_ptr(&r->material), mentry_id);
      
      glBindBuffer(GL_ARRAY_BUFFER, s->vertex_vbo);
      
      shader_program_enable_attribute(shader, "vPosition",  3, 18, (void*)0);
      shader_program_enable_attribute(shader, "vNormal",    3, 18, (void*)(sizeof(float) * 3));
      //shader_program_enable_attribute(shader, "vTangent",   3, 18, (void*)(sizeof(float) * 6));
      //shader_program_enable_attribute(shader, "vBinormal",  3, 18, (void*)(sizeof(float) * 9));
      //shader_program_enable_attribute(shader, "vTexcoord",  2, 18, (void*)(sizeof(float) * 12));
      
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->triangle_vbo);
        glDrawElements(GL_TRIANGLES, s->num_triangles * 3, GL_UNSIGNED_INT, (void*)0);
      
      shader_program_disable_attribute(shader, "vPosition");
      shader_program_disable_attribute(shader, "vNormal");
      //shader_program_disable_attribute(shader, "vTangent");
      //shader_program_disable_attribute(shader, "vBinormal");
      //shader_program_disable_attribute(shader, "vTexcoord");
      
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);

    }
  
    shader_program_disable(shader);
    
    glDisable(GL_DEPTH_TEST);
    ui_render();
    
    graphics_swap();
    
    frame_end();
  }
  
  corange_finish();
  
  return 0;
  
}
Example #21
0
File: vector.c Project: Murii/CLove
void m4x4_rotateX(mat4x4 *inout, float a, float s_x, float s_y, float s_z) {
    m4x4_newRotationScale(inout, a, vec3_new(0,1,0), s_x, s_y, s_z);
}
Example #22
0
void sea_init() {
  
  graphics_viewport_set_dimensions(1280, 720);
  graphics_viewport_set_title("Sea");

  camera* cam = entity_new("camera", camera);
  cam->position = vec3_new(50.0, 50.0, 50.0);
  cam->target = vec3_new(0, 5, 0);
  cam->near_clip = 0.1;
  
  light* sun = entity_new("sun", light);
  light_set_type(sun, light_type_spot);
  sun->position = vec3_new(20,23,16);
  sun->ambient_color = vec3_new(0.5, 0.5, 0.5);
  sun->diffuse_color = vec3_new(1.0,  0.894, 0.811);
  sun->specular_color = vec3_mul(vec3_new(1.0,  0.894, 0.811), 4);
  sun->power = 5;
  
  light* backlight = entity_new("backlight", light);
  light_set_type(backlight, light_type_point);
  backlight->position = vec3_new(-22,10,-13);
  backlight->ambient_color = vec3_new(0.2, 0.2, 0.2);
  backlight->diffuse_color = vec3_new(0.729, 0.729, 1.0);
  backlight->specular_color = vec3_mul(vec3_new(0.729, 0.729, 1.0), 1);
  backlight->power = 2;
  
  shadow_mapper_init(sun);  
  
  forward_renderer_init();
  forward_renderer_set_camera(cam);
  forward_renderer_set_shadow_light(sun);
  forward_renderer_set_shadow_texture( shadow_mapper_depth_texture() );
  forward_renderer_add_light(sun);
  forward_renderer_add_light(backlight);
  
  folder_load(P("./resources/"));
  
  renderable* r_seaplane = asset_get(P("./resources/seaplane.obj"));
  r_seaplane->material = asset_hndl_new(P("./resources/seaplane.mat"));
  
  static_object* s_seaplane = entity_new("seaplane", static_object);
  s_seaplane->renderable = asset_hndl_new_ptr(r_seaplane);
  s_seaplane->scale = vec3_new(3,1,3);
  
  renderable* r_skydome = asset_get(P("./resources/skydome.obj"));
  r_skydome->material = asset_hndl_new_load(P("$CORANGE/shaders/skydome.mat"));
  
  static_object* skydome = entity_new("skydome", static_object);
  skydome->renderable = asset_hndl_new_ptr(r_skydome);
  skydome->position = vec3_new(0, -512, 0);
  skydome->scale = vec3_new(1024, 1024, 1024);
  
  folder_load(P("./resources/corvette/"));
  
  renderable* r_corvette = asset_get(P("./resources/corvette/corvette.obj"));
  r_corvette->material = asset_hndl_new_load(P("./resources/corvette/corvette.mat"));
  
  static_object* s_corvette = entity_new("corvette", static_object);
  s_corvette->renderable = asset_hndl_new_ptr(r_corvette);
  //s_corvette->collision_body = collision_body_new_mesh(asset_get("./resources/corvette/corvette.col"));
  s_corvette->scale = vec3_new(1.5, 1.5, 1.5);
  s_corvette->position = vec3_new(0, 0.5, 0);
  
  static_object* center_sphere = entity_new("center_sphere", static_object);
  center_sphere->position = vec3_new(0, 5, 0);
  //center_sphere->renderable = asset_get("./resources/ball.obj");
  //center_sphere->collision_body = collision_body_new_sphere(sphere_new(v3_zero(), 1.0f));
  
  ui_button* framerate = ui_elem_new("framerate", ui_button);
  ui_button_move(framerate, vec2_new(10,10));
  ui_button_resize(framerate, vec2_new(30,25));
  ui_button_set_label(framerate, "FRAMERATE");
  ui_button_disable(framerate);
  
}
Example #23
0
static void terrain_new_chunk(terrain* ter, int i) {

  const int SUBDIVISIONS = NUM_TERRAIN_SUBDIVISIONS+1; 

  terrain_chunk* tc = malloc(sizeof(terrain_chunk));
  tc->id = i;
  tc->x = i % ter->num_cols;
  tc->y = i / ter->num_cols;
  tc->width = ter->chunk_width;
  tc->height = ter->chunk_height;
  
  int x_max = tc->width * SUBDIVISIONS + 1;
  int y_max = tc->height * SUBDIVISIONS + 1;
  
  tc->num_verts = x_max * y_max + x_max * 2 + y_max * 2;
  vec3* vertex_buffer = malloc(sizeof(vec3) * 4 * tc->num_verts);
  int index = 0;
  
  for(int x = 0; x < x_max; x++)
  for(int y = 0; y < y_max; y++) {
    float gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS;
    float gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS;
    
    float height = terrain_height(ter, vec2_new(gx, gy));
    mat3  axis   = terrain_tbn(ter, vec2_new(gx, gy));
    
    vec3 pos = vec3_new(gx, height, gy);
    vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0));
    vec3 normal  = mat3_mul_vec3(axis, vec3_new(0,1,0));
    vec3 binorm  = mat3_mul_vec3(axis, vec3_new(0,0,1));
    
    vertex_buffer[index] = pos; index++;
    vertex_buffer[index] = normal; index++;
    vertex_buffer[index] = tangent; index++;
    vertex_buffer[index] = binorm; index++;
    
  }
  
  /* Adding fins. Don't look, horrible code */
  
  const float FIN_DEPTH = 5.0;
  
  for(int y = 0; y < y_max; y++) {
    int gx = tc->x * ter->chunk_width + 0;
    int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS;
    
    float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH;
    mat3  axis   = terrain_tbn(ter, vec2_new(gx, gy));
    
    vec3 pos = vec3_new(gx, height, gy);
    vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0));
    vec3 normal  = mat3_mul_vec3(axis, vec3_new(0,1,0));
    vec3 binorm  = mat3_mul_vec3(axis, vec3_new(0,0,1));
    
    vertex_buffer[index] = pos; index++;
    vertex_buffer[index] = normal; index++;
    vertex_buffer[index] = tangent; index++;
    vertex_buffer[index] = binorm; index++;
  }
  
  for(int y = 0; y < y_max; y++) {
    int gx = tc->x * ter->chunk_width + ter->chunk_width;
    int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS;
    
    float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH;
    mat3  axis   = terrain_tbn(ter, vec2_new(gx, gy));
    
    vec3 pos = vec3_new(gx, height, gy);
    vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0));
    vec3 normal  = mat3_mul_vec3(axis, vec3_new(0,1,0));
    vec3 binorm  = mat3_mul_vec3(axis, vec3_new(0,0,1));
    
    vertex_buffer[index] = pos; index++;
    vertex_buffer[index] = normal; index++;
    vertex_buffer[index] = tangent; index++;
    vertex_buffer[index] = binorm; index++;
  }
  
  for(int x = 0; x < x_max; x++) {
    int  gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS;
    int  gy = tc->y * ter->chunk_height + 0;
    
    float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH;
    mat3  axis   = terrain_tbn(ter, vec2_new(gx, gy));
    
    vec3 pos = vec3_new(gx, height, gy);
    vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0));
    vec3 normal  = mat3_mul_vec3(axis, vec3_new(0,1,0));
    vec3 binorm  = mat3_mul_vec3(axis, vec3_new(0,0,1));
    
    vertex_buffer[index] = pos; index++;
    vertex_buffer[index] = normal; index++;
    vertex_buffer[index] = tangent; index++;
    vertex_buffer[index] = binorm; index++;
  }
  
  for(int x = 0; x < x_max; x++) {
    int  gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS;
    int  gy = tc->y * ter->chunk_height + ter->chunk_height;
    
    float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH;
    mat3  axis   = terrain_tbn(ter, vec2_new(gx, gy));
    
    vec3 pos = vec3_new(gx, height, gy);
    vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0));
    vec3 normal  = mat3_mul_vec3(axis, vec3_new(0,1,0));
    vec3 binorm  = mat3_mul_vec3(axis, vec3_new(0,0,1));
    
    vertex_buffer[index] = pos; index++;
    vertex_buffer[index] = normal; index++;
    vertex_buffer[index] = tangent; index++;
    vertex_buffer[index] = binorm; index++;
  }
  
  tc->bound.center = vec3_zero();
  for (int i = 0; i < index; i+=4) {
    tc->bound.center = vec3_add(tc->bound.center, vertex_buffer[i]);
  }
  tc->bound.center = vec3_div(tc->bound.center, tc->num_verts);
  
  tc->bound.radius = 0;
  for (int i = 0; i < index; i+=4) {
    tc->bound.radius = max(tc->bound.radius, vec3_dist(tc->bound.center, vertex_buffer[i]));
  }
  
  if (net_is_client()) {
    glGenBuffers(1, &tc->vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, tc->vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * 4 * tc->num_verts, vertex_buffer, GL_STATIC_DRAW);
  }
  
  free(vertex_buffer);
  
  if (net_is_client()) {
    glGenBuffers(NUM_TERRAIN_BUFFERS, tc->index_buffers);
  }
  
  for(int j = 0; j < NUM_TERRAIN_BUFFERS; j++) {
  
    int off = pow(2, j);
    int x_max = tc->width * SUBDIVISIONS;
    int y_max = tc->height * SUBDIVISIONS;
    
    tc->num_indicies[j] = (x_max / off) * (y_max / off) * 6 + (x_max / off) * 12 + (y_max / off) * 12;
    
    uint32_t* index_buffer = malloc(sizeof(uint32_t) * tc->num_indicies[j]);
    index = 0;
    
    for(int x = 0; x < x_max; x+=off)
    for(int y = 0; y < y_max; y+=off) {
      index_buffer[index] =  x +  y * (x_max+1); index++;
      index_buffer[index] = (x+off) +  y * (x_max+1); index++;
      index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++;
      index_buffer[index] =  x +  y * (x_max+1); index++;
      index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++;
      index_buffer[index] =  x + (y+off) * (x_max+1); index++;
    }
    
    /* Again, adding fins. Don't look horrible code */
    
    int x_base = (x_max + 1) * (y_max + 1);
    int y_base = (x_max + 1) * (y_max + 1) + (x_max + 1) * 2;
    
    for(int x = 0; x < x_max; x+=off) {
      index_buffer[index] = x + 0 * (x_max+1); index++;
      index_buffer[index] =  x_base + x; index++;
      index_buffer[index] = (x+off) + 0 * (x_max+1); index++;
      
      index_buffer[index] = (x+off) + 0 * (x_max+1); index++;
      index_buffer[index] = x_base + x; index++;
      index_buffer[index] = x_base + x+off; index++;
    }
    
    for(int x = 0; x < x_max; x+=off) {
      index_buffer[index] = x + y_max * (x_max+1); index++;
      index_buffer[index] = (x+off) + y_max * (x_max+1); index++;
      index_buffer[index] =  x_base + y_max+1 + x; index++;
      
      index_buffer[index] = (x+off) + y_max * (x_max+1); index++;
      index_buffer[index] = x_base + x_max+1 + x+off; index++;
      index_buffer[index] = x_base + x_max+1 + x; index++;
    }
    
    for(int y = 0; y < y_max; y+=off) {
      index_buffer[index] = 0 + y * (x_max+1); index++;
      index_buffer[index] = 0 + (y+off) * (x_max+1); index++;
      index_buffer[index] = y_base + y; index++;
      
      index_buffer[index] = 0 + (y+off) * (x_max+1); index++;
      index_buffer[index] = y_base + y+off; index++;
      index_buffer[index] = y_base + y; index++;
    }
    
    for(int y = 0; y < y_max; y+=off) {
      index_buffer[index] = x_max + y * (x_max+1); index++;
      index_buffer[index] = y_base + y_max+1 + y; index++;
      index_buffer[index] = x_max + (y+off) * (x_max+1); index++;
      
      index_buffer[index] = x_max + (y+off) * (x_max+1); index++;
      index_buffer[index] = y_base + y_max+1 + y; index++;
      index_buffer[index] = y_base + y_max+1 + y+off; index++;
    }
    
    if (net_is_client()) {
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tc->index_buffers[j]);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * tc->num_indicies[j], index_buffer, GL_DYNAMIC_DRAW);
    }
    
    free(index_buffer);
  }
  
  tc->colmesh = malloc(sizeof(cmesh));
  tc->colmesh->is_leaf = true;
  tc->colmesh->triangles_num = (tc->width/4) * (tc->height/4) * 2;
  tc->colmesh->triangles = malloc(sizeof(ctri) * tc->colmesh->triangles_num);
  
  int tri_i = 0;
  
  for (int x = 0; x < tc->width;  x += 4)
  for (int y = 0; y < tc->height; y += 4) {
    
    float gx = tc->x * ter->chunk_width  + (float)x;
    float gy = tc->y * ter->chunk_height + (float)y;    
    
    vec3 a = vec3_new(gx  , terrain_height(ter, vec2_new(gx  , gy  )) , gy  );
    vec3 b = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy  )) , gy  );
    vec3 c = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy+4)) , gy+4);
    vec3 d = vec3_new(gx  , terrain_height(ter, vec2_new(gx  , gy+4)) , gy+4);
    
    vec3 tang   = vec3_normalize(vec3_sub(b, a));
    vec3 binorm = vec3_normalize(vec3_sub(d, a));
    vec3 norm   = vec3_cross( binorm, tang );
    
    tc->colmesh->triangles[tri_i] = ctri_new(a, c, b, norm); tri_i++;
    tc->colmesh->triangles[tri_i] = ctri_new(a, d, c, norm); tri_i++;
  
  }
  
  tc->colmesh->bound = cmesh_bound(tc->colmesh);
  
  /* For some reason this is not working correctly */
  cmesh_subdivide(tc->colmesh, 5);

  ter->chunks[i] = tc;

}
Example #24
0
static int vec3_mt_sub(lua_State *L)
{
	vec3_t *a = (vec3_t *)luaL_checkudata(L, 1, "vec3");
	vec3_t *b = (vec3_t *)luaL_checkudata(L, 2, "vec3");
	return vec3_new(L, a->x - b->x, a->y - b->y, a->z - b->z);
}
Example #25
0
static int vec3_mt_unm(lua_State *L)
{
	vec3_t *v = (vec3_t *)luaL_checkudata(L, 1, "vec3");
	return vec3_new(L, -v->x, -v->y, -v->z);
}
Example #26
0
static int vec3_index_unit(lua_State *L)
{
	vec3_t *v = (vec3_t *)luaL_checkudata(L, 1, "vec3");
	lua_Number l = sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
	return vec3_new(L, v->x / l, v->y / l, v->z / l);
}
Example #27
0
mat4 camera_view_matrix(camera* c) {
  return mat4_view_look_at(c->position, c->target, vec3_new(0.0f,1.0f,0.0f) );
}
Example #28
0
material* mat_load_file(char* filename) {
  
  SDL_RWops* file = SDL_RWFromFile(filename, "r");
  if(file == NULL) {
    error("Cannot load file %s", filename);
  }
  
  material* m = material_new();
  material_entry* me = material_add_entry(m);
  
  char line[1024];
  while(SDL_RWreadline(file, line, 1024)) {
    
    if (line[0] == '#') { continue; }
    if (line[0] == '\r') { continue; }
    if (line[0] == '\n') { continue; }
    
    if (strstr(line, "submaterial")) {
      
      /* Skip Empty Submaterials */
      if (me->num_items == 0) {
        continue;
      } else {
        me = material_add_entry(m);
        continue;
      }
      
    }
    
    char type[512]; char name[512]; char value[512];
    int matches = sscanf(line, "%511s %511s = %511s", type, name, value);
    
    if (matches != 3) continue;
    
    material_item mi;
    int type_id;
    char* end;
    float f0, f1, f2, f3;
    
    if (strcmp(type, "shader") == 0) {
    
      mi.as_asset = asset_hndl_new_load(P(value));
      type_id = mat_item_shader;
      
    } else if (strcmp(type, "texture") == 0) {
    
      mi.as_asset = asset_hndl_new_load(P(value));
      type_id = mat_item_texture;
    
    } else if (strcmp(type, "int") == 0) {
    
      mi.as_int = atoi(value);
      type_id = mat_item_int;
    
    } else if (strcmp(type, "float") == 0) {
      
      mi.as_float = atof(value);
      type_id = mat_item_float;
      
    } else if (strcmp(type, "vec2") == 0) {
    
      f0 = strtod(value, &end); f1 = strtod(end, NULL);
      mi.as_vec2 = vec2_new(f0, f1);
      type_id = mat_item_vec2;
      
    } else if (strcmp(type, "vec3") == 0) {
      
      f0 = strtod(value, &end); f1 = strtod(end, &end);
      f2 = strtod(end, NULL);
      mi.as_vec3 = vec3_new(f0, f1, f2);
      type_id = mat_item_vec3;
      
    } else if (strcmp(type, "vec4") == 0) {
    
      f0 = strtod(value, &end); f1 = strtod(end, &end);
      f2 = strtod(end, &end); f3 = strtod(end, NULL);
      mi.as_vec4 = vec4_new(f0, f1, f2, f3);
      type_id = mat_item_vec4;
      
    } else {
      error("Unknown material item type '%s'", type);
      return NULL;
    }
    
    material_entry_add_item(me, name, type_id, mi);
    
  }
  
  SDL_RWclose(file);
  
  material_generate_programs(m);
  
  SDL_GL_CheckError();
  
  return m;
}
Example #29
0
animation* ani_load_file(char* filename) {
  
  int state = STATE_LOAD_EMPTY;
  
  animation* a =  animation_new();
  skeleton* base = skeleton_new();
  frame* f = NULL;
  
  SDL_RWops* file = SDL_RWFromFile(filename, "r");
  
  if(file == NULL) {
    error("Could not load file %s", filename);
  }
  
  char line[1024];
  while(SDL_RWreadline(file, line, 1024)) {
    
    if (state == STATE_LOAD_EMPTY) {
      
      int version;
      if (sscanf(line, "version %i", &version) > 0) {
        if (version != 1) {
          error("Can't load ani file '%s'. Don't know how to load version %i\n", filename, version);
        }
      }
      
      if (strstr(line, "nodes")) {
        state = STATE_LOAD_NODES;
      }
      
      if (strstr(line, "skeleton")) {
        state = STATE_LOAD_SKELETON;
      }
    }
    
    else if (state == STATE_LOAD_NODES) {
      char name[1024];
      int id, parent;
      if (sscanf(line, "%i \"%[^\"]\" %i", &id, name, &parent) == 3) {
        skeleton_joint_add(base, name, parent);
      }
      
      if (strstr(line, "end")) {
        state = STATE_LOAD_EMPTY;
      }
    }
    
    else if (state == STATE_LOAD_SKELETON) {
    
      float time;
      if (sscanf(line, "time %f", &time) == 1) {
        f = animation_add_frame(a, base->rest_pose);
      }
    
      int id;
      float x, y, z, rx, ry, rz;
      if (sscanf(line, "%i %f %f %f %f %f %f", &id, &x, &y, &z, &rx, &ry, &rz) > 0) {
        
        f->joint_positions[id] = vec3_new(x, z, y);
        
        mat4 rotation = mat4_rotation_euler(rx, ry, rz);
        mat4 handedflip = mat4_new(1,0,0,0,
                                   0,0,1,0,
                                   0,1,0,0,
                                   0,0,0,1);
      
        rotation = mat4_mul_mat4(handedflip, rotation);
        rotation = mat4_mul_mat4(rotation, handedflip);
        rotation = mat4_transpose(rotation);
        
        f->joint_rotations[id] = mat4_to_quat(rotation);
        
      }
      
      if (strstr(line, "end")) {
        state = STATE_LOAD_EMPTY;
      }
      
    }
  }
  
  SDL_RWclose(file);
  
  skeleton_delete(base);
  
  return a;
}
Example #30
0
File: gx.c Project: LWSS/gx
void tick_game(struct GameMemory *memory, struct Input *input, uint32 screen_width, uint32 screen_height, float dt)
{
    struct GameState *game_state = (struct GameState *)memory->game_memory;
    struct RenderBuffer *render_buffer = (struct RenderBuffer *)memory->render_memory;

    clear_render_buffer(render_buffer);

    for (uint32 i = 0; i < game_state->visibility_graph.vertex_count; ++i)
    {
        vec2 vertex = game_state->visibility_graph.vertices[i];
        draw_world_quad_buffered(render_buffer, vertex, vec2_scalar(0.1f), vec4_zero(), vec3_new(0, 1, 1));
    }

    for (uint32 i = 0; i < game_state->visibility_graph.edge_count; ++i)
    {
        uint32 *edge = &game_state->visibility_graph.edges[i][0];

        vec2 p0 = game_state->visibility_graph.vertices[edge[0]];
        vec2 p1 = game_state->visibility_graph.vertices[edge[1]];

        draw_world_line_buffered(render_buffer, p0, p1, vec3_new(1, 1, 0));
    }

    if (mouse_down(MOUSE_LEFT, input))
    {
        struct AABB box = calc_mouse_selection_box(input, MOUSE_LEFT);

        vec2 size = vec2_sub(box.max, box.min);
        vec2 bottom_left  = vec2_new(box.min.x, box.max.y);
        vec2 bottom_right = vec2_new(box.max.x, box.max.y);
        vec2 top_left     = vec2_new(box.min.x, box.min.y);
        vec2 top_right    = vec2_new(box.max.x, box.min.y);

        const uint32 outline_thickness = 1;

        draw_screen_quad_buffered(render_buffer, top_left, vec2_new(size.x, outline_thickness), vec4_zero(), vec3_new(1, 1, 0));
        draw_screen_quad_buffered(render_buffer, bottom_left, vec2_new(size.x, outline_thickness), vec4_zero(), vec3_new(1, 1, 0));
        draw_screen_quad_buffered(render_buffer, top_left, vec2_new(outline_thickness, size.y), vec4_zero(), vec3_new(1, 1, 0));
        draw_screen_quad_buffered(render_buffer, top_right, vec2_new(outline_thickness, size.y), vec4_zero(), vec3_new(1, 1, 0));
    }

    if (mouse_released(MOUSE_LEFT, input))
    {
        // Clear previous selection.
        game_state->selected_ship_count = 0;

        struct AABB screen_selection_box = calc_mouse_selection_box(input, MOUSE_LEFT);

        // Because screen space y-values are inverted, these two results have conflicting
        // y-values, i.e. screen_to_world_min.y is actually the maximum y. These values
        // are then properly min/maxed and stored correctly in world_selection_box.
        vec2 screen_to_world_min = screen_to_world_coords(screen_selection_box.min, &game_state->camera, screen_width, screen_height);
        vec2 screen_to_world_max = screen_to_world_coords(screen_selection_box.max, &game_state->camera, screen_width, screen_height);

        struct AABB world_selection_box;
        world_selection_box.min = min_vec2(screen_to_world_min, screen_to_world_max);
        world_selection_box.max = max_vec2(screen_to_world_min, screen_to_world_max);

        // Add colliding ships to the selection list.
        // TODO: optimize, spatial grid hash?
        for (uint32 i = 0; i < game_state->ship_count; ++i)
        {
            struct Ship *ship = &game_state->ships[i];
            struct AABB ship_aabb = aabb_from_transform(ship->position, ship->size);

            vec2 center = vec2_div(vec2_add(ship_aabb.min, ship_aabb.max), 2.0f);

            if (aabb_aabb_intersection(world_selection_box, ship_aabb))
                game_state->selected_ships[game_state->selected_ship_count++] = ship->id;
        }

        if (game_state->selected_ship_count > 0)
            fprintf(stderr, "selected %u ships\n", game_state->selected_ship_count);
    }

    if (mouse_down(MOUSE_RIGHT, input))
    {
        vec2 target_position = screen_to_world_coords(input->mouse_position, &game_state->camera, screen_width, screen_height);

        for (uint32 i = 0; i < game_state->selected_ship_count; ++i)
        {
            uint32 id = game_state->selected_ships[i];
            struct Ship *ship = get_ship_by_id(game_state, id);

            ship->target_position = target_position;
            ship->move_order = true;
        }
    }

    // Outline selected ships.
    for (uint32 i = 0; i < game_state->selected_ship_count; ++i)
    {
        uint32 id = game_state->selected_ships[i];
        struct Ship *ship = get_ship_by_id(game_state, id);

        draw_world_quad_buffered(render_buffer, ship->position, vec2_mul(ship->size, 1.1f), vec4_zero(), vec3_new(0, 1, 0));

        if (ship->move_order)
            draw_world_quad_buffered(render_buffer, ship->target_position, vec2_new(0.5f, 0.5f), vec4_zero(), vec3_new(0, 1, 0));
    }

    // Handle move orders.
    for (uint32 i = 0; i < game_state->ship_count; ++i)
    {
        struct Ship *ship = &game_state->ships[i];
        if (ship->move_order)
        {
            vec2 direction = vec2_zero();
            /*
            if (vec2_length2(direction) < FLOAT_EPSILON)
                direction = vec2_normalize(vec2_sub(ship->target_position, ship->position));
                */
            ship->move_velocity = vec2_mul(direction, 2.0f);

            /*
            vec2 direction = vec2_normalize(vec2_sub(ship->target_position, ship->position));
            ship->move_velocity = vec2_mul(direction, 2.0f);
            */

            if (vec2_distance2(ship->position, ship->target_position) < 0.1f)
            {
                ship->move_velocity = vec2_zero();
                ship->move_order = false;
            }
        }
    }

    tick_camera(input, &game_state->camera, dt);

    tick_combat(game_state, dt);
    tick_physics(game_state, dt);
}