/* * Copyright (c) 2008-2009 Bill Whitacre http://rampancy.g0dsoft.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "island.h" #include "world.h" rat_island *rat_island_create(unsigned int maxbods,unsigned int maxconsts,unsigned int maxsprings,unsigned int maxarbs,rat_world *world_ref) { rat_island *island=(rat_island *)rat_stack_alloc(world_ref->sal,sizeof(rat_island)); memset(island,0,sizeof(rat_island)); island->world_ref=world_ref; island->sal=world_ref->sal; island->bodies=(rat_body **)rat_stack_alloc(island->sal,sizeof(rat_body *)*maxbods); island->constraints=(rat_constraint **)rat_stack_alloc(island->sal,sizeof(rat_constraint *)*maxconsts); island->springs=(rat_spring **)rat_stack_alloc(island->sal,sizeof(rat_spring *)*maxsprings); island->arbiters=(rat_arbiter **)rat_stack_alloc(island->sal,sizeof(rat_arbiter *)*maxarbs); return island; } void rat_island_destroy(rat_island *island) { rat_stack_dealloc(island->sal,(void *)island->arbiters); rat_stack_dealloc(island->sal,(void *)island->springs); rat_stack_dealloc(island->sal,(void *)island->constraints); rat_stack_dealloc(island->sal,(void *)island->bodies); rat_stack_dealloc(island->sal,(void *)island); } void rat_island_add_body(rat_island *island,rat_body *body) { island->bodies[island->numbods++]=body; } void rat_island_add_constraint(rat_island *island,rat_constraint *constraint) { island->constraints[island->numconsts++]=constraint; } void rat_island_add_spring(rat_island *island,rat_spring *spring) { island->springs[island->numsprings++]=spring; } void rat_island_add_arbiter(rat_island *island,rat_arbiter *arbiter) { island->arbiters[island->numarbs++]=arbiter; } void rat_island_clear(rat_island *island) { island->numbods=0; island->numconsts=0; island->numsprings=0; island->numarbs=0; } void rat_island_integrate(rat_island *island,rat_real step) { register unsigned int i,j; const rat_real linear_tolerance_sq=rat_linear_sleep_tolerance*rat_linear_sleep_tolerance; const rat_real angular_tolerance_sq=rat_angular_sleep_tolerance*rat_angular_sleep_tolerance; rat_real min_sleep_time=FLT_MAX; rat_real inv_step=(inv_step=1.0/step)>1.0?1.0:inv_step; // prime arbiters for (i=0; inumarbs; i++) rat_arbiter_prime(island->arbiters[i],island->world_ref->bias_coef*(1.0/step)); // prime constraints for (i=0; inumconsts; i++) rat_constraint_prime(island->constraints[i],island->world_ref->bias_coef*inv_step); // solve springs for (j=0; jnumsprings; j++) rat_spring_integrate(island->springs[j],1.0/step,step); // elastic solver for (i=0; iworld_ref->elastic_iterations; i++) { // solve arbiters for (j=0; jnumarbs; j++) rat_arbiter_step_solver(island->arbiters[j],1.0); // solve constraints for (j=0; jnumconsts; j++) rat_constraint_step(island->constraints[j]); } // integrate velocity for (i=0; inumbods; i++) rat_body_integrate_velocity(island->bodies[i],island->world_ref->gravity,step,island->world_ref->damping); // apply cached step for (i=0; inumarbs; i++) rat_arbiter_step_cached(island->arbiters[i]); // inelastic solver for (i=0; iworld_ref->inelastic_iterations; i++) { // solve arbiters for (j=0; jnumarbs; j++) rat_arbiter_step_solver(island->arbiters[j],0.0); // solve constraints for (j=0; jnumconsts; j++) rat_constraint_step(island->constraints[j]); } // now we do island wide sleep checks for (i=0; inumbods; i++) { rat_body *thisbody=island->bodies[i]; if (thisbody->mass==0.0) continue; if (thisbody->omega*thisbody->omega>angular_tolerance_sq|| vector2_dot(thisbody->velocity,thisbody->velocity)>linear_tolerance_sq) { thisbody->sleep_timer=0.0; min_sleep_time=0.0; } else { thisbody->sleep_timer+=step; min_sleep_time=min_sleep_time>thisbody->sleep_timer?thisbody->sleep_timer:min_sleep_time; } } // if everyone in the island is ready to sleep then put 'em to sleep if (min_sleep_time>=rat_time_to_sleep) { for (i=0; inumbods; i++) { rat_body_set_is_asleep(island->bodies[i],1); vector2_init(&(island->bodies[i]->velocity)); island->bodies[i]->omega=0.0; } } }