diff --git a/examples/chains.c b/examples/chains.c index 8a01a34..f8313ff 100644 --- a/examples/chains.c +++ b/examples/chains.c @@ -29,8 +29,11 @@ void setup(Example *example) { (nv_Material){1.0, 0.0, 0.0}, width, height ); - + chain_part->collision_group = 1; nv_Space_add(example->space, chain_part); + + // Temporary solution to avoid constraints exploding + nv_Body_apply_force(chain_part, NV_VEC2((nv_float)(i%10)*50.0, 0.0)); } // Link chain parts @@ -69,10 +72,10 @@ void setup(Example *example) { (nv_Material){1.0, 0.0, 0.0}, radius ); - + chain_part->collision_group = 2; nv_Space_add(example->space, chain_part); - // Temporary solution to circle chain going crazy + // Temporary solution to avoid constraints exploding nv_Body_apply_force(chain_part, NV_VEC2((nv_float)(i%10)*50.0, 0.0)); } @@ -110,7 +113,7 @@ void setup(Example *example) { (nv_Material){1.0, 0.0, 0.0}, size, size / 3.0 ); - + chain_part->collision_group = 3; nv_Space_add(example->space, chain_part); } diff --git a/examples/example_base.h b/examples/example_base.h index 849c8da..8c11e3a 100644 --- a/examples/example_base.h +++ b/examples/example_base.h @@ -1909,7 +1909,7 @@ void Example_run(Example *example) { nv_Material_WOOD, 0.3 ); - mouse_body->collision = false; + mouse_body->enable_collision = false; nv_Space_add(example->space, mouse_body); nv_Array_add(example->sprites, NULL); @@ -2184,7 +2184,7 @@ void Example_run(Example *example) { nv_Material_WOOD, 0.3 ); - mouse_body->collision = false; + mouse_body->enable_collision = false; nv_Space_add(example->space, mouse_body); example->counter = 0; diff --git a/examples/spring_car.c b/examples/spring_car.c index d0149b6..516c627 100644 --- a/examples/spring_car.c +++ b/examples/spring_car.c @@ -13,10 +13,10 @@ void update(Example *example) { if (example->keys[SDL_SCANCODE_LEFT] || example->keys[SDL_SCANCODE_RIGHT]) { - nv_Body *wheel1 = (nv_Body *)example->space->bodies->data[4]; + nv_Body *wheel1 = (nv_Body *)example->space->bodies->data[6]; nv_Body *wheel2 = (nv_Body *)example->space->bodies->data[5]; - double strength = 7.0 * 1e2; + double strength = 12.0 * 1e2; double limit = 30.0; if (example->keys[SDL_SCANCODE_LEFT]) { @@ -82,26 +82,26 @@ void setup(Example *example) { // Create wheels - nv_Material wheel_mat = (nv_Material){1.5, 0.8, 3.0}; + nv_Material wheel_mat = (nv_Material){1.5, 0.7, 3.0}; nv_Body *wheel1 = nv_Circle_new( nv_BodyType_DYNAMIC, - NV_VEC2(49.0, 40.0), + NV_VEC2(53.0, 32.0), 0.0, wheel_mat, - 1.5 + 2.0 ); - + wheel1->collision_group = 1; nv_Space_add(example->space, wheel1); nv_Body *wheel2 = nv_Circle_new( nv_BodyType_DYNAMIC, - NV_VEC2(61.0, 40.0), + NV_VEC2(57.0, 32.0), 0.0, wheel_mat, - 1.5 + 2.0 ); - + wheel2->collision_group = 1; nv_Space_add(example->space, wheel2); @@ -113,21 +113,21 @@ void setup(Example *example) { (nv_Material){4.0, 0.3, 0.5}, 10.0, 3.0 ); - + body->collision_group = 1; nv_Space_add(example->space, body); // Create spring constraints - double suspension_length = 2.5; - double suspension_strength = 1500.0; + double suspension_length = 2.3; + double suspension_strength = 2700.0; double suspension_damping = 150.00; nv_Constraint *spring1 = nv_Spring_new( wheel1, body, - NV_VEC2(0.0, 0.0), NV_VEC2(-4.0, 1.5), + NV_VEC2(0.0, 0.0), NV_VEC2(-4.0, 0.0), suspension_length, - suspension_strength, + suspension_strength * 1.0, suspension_damping ); @@ -135,10 +135,10 @@ void setup(Example *example) { nv_Constraint *spring2 = nv_Spring_new( wheel1, body, - NV_VEC2(0.0, 0.0), NV_VEC2(-1.5, 1.5), + NV_VEC2(0.0, 0.0), NV_VEC2(-1.5, 0.0), suspension_length, - suspension_strength * 3.0, - suspension_damping + suspension_strength * 6.0, + suspension_damping * 2.0 ); @@ -146,9 +146,9 @@ void setup(Example *example) { nv_Constraint *spring3 = nv_Spring_new( wheel2, body, - NV_VEC2(0.0, 0.0), NV_VEC2(4.0, 1.5), + NV_VEC2(0.0, 0.0), NV_VEC2(4.0, 0.0), suspension_length, - suspension_strength, + suspension_strength * 1.0, suspension_damping ); @@ -156,10 +156,10 @@ void setup(Example *example) { nv_Constraint *spring4 = nv_Spring_new( wheel2, body, - NV_VEC2(0.0, 0.0), NV_VEC2(1.5, 1.5), + NV_VEC2(0.0, 0.0), NV_VEC2(1.5, 0.0), suspension_length, - suspension_strength * 3.0, - suspension_damping + suspension_strength * 6.0, + suspension_damping * 2.0 ); nv_Space_add_constraint(example->space, spring4); diff --git a/include/novaphysics/body.h b/include/novaphysics/body.h index 904dbc8..4e842e8 100644 --- a/include/novaphysics/body.h +++ b/include/novaphysics/body.h @@ -103,7 +103,11 @@ typedef struct { bool is_attractor; /**< Flag reporting if the body is an attractor. */ - bool collision; + bool enable_collision; /**< Whether to collide this body with other bodies or not. */ + nv_uint32 collision_group; /**< Collision group of the body. + Bodies that share the same non-zero group do not collide. */ + nv_uint32 collision_category; /**< Bitmask defining this body's collision category. */ + nv_uint32 collision_mask; /**< Bitmask defining this body's collision mask. */ } nv_Body; /** diff --git a/src/body.c b/src/body.c index 621ae88..1e3ccc4 100644 --- a/src/body.c +++ b/src/body.c @@ -66,7 +66,10 @@ nv_Body *nv_Body_new( body->is_attractor = false; - body->collision = true; + body->enable_collision = true; + body->collision_group = 0; + body->collision_category = 0b11111111111111111111111111111111; + body->collision_mask = 0b11111111111111111111111111111111; nv_Body_calc_mass_and_inertia(body); diff --git a/src/broadphase.c b/src/broadphase.c index 7b6c141..6c8246f 100644 --- a/src/broadphase.c +++ b/src/broadphase.c @@ -30,7 +30,7 @@ static inline bool nv_BroadPhase_early_out(nv_Space *space, nv_Body *a, nv_Body if (a == b) return true; - if (!a->collision || !b->collision) + if (!a->enable_collision || !b->enable_collision) return true; // Two static bodies do not need to interact @@ -48,6 +48,15 @@ static inline bool nv_BroadPhase_early_out(nv_Space *space, nv_Body *a, nv_Body return true; } + // Bodies share the same non-zero group + if (a->collision_group == b->collision_group && a->collision_group != 0) + return true; + + // One of the collision mask doesn't fit the category + if (a->collision_mask & b->collision_category == 0 || + b->collision_mask & a->collision_category == 0) + return true; + return false; }