diff --git a/src/game/editor.c b/src/game/editor.c index 84624df..aa49ff4 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -55,11 +55,13 @@ enum Editor_Mode enum Editor_Axis { - EDITOR_AXIS_XZ = 0, + EDITOR_AXIS_NONE = 0, EDITOR_AXIS_X, EDITOR_AXIS_Y, EDITOR_AXIS_Z, - EDITOR_AXIS_NONE + EDITOR_AXIS_XZ, + EDITOR_AXIS_XY, + EDITOR_AXIS_YZ, }; static struct Debug_Variable* debug_vars_list = NULL; @@ -98,6 +100,7 @@ static void editor_window_settings_editor(struct nk_context* context, struct Edi static void editor_axis_set(struct Editor* editor, int axis); static void editor_entity_select(struct Editor* editor, struct Entity* entity); static void editor_mode_set(struct Editor* editor, int mode); +static void editor_tool_reset(struct Editor* editor); void editor_init(struct Editor* editor) { @@ -125,7 +128,8 @@ void editor_init(struct Editor* editor) editor->tool_rotate_increment = 5.f; editor->tool_rotate_arc_radius = 5.f; editor->tool_rotate_arc_segments = 50.f; - editor->tool_rotate_axis_selection_enabled = true; + editor->tool_rotate_rotation_started = false; + editor->tool_rotate_allowed = false; editor->axis_line_length = 500.f; editor->picking_enabled = true; @@ -359,15 +363,18 @@ void editor_update(struct Editor* editor, float dt) } nk_layout_row_push(context, 0.1f); - static const char* editor_axes[] = { "Axis: XZ", "Axis: X", "Axis: Y", "Axis: Z", "Axis: None" }; + static const char* editor_axes[] = { "Axis: None", "Axis: X", "Axis: Y", "Axis: Z", "Axis: XZ", "Axis: XY", "Axis: YZ" }; if(nk_combo_begin_label(context, editor_axes[editor->current_axis], nk_vec2(160, 125))) { nk_layout_row_dynamic(context, row_height, 1); int axis = editor->current_axis; - axis = nk_option_label(context, "X", axis == EDITOR_AXIS_X) ? EDITOR_AXIS_X : axis; - axis = nk_option_label(context, "Y", axis == EDITOR_AXIS_Y) ? EDITOR_AXIS_Y : axis; - axis = nk_option_label(context, "Z", axis == EDITOR_AXIS_Z) ? EDITOR_AXIS_Z : axis; - axis = nk_option_label(context, "XZ", axis == EDITOR_AXIS_XZ) ? EDITOR_AXIS_XZ : axis; + axis = nk_option_label(context, "X", axis == EDITOR_AXIS_X) ? EDITOR_AXIS_X : axis; + axis = nk_option_label(context, "Y", axis == EDITOR_AXIS_Y) ? EDITOR_AXIS_Y : axis; + axis = nk_option_label(context, "Z", axis == EDITOR_AXIS_Z) ? EDITOR_AXIS_Z : axis; + axis = nk_option_label(context, "XZ", axis == EDITOR_AXIS_XZ) ? EDITOR_AXIS_XZ : axis; + axis = nk_option_label(context, "XY", axis == EDITOR_AXIS_XY) ? EDITOR_AXIS_XY : axis; + axis = nk_option_label(context, "YZ", axis == EDITOR_AXIS_YZ) ? EDITOR_AXIS_YZ : axis; + axis = nk_option_label(context, "None", axis == EDITOR_AXIS_NONE) ? EDITOR_AXIS_NONE : axis; editor_axis_set(editor, axis); nk_combo_end(context); } @@ -461,10 +468,6 @@ void editor_update(struct Editor* editor, float dt) //Draw Axes switch(editor->current_axis) { - case EDITOR_AXIS_XZ: - im_line((vec3) { -editor->axis_line_length, 0.f, 0.f }, (vec3) { editor->axis_line_length, 0.f, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_x, 3); - im_line((vec3) { 0.f, 0.f, -editor->axis_line_length }, (vec3) { 0.f, 0.f, editor->axis_line_length }, editor->tool_mesh_position, rotation, scale, editor->axis_color_z, 3); - break; case EDITOR_AXIS_Y: im_line((vec3) { 0.f, -editor->axis_line_length, 0.f }, (vec3) { 0.f, editor->axis_line_length, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_y, 3); break; @@ -474,6 +477,18 @@ void editor_update(struct Editor* editor, float dt) case EDITOR_AXIS_Z: im_line((vec3) { 0.f, 0.f, -editor->axis_line_length }, (vec3) { 0.f, 0.f, editor->axis_line_length }, editor->tool_mesh_position, rotation, scale, editor->axis_color_z, 3); break; + case EDITOR_AXIS_XZ: + im_line((vec3) { -editor->axis_line_length, 0.f, 0.f }, (vec3) { editor->axis_line_length, 0.f, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_x, 3); + im_line((vec3) { 0.f, 0.f, -editor->axis_line_length }, (vec3) { 0.f, 0.f, editor->axis_line_length }, editor->tool_mesh_position, rotation, scale, editor->axis_color_z, 3); + break; + case EDITOR_AXIS_XY: + im_line((vec3) { -editor->axis_line_length, 0.f, 0.f }, (vec3) { editor->axis_line_length, 0.f, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_x, 3); + im_line((vec3) { 0.f, -editor->axis_line_length, 0.f }, (vec3) { 0.f, editor->axis_line_length, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_y, 3); + break; + case EDITOR_AXIS_YZ: + im_line((vec3) { 0.f, -editor->axis_line_length, 0.f }, (vec3) { 0.f, editor->axis_line_length, 0.f }, editor->tool_mesh_position, rotation, scale, editor->axis_color_y, 3); + im_line((vec3) { 0.f, 0.f, -editor->axis_line_length }, (vec3) { 0.f, 0.f, editor->axis_line_length }, editor->tool_mesh_position, rotation, scale, editor->axis_color_z, 3); + break; } } break; @@ -481,17 +496,46 @@ void editor_update(struct Editor* editor, float dt) { quat rotation = { 0.f, 0.f, 0.f, 1.f }; vec3 scale = { 1.f, 1.f, 1.f }; - im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); - //im_arc(editor->tool_rotate_arc_radius, 0.f, 90.f, editor->tool_rotate_arc_segments, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); - - quat_axis_angle(&rotation, &UNIT_X, -90.f); - im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); - //im_arc(editor->tool_rotate_arc_radius, 90.f, 180.f, editor->tool_rotate_arc_segments, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); - - quat_identity(&rotation); - quat_axis_angle(&rotation, &UNIT_Y, -90.f); - im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); - //im_arc(editor->tool_rotate_arc_radius, 0.f, 90.f, editor->tool_rotate_arc_segments, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); + switch(editor->current_axis) + { + case EDITOR_AXIS_X: + quat_axis_angle(&rotation, &UNIT_Y, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); + break; + case EDITOR_AXIS_Y: + quat_axis_angle(&rotation, &UNIT_X, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); + break; + case EDITOR_AXIS_Z: + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); + break; + case EDITOR_AXIS_XZ: + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); + quat_axis_angle(&rotation, &UNIT_Y, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); + break; + case EDITOR_AXIS_XY: + quat_axis_angle(&rotation, &UNIT_Y, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); + quat_identity(&rotation); + quat_axis_angle(&rotation, &UNIT_X, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); + break; + case EDITOR_AXIS_YZ: + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); + quat_axis_angle(&rotation, &UNIT_X, -90.f); + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); + break; + } + + //im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_z, 3); + // + //quat_axis_angle(&rotation, &UNIT_X, -90.f); + //im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_y, 3); + + //quat_identity(&rotation); + //quat_axis_angle(&rotation, &UNIT_Y, -90.f); + //im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, false, editor->tool_mesh_position, rotation, editor->axis_color_x, 3); if(editor->current_axis != EDITOR_AXIS_NONE) { @@ -504,15 +548,17 @@ void editor_update(struct Editor* editor, float dt) case EDITOR_AXIS_Z: vec4_assign(&arc_color, &editor->axis_color_z); break; } - arc_color.w = 0.1f; - im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, true, editor->tool_mesh_position, rotation, arc_color, 2); + if(editor->tool_rotate_allowed) + { + arc_color.w = 0.1f; + im_circle(editor->tool_rotate_arc_radius, editor->tool_rotate_arc_segments, true, editor->tool_mesh_position, rotation, arc_color, 2); + } + if(editor->tool_rotate_amount != 0.f) { arc_color.w = 0.5f; im_arc(editor->tool_rotate_arc_radius / 2.f, 0.f, editor->tool_rotate_amount, editor->tool_rotate_arc_segments, true, editor->tool_mesh_position, rotation, arc_color, 4); } - - } } break; @@ -575,24 +621,25 @@ void editor_on_mousebutton_release(const struct Event* event) transform_translate(editor->selected_entity, &translation, TS_WORLD); } } - else if(editor->current_mode == EDITOR_MODE_ROTATE) + else if(editor->current_mode == EDITOR_MODE_ROTATE && editor->tool_rotate_rotation_started) { - if(!editor->tool_rotate_axis_selection_enabled) + editor->picking_enabled = true; + editor->tool_rotate_rotation_started = false; + if(editor->tool_rotate_amount != 0.f) { - editor->tool_rotate_axis_selection_enabled = true; - editor->picking_enabled = true; - if(editor->tool_rotate_amount != 0.f) + vec3 axis = { 0.f, 0.f, 0.f }; + bool should_rotate = true; + switch(editor->current_axis) { - vec3 axis = { 0.f, 0.f, 0.f }; - switch(editor->current_axis) - { - case EDITOR_AXIS_X: vec3_assign(&axis, &UNIT_X); break; - case EDITOR_AXIS_Y: vec3_assign(&axis, &UNIT_Y); break; - case EDITOR_AXIS_Z: vec3_assign(&axis, &UNIT_Z); break; - } - transform_rotate(editor->selected_entity, &axis, editor->tool_rotate_amount, TS_WORLD); - editor->tool_rotate_amount = 0.f; + case EDITOR_AXIS_X: vec3_assign(&axis, &UNIT_X); break; + case EDITOR_AXIS_Y: vec3_assign(&axis, &UNIT_Y); break; + case EDITOR_AXIS_Z: vec3_assign(&axis, &UNIT_Z); break; + default: should_rotate = false; } + + if(should_rotate) + transform_rotate(editor->selected_entity, &axis, editor->tool_rotate_amount, TS_WORLD); + editor->tool_rotate_amount = 0.f; } } } @@ -609,13 +656,10 @@ void editor_on_mousebutton_press(const struct Event* event) if(event->mousebutton.button == MSB_LEFT && event->type == EVT_MOUSEBUTTON_PRESSED && editor->selected_entity) { - if(editor->current_mode == EDITOR_MODE_ROTATE) + if(editor->current_mode == EDITOR_MODE_ROTATE && editor->tool_rotate_allowed) { - if(editor->tool_rotate_axis_selection_enabled) - { - editor->tool_rotate_axis_selection_enabled = false; - editor->picking_enabled = false; - } + editor->picking_enabled = false; + editor->tool_rotate_rotation_started = true; } } } @@ -624,6 +668,8 @@ void editor_on_mousemotion(const struct Event* event) { struct Game_State* game_state = game_state_get(); struct Editor* editor = game_state->editor; + struct Gui* gui = game_state->gui; + if(nk_window_is_any_hovered(&gui->context)) return; switch(editor->current_mode) { @@ -677,8 +723,7 @@ void editor_on_mousemotion(const struct Event* event) break; case EDITOR_MODE_ROTATE: { - /* Select Axis to rotate on */ - if(editor->selected_entity && editor->tool_rotate_axis_selection_enabled) + if(editor->selected_entity && editor->current_axis < EDITOR_AXIS_XZ) { struct Camera* editor_camera = &game_state->scene->cameras[CAM_EDITOR]; vec3 position = { 0.f }; @@ -686,49 +731,62 @@ void editor_on_mousemotion(const struct Event* event) struct Ray cam_ray; cam_ray = camera_screen_coord_to_ray(editor_camera, event->mousemotion.x, event->mousemotion.y); + + /* Instead of using a spehre intersection, get the point where the ray intersects the plane + then check if the distance of that point from the selected entity is less than or equal to + the radius of the circle/disc, if it is, then we are inside the circle and can rotate */ + + + struct Bounding_Sphere gizmo_sphere; //vec3_assign(&gizmo_sphere.center, &position); gizmo_sphere.center = (vec3) { 0.f, 0.f, 0.f }; gizmo_sphere.radius = editor->tool_rotate_arc_radius; if(bv_intersect_sphere_ray(&gizmo_sphere, &position, &cam_ray)) { - Plane ground_plane; - plane_init(&ground_plane, &UNIT_X, &position); - float distance_x = bv_distance_ray_plane(&cam_ray, &ground_plane); + //Plane ground_plane; + //plane_init(&ground_plane, &UNIT_X, &position); + //float distance_x = bv_distance_ray_plane(&cam_ray, &ground_plane); - plane_init(&ground_plane, &UNIT_Y, &position); - float distance_y = bv_distance_ray_plane(&cam_ray, &ground_plane); + //plane_init(&ground_plane, &UNIT_Y, &position); + //float distance_y = bv_distance_ray_plane(&cam_ray, &ground_plane); - plane_init(&ground_plane, &UNIT_Z, &position); - float distance_z = bv_distance_ray_plane(&cam_ray, &ground_plane); + //plane_init(&ground_plane, &UNIT_Z, &position); + //float distance_z = bv_distance_ray_plane(&cam_ray, &ground_plane); - //Determine the closest plane - log_message("X: %.3f Y: %.3f Z: %.3f", distance_x, distance_y, distance_z); + ////Determine the closest plane + ////log_message("X: %.3f Y: %.3f Z: %.3f", distance_x, distance_y, distance_z); - float shortest_distance = distance_x < distance_y ? distance_x : distance_y; - shortest_distance = shortest_distance < distance_z ? shortest_distance : distance_z; + //float shortest_distance = distance_x < distance_y ? distance_x : distance_y; + //shortest_distance = shortest_distance < distance_z ? shortest_distance : distance_z; - if(shortest_distance == distance_x) editor->current_axis = EDITOR_AXIS_X; - if(shortest_distance == distance_y) editor->current_axis = EDITOR_AXIS_Y; - if(shortest_distance == distance_z) editor->current_axis = EDITOR_AXIS_Z; + //if(shortest_distance == distance_x) editor->tool_rotate_axis = EDITOR_AXIS_X; + //if(shortest_distance == distance_y) editor->tool_rotate_axis = EDITOR_AXIS_Y; + //if(shortest_distance == distance_z) editor->tool_rotate_axis = EDITOR_AXIS_Z; + editor->tool_rotate_allowed = true; } else { - editor->current_axis = EDITOR_AXIS_NONE; + editor->tool_rotate_allowed = false; + } + //else + //{ + // editor->tool_rotate_axis = EDITOR_AXIS_NONE; + //} + if(editor->current_axis != EDITOR_AXIS_NONE && editor->tool_rotate_rotation_started) + { + if(editor->tool_snap_enabled) + editor->tool_rotate_amount += editor->grid_scale * editor->tool_rotate_increment * ((float)event->mousemotion.xrel / 2.f); + else + editor->tool_rotate_amount += event->mousemotion.xrel / 2; + + if(editor->tool_rotate_amount > 360.f) + editor->tool_rotate_amount = editor->tool_rotate_amount - 360.f; + else if(editor->tool_rotate_amount < -360.f) + editor->tool_rotate_amount = editor->tool_rotate_amount + 360.f; } } - else /* Rotate on selected axis */ - { - if(editor->tool_snap_enabled) - editor->tool_rotate_amount += editor->grid_scale * editor->tool_rotate_increment * ((float)event->mousemotion.xrel / 2.f); - else - editor->tool_rotate_amount += event->mousemotion.xrel / 2; - - if(editor->tool_rotate_amount > 360.f) - editor->tool_rotate_amount = editor->tool_rotate_amount - 360.f; - else if(editor->tool_rotate_amount < -360.f) - editor->tool_rotate_amount = editor->tool_rotate_amount + 360.f; - } + } break; default: break; @@ -765,8 +823,10 @@ void editor_on_key_release(const struct Event* event) if(event->key.key == KEY_X) selected_axis = EDITOR_AXIS_X; if(event->key.key == KEY_Y) selected_axis = EDITOR_AXIS_Y; if(event->key.key == KEY_Z) selected_axis = EDITOR_AXIS_Z; + if(event->key.key == KEY_X && input_is_key_pressed(KEY_LSHIFT)) selected_axis = EDITOR_AXIS_YZ; if(event->key.key == KEY_Y && input_is_key_pressed(KEY_LSHIFT)) selected_axis = EDITOR_AXIS_XZ; - if(event->key.key == KEY_ALT) selected_axis = editor->previous_axis; + if(event->key.key == KEY_Z && input_is_key_pressed(KEY_LSHIFT)) selected_axis = EDITOR_AXIS_XY; + if(event->key.key == KEY_ALT && editor->current_mode == EDITOR_MODE_TRANSLATE) selected_axis = editor->previous_axis; // Revert to previous axis when alt is released editor_axis_set(editor, selected_axis); /* Grid Scale select */ @@ -794,18 +854,7 @@ void editor_mode_set(struct Editor* editor, int mode) editor->current_mode = mode; } - if(editor->selected_entity) - transform_get_absolute_position(editor->selected_entity, &editor->tool_mesh_position); - else - vec3_fill(&editor->tool_mesh_position, 0.f, 0.f, 0.f); - - editor->tool_rotate_amount = 0.f; - editor->tool_rotate_axis_selection_enabled = true; - editor->picking_enabled = true; - if(mode == EDITOR_MODE_TRANSLATE) - editor_axis_set(editor, EDITOR_AXIS_XZ); - else - editor_axis_set(editor, EDITOR_AXIS_NONE); + editor_tool_reset(editor); } void editor_entity_select(struct Editor* editor, struct Entity* entity) @@ -814,7 +863,7 @@ void editor_entity_select(struct Editor* editor, struct Entity* entity) { editor->selected_entity->editor_selected = false; editor->selected_entity = NULL; - vec3_fill(&editor->tool_mesh_position, 0.f, 0.f, 0.f); + editor_tool_reset(editor); } else if(entity) // Select { @@ -830,12 +879,28 @@ void editor_entity_select(struct Editor* editor, struct Entity* entity) } } +void editor_tool_reset(struct Editor* editor) +{ + if(editor->selected_entity) + transform_get_absolute_position(editor->selected_entity, &editor->tool_mesh_position); + else + vec3_fill(&editor->tool_mesh_position, 0.f, 0.f, 0.f); + + editor->tool_rotate_amount = 0.f; + editor->tool_rotate_allowed = false; + editor->picking_enabled = true; + if(editor->current_mode == EDITOR_MODE_TRANSLATE) + editor_axis_set(editor, EDITOR_AXIS_XZ); + else + editor_axis_set(editor, EDITOR_AXIS_NONE); +} + void editor_on_key_press(const struct Event* event) { struct Editor* editor = game_state_get()->editor; if(!nk_window_is_any_hovered(&game_state_get()->gui->context)) { - if(event->key.key == KEY_ALT) editor_axis_set(editor, EDITOR_AXIS_Y); + if(event->key.key == KEY_ALT && editor->current_mode == EDITOR_MODE_TRANSLATE) editor_axis_set(editor, EDITOR_AXIS_Y); } } @@ -843,15 +908,24 @@ void editor_axis_set(struct Editor* editor, int axis) { if(editor->current_axis != axis) { - if(axis != editor->current_axis) + editor->previous_axis = editor->current_axis; + editor->current_axis = axis; + + /* Reset tool position after axis has changed */ + if(editor->selected_entity) { - editor->previous_axis = editor->current_axis; - editor->current_axis = axis; + transform_get_absolute_position(editor->selected_entity, &editor->tool_mesh_position); + } - /* Reset tool position after axis has changed */ - if(editor->selected_entity) + if(editor->current_mode == EDITOR_MODE_ROTATE) + { + // Assign rotation axis only if it is a single axis since we don't want to rotate on multiple axes at the same time + if(axis >= EDITOR_AXIS_XZ) { - transform_get_absolute_position(editor->selected_entity, &editor->tool_mesh_position); + editor->previous_axis = EDITOR_AXIS_NONE; + editor->current_axis = EDITOR_AXIS_NONE; + editor->tool_rotate_allowed = false; + editor->tool_rotate_amount = 0.f; } } } @@ -860,7 +934,7 @@ void editor_camera_update(struct Editor* editor, float dt) { struct Camera* editor_camera = &game_state_get()->scene->cameras[CAM_EDITOR]; static float total_up_down_rot = 0.f; - float move_speed = editor->camera_move_speed, turn_speed = editor->camera_turn_speed; + float move_speed = editor->camera_move_speed, turn_speed = editor->camera_turn_speed; float turn_up_down = 0.f; float turn_left_right = 0.f; float max_up_down = 60.f; diff --git a/src/game/editor.h b/src/game/editor.h index 9fe39b5..aa71de6 100755 --- a/src/game/editor.h +++ b/src/game/editor.h @@ -36,8 +36,9 @@ struct Editor int tool_mesh_draw_enabled; float tool_rotate_arc_radius; int tool_rotate_arc_segments; - bool tool_rotate_axis_selection_enabled; float tool_rotate_amount; + bool tool_rotate_allowed; + bool tool_rotate_rotation_started; float tool_rotate_increment; vec3 tool_scale_amount; float axis_line_length; diff --git a/src/game/renderer.c b/src/game/renderer.c index e99f79a..a8574bc 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -146,185 +146,179 @@ void renderer_init(struct Renderer* renderer) void renderer_render(struct Renderer* renderer, struct Scene* scene) { - /* Render each camera output into it's framebuffer or to the default framebuffer */ - for(int i = 0; i < MAX_CAMERAS; i++) - { - struct Camera* camera = &scene->cameras[i]; - if(!camera->base.active) continue; - - int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; - framebuffer_bind(fbo); + struct Camera* camera = &scene->cameras[scene->active_camera_index]; + int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; + framebuffer_bind(fbo); + { + glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glClearColor(camera->clear_color.x, + camera->clear_color.y, + camera->clear_color.z, + camera->clear_color.w); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + static mat4 mvp; + for(int i = 0; i < MAT_MAX; i++) { - glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glClearColor(camera->clear_color.x, - camera->clear_color.y, - camera->clear_color.z, - camera->clear_color.w); - glEnable(GL_CULL_FACE ); - glCullFace(GL_BACK); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - static mat4 mvp; - for(int i = 0; i < MAT_MAX; i++) - { - /* for each material, get all the registered models and render them */ - struct Material* material = &renderer->materials[i]; - GL_CHECK(shader_bind(material->shader)); + /* for each material, get all the registered models and render them */ + struct Material* material = &renderer->materials[i]; + GL_CHECK(shader_bind(material->shader)); - if(material->lit) /* Set light information */ + if(material->lit) /* Set light information */ + { + char uniform_name[MAX_UNIFORM_NAME_LEN]; + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + int light_count = -1; + for(int j = 0; j < MAX_LIGHTS; j++) { - char uniform_name[MAX_UNIFORM_NAME_LEN]; - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - int light_count = -1; - for(int i = 0; i < MAX_LIGHTS; i++) + struct Light* light = &scene->lights[j]; /* TODO: Cull lights according to camera frustum */ + if(!light->base.active || !light->valid) continue; + light_count++; + + vec3 light_pos = { 0, 0, 0 }; + transform_get_absolute_position(&light->base, &light_pos); + + if(light->type != LT_POINT) { - struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */ - if(!light->base.active || !light->valid) continue; - light_count++; - - vec3 light_pos = {0, 0, 0}; - transform_get_absolute_position(&light->base, &light_pos); - - if(light->type != LT_POINT) - { - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count); - vec3 light_dir = {0.f, 0.f, 0.f}; - transform_get_absolute_lookat(&light->base, &light_dir); - vec3_norm(&light_dir, &light_dir); - shader_set_uniform_vec3(material->shader, uniform_name, &light_dir); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - } - - if(light->type != LT_DIR) - { - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count); - shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count); - shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count); - shader_set_uniform_float(material->shader, uniform_name, light->inner_angle); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count); - shader_set_uniform_float(material->shader, uniform_name, light->falloff); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count); - shader_set_uniform_int(material->shader, uniform_name, light->radius); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - } - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count); - shader_set_uniform_vec3(material->shader, uniform_name, &light->color); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count); + vec3 light_dir = { 0.f, 0.f, 0.f }; + transform_get_absolute_lookat(&light->base, &light_dir); + vec3_norm(&light_dir, &light_dir); + shader_set_uniform_vec3(material->shader, uniform_name, &light_dir); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count); - shader_set_uniform_float(material->shader, uniform_name, light->intensity); + } + + if(light->type != LT_DIR) + { + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count); + shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count); - shader_set_uniform_int(material->shader, uniform_name, light->type); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count); + shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count); + shader_set_uniform_float(material->shader, uniform_name, light->inner_angle); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count); + shader_set_uniform_float(material->shader, uniform_name, light->falloff); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count); + shader_set_uniform_int(material->shader, uniform_name, light->radius); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); } - light_count++; // this variable is going to be sent as a uniform and be used for looping an array so increase its length by one - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_TOTAL_LIGHTS].type, material->pipeline_params[MPP_TOTAL_LIGHTS].location, &light_count)); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count); + shader_set_uniform_vec3(material->shader, uniform_name, &light->color); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count); + shader_set_uniform_float(material->shader, uniform_name, light->intensity); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count); + shader_set_uniform_int(material->shader, uniform_name, light->type); + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + } + + light_count++; // this variable is going to be sent as a uniform and be used for looping an array so increase its length by one + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_TOTAL_LIGHTS].type, material->pipeline_params[MPP_TOTAL_LIGHTS].location, &light_count)); - vec3 camera_pos = {0, 0, 0}; - transform_get_absolute_position(&camera->base, &camera_pos); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos)); + vec3 camera_pos = { 0, 0, 0 }; + transform_get_absolute_position(&camera->base, &camera_pos); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos)); + } + + /* Set material pipeline uniforms */ + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_START_DIST].type, material->pipeline_params[MPP_FOG_START_DIST].location, &renderer->settings.fog.start_dist)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MAX_DIST].type, material->pipeline_params[MPP_FOG_MAX_DIST].location, &renderer->settings.fog.max_dist)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light)); + if(material->lit) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); + + + for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++) + { + if(!material->registered_static_meshes[j]) continue; + + /* for each registered model, set up uniforms and render */ + struct Static_Mesh* mesh = material->registered_static_meshes[j]; + struct Geometry* geometry = geom_get(mesh->model.geometry_index); + + /* Check if model is in frustum */ + vec3 abs_pos, abs_scale; + transform_get_absolute_position(&mesh->base, &abs_pos); + transform_get_absolute_scale(&mesh->base, &abs_scale); + int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); + if(intersection == IT_OUTSIDE) + { + renderer->num_culled++; + continue; + } + else + { + renderer->num_indices += array_len(geometry->indices); + renderer->num_rendered++; } - /* Set material pipeline uniforms */ - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_START_DIST].type, material->pipeline_params[MPP_FOG_START_DIST].location, &renderer->settings.fog.start_dist)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MAX_DIST].type, material->pipeline_params[MPP_FOG_MAX_DIST].location, &renderer->settings.fog.max_dist)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light)); - if(material->lit) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); - - - for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++) + /* set material params for the model */ + for(int k = 0; k < MMP_MAX; k++) { - if(!material->registered_static_meshes[j]) continue; - - /* for each registered model, set up uniforms and render */ - struct Static_Mesh* mesh = material->registered_static_meshes[j]; - struct Geometry* geometry = geom_get(mesh->model.geometry_index); - - /* Check if model is in frustum */ - vec3 abs_pos, abs_scale; - transform_get_absolute_position(&mesh->base, &abs_pos); - transform_get_absolute_scale(&mesh->base, &abs_scale); - int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); - if(intersection == IT_OUTSIDE) - { - renderer->num_culled++; - continue; - } - else + switch(mesh->model.material_params[k].type) { - renderer->num_indices += array_len(geometry->indices); - renderer->num_rendered++; + case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_int)); break; + case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_float)); break; + case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec3)); break; + case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec4)); break; } + } - /* set material params for the model */ - for(int k = 0; k < MMP_MAX; k++) - { - switch(mesh->model.material_params[k].type) - { - case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_int)); break; - case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_float)); break; - case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec3)); break; - case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec4)); break; - } - } + /* Set pipeline uniforms that are derived per model */ + mat4_identity(&mvp); + mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MVP].type, material->pipeline_params[MPP_MVP].location, &mvp)); - /* Set pipeline uniforms that are derived per model */ - mat4_identity(&mvp); - mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MVP].type, material->pipeline_params[MPP_MVP].location, &mvp)); + if(material->lit) + { + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MODEL_MAT].type, material->pipeline_params[MPP_MODEL_MAT].location, &mesh->base.transform.trans_mat)); + mat4 inv_mat; + mat4_identity(&inv_mat); + mat4_inverse(&inv_mat, &mesh->base.transform.trans_mat); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_INV_MODEL_MAT].type, material->pipeline_params[MPP_INV_MODEL_MAT].location, &inv_mat)); + } - if(material->lit) - { - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MODEL_MAT].type, material->pipeline_params[MPP_MODEL_MAT].location, &mesh->base.transform.trans_mat)); - mat4 inv_mat; - mat4_identity(&inv_mat); - mat4_inverse(&inv_mat, &mesh->base.transform.trans_mat); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_INV_MODEL_MAT].type, material->pipeline_params[MPP_INV_MODEL_MAT].location, &inv_mat)); - } - - /* Render the geometry */ - //int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode); - //geom_render(model->geometry_index, draw_mode); - geom_render(mesh->model.geometry_index, GDM_TRIANGLES); + /* Render the geometry */ + //int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode); + //geom_render(model->geometry_index, draw_mode); + geom_render(mesh->model.geometry_index, GDM_TRIANGLES); - for(int k = 0; k < MMP_MAX; k++) - { - /* unbind textures, if any */ - if(material->model_params[k].type == UT_TEX) - GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int)); - } + for(int k = 0; k < MMP_MAX; k++) + { + /* unbind textures, if any */ + if(material->model_params[k].type == UT_TEX) + GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int)); } - shader_unbind(); } - editor_debugvar_slot_set_int(renderer->num_rendered_slot, renderer->num_rendered); - editor_debugvar_slot_set_int(renderer->num_culled_slot, renderer->num_culled); - editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices); - - renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; + shader_unbind(); } - framebuffer_unbind(); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - } + editor_debugvar_slot_set_int(renderer->num_rendered_slot, renderer->num_rendered); + editor_debugvar_slot_set_int(renderer->num_culled_slot, renderer->num_culled); + editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices); + + renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; + } + framebuffer_unbind(); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); /* Final Render */ struct Camera* active_camera = &scene->cameras[scene->active_camera_index]; diff --git a/todo.txt b/todo.txt index d16cb98..990ec07 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,5 @@ Todo: - - Only show rotation gizmo for one axis at a time + - Cancel tool action when right click is pressed in between - Rotate mesh along mouse movement or show what the rotation is going to look like by using a wireframe version of mesh when rotating - Match amount to be rotate with actual axes and the gizmo arc being drawn - Handle all other axes combinations @@ -83,16 +83,15 @@ Todo: Improvements: - Better naming semantics for example, init/deinit for initialization and cleanup and create/destroy when memory is allocated or deallocated - - Reset mouse cursor position to the center of the screen in editor mode after the right click is released - Categorized entity list in editor for example different subtree for lights and static meshes - Depth testing for editor grid - - Remove fixed editor windows locations and bring back floating windows + - Improve picking and automatically improve everything in editor + - Improve culling Bugs: - Better handling of wav format checking at load time - Fix light rotation/direction bugs - Fix lights type not being correctly saved/loaded from file - - Fix culling - Fix bounding boxes not aligning in editor - Investigate memory usage increase when window is minimized - Fix hang on fullscreen toggle @@ -264,4 +263,7 @@ Done: * Complete rotate mode * Implement arc values greater than 360 or -360 * Rotation degree snapping + * Reset mouse cursor position to the center of the screen in editor mode after the right click is released + * Remove fixed editor windows locations and bring back floating windows + * Only show rotation gizmo for one axis at a time