/* * 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. */ #ifndef RAT_PHYSICS_WORLD #define RAT_PHYSICS_WORLD #include "common.h" #include "body.h" #include "body_manager.h" #include "body_manager_array_table.h" #include "body_manager_quad_tree.h" #include "collision_filter.h" #include "constraint.h" #include "spring.h" #include "island.h" typedef enum rat_integrator_type { rat_integrator_null=0, rat_integrator_euler=1, rat_integrator_rk4=2 } rat_integrator_type; struct rat_world; typedef struct rat_world_callbacks { void (*body_left_world)(struct rat_world *thisworld,rat_body *thisbody,void *userdata); void (*collision_occurs)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata); void (*collision_persists)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata); void (*collision_ending)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata); void *body_left_world_userdata; void *collision_occurs_userdata; void *collision_persists_userdata; void *collision_ending_userdata; } rat_world_callbacks; typedef struct rat_world { // special internal allocators rat_stack_allocator *sal; rat_block_allocator *bal; // world attributes aabb world_bounds; vector2 gravity; rat_real damping; // collision accuracy unsigned int elastic_iterations; unsigned int inelastic_iterations; rat_real bias_coef,elastic_coef; // pointer to integrator function (euler or runge kutta) void (*body_integrate_position)(rat_body *body,rat_real timestep); // world callbacks rat_world_callbacks *callbacks; // holds body data and collides them (broadphase where implemented) rat_body_manager *body_manager; // collision filters rat_collision_filter_list *filters; // constraints unsigned int numconsts,numconstsdel; unsigned int numsprings,numspringsdel; rat_constraint **constraints,**constsdel; rat_spring **springs,**springsdel; unsigned int numislands; } rat_world; #ifdef __cplusplus extern "C" { #endif // default world event callbacks void rat_default_body_left_world(rat_world *thisworld,rat_body *thisbody,void *userdata); void rat_default_collision_occurs(rat_world *thisworld,rat_arbiter *arbiter,void *userdata); void rat_default_collision_persists(rat_world *thisworld,rat_arbiter *arbiter,void *userdata); void rat_default_collision_ending(rat_world *thisworld,rat_arbiter *arbiter,void *userdata); // world stuff // note that world bounds only effect spatial indexing methods // and the leave world callback. rat_world *rat_world_create(aabb world_bounds,rat_integrator_type integrator, unsigned int collision_iterations,rat_body_manager_type bmtype,void *bmdata); void rat_world_destroy(rat_world *world); void rat_world_set_body_left_world_callback(rat_world *world,void (*body_left_world)(struct rat_world *thisworld,rat_body *thisbody,void *userdata),void *userdata); void rat_world_set_collision_occurs_callback(rat_world *world,void (*collision_occurs)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata),void *userdata); void rat_world_set_collision_persists_callback(rat_world *world,void (*collision_persists)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata),void *userdata); void rat_world_set_collision_ending_callback(rat_world *world,void (*collision_ending)(struct rat_world *thisworld,rat_arbiter *arbiter,void *userdata),void *userdata); // free everything; convenience function for little stuff void rat_world_free_entities(rat_world *world); // awaken all bodies. good for a gravity change, for example void rat_world_awaken_all(rat_world *world); void rat_world_add_body(rat_world *world,rat_body *body); void rat_world_remove_body(rat_world *world,rat_body *body); void rat_world_remove_and_destroy_body(rat_world *world,rat_body *body); void rat_world_clear_bodies(rat_world *world); void rat_world_add_constraint(rat_world *world,rat_constraint *constraint); void rat_world_remove_constraint(rat_world *world,rat_constraint *constraint); void rat_world_remove_and_destroy_constraint(rat_world *world,rat_constraint *constraint); void rat_world_clear_constraints(rat_world *world); void rat_world_add_spring(rat_world *world,rat_spring *spring); void rat_world_remove_spring(rat_world *world,rat_spring *spring); void rat_world_remove_and_destroy_spring(rat_world *world,rat_spring *spring); void rat_world_clear_springs(rat_world *world); void rat_world_set_gravity(rat_world *world,vector2 gravity); void rat_world_set_damping(rat_world *world,rat_real damping); void rat_world_set_solver_iterations(rat_world *world,unsigned int iterations); vector2 rat_world_get_gravity(rat_world *world); rat_real rat_world_get_damping(rat_world *world); unsigned int rat_world_get_solver_iterations(rat_world *world); void rat_world_add_collision_filter(rat_world *world,int tag_a,int tag_b,int atroot); int rat_world_remove_collision_filter(rat_world *world,int tag_a,int tag_b,int fromlast); void rat_world_clear_collision_filters(rat_world *world); rat_iterator *rat_world_all_bodies_iterator(rat_world *world); rat_iterator *rat_world_static_bodies_iterator(rat_world *world); rat_iterator *rat_world_dynamic_bodies_iterator(rat_world *world); rat_iterator *rat_world_arbiters_iterator(rat_world *world); // the last argument, clean_blocks, says whether or not we should clean // out the contact block recycler. takes some extra time, but more memory // efficient. oh, what to chose!? void rat_world_update(rat_world *world,rat_real timestep,int clean_blocks); #ifdef __cplusplus } #endif // this is used internally by rat_world_update; do not use void rat_world_integrate(rat_world *world,rat_real step); #endif