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); }
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); }
vec3 terrain_normal(terrain* ter, vec2 position) { mat3 axis = terrain_axis(ter, position); return mat3_mul_vec3(axis, vec3_new(0, 1, 0)); }
static void quaternion_unit_inv_mul_vec3(const struct quaternion *q, const float *v1, float *v2) { struct mat3 temp; struct quaternion q_inv; quaternion_unit_inv(q, &q_inv); quaternion_to_mat3(&q_inv, &temp); mat3_mul_vec3(&temp, v1, v2); }
collision ellipsoid_collide_mesh(ellipsoid e, vec3 v, cmesh* m, mat4 world, mat3 world_normal) { world.xw -= e.center.x; world.yw -= e.center.y; world.zw -= e.center.z; mat3 space = mat3_scale(vec3_div_vec3(vec3_one(), e.radiuses)); mat3 space_inv = mat3_scale(e.radiuses); v = mat3_mul_vec3(space, v); collision c = sphere_collide_mesh_space(sphere_unit(), v, m, world, world_normal, space, mat3_transpose(space_inv)); c.point = mat3_mul_vec3(space_inv, c.point); c.point = vec3_add(c.point, e.center); c.norm = vec3_normalize(mat3_mul_vec3(space, c.norm)); return c; }
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); }
static void quaternion_mul_vec3(const struct quaternion *q, const float *v1, float *v2) { struct mat3 temp; quaternion_to_mat3(q, &temp); mat3_mul_vec3(&temp, v1, v2); }
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; }