diff --git a/src/common/linmath.c b/src/common/linmath.c index ad057df..c440c61 100755 --- a/src/common/linmath.c +++ b/src/common/linmath.c @@ -79,11 +79,11 @@ void vec3_add(vec3* res, const vec3* v1, const vec3* v3) res->z = v1->z + v3->z; } -void vec3_sub(vec3* res, const vec3* v1, const vec3* v3) +void vec3_sub(vec3* res, const vec3* v1, const vec3* v2) { - res->x = v1->x - v3->x; - res->y = v1->y - v3->y; - res->z = v1->z - v3->z; + res->x = v1->x - v2->x; + res->y = v1->y - v2->y; + res->z = v1->z - v2->z; } void vec3_assign(vec3* res, const vec3* val) diff --git a/src/game/bounding_volumes.c b/src/game/bounding_volumes.c index d13edc5..e37495f 100755 --- a/src/game/bounding_volumes.c +++ b/src/game/bounding_volumes.c @@ -82,21 +82,24 @@ bool bv_intersect_frustum_point(vec4* frustum, const vec3* point) return success; } -bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray) +int bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, vec3* sphere_abs_scale, struct Ray* ray) { - - vec3 center = {0.f}; + int intersection_type = IT_OUTSIDE; + vec3 center = {0.f, 0.f, 0.f}; vec3_add(¢er, &sphere->center, sphere_abs_position); - float squared_radius = sphere->radius * sphere->radius; + float radius = sphere->radius * sphere_abs_scale->x; + //float squared_radius = sphere->radius * sphere->radius; + float squared_radius = radius * radius; vec3 centered_origin; vec3_sub(¢ered_origin, &ray->origin, ¢er); + //vec3_sub(¢ered_origin, ¢er, &ray->origin); float centered_origin_len_sqrd = vec3_len(¢ered_origin); centered_origin_len_sqrd *= centered_origin_len_sqrd; //Check if ray originates inside the sphere if(centered_origin_len_sqrd <= squared_radius) - return true; + return IT_INSIDE; // Calculate the intersection by quatratic equation' float a = vec3_dot(&ray->direction, &ray->direction); @@ -106,24 +109,24 @@ bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_po //No solution if(d < 0.f) - return false; + return IT_OUTSIDE; //Get the near solution float d_sqrt = sqrtf(d); float dist = (-b - d_sqrt) / (2.f * a); if(dist >= 0.f) - return true; + return IT_INTERSECT; else - return true; + return IT_OUTSIDE; //float tca = vec3_dot(¢ered_origin, &ray->direction); - //if(tca < 0.0) return false; + //if(tca < 0.0) return IT_OUTSIDE; //float L_dot = vec3_dot(¢ered_origin, ¢ered_origin); - //float d2 = L_dot - (tca); - //float radius_sqr = sphere->radius * sphere->radius; + //float d2 = L_dot - (tca * tca); + //float radius_sqr = radius * radius; - //if (d2 > radius_sqr) return false; + //if (d2 > radius_sqr) return IT_OUTSIDE; //float thc = sqrtf(radius_sqr - d2); //float t0 = tca - thc; //float t1 = tca + thc; @@ -138,10 +141,10 @@ bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_po //if(t0 < 0) //{ // t0 = t1; - // if(t0 < 0) return false; + // if(t0 < 0) return IT_OUTSIDE; //} - //return true; + //return IT_INTERSECT; } float bv_distance_ray_plane(struct Ray* ray, Plane* plane) diff --git a/src/game/bounding_volumes.h b/src/game/bounding_volumes.h index 56e3cc7..b9380e6 100755 --- a/src/game/bounding_volumes.h +++ b/src/game/bounding_volumes.h @@ -52,7 +52,8 @@ struct Raycast_Result int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale); int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, vec3* sphere_abs_pos, vec3* sphere_abs_scale); bool bv_intersect_frustum_point(vec4* frustum, const vec3* point); -bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray); +//bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray); +int bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, vec3* sphere_abs_scale, struct Ray* ray); float bv_distance_ray_plane(struct Ray* ray, Plane* plane); #endif diff --git a/src/game/editor.c b/src/game/editor.c index 2d2fdcc..ff4ce88 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -161,7 +161,7 @@ void editor_init(struct Editor* editor) void editor_init_entities(struct Editor* editor) { editor->cursor_entity = scene_static_mesh_create(game_state_get()->scene, "EDITOR_SELECTED_ENTITY_WIREFRAME", NULL, "sphere.symbres", MAT_UNSHADED); - editor->cursor_entity->base.flags |= EF_TRANSIENT | EF_SKIP_RENDER | EF_HIDE_IN_EDITOR_SCENE_HIERARCHY; + editor->cursor_entity->base.flags |= EF_TRANSIENT | EF_SKIP_RENDER | EF_HIDE_IN_EDITOR_SCENE_HIERARCHY | EF_IGNORE_RAYCAST; } void editor_init_camera(struct Editor* editor, struct Hashmap* cvars) @@ -989,8 +989,10 @@ void editor_on_mousemotion(const struct Event* event) if(editor->selected_entity && editor->current_axis < EDITOR_AXIS_XZ) { struct Camera* editor_camera = &game_state->scene->cameras[CAM_EDITOR]; - vec3 position = { 0.f }; + vec3 position = { 0.f, 0.f, 0.f }; + vec3 scale = {1.f, 1.f, 1.f}; transform_get_absolute_position(editor->selected_entity, &position); + transform_get_absolute_scale(editor->selected_entity, &scale); struct Ray cam_ray; cam_ray = camera_screen_coord_to_ray(editor_camera, event->mousemotion.x, event->mousemotion.y); @@ -1005,7 +1007,7 @@ void editor_on_mousemotion(const struct Event* event) //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)) + if(bv_intersect_sphere_ray(&gizmo_sphere, &position, &scale, &cam_ray) == IT_INTERSECT) { //Plane ground_plane; //plane_init(&ground_plane, &UNIT_X, &position); @@ -1099,17 +1101,8 @@ void editor_on_mousemotion(const struct Event* event) if(ray_result.num_entities_intersected > 0) { struct Entity* intersected_entity = ray_result.entities_intersected[0]; - if(intersected_entity == editor->cursor_entity) - { - if(ray_result.num_entities_intersected > 1) - intersected_entity = ray_result.entities_intersected[1]; - else - intersected_entity = NULL; - } if(intersected_entity && intersected_entity != editor->hovered_entity) editor->hovered_entity = intersected_entity; - else if(editor->hovered_entity) - editor->hovered_entity = NULL; } else { diff --git a/src/game/entity.h b/src/game/entity.h index 5f48c26..a059f6f 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -53,7 +53,8 @@ enum Entity_Flags EF_MARKED_FOR_DELETION = 1 << 2, EF_TRANSIENT = 1 << 3, EF_HIDE_IN_EDITOR_SCENE_HIERARCHY = 1 << 4, - EF_SKIP_RENDER = 1 << 5 + EF_SKIP_RENDER = 1 << 5, + EF_IGNORE_RAYCAST = 1 << 6 }; struct Transform diff --git a/src/game/renderer.c b/src/game/renderer.c index 1f40d16..d590115 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -350,7 +350,8 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) if(!(mesh->base.flags & EF_ACTIVE)) continue; struct Model* model = &mesh->model; struct Transform* transform = &mesh->base.transform; - int geometry = model->geometry_index; + //int geometry = model->geometry_index; + int geometry = geom_find("sphere.symbres");// ->geometry_index; mat4_identity(&mvp); mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); diff --git a/src/game/scene.c b/src/game/scene.c index 3331b75..8701be6 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -802,12 +802,14 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re for(int i = 0; i < MAX_STATIC_MESHES; i++) { struct Static_Mesh* mesh = &scene->static_meshes[i]; - if(!(mesh->base.flags & EF_ACTIVE)) continue; - vec3 abs_pos = { 0.f }; + if(!(mesh->base.flags & EF_ACTIVE) || (mesh->base.flags & EF_IGNORE_RAYCAST)) continue; + vec3 abs_pos = { 0.f, 0.f, 0.f }; + vec3 abs_scale = { 1.f, 1.f, 1.f }; transform_get_absolute_position(mesh, &abs_pos); + transform_get_absolute_scale(mesh, &abs_scale); struct Geometry* geometry = geom_get(mesh->model.geometry_index); - if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, ray)) + if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, &abs_scale, ray) == IT_INTERSECT) { out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base; out_results->num_entities_intersected++; @@ -815,113 +817,6 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re } } - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool scene_load_(const char* filename, int directory_type) -{ - // FILE* entity_file = platform->file.open(directory_type, filename, "r"); - //if(!entity_file) - //{ - // log_error("scene:load", "Failed to open scenefile %s for reading", filename); - // return false; - //} - - //int count = 0; - //int eof_char = -1; - //while(!feof(entity_file)) - //{ - // if(eof_char != -1) ungetc(eof_char, entity_file); - // struct Entity* new_entity = NULL; - // new_entity = entity_read(entity_file); - // if(!new_entity) - // { - // log_error("scene:load", "Error reading entity"); - // } - // else - // { - // log_message("Loaded %s", new_entity->name); - // count++; - // } - // eof_char = fgetc(entity_file); - // /* To check end of file, we get the next character and before beginning - // loop we check if eof occured, feof only returns true if the last read - // was an eof. If it wasn't eof then we return the character back to the - // stream and carry on. */ - //} - - //log_message("%d entites loaded from %s", count, filename); - //fclose(entity_file); - return entity_load(filename, directory_type); -} - -bool scene_save_(const char* filename, int directory_type) -{ - bool success = false; - /*FILE* scene_file = platform->file.open(directory_type, filename, "w"); - if(!scene_file) - { - log_error("scene:save", "Failed to create scenefile %s for writing", filename); - return false; - } - - struct Parser* parser = parser_new(); - if(!parser) - { - log_error("scene:save", "Could not create Parser"); - fclose(scene_file); - return false; - } - - int* entities_to_write = array_new(int); - array_push(entities_to_write, root_node, int); - - bool done = false; - int count = 0; - while(!done) - { - struct Entity* entity = entity_get(entities_to_write[0]); - struct Parser_Object* object = parser_object_new(parser, PO_ENTITY); - if(!object) - { - log_error("scene:save", "Failed to create parser object for %s", entity->name); - continue; - } - - if(!entity_write(entity, object)) - { - log_error("scene:save", "Failed to write '%s' into parser object", entity->name); - continue; - } - - log_message("Entity '%s' written to file", entity->name); - count++; - for(int i = 0; i < array_len(entity->transform.children); i++) - array_push(entities_to_write, entity->transform.children[i], int); - - array_remove_at(entities_to_write, 0); - if(array_len(entities_to_write) == 0) done = true; - } - - if(parser_write_objects(parser, scene_file, filename)) - { - log_message("%d entities written to %s", count, filename); - } - else - { - log_error("scene:save", "Failed to write scene to %s", filename); - success = false; - } - - array_free(entities_to_write); - parser_free(parser); - fclose(scene_file);*/ - - return success; -} - int scene_entity_archetype_add(struct Scene* scene, const char* filename) { // check if we have already added this archetype, if we have, return that index diff --git a/todo.txt b/todo.txt index a982536..5baf285 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,6 @@ Todo: - - Better, more accurate picking - Add editor undo for transformation operations - Add material export for blender exporter? - - Remove flickering from selection in editor - Fix crash when exiting from fullscreen mode - Allow renaming scene objects in editor - Check if we still need to rotate by 90 degrees when exporting from blender @@ -120,6 +118,7 @@ Improvements: - Allow scaling on all axes at once - Improve grid/immediate mode drawing by switching to glDrawElements instead of glDrawArrays. - Investigate why transparency is not working for materials + - Picking for other entity types like lights etc by specifically ray casting for them or in editor switching to pick-mode that specifies if we're picking lights or meshes etc Bugs: - Better handling of wav format checking at load time @@ -357,4 +356,6 @@ Done: * Implment/Test reading/writing scene that has a mixture of default entites and entity archetypes * Add simple player fps controls * Fixed gimbal lock in fps camera by fixing the order of quaternion multiplication when getting absolute rotation - * Fix hierarchical transforms not working in editor mode \ No newline at end of file + * Fix hierarchical transforms not working in editor mode + * Better, slightly accurate picking + * Removed flickering from selection in editor \ No newline at end of file