Implemented getting/setting collision shape values and separated collision shapes from rigidbodies

dev
Shariq Shah 8 years ago
parent 0547958961
commit 0af53d7456
  1. 5
      README.md
  2. 391
      src/common/common.h
  3. 40
      src/game/main.c
  4. 623
      src/game/physics.c
  5. 30
      src/game/physics.h
  6. 7
      src/libsymmetry/game.c

@ -156,6 +156,8 @@
- ## TODO
- Update physics if entity position/rotation/scale etc are changed
- Physics raycasting
- Physics forces/torque etc
- Fix lights type not being correctly saved/loaded from file
- Physics Trimesh support
- Debug physics mesh drawing
@ -358,3 +360,6 @@
* Got rid of pkg-confg and system-installed SDL2 dependancy on linux and instead put custom compiled SDL libs in libs folder similar to how we're handling it in windows
* Proper physics time-step and speed
* Proper handling of rigidbody associated with an entity and notifying it of movement or collision
* Added physics spheres and other primitive shapes
* Separated collision shape and rigidbody
* Implemented Getting/Modifying primitive physics shapes' values like length, radius etc

@ -1,186 +1,211 @@
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
#include "num_types.h"
#ifdef GAME_LIB
extern struct Platform_Api* platform;
#endif
#ifdef GAME
extern struct Game_Api game;
#endif
struct Window;
struct Hashmap;
struct Sound_Source_Buffer;
//Physics Decls
typedef void* Rigidbody;
typedef void (*RigidbodyMoveCB)(Rigidbody);
typedef void (*RigidbodyColCB)(Rigidbody, Rigidbody);
// Function Pointer decls
typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt);
typedef void (*Mousebutton_Event_Func) (int button, int state, int x, int y, int8 num_clicks);
typedef void (*Mousemotion_Event_Func) (int x, int y, int xrel, int yrel);
typedef void (*Mousewheel_Event_Func) (int x, int y);
typedef void (*Windowresize_Event_Func) (int x, int y);
typedef void (*Textinput_Event_Func) (const char* text);
enum Directory_Type
{
DIRT_USER, /* User directory or preferences directory */
DIRT_INSTALL, /* Directory where the game's assets are, usually alongside the game's executable where the game is installed */
DIRT_EXECUTABLE, /* Directory where the game's executable is located */
DIRT_COUNT
};
enum Sound_Source_Type
{
ST_WAV = 0,
ST_WAV_STREAM
};
enum Sound_Attenuation_Type
{
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
#include "num_types.h"
#ifdef GAME_LIB
extern struct Platform_Api* platform;
#endif
#ifdef GAME
extern struct Game_Api game;
#endif
struct Window;
struct Hashmap;
struct Sound_Source_Buffer;
//Physics Decls
typedef void* Rigidbody;
typedef void* Collision_Shape;
typedef void (*RigidbodyMoveCB)(Rigidbody);
typedef void (*RigidbodyColCB)(Rigidbody, Rigidbody);
// Function Pointer decls
typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt);
typedef void (*Mousebutton_Event_Func) (int button, int state, int x, int y, int8 num_clicks);
typedef void (*Mousemotion_Event_Func) (int x, int y, int xrel, int yrel);
typedef void (*Mousewheel_Event_Func) (int x, int y);
typedef void (*Windowresize_Event_Func) (int x, int y);
typedef void (*Textinput_Event_Func) (const char* text);
enum Directory_Type
{
DIRT_USER, /* User directory or preferences directory */
DIRT_INSTALL, /* Directory where the game's assets are, usually alongside the game's executable where the game is installed */
DIRT_EXECUTABLE, /* Directory where the game's executable is located */
DIRT_COUNT
};
enum Sound_Source_Type
{
ST_WAV = 0,
ST_WAV_STREAM
};
enum Sound_Attenuation_Type
{
SA_NONE = 0, // No attenuation
SA_INVERSE, // Inverse distance attenuation model
SA_LINEAR, // Linear distance attenuation model
SA_EXPONENTIAL // Exponential distance attenuation model
};
struct Physics_Api
{
void (*init)(void);
void (*cleanup)(void);
void (*step)(float);
void (*gravity_set)(float x, float y, float z);
void (*gravity_get)(float* x, float* y, float* z);
void (*body_position_set)(Rigidbody body, float x, float y, float z);
void (*body_position_get)(Rigidbody body, float* x, float* y, float* z);
void (*body_rotation_set)(Rigidbody body, float x, float y, float z, float w);
void (*body_rotation_get)(Rigidbody body, float* x, float* y, float* z, float* w);
Rigidbody (*plane_create)(float a, float b, float c, float d);
Rigidbody (*box_create)(float length, float width, float height);
void (*body_set_moved_callback)(RigidbodyMoveCB callback);
void (*body_set_collision_callback)(RigidbodyColCB callback);
void (*body_kinematic_set)(Rigidbody body);
void (*body_mass_set)(Rigidbody body, float mass);
float (*body_mass_get)(Rigidbody body);
void* (*body_data_get)(Rigidbody body);
void (*body_data_set)(Rigidbody body, void* data);
};
struct Sound_Api
{
void (*update_3d)(void);
void (*volume_set)(float volume);
void (*listener_update)(float apos_x, float apos_y, float apos_z,
float afwd_x, float afwd_y, float afwd_z,
float aup_x, float aup_y, float aup_z);
void (*source_instance_update_position)(uint source_instance, float apos_x, float apos_y, float apos_z);
uint (*source_instance_create)(struct Sound_Source_Buffer* source, bool is3d);
void (*source_instance_destroy)(uint source_instance);
void (*source_instance_volume_set)(uint source_instance, float volume);
void (*source_instance_loop_set)(uint source_instance, bool loop);
void (*source_instance_play)(uint source_instance);
void (*source_instance_pause)(uint source_instance);
void (*source_instance_rewind)(uint source_instance);
void (*source_instance_stop)(uint source_instance);
void (*source_instance_min_max_distance_set)(uint source_instance, float min_distance, float max_distance);
void (*source_instance_attenuation_set)(uint source_instance, int attenuation_type, float rolloff_factor);
float (*source_instance_volume_get)(uint source_instance);
bool (*source_instance_loop_get)(uint source_instance);
bool (*source_instance_is_paused)(uint source_instance);
struct Sound_Source_Buffer* (*source_create)(const char* filename, int type);
struct Sound_Source_Buffer* (*source_get)(const char* name);
void (*source_destroy)(const char* buffer_name);
void (*source_volume_set)(struct Sound_Source_Buffer* source, float volume);
void (*source_loop_set)(struct Sound_Source_Buffer* source, bool loop);
void (*source_stop_all)(struct Sound_Source_Buffer* source);
void (*source_min_max_distance_set)(struct Sound_Source_Buffer* source, float min_distance, float max_distance);
};
struct Window_Api
{
struct Window* (*create)(const char* title, int width, int height, int msaa, int msaa_levels);
void (*destroy)(struct Window* window);
void (*show)(struct Window* window);
void (*hide)(struct Window* window);
void (*raise)(struct Window* window);
void (*make_context_current)(struct Window* window);
void (*set_size)(struct Window* window, int width, int height);
void (*get_size)(struct Window* window, int* out_width, int* out_height);
void (*get_drawable_size)(struct Window* window, int* out_width, int* out_height);
void (*swap_buffers)(struct Window* window);
int (*fullscreen_set)(struct Window* window, int fullscreen);
};
struct File_Api
{
char* (*read)(const int directory_type, const char* path, const char* mode, long* file_size);
FILE* (*open)(const int directory_type, const char* path, const char* mode);
bool (*copy)(const int directory_type, const char* source, const char* destination);
bool (*delete)(const int directory_type, const char* filename);
};
struct Config_Api
{
bool (*load)(const char* filename, int directory_type);
bool (*save)(const char* filename, int directory_types);
struct Hashmap* (*get)(void);
};
struct Log_Api
{
FILE* (*file_handle_get)(void);
};
struct Platform_Api
{
// General platform api
void (*poll_events)(bool* out_quit);
void (*keyboard_callback_set)(Keyboard_Event_Func func);
void (*mousebutton_callback_set)(Mousebutton_Event_Func func);
void (*mousemotion_callback_set)(Mousemotion_Event_Func func);
void (*mousewheel_callback_set)(Mousewheel_Event_Func func);
void (*windowresize_callback_set)(Windowresize_Event_Func func);
void (*textinput_callback_set)(Textinput_Event_Func func);
int (*is_key_pressed)(int key);
int (*mousebutton_state_get)(uint button);
void (*mouse_position_get)(int* x, int* y);
void (*mouse_delta_get)(int* x, int* y);
void (*mouse_position_set)(struct Window* window, int x, int y);
void (*mouse_global_position_set)(int x, int y);
void (*mouse_relative_mode_set)(int relative_mode);
int (*mouse_relative_mode_get)(void);
uint32 (*ticks_get)(void);
char* (*install_directory_get)(void);
char* (*user_directory_get)(const char* organization, const char* application);
void (*clipboard_text_set)(const char* text);
char* (*clipboard_text_get)(void);
int (*key_from_name)(const char* key_name);
const char* (*key_name_get)(int key);
void* (*load_function_gl)(const char* name);
void (*reload_game_lib)(void);
struct Window_Api window;
struct Sound_Api sound;
struct File_Api file;
struct Config_Api config;
struct Log_Api log;
struct Physics_Api physics;
};
struct Game_Api
{
bool (*init)(struct Window*, struct Platform_Api* platform_api);
void (*cleanup)(void);
};
#endif
SA_EXPONENTIAL // Exponential distance attenuation model
};
struct Physics_Api
{
void (*init)(void);
void (*cleanup)(void);
void (*step)(float);
void (*gravity_set)(float x, float y, float z);
void (*gravity_get)(float* x, float* y, float* z);
void (*cs_remove)(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);
void (*cs_plane_params_get)(Collision_Shape shape, float* a, float* b, float* c, float* d);
Collision_Shape (*cs_box_create)(float x, float y, float z);
void (*cs_box_params_set)(Collision_Shape shape, float x, float y, float z);
void (*cs_box_params_get)(Collision_Shape shape, float* x, float* y, float* z);
Collision_Shape (*cs_sphere_create)(float radius);
void (*cs_shpere_radius_set)(Collision_Shape shape, float radius);
float (*cs_sphere_radius_get)(Collision_Shape shape);
Collision_Shape (*cs_capsule_create)(float radius, float length);
void (*cs_capsule_params_set)(Collision_Shape shape, float radius, float length);
void (*cs_capsule_params_get)(Collision_Shape shape, float* radius, float* length);
void (*body_remove)(Rigidbody body);
Rigidbody (*body_box_create)(float length, float width, float height);
Rigidbody (*body_sphere_create)(float radius);
Rigidbody (*body_capsule_create)(float radius, float height);
Collision_Shape (*body_cs_get)(Rigidbody body);
void (*body_cs_set)(Rigidbody body, Collision_Shape shape);
void (*body_position_set)(Rigidbody body, float x, float y, float z);
void (*body_position_get)(Rigidbody body, float* x, float* y, float* z);
void (*body_rotation_set)(Rigidbody body, float x, float y, float z, float w);
void (*body_rotation_get)(Rigidbody body, float* x, float* y, float* z, float* w);
void (*body_set_moved_callback)(RigidbodyMoveCB callback);
void (*body_set_collision_callback)(RigidbodyColCB callback);
void (*body_kinematic_set)(Rigidbody body);
void (*body_mass_set)(Rigidbody body, float mass);
float (*body_mass_get)(Rigidbody body);
void* (*body_data_get)(Rigidbody body);
void (*body_data_set)(Rigidbody body, void* data);
void (*body_force_add)(Rigidbody body, float fx, float fy, float fz);
};
struct Sound_Api
{
void (*update_3d)(void);
void (*volume_set)(float volume);
void (*listener_update)(float apos_x, float apos_y, float apos_z,
float afwd_x, float afwd_y, float afwd_z,
float aup_x, float aup_y, float aup_z);
void (*source_instance_update_position)(uint source_instance, float apos_x, float apos_y, float apos_z);
uint (*source_instance_create)(struct Sound_Source_Buffer* source, bool is3d);
void (*source_instance_destroy)(uint source_instance);
void (*source_instance_volume_set)(uint source_instance, float volume);
void (*source_instance_loop_set)(uint source_instance, bool loop);
void (*source_instance_play)(uint source_instance);
void (*source_instance_pause)(uint source_instance);
void (*source_instance_rewind)(uint source_instance);
void (*source_instance_stop)(uint source_instance);
void (*source_instance_min_max_distance_set)(uint source_instance, float min_distance, float max_distance);
void (*source_instance_attenuation_set)(uint source_instance, int attenuation_type, float rolloff_factor);
float (*source_instance_volume_get)(uint source_instance);
bool (*source_instance_loop_get)(uint source_instance);
bool (*source_instance_is_paused)(uint source_instance);
struct Sound_Source_Buffer* (*source_create)(const char* filename, int type);
struct Sound_Source_Buffer* (*source_get)(const char* name);
void (*source_destroy)(const char* buffer_name);
void (*source_volume_set)(struct Sound_Source_Buffer* source, float volume);
void (*source_loop_set)(struct Sound_Source_Buffer* source, bool loop);
void (*source_stop_all)(struct Sound_Source_Buffer* source);
void (*source_min_max_distance_set)(struct Sound_Source_Buffer* source, float min_distance, float max_distance);
};
struct Window_Api
{
struct Window* (*create)(const char* title, int width, int height, int msaa, int msaa_levels);
void (*destroy)(struct Window* window);
void (*show)(struct Window* window);
void (*hide)(struct Window* window);
void (*raise)(struct Window* window);
void (*make_context_current)(struct Window* window);
void (*set_size)(struct Window* window, int width, int height);
void (*get_size)(struct Window* window, int* out_width, int* out_height);
void (*get_drawable_size)(struct Window* window, int* out_width, int* out_height);
void (*swap_buffers)(struct Window* window);
int (*fullscreen_set)(struct Window* window, int fullscreen);
};
struct File_Api
{
char* (*read)(const int directory_type, const char* path, const char* mode, long* file_size);
FILE* (*open)(const int directory_type, const char* path, const char* mode);
bool (*copy)(const int directory_type, const char* source, const char* destination);
bool (*delete)(const int directory_type, const char* filename);
};
struct Config_Api
{
bool (*load)(const char* filename, int directory_type);
bool (*save)(const char* filename, int directory_types);
struct Hashmap* (*get)(void);
};
struct Log_Api
{
FILE* (*file_handle_get)(void);
};
struct Platform_Api
{
// General platform api
void (*poll_events)(bool* out_quit);
void (*keyboard_callback_set)(Keyboard_Event_Func func);
void (*mousebutton_callback_set)(Mousebutton_Event_Func func);
void (*mousemotion_callback_set)(Mousemotion_Event_Func func);
void (*mousewheel_callback_set)(Mousewheel_Event_Func func);
void (*windowresize_callback_set)(Windowresize_Event_Func func);
void (*textinput_callback_set)(Textinput_Event_Func func);
int (*is_key_pressed)(int key);
int (*mousebutton_state_get)(uint button);
void (*mouse_position_get)(int* x, int* y);
void (*mouse_delta_get)(int* x, int* y);
void (*mouse_position_set)(struct Window* window, int x, int y);
void (*mouse_global_position_set)(int x, int y);
void (*mouse_relative_mode_set)(int relative_mode);
int (*mouse_relative_mode_get)(void);
uint32 (*ticks_get)(void);
char* (*install_directory_get)(void);
char* (*user_directory_get)(const char* organization, const char* application);
void (*clipboard_text_set)(const char* text);
char* (*clipboard_text_get)(void);
int (*key_from_name)(const char* key_name);
const char* (*key_name_get)(int key);
void* (*load_function_gl)(const char* name);
void (*reload_game_lib)(void);
struct Window_Api window;
struct Sound_Api sound;
struct File_Api file;
struct Config_Api config;
struct Log_Api log;
struct Physics_Api physics;
};
struct Game_Api
{
bool (*init)(struct Window*, struct Platform_Api* platform_api);
void (*cleanup)(void);
};
#endif

@ -79,15 +79,15 @@ int main(int argc, char** args)
.source_instance_stop = &sound_source_instance_stop,
.source_instance_min_max_distance_set = &sound_source_instance_min_max_distance_set,
.source_instance_attenuation_set = &sound_source_instance_attenuation_set,
.source_instance_volume_get = &sound_source_instance_volume_get,
.source_instance_loop_get = &sound_source_instance_loop_get,
.source_instance_volume_get = &sound_source_instance_volume_get,
.source_instance_loop_get = &sound_source_instance_loop_get,
.source_instance_is_paused = &sound_source_instance_is_paused,
.source_create = &sound_source_create,
.source_get = &sound_source_get,
.source_destroy = &sound_source_destroy,
.source_volume_set = &sound_source_volume_set,
.source_loop_set = &sound_source_loop_set,
.source_stop_all = &sound_source_stop_all,
.source_create = &sound_source_create,
.source_get = &sound_source_get,
.source_destroy = &sound_source_destroy,
.source_volume_set = &sound_source_volume_set,
.source_loop_set = &sound_source_loop_set,
.source_stop_all = &sound_source_stop_all,
.source_min_max_distance_set = &sound_source_min_max_distance_set
},
.window =
@ -127,6 +127,7 @@ int main(int argc, char** args)
.step = &physics_step,
.gravity_set = &physics_gravity_set,
.gravity_get = &physics_gravity_get,
.body_position_set = &physics_body_position_set,
.body_position_get = &physics_body_position_get,
.body_rotation_set = &physics_body_rotation_set,
@ -138,8 +139,27 @@ int main(int argc, char** args)
.body_data_get = &physics_body_data_get,
.body_set_moved_callback = &physics_body_set_moved_callback,
.body_set_collision_callback = &physics_body_set_collision_callback,
.plane_create = &physics_plane_create,
.box_create = &physics_box_create
.body_force_add = &physics_body_force_add,
.body_box_create = &physics_body_box_create,
.body_sphere_create = &physics_body_sphere_create,
.body_capsule_create = &physics_body_capsule_create,
.body_remove = &physics_body_remove,
.body_cs_set = &physics_body_cs_set,
.body_cs_get = &physics_body_cs_get,
.cs_box_create = &physics_cs_box_create,
.cs_plane_create = &physics_cs_plane_create,
.cs_sphere_create = &physics_cs_sphere_create,
.cs_capsule_create = &physics_cs_capsule_create,
.cs_remove = &physics_cs_remove,
.cs_plane_params_get = &physics_cs_plane_params_get,
.cs_capsule_params_get = &physics_cs_capsule_params_get,
.cs_box_params_get = &physics_cs_box_params_get,
.cs_sphere_radius_get = &physics_cs_sphere_radius_get,
.cs_plane_params_set = &physics_cs_plane_params_set,
.cs_capsule_params_set = &physics_cs_capsule_params_set,
.cs_box_params_set = &physics_cs_box_params_set,
.cs_shpere_radius_set = &physics_cs_sphere_radius_set
}
};

@ -1,229 +1,385 @@
#include "physics.h"
#include "../common/log.h"
#include <ode/ode.h>
#include <assert.h>
static struct
{
dWorldID world;
dSpaceID space;
dJointGroupID contact_group;
double step_size;
RigidbodyColCB on_collision;
RigidbodyMoveCB on_move;
}
Physics;
static void physics_near_callback(void* data, dGeomID body1, dGeomID body2);
void physics_init(void)
{
if(dInitODE2(0) == 0)
{
log_error("physics:init", "Failed to initialize ode");
return;
}
dAllocateODEDataForThread(dAllocateMaskAll);
Physics.world = dWorldCreate();
if(!Physics.world)
{
log_error("physics:init", "Physics world created!");
}
else
{
log_message("Physics world created");
Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.016;
dWorldSetCFM(Physics.world,1e-5);
dWorldSetAutoDisableFlag(Physics.world, 1);
dWorldSetLinearDamping(Physics.world, 0.00001);
dWorldSetAngularDamping(Physics.world, 0.005);
dWorldSetMaxAngularSpeed(Physics.world, 200);
dWorldSetContactMaxCorrectingVel(Physics.world,0.1);
dWorldSetContactSurfaceLayer(Physics.world,0.001);
}
}
void physics_cleanup(void)
{
dJointGroupDestroy(Physics.contact_group);
dSpaceDestroy(Physics.space);
if(Physics.world)
{
dWorldDestroy(Physics.world);
}
dCleanupODEAllDataForThread();
dCloseODE();
}
void physics_step(float delta_time)
{
int steps = (int)ceilf(delta_time / Physics.step_size);
for(int i = 0; i < steps; i++)
{
dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group);
}
}
void physics_gravity_set(float x, float y, float z)
{
dWorldSetGravity(Physics.world, x, y, z);
}
void physics_gravity_get(float * x, float * y, float * z)
{
assert(x && y && z);
dVector3 gravity;
dWorldGetGravity(Physics.world, gravity);
*x = gravity[0];
*y = gravity[1];
*z = gravity[2];
}
void physics_body_position_get(Rigidbody body, float * x, float * y, float * z)
{
assert(x && y && z);
const dReal* position = dBodyGetPosition(body);
*x = position[0];
*y = position[1];
*z = position[2];
}
void physics_body_position_set(Rigidbody body, float x, float y, float z)
{
dBodySetPosition(body, x, y, z);
}
void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, float * w)
{
assert(x && y && z && w);
const dReal* rotation = dBodyGetQuaternion(body);
*x = rotation[1];
*y = rotation[2];
*z = rotation[3];
*w = rotation[0];
}
void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w)
{
dReal rotation[4] = { 0 };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dBodySetQuaternion(body, &rotation[0]);
}
void physics_near_callback(void* data, dGeomID o1, dGeomID o2)
{
assert(o1);
assert(o2);
//if(dGeomIsSpace(o1) || dGeomIsSpace(o2))
//{
// fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2);
// // colliding a space with something
// dSpaceCollide2(o1, o2, data, &physics_near_callback);
// // Note we do not want to test intersections within a space,
// // only between spaces.
// return;
//}
// fprintf(stderr,"testing geoms %p %p\n", o1, o2);
// exit without doing anything if the two bodies are connected by a joint
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))
return;
if(o1 == o2)
log_message("same body!");
#define MAX_CONTACTS 8
dContact contact[MAX_CONTACTS];
for (int i = 0; i < MAX_CONTACTS; i++)
{
//contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.1;
contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 0.01;
}
int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact));
if(n > 0)
{
Physics.on_collision(b1, b2);
for(int i = 0; i < n; i++)
{
//contact[i].surface.slip1 = 0.7;
//contact[i].surface.slip2 = 0.7;
//contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
//contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.soft_erp = 0.96;
//contact[i].surface.soft_cfm = 0.04;
dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]);
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
}
}
Rigidbody physics_plane_create(float a, float b, float c, float d)
{
dGeomID plane = dCreatePlane(Physics.space, a, b, c, d);
/*dBodyID body = dBodyCreate(Physics.world);
dGeomSetBody(plane, body);*/
return plane;
}
Rigidbody physics_box_create(float length, float width, float height)
{
dGeomID box = dCreateBox(Physics.space, length, height, width);
dBodyID body = dBodyCreate(Physics.world);
dGeomSetBody(box, body);
dBodySetAngularVel(body, 0, 0, 0);
dBodySetLinearVel(body, 0, 0, 0);
dBodySetTorque(body, 0, 0, 0);
dBodySetMovedCallback(body, Physics.on_move);
return body;
}
void physics_body_set_moved_callback(RigidbodyMoveCB callback)
{
Physics.on_move = callback;
#include "physics.h"
#include "../common/log.h"
#include <ode/ode.h>
#include <assert.h>
static struct
{
dWorldID world;
dSpaceID space;
dJointGroupID contact_group;
double step_size;
RigidbodyColCB on_collision;
RigidbodyMoveCB on_move;
}
Physics;
static void physics_near_callback(void* data, dGeomID body1, dGeomID body2);
void physics_init(void)
{
if(dInitODE2(0) == 0)
{
log_error("physics:init", "Failed to initialize ode");
return;
}
dAllocateODEDataForThread(dAllocateMaskAll);
Physics.world = dWorldCreate();
if(!Physics.world)
{
log_error("physics:init", "Physics world created!");
}
else
{
log_message("Physics world created");
Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.016;
dWorldSetCFM(Physics.world,1e-5);
dWorldSetAutoDisableFlag(Physics.world, 1);
dWorldSetLinearDamping(Physics.world, 0.00001);
dWorldSetAngularDamping(Physics.world, 0.005);
dWorldSetMaxAngularSpeed(Physics.world, 200);
dWorldSetContactMaxCorrectingVel(Physics.world,0.1);
dWorldSetContactSurfaceLayer(Physics.world,0.001);
}
}
void physics_cleanup(void)
{
dJointGroupDestroy(Physics.contact_group);
dSpaceDestroy(Physics.space);
if(Physics.world)
{
dWorldDestroy(Physics.world);
}
dCleanupODEAllDataForThread();
dCloseODE();
}
void physics_step(float delta_time)
{
int steps = (int)ceilf(delta_time / Physics.step_size);
for(int i = 0; i < steps; i++)
{
dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group);
}
}
void physics_gravity_set(float x, float y, float z)
{
dWorldSetGravity(Physics.world, x, y, z);
}
void physics_gravity_get(float * x, float * y, float * z)
{
assert(x && y && z);
dVector3 gravity;
dWorldGetGravity(Physics.world, gravity);
*x = gravity[0];
*y = gravity[1];
*z = gravity[2];
}
void physics_body_position_get(Rigidbody body, float * x, float * y, float * z)
{
assert(x && y && z);
const dReal* position = dBodyGetPosition(body);
*x = position[0];
*y = position[1];
*z = position[2];
}
void physics_body_position_set(Rigidbody body, float x, float y, float z)
{
dBodySetPosition(body, x, y, z);
}
void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, float * w)
{
assert(x && y && z && w);
const dReal* rotation = dBodyGetQuaternion(body);
*x = rotation[1];
*y = rotation[2];
*z = rotation[3];
*w = rotation[0];
}
void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w)
{
dReal rotation[4] = { 0 };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dBodySetQuaternion(body, &rotation[0]);
}
void physics_near_callback(void* data, dGeomID o1, dGeomID o2)
{
assert(o1);
assert(o2);
//if(dGeomIsSpace(o1) || dGeomIsSpace(o2))
//{
// fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2);
// // colliding a space with something
// dSpaceCollide2(o1, o2, data, &physics_near_callback);
// // Note we do not want to test intersections within a space,
// // only between spaces.
// return;
//}
// fprintf(stderr,"testing geoms %p %p\n", o1, o2);
// exit without doing anything if the two bodies are connected by a joint
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))
return;
if(o1 == o2)
log_message("same body!");
#define MAX_CONTACTS 8
dContact contact[MAX_CONTACTS];
for (int i = 0; i < MAX_CONTACTS; i++)
{
//contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.1;
contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 0.01;
}
int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact));
if(n > 0)
{
Physics.on_collision(b1, b2);
for(int i = 0; i < n; i++)
{
//contact[i].surface.slip1 = 0.7;
//contact[i].surface.slip2 = 0.7;
//contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
//contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.soft_erp = 0.96;
//contact[i].surface.soft_cfm = 0.04;
dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]);
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
}
}
Collision_Shape physics_body_cs_get(Rigidbody body)
{
return dBodyGetFirstGeom(body);
}
void physics_body_cs_set(Rigidbody body, Collision_Shape shape)
{
dGeomSetBody(shape, body);
}
Collision_Shape physics_cs_plane_create(float a, float b, float c, float d)
{
dGeomID plane = dCreatePlane(Physics.space, a, b, c, d);
return plane;
}
void physics_cs_plane_params_set(Collision_Shape shape, float a, float b, float c, float d)
{
dGeomPlaneSetParams(shape, a, b, c, d);
}
void physics_cs_plane_params_get(Collision_Shape shape, float* a, float* b, float* c, float* d)
{
assert(a && b && c && d);
*a = *b = *c = *d = 0.f;
float result[4] = { 0.f };
dGeomPlaneGetParams(shape, result);
*a = result[0];
*b = result[1];
*c = result[2];
*d = result[3];
}
Collision_Shape physics_cs_box_create(float x, float y, float z)
{
dGeomID box = dCreateBox(Physics.space, x, y, z);
if(!box)
{
log_error("physics:cs_box_create", "Failed to create box collision shape");
}
return box;
}
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);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
}
void physics_cs_box_params_set(Collision_Shape shape, float x, float y, float z)
{
dGeomBoxSetLengths(shape, x, y, z);
}
Collision_Shape physics_cs_sphere_create(float radius)
{
dGeomID sphere = dCreateSphere(Physics.space, radius);
if(!sphere)
{
log_error("physics:cs_sphere_create", "Failed to create sphere collision shape");
}
return sphere;
}
float physics_cs_sphere_radius_get(Collision_Shape shape)
{
return dGeomSphereGetRadius(shape);
}
void physics_cs_sphere_radius_set(Collision_Shape shape, float radius)
{
dGeomSphereSetRadius(shape, radius);
}
Collision_Shape physics_cs_capsule_create(float radius, float length)
{
dGeomID capsule = dCreateCapsule(Physics.space, radius, length);
if(!capsule)
{
log_error("physics:cs_capsule_create", "Failed to create capsule collision shape");
}
return capsule;
}
void physics_cs_capsule_params_get(Collision_Shape shape, float* radius, float* length)
{
assert(radius && length);
*radius = *length = 0.f;
dGeomCapsuleGetParams(shape, radius, length);
}
void physics_cs_capsule_params_set(Collision_Shape shape, float radius, float length)
{
dGeomCapsuleSetParams(shape, radius, length);
}
void physics_box_params_get(Rigidbody body, float* x, float* y, float* z)
{
assert(x && y && z);
*x = *y = *z = 0.f;
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
float lengths[3] = { 0.f };
dGeomBoxGetLengths(box, lengths);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
}
void physics_box_params_set(Rigidbody body, float x, float y, float z)
{
assert(x && y && z);
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
dGeomBoxSetLengths(box, x, y, z);
}
Rigidbody physics_body_box_create(float x, float y, float z)
{
Rigidbody body = NULL;
Collision_Shape box = physics_cs_box_create(x, y, z);
if(box)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, box);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
}
Rigidbody physics_body_sphere_create(float radius)
{
Rigidbody body = NULL;
Collision_Shape sphere = physics_cs_sphere_create(radius);
if(sphere)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, sphere);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
}
Rigidbody physics_body_capsule_create(float radius, float length)
{
Rigidbody body = NULL;
Collision_Shape capsule = physics_cs_capsule_create(radius, length);
if(capsule)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, capsule);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
}
void physics_body_force_add(Rigidbody body, float fx, float fy, float fz)
{
dBodyAddForce(body, fx, fy, fz);
}
void physics_body_set_moved_callback(RigidbodyMoveCB callback)
{
Physics.on_move = callback;
}
void physics_body_set_collision_callback(RigidbodyColCB callback)
{
Physics.on_collision = callback;
}
float physics_body_mass_get(Rigidbody body)
{
return 0.0f;
}
void physics_body_mass_set(Rigidbody body, float mass)
{
/*dMass dmass;
dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/
}
float physics_body_mass_get(Rigidbody body)
{
return 0.0f;
}
void physics_body_mass_set(Rigidbody body, float mass)
{
/*dMass dmass;
dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/
}
void physics_body_data_set(Rigidbody body, void * data)
@ -234,9 +390,22 @@ void physics_body_data_set(Rigidbody body, void * data)
void * physics_body_data_get(Rigidbody body)
{
return dBodyGetData(body);
}
void physics_body_kinematic_set(Rigidbody body)
{
dBodySetKinematic(body);
}
}
void physics_body_kinematic_set(Rigidbody body)
{
dBodySetKinematic(body);
}
void physics_body_remove(Rigidbody body)
{
dGeomID shape = dBodyGetFirstGeom(body);
if(shape)
physics_cs_remove(shape);
dBodyDestroy(body);
}
void physics_cs_remove(Collision_Shape shape)
{
dGeomDestroy(shape);
}

@ -15,8 +15,32 @@ void physics_body_position_set(Rigidbody body, float x, float y, float z);
void physics_body_rotation_get(Rigidbody body, float* x, float* y, float* z, float* w);
void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w);
Rigidbody physics_plane_create(float a, float b, float c, float d);
Rigidbody physics_box_create(float length, float width, float height);
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);
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);
void physics_cs_plane_params_get(Collision_Shape shape, float* a, float* b, float* c, float* d);
Collision_Shape physics_cs_box_create(float x, float y, float z);
void physics_cs_box_params_get(Collision_Shape shape, float* x, float* y, float* z);
void physics_cs_box_params_set(Collision_Shape shape, float x, float y, float z);
Collision_Shape physics_cs_sphere_create(float radius);
float physics_cs_sphere_radius_get(Collision_Shape shape);
void physics_cs_sphere_radius_set(Collision_Shape shape, float radius);
Collision_Shape physics_cs_capsule_create(float radius, float height);
void physics_cs_capsule_params_get(Collision_Shape shape, float* radius, float* height);
void physics_cs_capsule_params_set(Collision_Shape shape, float radius, float height);
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);
void physics_body_remove(Rigidbody body);
void physics_body_set_moved_callback(RigidbodyMoveCB callback);
void physics_body_set_collision_callback(RigidbodyColCB callback);
@ -27,6 +51,8 @@ void physics_body_mass_set(Rigidbody body, float mass);
void physics_body_data_set(Rigidbody body, void* data);
void* physics_body_data_get(Rigidbody body);
void physics_body_force_add(Rigidbody body, float fx, float fy, float fz);
void physics_body_kinematic_set(Rigidbody body);
#endif

@ -252,14 +252,15 @@ void scene_setup(void)
camera_update_proj(player);*/
}
platform->physics.plane_create(0, 1, 0, 0);
Rigidbody box = platform->physics.box_create(2.5, 2.5, 2.5);
platform->physics.cs_plane_create(0, 1, 0, 0);
Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.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);
platform->physics.body_force_add(box, -100.f, 0.f, 0.f);
/*Rigidbody plane = platform->physics.plane_create(0, 1, 0, 0);*/
Rigidbody ground_box = platform->physics.box_create(10, 10, 10);
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");

Loading…
Cancel
Save