Fixed vec4 and mat4 multiplication, Implemented screen coord to ray and ray-sphere collision

dev
Shariq Shah 7 years ago
parent ada2e0efe2
commit ad5b56b717
  1. 5
      README.md
  2. 2
      build/genie.lua
  3. 8
      src/common/linmath.c
  4. 62
      src/libsymmetry/bounding_volumes.c
  5. 11
      src/libsymmetry/bounding_volumes.h
  6. 62
      src/libsymmetry/camera.c
  7. 2
      src/libsymmetry/camera.h
  8. 20
      src/libsymmetry/game.c
  9. 6
      src/libsymmetry/geometry.c
  10. 13
      src/libsymmetry/player.c
  11. 40
      src/libsymmetry/scene.c
  12. 5
      src/libsymmetry/scene.h

@ -155,11 +155,13 @@
- ## TODO
- Improve bounding sphere calculation
- Screen mouse coordinates to world-coordinates for aiming
- Player projectiles and sounds
- Console commands
- Console fix bug when enabled in editor mode
- Console command history
- Console command help
- Player projectiles and sounds
- NPR and cross-hatching
- Move Gui_State and Editor_State into game_state and modify usage as needed
- Remove model and replace all usages with static mesh
@ -413,3 +415,4 @@
* Console log output
* Console error/warning output
* Implemented Auto scrolling to the bottom in console
* Implemented screen coordinate to ray conversion and ray-sphere collision

@ -137,7 +137,7 @@ solution "Symmetry"
newaction {
trigger = "build_addon",
description = "Build blender addon into zip file that can be loaded into blender, needs zip installed and available on PATH",
description = "Build blender addon into zip file that can be loaded into blender, needs zip installed and available on PATH(Only works on bash/nix-style shell for now)",
execute = function ()
local output = os.outputof("cd ../blender_addon && zip -r io_symmetry_exp.zip io_symmetry_exp/__init__.py io_symmetry_exp/exporter.py && mv io_symmetry_exp.zip ../build");
printf("Output of blender addon build : \n%s\n", output)

@ -269,10 +269,10 @@ void vec4_mul(vec4* res, vec4* v1, vec4* v4)
void vec4_mul_mat4(vec4* res, vec4* val, mat4* mat)
{
vec4 v;
v.x = val->x * mat->mat[0] + val->y * mat->mat[4] + val->z * mat->mat[8] + mat->mat[12];
v.y = val->x * mat->mat[1] + val->y * mat->mat[5] + val->z * mat->mat[9] + mat->mat[14];
v.z = val->x * mat->mat[2] + val->y * mat->mat[6] + val->z * mat->mat[10] + mat->mat[14];
v.w = val->x * mat->mat[2] + val->y * mat->mat[6] + val->w * mat->mat[10] + mat->mat[14];
v.x = val->x * mat->mat[0] + val->y * mat->mat[4] + val->z * mat->mat[8] + val->w * mat->mat[12];
v.y = val->x * mat->mat[1] + val->y * mat->mat[5] + val->z * mat->mat[9] + val->w * mat->mat[13];
v.z = val->x * mat->mat[2] + val->y * mat->mat[6] + val->z * mat->mat[10] + val->w * mat->mat[14];
v.w = val->x * mat->mat[3] + val->y * mat->mat[7] + val->z * mat->mat[11] + val->w * mat->mat[15];
res->x = v.x;
res->y = v.y;
res->z = v.z;

@ -81,3 +81,65 @@ 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)
{
vec3 center = {0.f};
vec3_add(&center, &sphere->center, sphere_abs_position);
float squared_radius = sphere->radius * sphere->radius;
vec3 centered_origin;
vec3_sub(&centered_origin, &ray->origin, &center);
float centered_origin_len_sqrd = vec3_len(&centered_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;
// Calculate the intersection by quatratic equation'
float a = vec3_dot(&ray->direction, &ray->direction);
float b = 2.f * vec3_dot(&centered_origin, &ray->direction);
float c = vec3_dot(&centered_origin, &centered_origin) - squared_radius;
float d = b * b - 4.f * a * c;
//No solution
if(d < 0.f)
return false;
//Get the near solution
float d_sqrt = sqrtf(d);
float dist = (-b - d_sqrt) / (2.f * a);
if(dist >= 0.f)
return true;
else
return true;
//float tca = vec3_dot(&centered_origin, &ray->direction);
//if(tca < 0.0) return false;
//float L_dot = vec3_dot(&centered_origin, &centered_origin);
//float d2 = L_dot - (tca);
//float radius_sqr = sphere->radius * sphere->radius;
//if (d2 > radius_sqr) return false;
//float thc = sqrtf(radius_sqr - d2);
//float t0 = tca - thc;
//float t1 = tca + thc;
//if(t0 > t1)
//{
// float temp = t0;
// t0 = t1;
// t1 = temp;
//}
//if(t0 < 0)
//{
// t0 = t1;
// if(t0 < 0) return false;
//}
//return true;
}

@ -34,8 +34,15 @@ enum Frustum_Planes
FP_NUM_PLANES
};
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, struct Transform* transform);
struct Ray
{
vec3 direction;
vec3 origin;
};
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);
#endif

@ -202,3 +202,65 @@ static void update_frustum(struct Camera* camera)
vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length));
}
}
struct Ray camera_screen_coord_to_ray(struct Camera* camera, int mouse_x, int mouse_y)
{
struct Ray ray;
int win_width = 0, win_height = 0;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &win_width, &win_height);
float normalized_x = (2.f * (float)mouse_x) / (float)win_width - 1.f;
float normalized_y = 1.f - (2.f * (float)mouse_y) / (float)win_height;
vec3 near_point = {0.f};
vec3 far_point = {0.f};
mat4 inverse_view_proj_mat;
mat4_identity(&inverse_view_proj_mat);
mat4_inverse(&inverse_view_proj_mat, &camera->view_proj_mat);
//Project the near point
quat rot_near = {normalized_x, normalized_y, 0.f, 1.f};
vec4_mul_mat4(&rot_near, &rot_near, &inverse_view_proj_mat);
near_point.x = rot_near.x / rot_near.w;
near_point.y = rot_near.y / rot_near.w;
near_point.z = rot_near.z / rot_near.w;
//Project far point
quat rot_far = {normalized_x, normalized_y, 1.f, 1.f};
vec4_mul_mat4(&rot_far, &rot_far, &inverse_view_proj_mat);
far_point.x = rot_far.x / rot_far.w;
far_point.y = rot_far.y / rot_far.w;
far_point.z = rot_far.z / rot_far.w;
vec3_sub(&ray.direction, &far_point, &near_point);
vec3_norm(&ray.direction, &ray.direction);
transform_get_absolute_position(&camera->base, &ray.origin);
return ray;
/*vec4 clip_coords = {normalized_x, normalized_y, -1.f, 1.f};
vec4 ray_eye = {0.f};
mat4 inverse_proj_mat;
mat4_identity(&inverse_proj_mat);
mat4_inverse(&inverse_proj_mat, &camera->proj_mat);
vec4_mul_mat4(&ray_eye, &clip_coords, &inverse_proj_mat);
ray_eye.z = -1.f;
ray_eye.w = 0.f;
vec4 ray_world = {0.f};
mat4 inverse_view_mat;
mat4_identity(&inverse_view_mat);
mat4_inverse(&inverse_view_mat, &camera->view_mat);
vec4_mul_mat4(&ray_world, &ray_eye, &inverse_view_mat);
vec3 world_coords = {ray_world.x, ray_world.y, ray_world.z};
vec3_norm(&world_coords, &world_coords);
return world_coords;*/
}

@ -2,6 +2,7 @@
#define CAMERA_H
#include "../common/num_types.h"
#include "../common/linmath.h"
struct Camera;
@ -16,6 +17,7 @@ void camera_attach_fbo(struct Camera* camera,
bool has_depth,
bool has_color,
bool resizeable);
struct Ray camera_screen_coord_to_ray(struct Camera* camera, int mouse_x, int mouse_y);
/* void camera_resize_all(int width, int height); */
#endif

@ -292,6 +292,26 @@ void game_scene_setup(void)
ground->model.material_params[MMP_SPECULAR_STRENGTH].val_float = 1.f;
vec3_fill(&ground->model.material_params[MMP_DIFFUSE_COL].val_vec3, 1.f, 1.f, 1.f);
int num_suz = 50;
char suz_name[MAX_ENTITY_NAME_LEN];
vec3 suz_pos = {0.f};
for(int i = 0; i < num_suz; i++)
{
memset(&suz_name, '\0', MAX_ENTITY_NAME_LEN);
snprintf(&suz_name, MAX_ENTITY_NAME_LEN, "Suzanne_%d", i);
struct Static_Mesh* suzanne = scene_static_mesh_create(game_state->scene, suz_name, NULL, "sphere.symbres", MAT_BLINN);
suzanne->model.material_params[MMP_DIFFUSE_TEX].val_int = texture_create_from_file("white.tga", TU_DIFFUSE);
suzanne->model.material_params[MMP_DIFFUSE].val_float = 0.5f;
suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f;
suzanne->model.material_params[MMP_SPECULAR_STRENGTH].val_float = 1.f;
vec3_fill(&suzanne->model.material_params[MMP_DIFFUSE_COL].val_vec3, 1.f, 0.f, 1.f);
suz_pos.x = i + 10.f;
suz_pos.y = 5.f;
suz_pos.z = i + 5.f;
transform_set_position(suzanne, &suz_pos);
}
struct Light* light = scene_light_create(game_state->scene, "Test_Light", NULL, LT_POINT);
light->color.x = 1.f;

@ -363,9 +363,13 @@ int geom_render_in_frustum(int index,
struct Entity* entity,
enum Geometry_Draw_Mode draw_mode)
{
vec3 abs_pos, abs_scale;
transform_get_absolute_position(entity, &abs_pos);
transform_get_absolute_scale(entity, &abs_scale);
struct Geometry* geometry = &geometry_list[index];
int indices_rendered = 0;
int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, entity);
int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, &abs_pos, &abs_scale);
if(intersection == IT_INTERSECT || intersection == IT_INSIDE)
{
geom_render(index, draw_mode);

@ -4,6 +4,8 @@
#include "../common/utils.h"
#include "transform.h"
#include "../common/common.h"
#include "camera.h"
#include "bounding_volumes.h"
void player_init(struct Player* player, struct Scene* scene)
{
@ -65,4 +67,15 @@ void player_update(struct Player* player, struct Scene* scene, float dt)
{
transform_translate(player, &offset, TS_LOCAL);
}
/* Aiming and Projectiles*/
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED))
{
int mouse_x = 0, mouse_y = 0;
platform->mouse_position_get(&mouse_x, &mouse_y);
struct Ray ray = camera_screen_coord_to_ray(player->camera_node, mouse_x, mouse_y);
log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z);
scene_ray_intersect(scene, &ray);
}
}

@ -10,6 +10,8 @@
#include "light.h"
#include "player.h"
#include "game.h"
#include "bounding_volumes.h"
#include "geometry.h"
#include <assert.h>
#include <string.h>
@ -553,6 +555,44 @@ void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct
transform_parent_set(entity, parent, true);
}
void scene_ray_intersect(struct Scene* scene, struct Ray* ray)
{
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active) continue;
vec3 abs_pos = {0.f};
transform_get_absolute_position(mesh, &abs_pos);
struct Geometry* geometry = geom_get(mesh->model.geometry_index);
if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, ray))
{
log_message("Ray intersected with %s", &mesh->base.name);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool scene_load(const char* filename, int directory_type)
{
// FILE* entity_file = platform->file.open(directory_type, filename, "r");

@ -10,6 +10,9 @@
#define MAX_STATIC_MESHES 1024
#define MAX_SOUND_SOURCES 128
struct Ray;
struct Scene
{
struct Render_Settings renderer_profile;
@ -53,6 +56,8 @@ struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent);
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent
void scene_ray_intersect(struct Scene* scene, struct Ray* ray);
//
//void scene_init(void);
//void scene_remove(struct Entity* entity);

Loading…
Cancel
Save