diff --git a/README.md b/README.md index 43960af..0117f69 100644 --- a/README.md +++ b/README.md @@ -155,17 +155,17 @@ - ## TODO - - Convert IM_Vertex array to only be used as temporary storage for vertices between begin and end calls - Physics forces/torque etc + - Implement physics debug visualizations for other primitives and tri mesh shapes - Replace all renderer_check_gl calls with GL_CHECK macro - Fix lights type not being correctly saved/loaded from file - Physics Trimesh support - - Debug physics mesh drawing - Serializing/Deserializing physics data - Storing entity reference/id in rigidbody - Storing rigidbody in entity - Expose complete physics api with forces/joints etc - Complete ODE integration + - Proper implementation of Scene struct with per-scene settings and configurations that can be loaded/saved to file instead of just dumping entities into a file - Test physics code on linux - Pipeline improvements, getting models/materials etc to/from other programs - Necessary basic editor additions like placing objects, scaling, rotating etc @@ -368,3 +368,5 @@ * Update physics if entity position/rotation/scale etc are changed * Implemented Physics raycasting * Implemented immediate mode renderer that can draw arbitrary points, lines and triangles + * Converted IM_Vertex array to only be used as temporary storage for vertices between begin and end calls + * Implemented Debug physics mesh drawing for box and sphere primitives diff --git a/assets/test_scene.symtres b/assets/test_scene.symtres index 1bf587e..cb81d28 100644 --- a/assets/test_scene.symtres +++ b/assets/test_scene.symtres @@ -312,11 +312,11 @@ Entity scale : 1.000 1.000 1.000 material : Blinn_Phong rotation : 0.000 0.000 0.000 1.000 - geometry : default.pamesh + geometry : sphere.symbres is_listener : false - position : 3.000 0.000 4.000 - parent : Model_Entity - name : Suzanne + position : 3.000 10.000 4.000 + parent : ROOT + name : Sphere_Ent renderable : true } diff --git a/src/common/common.h b/src/common/common.h index 003321f..9e673e5 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -53,6 +53,15 @@ enum Sound_Attenuation_Type SA_EXPONENTIAL // Exponential distance attenuation model }; +enum Collision_Shape_Type +{ + CST_BOX = 0, + CST_SPHERE, + CST_CYLINDER, + CST_TRIMESH, + CST_UNKNOWN +}; + struct Raycast_Hit { int entity_id; @@ -70,6 +79,7 @@ struct Physics_Api void (*cs_remove)(Collision_Shape shape); void (*cs_data_set)(Collision_Shape shape, void* data); void* (*cs_data_get)(Collision_Shape shape); + int (*cs_type_get)(Collision_Shape shape); Collision_Shape (*cs_plane_create)(float a, float b, float c, float d); void (*cs_plane_params_set)(Collision_Shape shape, float a, float b, float c, float d); @@ -93,6 +103,11 @@ struct Physics_Api float pos_x, float pos_y, float pos_z, float dir_x, float dir_y, float dir_z); + void (*cs_position_set)(Collision_Shape shape, float x, float y, float z); + void (*cs_position_get)(Collision_Shape shape, float* x, float* y, float* z); + void (*cs_rotation_set)(Collision_Shape shape, float x, float y, float z, float w); + void (*cs_rotation_get)(Collision_Shape shape, float* x, float* y, float* z, float* w); + void (*body_remove)(Rigidbody body); Rigidbody (*body_box_create)(float length, float width, float height); Rigidbody (*body_sphere_create)(float radius); diff --git a/src/game/config_vars.c b/src/game/config_vars.c index 9cb3e3e..034c114 100644 --- a/src/game/config_vars.c +++ b/src/game/config_vars.c @@ -28,7 +28,8 @@ void config_vars_init(void) hashmap_vec3_setf(cvars, "ambient_light", 0.1f, 0.1f, 0.1f); hashmap_bool_set(cvars, "msaa_enabled", 1); hashmap_int_set(cvars, "msaa_levels", 4); - hashmap_bool_set(cvars, "debug_draw_enabled", 1); + hashmap_bool_set(cvars, "debug_draw_enabled", true); + hashmap_bool_set(cvars, "debug_draw_physics", true); hashmap_int_set(cvars, "video_driver_linux", VD_WAYLAND); hashmap_int_set(cvars, "debug_draw_mode", 0); hashmap_vec4_setf(cvars, "debug_draw_color", 1.f, 0.f, 0.f, 1.f); diff --git a/src/game/main.c b/src/game/main.c index 7c12af6..c84d8fc 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -152,6 +152,11 @@ int main(int argc, char** args) .cs_sphere_create = &physics_cs_sphere_create, .cs_capsule_create = &physics_cs_capsule_create, .cs_remove = &physics_cs_remove, + .cs_position_set = &physics_cs_position_set, + .cs_position_get = &physics_cs_position_get, + .cs_rotation_set = &physics_cs_rotation_set, + .cs_rotation_get = &physics_cs_rotation_get, + .cs_type_get = &physics_cs_type_get, .cs_data_set = &physics_cs_data_set, .cs_data_get = &physics_cs_data_get, .cs_plane_params_get = &physics_cs_plane_params_get, diff --git a/src/game/physics.c b/src/game/physics.c index f44fb94..a73935d 100644 --- a/src/game/physics.c +++ b/src/game/physics.c @@ -113,7 +113,7 @@ void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w) { - dReal rotation[4] = { 0 }; + dReal rotation[4] = { 0.f }; rotation[1] = x; rotation[2] = y; rotation[3] = z; @@ -229,12 +229,25 @@ Collision_Shape physics_cs_box_create(float x, float y, float z) } +int physics_cs_type_get(Collision_Shape shape) +{ + int geom_class = dGeomGetClass(shape); + switch(geom_class) + { + case dBoxClass: return CST_BOX; + case dSphereClass: return CST_SPHERE; + case dCylinderClass: return CST_CYLINDER; + case dTriMeshClass: return CST_TRIMESH; + default: return CST_UNKNOWN; + } +} + void physics_cs_box_params_get(Collision_Shape shape, float* x, float* y, float* z) { assert(x && y && z); *x = *y = *z = 0.f; - float lengths[3] = { 0.f }; - dGeomBoxGetLengths(shape, lengths); + dReal lengths[3] = { 0 }; + dGeomBoxGetLengths(shape, &lengths[0]); *x = lengths[0]; *y = lengths[1]; *z = lengths[2]; @@ -432,6 +445,65 @@ bool physics_cs_ray_cast(Collision_Shape ray, return out_rayhit->entity_id == -1 ? false : true; } +void physics_cs_position_get(Collision_Shape shape, float * x, float * y, float * z) +{ + assert(x && y && z); + if(dGeomGetClass(shape) == dPlaneClass) + { + *x = 0.f; + *y = 0.f; + *z = 0.f; + return; + } + + const dReal* pos = dGeomGetPosition(shape); + *x = pos[0]; + *y = pos[1]; + *z = pos[2]; +} + +void physics_cs_position_set(Collision_Shape shape, float x, float y, float z) +{ + if(dGeomGetClass(shape) == dPlaneClass) + return; + + dGeomSetPosition(shape, x, y, z); +} + +void physics_cs_rotation_get(Collision_Shape shape, float* x, float* y, float* z, float* w) +{ + assert(x && y && z && w); + + if(dGeomGetClass(shape) == dPlaneClass) + { + *x = 0.f; + *y = 0.f; + *z = 0.f; + *w = 1.f; + return; + } + + dReal rotation[4] = { 1, 0, 0, 0 }; + dGeomGetQuaternion(shape, &rotation[0]); + *x = rotation[1]; + *y = rotation[2]; + *z = rotation[3]; + *w = rotation[0]; +} + +void physics_cs_rotation_set(Collision_Shape shape, float x, float y, float z, float w) +{ + if(dGeomGetClass(shape) == dPlaneClass) + return; + + dReal rotation[4] = { 0.f }; + rotation[1] = x; + rotation[2] = y; + rotation[3] = z; + rotation[0] = w; + dGeomSetQuaternion(shape, &rotation[0]); +} + Collision_Shape physics_cs_ray_create(float length, bool first_contact, bool backface_cull) { dGeomID ray = dCreateRay(Physics.space, length); diff --git a/src/game/physics.h b/src/game/physics.h index 8aa8dfe..536542a 100644 --- a/src/game/physics.h +++ b/src/game/physics.h @@ -19,6 +19,7 @@ Collision_Shape physics_body_cs_get(Rigidbody body); void physics_body_cs_set(Rigidbody body, Collision_Shape shape); void physics_cs_remove(Collision_Shape shape); +int physics_cs_type_get(Collision_Shape shape); Collision_Shape physics_cs_plane_create(float a, float b, float c, float d); void physics_cs_plane_params_set(Collision_Shape shape, float a, float b, float c, float d); @@ -45,6 +46,12 @@ bool physics_cs_ray_cast(Collision_Shape ray, float pos_x, float pos_y, float pos_z, float dir_x, float dir_y, float dir_z); +void physics_cs_position_get(Collision_Shape shape, float* x, float* y, float* z); +void physics_cs_position_set(Collision_Shape shape, float x, float y, float z); + +void physics_cs_rotation_get(Collision_Shape shape, float* x, float* y, float* z, float* w); +void physics_cs_rotation_set(Collision_Shape shape, float x, float y, float z, float w); + Rigidbody physics_body_box_create(float x, float y, float z); Rigidbody physics_body_sphere_create(float radius); Rigidbody physics_body_capsule_create(float radius, float height); diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index eafef5b..5f20fab 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -255,7 +255,8 @@ void scene_setup(void) } platform->physics.cs_plane_create(0, 1, 0, 0); - Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5); + //Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5); + Rigidbody box = platform->physics.body_sphere_create(3.5); /*platform->physics.body_position_set(box, 0.f, 50.f, 0.f); platform->physics.body_mass_set(box, 10.f);*/ /*platform->physics.body_data_set(box, (void*)suz_id);*/ @@ -264,15 +265,17 @@ void scene_setup(void) entity_rigidbody_set(suz, box); suz->collision.on_collision = &on_collision_test; - Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0); - //Rigidbody ground_box = platform->physics.body_box_create(10, 10, 10); - /*platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f); - platform->physics.body_kinematic_set(ground_box);*/ - struct Entity* ground = entity_find("Ground"); - entity_collision_shape_set(ground, plane); - //entity_rigidbody_set(ground, ground_box); - /*platform->physics.body_data_set(ground_box, (void*)ground->id);*/ + Rigidbody sphere = platform->physics.body_sphere_create(3.5f); + struct Entity* sphere_ent = entity_find("Sphere_Ent"); + entity_rigidbody_set(sphere_ent, sphere); + //Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0); + Rigidbody ground_box = platform->physics.body_box_create(10, 5, 10); + platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f); + /*platform->physics.body_kinematic_set(ground_box);*/ + struct Entity* ground = entity_find("Ground"); + //entity_collision_shape_set(ground, plane); + entity_rigidbody_set(ground, ground_box); } void debug(float dt) @@ -525,8 +528,13 @@ void debug(float dt) im_end(); vec4 prim_color = {1.f, 1.f, 0.f, 1.f}; - im_cube(5.f, im_position, im_rot, prim_color, GDM_TRIANGLES); - im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES); + im_box(5.f, 2.f, 10.f, im_position, im_rot, prim_color, GDM_TRIANGLES); + + for(int i = 0; i < 10; i++) + { + im_position.x += i * 2.f; + im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES); + } } bool run(void) diff --git a/src/libsymmetry/im_render.c b/src/libsymmetry/im_render.c index f1bdcdc..2cf770c 100644 --- a/src/libsymmetry/im_render.c +++ b/src/libsymmetry/im_render.c @@ -100,7 +100,7 @@ void im_pos(float x, float y, float z) active_vertex_index++; } -void im_cube(float length, vec3 position, quat rotation, vec4 color, int draw_mode) +void im_box(float x, float y, float z, vec3 position, quat rotation, vec4 color, int draw_mode) { if(active_geom) { @@ -113,7 +113,7 @@ void im_cube(float length, vec3 position, quat rotation, vec4 color, int draw_mo active_geom->draw_mode = draw_mode; active_geom->prim_geom_index = geom_create_from_file("cube.symbres"); vec3_assign(&active_geom->position, &position); - vec3 scale = { length, length, length }; + vec3 scale = { x, y, z}; vec3_assign(&active_geom->scale, &scale); vec4_assign(&active_geom->color, &color); quat_assign(&active_geom->rotation, &rotation); diff --git a/src/libsymmetry/im_render.h b/src/libsymmetry/im_render.h index 9450910..45a6b32 100644 --- a/src/libsymmetry/im_render.h +++ b/src/libsymmetry/im_render.h @@ -40,7 +40,7 @@ void im_init(void); void im_cleanup(void); void im_begin(vec3 position, quat rotation, vec3 scale, vec4 color, int draw_mode); void im_pos(float x, float y, float z); -void im_cube(float length, vec3 position, quat rotation, vec4 color, int draw_mode); +void im_box(float x, float y, float z, vec3 position, quat rotation, vec4 color, int draw_mode); void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode); void im_end(void); void im_render(struct Entity* active_viewer); diff --git a/src/libsymmetry/renderer.c b/src/libsymmetry/renderer.c index 41258fb..592655a 100644 --- a/src/libsymmetry/renderer.c +++ b/src/libsymmetry/renderer.c @@ -408,6 +408,51 @@ void renderer_draw(struct Entity* active_viewer) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } + // Debug Physics render + if(hashmap_bool_get(cvars, "debug_draw_physics")) + { + static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; + struct Entity* entity_list = entity_get_all(); + for(int i = 0; i < array_len(entity_list); i++) + { + if(!entity_list[i].has_collision) continue; + struct Entity* entity = &entity_list[i]; + + //Get collision mesh and it's props then render it + vec3 pos = {0.f}; + quat rot = {0.f, 0.f, 0.f, 1.f }; + if(entity->collision.rigidbody) + { + platform->physics.body_position_get(entity->collision.rigidbody, &pos.x, &pos.y, &pos.z); + platform->physics.body_rotation_get(entity->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w); + } + else + { + platform->physics.cs_position_get(entity->collision.collision_shape, &pos.x, &pos.y, &pos.z); + platform->physics.cs_rotation_get(entity->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w); + } + + int collision_shape_type = platform->physics.cs_type_get(entity->collision.collision_shape); + switch(collision_shape_type) + { + case CST_SPHERE: + { + float radius = platform->physics.cs_sphere_radius_get(entity->collision.collision_shape); + im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES); + } + break; + case CST_BOX: + { + float x = 0.f, y = 0.f, z = 0.f; + platform->physics.cs_box_params_get(entity->collision.collision_shape, &x, &y, &z); + im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); + }; + break; + default: break; + } + } + } + //Immediate mode geometry render im_render(active_viewer); @@ -508,6 +553,7 @@ void renderer_settings_get(struct Render_Settings* settings) settings->fog.max_dist = hashmap_float_get(cvars, "fog_max_dist"); settings->fog.color = hashmap_vec3_get(cvars, "fog_color"); settings->debug_draw_enabled = hashmap_bool_get(cvars, "debug_draw_enabled"); + settings->debug_draw_physics = hashmap_bool_get(cvars, "debug_draw_physics"); settings->debug_draw_mode = hashmap_int_get(cvars, "debug_draw_mode"); settings->debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); settings->ambient_light = hashmap_vec3_get(cvars, "ambient_light"); @@ -522,6 +568,7 @@ void renderer_settings_set(const struct Render_Settings* settings) hashmap_float_set(cvars, "fog_max_dist", settings->fog.max_dist); hashmap_vec3_set(cvars, "fog_color", &settings->fog.color); hashmap_bool_set(cvars, "debug_draw_enabled", settings->debug_draw_enabled); + hashmap_bool_set(cvars, "debug_draw_physics", settings->debug_draw_physics); hashmap_int_set(cvars, "debug_draw_mode", settings->debug_draw_mode); hashmap_vec4_set(cvars, "debug_draw_color", &settings->debug_draw_color); hashmap_vec3_set(cvars, "ambient_light", &settings->ambient_light); diff --git a/src/libsymmetry/renderer.h b/src/libsymmetry/renderer.h index b73c304..1db71f6 100644 --- a/src/libsymmetry/renderer.h +++ b/src/libsymmetry/renderer.h @@ -26,9 +26,10 @@ struct Render_Settings { struct Fog fog; vec3 ambient_light; - int debug_draw_enabled; + bool debug_draw_enabled; vec4 debug_draw_color; int debug_draw_mode; + bool debug_draw_physics; }; struct Entity;