/**
* Name: Restitution
* A model to demonstrate the role of the restitution in the collision of objects and some other techniques (display of contacts between objects, creation of comparisons
* between native and Java Bullet libraries...).
* Author: Alexis Drogoul - 2021
* Tags: 3D, physics
*/
model Restitution
global parent: physical_world {
string library_name <- use_native? "Native":"Java";
// The definition of the step plays a crucial role in the dynamics. If the physics engine can kick in at a high frequency, then the simulation is more accurate (but also slower).
// The outcome of a model can be completely changed by the step.
float step <- 1.0/60;
float wall_restitution <- 1.0 min: 0.0 max: 1.0 ;
float ball_restitution <- 0.8 min: 0.0 max: 1.0 ;
point ball_impulse <- {100,100,0} ;
geometry shape <- box(100,100,0.001);
float friction <- 0.0;
float restitution <- 0.0;
point ball_contact <- nil;
int ball_timer <- 0;
point wall_contact <- nil;
int wall_timer <- 0;
init {
do register([self]);
geometry box <- box(103,3,10);
create wall from: [box at_location({50,0}), box rotated_by 90 at_location({0,50}), box at_location({50,100}), box rotated_by 90 at_location({100, 50})];
create ball from: [sphere(6) at_location {50,50}, sphere(6) at_location {20,20}];
}
reflex r1 when: ball_timer > 0 {
ball_timer <- ball_timer - 1;
if (ball_timer = 0) {
ball_contact <- nil;
}
}
reflex r2 when: wall_timer > 0 {
wall_timer <- wall_timer - 1;
if (wall_timer = 0) {
wall_contact <- nil;
}
}
}
species wall skills: [static_body] {
float restitution <- wall_restitution;
float friction <- 0.0;
}
species ball skills: [dynamic_body] {
float contact_damping <- 0.0;
float damping <- 0.0;
float angular_damping <- 0.1;
float mass <- 5.0;
float restitution <- ball_restitution;
float friction <- 0.0;
action contact_added_with(agent other) {
if (other is ball) {
ball_contact <- location;
ball_timer <- 20;
} else if (other is wall) {
wall_contact <- location;
wall_timer <- 20;
}
}
reflex manage_location when: location.z < -20 {
do die;
}
}
experiment "Test Restitution !" type: gui {
image_file bang <- image_file("../images/bang.png");
image_file bam <- image_file("../images/bam.png");
// Ensure that the simulation does not go too fast
float minimum_cycle_duration <- 1.0/60;
font custom <- font("Helvetica", 24, #bold);
parameter "Impulse" var: ball_impulse;
user_command " Move balls" color: #darkgray {
ask simulations {
ask ball {
do apply impulse: ball_impulse;
}
}
}
user_command " Reset balls" color: #darkgray {
ask simulations {
ask ball {
do die;
}
create ball from: [sphere(5) at_location {50,50,5}, sphere(5) at_location {20,20,5}];
}
}
parameter "Restitution of the walls" var: wall_restitution {
ask simulations {
ask wall {
restitution <- wall_restitution;
}
}
}
parameter "Restitution of the balls" var: ball_restitution {
ask simulations {
ask ball {
restitution <- ball_restitution;
}
}
}
action _init_ {
bool prev0 <- gama.pref_experiment_expand_params;
bool prev1 <- gama.pref_append_simulation_name;
gama.pref_append_simulation_name <- true;
gama.pref_experiment_expand_params <- true;
create simulation with: [seed:: 1.0, use_native :: true];
create simulation with: [seed:: 1.0, use_native :: false];
gama.pref_experiment_expand_params <- prev0;
gama.pref_append_simulation_name <- prev1;
}
output {
layout #split;
display "Restitution" type: opengl antialias: true {
graphics "Title" refresh: false {
draw library_name + " (click to move the balls)" font: custom color: #cadetblue at: {5, 0, 20} depth: 5 precision: 0.001;
draw shape color: #khaki;
}
graphics "Bang" {
if (ball_contact != nil) {
draw bang at: ball_contact size:{20,20};
}
if (wall_contact != nil) {
draw bam at: wall_contact size:{20,20};
}
}
species wall refresh: false {draw shape color: #cadetblue;}
species ball {draw shape texture: image_file("../images/ball.jpg") rotate: rotation color: #darkseagreen;}
event "mouse_down" {
point target <- #user_location;
float divisor <- distance_to(target, ball[0].location);
point direction <- (target - ball[0].location) /divisor;
// When the user hits the mouse, we apply an impulse to the while ball, in the direction of the target. 'velocity' could also be used here
ask simulations {
ask ball {
do apply impulse: {ball_impulse.x * direction.x,ball_impulse.y * direction.y };
angular_velocity <- {rnd(10), rnd(10), rnd(10)};
}}
}
}
}
}