Fixed issue with physics timestep

dev
Shariq Shah 8 years ago
parent 9b8bc3f241
commit b2874e5786
  1. 5
      README.md
  2. 455
      assets/test_scene.symtres
  3. 1
      build/genie.lua
  4. BIN
      lib/windows/ode/ode_doubled.dll
  5. BIN
      lib/windows/ode/ode_doubled.pdb
  6. 2
      src/common/common.h
  7. 2
      src/game/main.c
  8. 99
      src/game/physics.c
  9. 52
      src/libsymmetry/entity.c
  10. 2
      src/libsymmetry/entity.h
  11. 3441
      src/libsymmetry/game.c

@ -155,10 +155,11 @@
- ## TODO
- Trimesh support
- Proper physics time-step and speed
- Fix lights type not being correctly saved/loaded from file
- Physics Trimesh support
- Debug physics mesh drawing
- Serializing/Deserializing physics data
- Proper physics time-step and speed
- Storing entity reference/id in rigidbody
- Storing rigidbody in entity
- Expose complete physics api with forces/joints etc

@ -0,0 +1,455 @@
Entity
{
type : 2
scale : 1.000 1.000 1.000
rotation : 0.000 0.000 0.000 1.000
is_listener : false
position : 0.000 0.000 0.000
parent : NONE
name : ROOT
renderable : false
}
Entity
{
type : 3
scale : 1.000 1.000 1.000
fov : 60.0000
rotation : 0.000 0.000 0.000 1.000
zoom : 1.0000
fbo_has_render_tex : true
resizeable : true
nearz : 0.1000
is_listener : false
position : 10.000 5.000 100.000
farz : 1000.0000
fbo_height : 720
parent : ROOT
ortho : false
fbo_width : 1280
fbo_has_depth_tex : true
name : player
renderable : false
has_fbo : true
clear_color : 0.300 0.600 0.900 1.000
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 0.000 50.000 0.000
parent : ROOT
name : Model_Entity
renderable : true
}
Entity
{
type : 5
scale : 400.000 2.000 400.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 0.000 0.000 0.000
parent : ROOT
name : Ground
renderable : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.500 0.500 0.167
radius : 20.0000
is_listener : false
position : 40.000 0.000 120.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.111 0.333 0.250
radius : 20.0000
is_listener : false
position : 180.000 0.000 80.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.200 0.111 0.125
radius : 20.0000
is_listener : false
position : 100.000 0.000 160.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.500 0.167 0.100
radius : 20.0000
is_listener : false
position : 40.000 0.000 200.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 1.000 1.000 0.111
radius : 20.0000
is_listener : false
position : 20.000 0.000 180.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.167 0.125 1.000
radius : 20.0000
is_listener : false
position : 120.000 0.000 20.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 1.000 1.000 0.333
radius : 20.0000
is_listener : false
position : 20.000 0.000 60.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.143 0.167 0.200
radius : 20.0000
is_listener : false
position : 140.000 0.000 100.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.167 0.333 0.167
radius : 20.0000
is_listener : false
position : 120.000 0.000 120.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.125 0.250 0.100
radius : 20.0000
is_listener : false
position : 160.000 0.000 200.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 3.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 3.000 0.000 4.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 5.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 6.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 10.000 0.000 1.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 8.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 4.000 0.000 4.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 6.000 0.000 1.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 10.000 0.000 5.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 6.000 0.000 9.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 6
scale : 1.000 1.000 1.000
volume : 0.5000
rolloff_factor : 0.9500
rotation : 0.000 0.000 0.000 1.000
loop : true
sound_min_distance : 1.0000
playing : true
is_listener : false
position : 0.000 0.000 0.000
source_filename : sounds/teh_beatz.wav
parent : Suzanne
sound_type : 0
sound_max_distance : 10.0000
name : Sound_Ent
sound_attenuation_type : 1
renderable : false
}

@ -104,6 +104,7 @@ solution "Symmetry"
"copy ..\\..\\lib\\windows\\sdl2\\SDL2.dll debug\\ /Y",
"copy ..\\..\\lib\\windows\\soloud\\soloud_x64_d.dll debug\\ /Y",
"copy ..\\..\\lib\\windows\\ode\\ode_doubled.dll debug\\ /Y",
"copy ..\\..\\lib\\windows\\ode\\ode_doubled.pdb debug\\ /Y",
"rmdir debug\\assets",
"mklink /D debug\\assets ..\\..\\..\\assets"
}

Binary file not shown.

Binary file not shown.

@ -66,6 +66,8 @@ struct Physics_Api
Rigidbody (*box_create)(float length, float width, float height);
void (*body_set_moved_callback)(Rigidbody body, RigidbodyMoveCB callback);
void (*body_kinematic_set)(Rigidbody body);
void (*body_mass_set)(Rigidbody body, float mass);
float (*body_mass_get)(Rigidbody body);
};
struct Sound_Api

@ -132,6 +132,8 @@ int main(int argc, char** args)
.body_rotation_set = &physics_body_rotation_set,
.body_rotation_get = &physics_body_rotation_get,
.body_kinematic_set = &physics_body_kinematic_set,
.body_mass_set = &physics_body_mass_set,
.body_mass_get = &physics_body_mass_get,
.body_set_moved_callback = &physics_body_set_moved_callback,
.plane_create = &physics_plane_create,
.box_create = &physics_box_create

@ -34,7 +34,15 @@ void physics_init(void)
log_message("Physics world created");
Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.16;
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);
}
}
@ -52,11 +60,19 @@ void physics_cleanup(void)
void physics_step(float delta_time)
{
//if(delta_time <= 0.f) delta_time = Physics.step_size;
//dSpaceCollide(Physics.space, NULL, physics_near_callback);
//dWorldQuickStep(Physics.world, delta_time);
////dWorldStep(Physics.world, Physics.step_size);
//dJointGroupEmpty(Physics.contact_group);
int steps = (int)ceilf(delta_time / Physics.step_size);
//log_message("Num steps : %d", steps);
for(int i = 0; i < steps; i++)
{
dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size);
//dWorldStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group);
}
}
@ -116,39 +132,59 @@ 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;
}
//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);
const int N = 32;
dContact contact[32];
int n = dCollide(o1, o2, N, &(contact[0].geom), sizeof(dContact));
// 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)
{
for(int i = 0; i<n; i++)
{
// Paranoia <-- not working for some people, temporarily removed for 0.6
//dIASSERT(dVALIDVEC3(contact[i].geom.pos));
//dIASSERT(dVALIDVEC3(contact[i].geom.normal));
//dIASSERT(!dIsNan(contact[i].geom.depth));
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;
log_message("Collision!");
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,
dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
}
}
@ -167,6 +203,9 @@ 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);
return body;
}
@ -182,7 +221,9 @@ float physics_body_mass_get(Rigidbody body)
void physics_body_mass_set(Rigidbody body, float mass)
{
/*dMass dmass;
dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/
}
void physics_body_kinematic_set(Rigidbody body)

@ -609,28 +609,28 @@ const char* entity_type_name_get(struct Entity* entity)
default: typename = "Unknown"; break;
};
return typename;
}
void entity_apply_sound_params(struct Entity* entity)
{
if(entity->type != ET_SOUND_SOURCE) return;
struct Sound_Source* sound_source = &entity->sound_source;
// Check if sound source has no buffer attached but filename exists, this would mean we have to load the file first
if(!sound_source->source && sound_source->source_filename)
{
sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type);
if(!sound_source->source)
{
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", sound_source->source_filename, entity->name);
free(sound_source->source_filename);
sound_source->source_filename = NULL;
sound_source->source_instance = 0;
return;
}
}
}
void entity_apply_sound_params(struct Entity* entity)
{
if(entity->type != ET_SOUND_SOURCE) return;
struct Sound_Source* sound_source = &entity->sound_source;
// Check if sound source has no buffer attached but filename exists, this would mean we have to load the file first
if(!sound_source->source && sound_source->source_filename)
{
sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type);
if(!sound_source->source)
{
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", sound_source->source_filename, entity->name);
free(sound_source->source_filename);
sound_source->source_filename = NULL;
sound_source->source_instance = 0;
return;
}
}
if(sound_source->source_instance == 0) sound_source->source_instance = platform->sound.source_instance_create(sound_source->source, true);
vec3 abs_pos = {0.f, 0.f, 0.f};
@ -647,5 +647,11 @@ void entity_apply_sound_params(struct Entity* entity)
platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume);
platform->sound.update_3d();
if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance);
if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance);
}
void entity_on_rigidbody_move(Rigidbody body_A, Rigidbody body_B)
{
}

@ -141,6 +141,6 @@ bool entity_write(struct Entity* entity, struct Parser_Object* object)
struct Entity* entity_read(struct Parser_Object* object);
const char* entity_type_name_get(struct Entity* entity);
void entity_apply_sound_params(struct Entity* entity); // Convenience function to sync the data set in entity's sound_source with the actual sound source's instance
void entity_on_rigidbody_move(Rigidbody body_A, Rigidbody body_B);
#endif

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save