diff options
Diffstat (limited to 'servers/physics_2d')
-rw-r--r-- | servers/physics_2d/SCsub | 1 | ||||
-rw-r--r-- | servers/physics_2d/area_2d_sw.cpp | 11 | ||||
-rw-r--r-- | servers/physics_2d/area_2d_sw.h | 4 | ||||
-rw-r--r-- | servers/physics_2d/body_2d_sw.cpp | 13 | ||||
-rw-r--r-- | servers/physics_2d/body_2d_sw.h | 8 | ||||
-rw-r--r-- | servers/physics_2d/body_pair_2d_sw.cpp | 22 | ||||
-rw-r--r-- | servers/physics_2d/body_pair_2d_sw.h | 1 | ||||
-rw-r--r-- | servers/physics_2d/joints_2d_sw.cpp | 12 | ||||
-rw-r--r-- | servers/physics_2d/joints_2d_sw.h | 2 | ||||
-rw-r--r-- | servers/physics_2d/physics_2d_server_sw.cpp | 61 | ||||
-rw-r--r-- | servers/physics_2d/physics_2d_server_sw.h | 16 | ||||
-rw-r--r-- | servers/physics_2d/physics_2d_server_wrap_mt.cpp | 169 | ||||
-rw-r--r-- | servers/physics_2d/physics_2d_server_wrap_mt.h | 316 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.cpp | 18 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.h | 11 |
15 files changed, 640 insertions, 25 deletions
diff --git a/servers/physics_2d/SCsub b/servers/physics_2d/SCsub index a2c2b51a61..ebb7f8be00 100644 --- a/servers/physics_2d/SCsub +++ b/servers/physics_2d/SCsub @@ -1,4 +1,3 @@ Import('env') env.add_source_files(env.servers_sources,"*.cpp") - diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index dad1891b77..a5a132020a 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -82,6 +82,10 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) { _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) { @@ -102,6 +106,10 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_meth _shape_changed(); + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + } @@ -120,6 +128,7 @@ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; @@ -136,6 +145,7 @@ Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { case Physics2DServer::AREA_PARAM_GRAVITY: return gravity; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; @@ -248,6 +258,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), gravity=9.80665; gravity_vector=Vector2(0,-1); gravity_is_point=false; + gravity_distance_scale=0; point_attenuation=1; angular_damp=1.0; diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 4a54a337ed..6d99764c68 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -46,6 +46,7 @@ class Area2DSW : public CollisionObject2DSW{ float gravity; Vector2 gravity_vector; bool gravity_is_point; + float gravity_distance_scale; float point_attenuation; float linear_damp; float angular_damp; @@ -139,6 +140,9 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 0ba661b4c4..3afbbe5455 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -275,6 +275,8 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va Matrix32 t = p_variant; t.orthonormalize(); new_transform=get_transform(); //used as old to compute motion + if (t==new_transform) + break; _set_transform(t); _set_inv_transform(get_transform().inverse()); @@ -381,9 +383,12 @@ void Body2DSW::set_space(Space2DSW *p_space){ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) { if (p_area->is_gravity_point()) { - - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - + if(p_area->get_gravity_distance_scale() > 0) { + Vector2 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale()+1, 2) ); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } } else { gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } @@ -437,7 +442,7 @@ void Body2DSW::integrate_forces(real_t p_step) { //compute motion, angular and etc. velocities from prev transform linear_velocity = (new_transform.elements[2] - get_transform().elements[2])/p_step; - real_t rot = new_transform.affine_inverse().basis_xform(get_transform().elements[1]).atan2(); + real_t rot = new_transform.affine_inverse().basis_xform(get_transform().elements[1]).angle(); angular_velocity = rot / p_step; motion = new_transform.elements[2] - get_transform().elements[2]; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index e34686f3ac..2fbfcaca60 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -203,7 +203,7 @@ public: _FORCE_INLINE_ bool is_active() const { return active; } _FORCE_INLINE_ void wakeup() { - if ((get_space() && active) || mode==Physics2DServer::BODY_MODE_STATIC || mode==Physics2DServer::BODY_MODE_KINEMATIC) + if ((!get_space()) || mode==Physics2DServer::BODY_MODE_STATIC || mode==Physics2DServer::BODY_MODE_KINEMATIC) return; set_active(true); } @@ -337,9 +337,9 @@ public: Body2DSW *body; real_t step; - virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area - virtual float get_total_angular_damp() const { return body->get_angular_damp(); } // get density of this body space/area - virtual float get_total_linear_damp() const { return body->get_linear_damp(); } // get density of this body space/area + virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area + virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index e8d37d346a..eb3abbb267 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -265,7 +265,7 @@ bool BodyPair2DSW::setup(float p_step) { } //faster to set than to check.. - bool prev_collided=collided; + //bool prev_collided=collided; collided = CollisionSolver2DSW::solve(shape_A_ptr,xform_A,motion_A,shape_B_ptr,xform_B,motion_B,_add_contact,this,&sep_axis); if (!collided) { @@ -282,12 +282,18 @@ bool BodyPair2DSW::setup(float p_step) { collided=true; } - if (!collided) + if (!collided) { + oneway_disabled=false; return false; + } } - if (!prev_collided) { + if (oneway_disabled) + return false; + + //if (!prev_collided) { + { if (A->is_using_one_way_collision()) { Vector2 direction = A->get_one_way_collision_direction(); @@ -309,6 +315,7 @@ bool BodyPair2DSW::setup(float p_step) { if (!valid) { collided=false; + oneway_disabled=true; return false; } } @@ -333,6 +340,7 @@ bool BodyPair2DSW::setup(float p_step) { } if (!valid) { collided=false; + oneway_disabled=true; return false; } } @@ -371,7 +379,12 @@ bool BodyPair2DSW::setup(float p_step) { } c.active=true; - +#ifdef DEBUG_ENABLED + if (space->is_debugging_contacts()) { + space->add_debug_contact(global_A+offset_A); + space->add_debug_contact(global_B+offset_A); + } +#endif int gather_A = A->can_report_contacts(); int gather_B = B->can_report_contacts(); @@ -525,6 +538,7 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_sha B->add_constraint(this,1); contact_count=0; collided=false; + oneway_disabled=false; } diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h index 2365512036..a7fa287be4 100644 --- a/servers/physics_2d/body_pair_2d_sw.h +++ b/servers/physics_2d/body_pair_2d_sw.h @@ -76,6 +76,7 @@ class BodyPair2DSW : public Constraint2DSW { Contact contacts[MAX_CONTACTS]; int contact_count; bool collided; + bool oneway_disabled; int cc; diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index b4c149e7e0..7c12000084 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -279,6 +279,18 @@ void PinJoint2DSW::solve(float p_step){ P += impulse; } +void PinJoint2DSW::set_param(Physics2DServer::PinJointParam p_param, real_t p_value) { + + if(p_param == Physics2DServer::PIN_JOINT_SOFTNESS) + softness = p_value; +} + +real_t PinJoint2DSW::get_param(Physics2DServer::PinJointParam p_param) const { + + if(p_param == Physics2DServer::PIN_JOINT_SOFTNESS) + return softness; + ERR_FAIL_V(0); +} PinJoint2DSW::PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b) : Joint2DSW(_arr,p_body_b?2:1) { diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h index 2093be88c9..e43f8eee33 100644 --- a/servers/physics_2d/joints_2d_sw.h +++ b/servers/physics_2d/joints_2d_sw.h @@ -121,6 +121,8 @@ public: virtual bool setup(float p_step); virtual void solve(float p_step); + void set_param(Physics2DServer::PinJointParam p_param, real_t p_value); + real_t get_param(Physics2DServer::PinJointParam p_param) const; PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b=NULL); ~PinJoint2DSW(); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 08d871be69..6a1c790da8 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -30,7 +30,7 @@ #include "broad_phase_2d_basic.h" #include "broad_phase_2d_hash_grid.h" #include "collision_solver_2d_sw.h" - +#include "globals.h" RID Physics2DServerSW::shape_create(ShapeType p_shape) { Shape2DSW *shape=NULL; @@ -257,11 +257,35 @@ real_t Physics2DServerSW::space_get_param(RID p_space,SpaceParameter p_param) co return space->get_param(p_param); } +void Physics2DServerSW::space_set_debug_contacts(RID p_space,int p_max_contacts) { + + Space2DSW *space = space_owner.get(p_space); + ERR_FAIL_COND(!space); + space->set_debug_contacts(p_max_contacts); + +} + +Vector<Vector2> Physics2DServerSW::space_get_contacts(RID p_space) const { + + Space2DSW *space = space_owner.get(p_space); + ERR_FAIL_COND_V(!space,Vector<Vector2>()); + return space->get_debug_contacts(); + +} + +int Physics2DServerSW::space_get_contact_count(RID p_space) const { + + Space2DSW *space = space_owner.get(p_space); + ERR_FAIL_COND_V(!space,0); + return space->get_debug_contact_count(); + +} + Physics2DDirectSpaceState* Physics2DServerSW::space_get_direct_state(RID p_space) { Space2DSW *space = space_owner.get(p_space); ERR_FAIL_COND_V(!space,NULL); - if (/*doing_sync ||*/ space->is_locked()) { + if ((using_threads && !doing_sync) || space->is_locked()) { ERR_EXPLAIN("Space state is inaccesible right now, wait for iteration or fixed process notification."); ERR_FAIL_V(NULL); @@ -733,7 +757,7 @@ void Physics2DServerSW::body_set_layer_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -750,7 +774,7 @@ void Physics2DServerSW::body_set_collision_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -1072,6 +1096,25 @@ RID Physics2DServerSW::damped_spring_joint_create(const Vector2& p_anchor_a,cons } +void Physics2DServerSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { + + Joint2DSW *j = joint_owner.get(p_joint); + ERR_FAIL_COND(!j); + ERR_FAIL_COND(j->get_type()!=JOINT_PIN); + + PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW*>(j); + pin_joint->set_param(p_param, p_value); +} + +real_t Physics2DServerSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { + Joint2DSW *j = joint_owner.get(p_joint); + ERR_FAIL_COND_V(!j,0); + ERR_FAIL_COND_V(j->get_type()!=JOINT_PIN,0); + + PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW*>(j); + return pin_joint->get_param(p_param); +} + void Physics2DServerSW::damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value) { @@ -1196,7 +1239,7 @@ void Physics2DServerSW::set_active(bool p_active) { void Physics2DServerSW::init() { - doing_sync=true; + doing_sync=false; last_step=0.001; iterations=8;// 8? stepper = memnew( Step2DSW ); @@ -1228,6 +1271,7 @@ void Physics2DServerSW::step(float p_step) { void Physics2DServerSW::sync() { + doing_sync=true; }; void Physics2DServerSW::flush_queries() { @@ -1235,7 +1279,7 @@ void Physics2DServerSW::flush_queries() { if (!active) return; - doing_sync=true; + for( Set<const Space2DSW*>::Element *E=active_spaces.front();E;E=E->next()) { Space2DSW *space=(Space2DSW *)E->get(); @@ -1244,6 +1288,10 @@ void Physics2DServerSW::flush_queries() { }; +void Physics2DServerSW::end_sync() { + doing_sync=false; +} + void Physics2DServerSW::finish() { @@ -1283,6 +1331,7 @@ Physics2DServerSW::Physics2DServerSW() { island_count=0; active_objects=0; collision_pairs=0; + using_threads=int(Globals::get_singleton()->get("physics_2d/thread_model"))==2; }; diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 341df2fdc9..b2c58b788e 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -51,6 +51,8 @@ friend class Physics2DDirectSpaceStateSW; int active_objects; int collision_pairs; + bool using_threads; + Step2DSW *stepper; Set<const Space2DSW*> active_spaces; @@ -100,6 +102,11 @@ public: virtual void space_set_param(RID p_space,SpaceParameter p_param, real_t p_value); virtual real_t space_get_param(RID p_space,SpaceParameter p_param) const; + virtual void space_set_debug_contacts(RID p_space,int p_max_contacts); + virtual Vector<Vector2> space_get_contacts(RID p_space) const; + virtual int space_get_contact_count(RID p_space) const; + + // this function only works on fixed process, errors and returns null otherwise virtual Physics2DDirectSpaceState* space_get_direct_state(RID p_space); @@ -179,10 +186,10 @@ public: virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; virtual void body_set_layer_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_layer_mask(RID p_body) const; virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_collision_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_collision_mask(RID p_) const; virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value); virtual float body_get_param(RID p_body, BodyParameter p_param) const; @@ -236,6 +243,8 @@ public: virtual RID pin_joint_create(const Vector2& p_pos,RID p_body_a,RID p_body_b=RID()); virtual RID groove_joint_create(const Vector2& p_a_groove1,const Vector2& p_a_groove2, const Vector2& p_b_anchor, RID p_body_a,RID p_body_b); virtual RID damped_spring_joint_create(const Vector2& p_anchor_a,const Vector2& p_anchor_b,RID p_body_a,RID p_body_b=RID()); + virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value); + virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const; virtual void damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value); virtual real_t damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const; @@ -248,8 +257,9 @@ public: virtual void set_active(bool p_active); virtual void init(); virtual void step(float p_step); - virtual void sync(); + virtual void sync(); virtual void flush_queries(); + virtual void end_sync(); virtual void finish(); int get_process_info(ProcessInfo p_info); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp new file mode 100644 index 0000000000..c5f023f162 --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -0,0 +1,169 @@ +#include "physics_2d_server_wrap_mt.h" + +#include "os/os.h" + +void Physics2DServerWrapMT::thread_exit() { + + exit=true; +} + +void Physics2DServerWrapMT::thread_step(float p_delta) { + + physics_2d_server->step(p_delta); + step_sem->post(); + +} + +void Physics2DServerWrapMT::_thread_callback(void *_instance) { + + Physics2DServerWrapMT *vsmt = reinterpret_cast<Physics2DServerWrapMT*>(_instance); + + + vsmt->thread_loop(); +} + +void Physics2DServerWrapMT::thread_loop() { + + server_thread=Thread::get_caller_ID(); + + OS::get_singleton()->make_rendering_thread(); + + physics_2d_server->init(); + + exit=false; + step_thread_up=true; + while(!exit) { + // flush commands one by one, until exit is requested + command_queue.wait_and_flush_one(); + } + + command_queue.flush_all(); // flush all + + physics_2d_server->finish(); + +} + + +/* EVENT QUEUING */ + + +void Physics2DServerWrapMT::step(float p_step) { + + if (create_thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_step,p_step); + } else { + + command_queue.flush_all(); //flush all pending from other threads + physics_2d_server->step(p_step); + } +} + +void Physics2DServerWrapMT::sync() { + + if (step_sem) { + if (first_frame) + first_frame=false; + else + step_sem->wait(); //must not wait if a step was not issued + } + physics_2d_server->sync();; +} + +void Physics2DServerWrapMT::flush_queries(){ + + physics_2d_server->flush_queries(); +} + +void Physics2DServerWrapMT::end_sync() { + + physics_2d_server->end_sync();; +} + +void Physics2DServerWrapMT::init() { + + if (create_thread) { + + step_sem = Semaphore::create(); + print_line("CREATING PHYSICS 2D THREAD"); + //OS::get_singleton()->release_rendering_thread(); + if (create_thread) { + thread = Thread::create( _thread_callback, this ); + print_line("STARTING PHYISICS 2D THREAD"); + } + while(!step_thread_up) { + OS::get_singleton()->delay_usec(1000); + } + print_line("DONE PHYSICS 2D THREAD"); + } else { + + physics_2d_server->init(); + } + +} + +void Physics2DServerWrapMT::finish() { + + + if (thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_exit); + Thread::wait_to_finish( thread ); + memdelete(thread); + +/* + shape_free_cached_ids(); + area_free_cached_ids(); + body_free_cached_ids(); + pin_joint_free_cached_ids(); + groove_joint_free_cached_ids(); + damped_string_free_cached_ids(); +*/ + thread=NULL; + } else { + physics_2d_server->finish(); + } + + if (step_sem) + memdelete(step_sem); + +} + + +Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) { + + physics_2d_server=p_contained; + create_thread=p_create_thread; + thread=NULL; + step_sem=NULL; + step_pending=0; + step_thread_up=false; + alloc_mutex=Mutex::create(); + + shape_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + area_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + body_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + pin_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + groove_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + damped_spring_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + + if (!p_create_thread) { + server_thread=Thread::get_caller_ID(); + } else { + server_thread=0; + } + + main_thread = Thread::get_caller_ID(); + first_frame=true; +} + + +Physics2DServerWrapMT::~Physics2DServerWrapMT() { + + memdelete(physics_2d_server); + memdelete(alloc_mutex); + //finish(); + +} + + diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h new file mode 100644 index 0000000000..60f8a4c879 --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -0,0 +1,316 @@ +#ifndef PHYSICS2DSERVERWRAPMT_H +#define PHYSICS2DSERVERWRAPMT_H + + +#include "servers/physics_2d_server.h" +#include "command_queue_mt.h" +#include "os/thread.h" +#include "globals.h" + +#ifdef DEBUG_SYNC +#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); +#else +#define SYNC_DEBUG +#endif + + +class Physics2DServerWrapMT : public Physics2DServer { + + mutable Physics2DServer *physics_2d_server; + + mutable CommandQueueMT command_queue; + + static void _thread_callback(void *_instance); + void thread_loop(); + + Thread::ID server_thread; + Thread::ID main_thread; + volatile bool exit; + Thread *thread; + volatile bool step_thread_up; + bool create_thread; + + Semaphore *step_sem; + int step_pending; + void thread_step(float p_delta); + void thread_flush(); + + void thread_exit(); + + Mutex*alloc_mutex; + bool first_frame; + + int shape_pool_max_size; + List<RID> shape_id_pool; + int area_pool_max_size; + List<RID> area_id_pool; + int body_pool_max_size; + List<RID> body_id_pool; + int pin_joint_pool_max_size; + List<RID> pin_joint_id_pool; + int groove_joint_pool_max_size; + List<RID> groove_joint_id_pool; + int damped_spring_joint_pool_max_size; + List<RID> damped_spring_joint_id_pool; + + +public: + +#define ServerName Physics2DServer +#define ServerNameWrapMT Physics2DServerWrapMT +#define server_name physics_2d_server +#include "servers/server_wrap_mt_common.h" + + //FUNC1RID(shape,ShapeType); todo fix + FUNC1R(RID,shape_create,ShapeType); + FUNC2(shape_set_data,RID,const Variant& ); + FUNC2(shape_set_custom_solver_bias,RID,real_t ); + + FUNC1RC(ShapeType,shape_get_type,RID ); + FUNC1RC(Variant,shape_get_data,RID); + FUNC1RC(real_t,shape_get_custom_solver_bias,RID); + + + //these work well, but should be used from the main thread only + bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); + return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count); + } + + /* SPACE API */ + + FUNC0R(RID,space_create); + FUNC2(space_set_active,RID,bool); + FUNC1RC(bool,space_is_active,RID); + + FUNC3(space_set_param,RID,SpaceParameter,real_t); + FUNC2RC(real_t,space_get_param,RID,SpaceParameter); + + // this function only works on fixed process, errors and returns null otherwise + Physics2DDirectSpaceState* space_get_direct_state(RID p_space) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),NULL); + return physics_2d_server->space_get_direct_state(p_space); + } + + FUNC2(space_set_debug_contacts,RID,int); + virtual Vector<Vector2> space_get_contacts(RID p_space) const { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),Vector<Vector2>()); + return physics_2d_server->space_get_contacts(p_space); + + } + + virtual int space_get_contact_count(RID p_space) const { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),0); + return physics_2d_server->space_get_contact_count(p_space); + + } + + + + /* AREA API */ + + //FUNC0RID(area); + FUNC0R(RID,area_create); + + FUNC2(area_set_space,RID,RID); + FUNC1RC(RID,area_get_space,RID); + + FUNC2(area_set_space_override_mode,RID,AreaSpaceOverrideMode); + FUNC1RC(AreaSpaceOverrideMode,area_get_space_override_mode,RID); + + FUNC3(area_add_shape,RID,RID,const Matrix32&); + FUNC3(area_set_shape,RID,int,RID); + FUNC3(area_set_shape_transform,RID,int,const Matrix32&); + + FUNC1RC(int,area_get_shape_count,RID); + FUNC2RC(RID,area_get_shape,RID,int); + FUNC2RC(Matrix32,area_get_shape_transform,RID,int); + FUNC2(area_remove_shape,RID,int); + FUNC1(area_clear_shapes,RID); + + FUNC2(area_attach_object_instance_ID,RID,ObjectID); + FUNC1RC(ObjectID,area_get_object_instance_ID,RID); + + FUNC3(area_set_param,RID,AreaParameter,const Variant&); + FUNC2(area_set_transform,RID,const Matrix32&); + + FUNC2RC(Variant,area_get_param,RID,AreaParameter); + FUNC1RC(Matrix32,area_get_transform,RID); + + FUNC2(area_set_collision_mask,RID,uint32_t); + FUNC2(area_set_layer_mask,RID,uint32_t); + + FUNC2(area_set_monitorable,RID,bool); + FUNC2(area_set_pickable,RID,bool); + + FUNC3(area_set_monitor_callback,RID,Object*,const StringName&); + FUNC3(area_set_area_monitor_callback,RID,Object*,const StringName&); + + + /* BODY API */ + + //FUNC2RID(body,BodyMode,bool); + FUNC2R(RID,body_create,BodyMode,bool) + + FUNC2(body_set_space,RID,RID); + FUNC1RC(RID,body_get_space,RID); + + FUNC2(body_set_mode,RID,BodyMode); + FUNC1RC(BodyMode,body_get_mode,RID); + + + FUNC3(body_add_shape,RID,RID,const Matrix32&); + FUNC3(body_set_shape,RID,int,RID); + FUNC3(body_set_shape_transform,RID,int,const Matrix32&); + FUNC3(body_set_shape_metadata,RID,int,const Variant&); + + FUNC1RC(int,body_get_shape_count,RID); + FUNC2RC(Matrix32,body_get_shape_transform,RID,int); + FUNC2RC(Variant,body_get_shape_metadata,RID,int); + FUNC2RC(RID,body_get_shape,RID,int); + + FUNC3(body_set_shape_as_trigger,RID,int,bool); + FUNC2RC(bool,body_is_shape_set_as_trigger,RID,int); + + FUNC2(body_remove_shape,RID,int); + FUNC1(body_clear_shapes,RID); + + FUNC2(body_attach_object_instance_ID,RID,uint32_t); + FUNC1RC(uint32_t,body_get_object_instance_ID,RID); + + FUNC2(body_set_continuous_collision_detection_mode,RID,CCDMode); + FUNC1RC(CCDMode,body_get_continuous_collision_detection_mode,RID); + + FUNC2(body_set_layer_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_layer_mask,RID); + + FUNC2(body_set_collision_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_collision_mask,RID); + + + FUNC3(body_set_param,RID,BodyParameter,float); + FUNC2RC(float,body_get_param,RID,BodyParameter); + + + FUNC3(body_set_state,RID,BodyState,const Variant&); + FUNC2RC(Variant,body_get_state,RID,BodyState); + + FUNC2(body_set_applied_force,RID,const Vector2&); + FUNC1RC(Vector2,body_get_applied_force,RID); + + FUNC2(body_set_applied_torque,RID,float); + FUNC1RC(float,body_get_applied_torque,RID); + + FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); + FUNC2(body_set_axis_velocity,RID,const Vector2&); + + FUNC2(body_add_collision_exception,RID,RID); + FUNC2(body_remove_collision_exception,RID,RID); + FUNC2S(body_get_collision_exceptions,RID,List<RID>*); + + FUNC2(body_set_max_contacts_reported,RID,int); + FUNC1RC(int,body_get_max_contacts_reported,RID); + + FUNC2(body_set_one_way_collision_direction,RID,const Vector2&); + FUNC1RC(Vector2,body_get_one_way_collision_direction,RID); + + FUNC2(body_set_one_way_collision_max_depth,RID,float); + FUNC1RC(float,body_get_one_way_collision_max_depth,RID); + + + FUNC2(body_set_contacts_reported_depth_treshold,RID,float); + FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID); + + FUNC2(body_set_omit_force_integration,RID,bool); + FUNC1RC(bool,body_is_omitting_force_integration,RID); + + FUNC4(body_set_force_integration_callback,RID ,Object *,const StringName& ,const Variant& ); + + + bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { + return physics_2d_server->body_collide_shape(p_body,p_body_shape,p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count); + } + + FUNC2(body_set_pickable,RID,bool); + + bool body_test_motion(RID p_body,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); + return physics_2d_server->body_test_motion(p_body,p_motion,p_margin,r_result); + } + + /* JOINT API */ + + + FUNC3(joint_set_param,RID,JointParam,real_t); + FUNC2RC(real_t,joint_get_param,RID,JointParam); + + + ///FUNC3RID(pin_joint,const Vector2&,RID,RID); + ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); + ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); + + FUNC3R(RID,pin_joint_create,const Vector2&,RID,RID); + FUNC5R(RID,groove_joint_create,const Vector2&,const Vector2&,const Vector2&,RID,RID); + FUNC4R(RID,damped_spring_joint_create,const Vector2&,const Vector2&,RID,RID); + + FUNC3(pin_joint_set_param,RID,PinJointParam,real_t); + FUNC2RC(real_t,pin_joint_get_param,RID,PinJointParam); + + FUNC3(damped_string_joint_set_param,RID,DampedStringParam,real_t); + FUNC2RC(real_t,damped_string_joint_get_param,RID,DampedStringParam); + + FUNC1RC(JointType,joint_get_type,RID); + + + /* MISC */ + + + FUNC1(free,RID); + FUNC1(set_active,bool); + + virtual void init(); + virtual void step(float p_step); + virtual void sync(); + virtual void end_sync(); + virtual void flush_queries(); + virtual void finish(); + + int get_process_info(ProcessInfo p_info) { + return physics_2d_server->get_process_info(p_info); + } + + Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread); + ~Physics2DServerWrapMT(); + + + template<class T> + static Physics2DServer* init_server() { + + int tm = GLOBAL_DEF("physics_2d/thread_model",1); + if (tm==0) //single unsafe + return memnew( T ); + else if (tm==1) //single saef + return memnew( Physics2DServerWrapMT( memnew( T ), false )); + else //single unsafe + return memnew( Physics2DServerWrapMT( memnew( T ), true )); + + + } + +#undef ServerNameWrapMT +#undef ServerName +#undef server_name + +}; + +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG + +#endif // PHYSICS2DSERVERWRAPMT_H diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index b38cf0c2df..9f2f03baec 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -36,8 +36,8 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec if ((p_object->get_layer_mask()&p_layer_mask)==0) return false; - if (p_object->get_type()==CollisionObject2DSW::TYPE_AREA && !(p_type_mask&Physics2DDirectSpaceState::TYPE_MASK_AREA)) - return false; + if (p_object->get_type()==CollisionObject2DSW::TYPE_AREA) + return p_type_mask&Physics2DDirectSpaceState::TYPE_MASK_AREA; Body2DSW *body = static_cast<Body2DSW*>(p_object); @@ -655,7 +655,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); - cbk.valid_dir=body->get_one_way_collision_direction(); + + Vector2 cdir = body->get_one_way_collision_direction(); + //if (cdir!=Vector2() && p_motion.dot(cdir)<0) + // continue; + + cbk.valid_dir=cdir; cbk.valid_depth=body->get_one_way_collision_max_depth(); } else { cbk.valid_dir=Vector2(); @@ -1225,6 +1230,7 @@ void Space2DSW::call_queries() { void Space2DSW::setup() { + contact_debug_count=0; while(inertia_update_list.first()) { inertia_update_list.first()->self()->update_inertias(); @@ -1297,6 +1303,8 @@ Space2DSW::Space2DSW() { active_objects=0; island_count=0; + contact_debug_count=0; + locked=false; contact_recycle_radius=0.01; contact_max_separation=0.05; @@ -1315,6 +1323,10 @@ Space2DSW::Space2DSW() { direct_access = memnew( Physics2DDirectSpaceStateSW ); direct_access->space=this; + + + + } Space2DSW::~Space2DSW() { diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index abee8628fc..97ad3d7f80 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -103,6 +103,9 @@ class Space2DSW { int _cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb); + Vector<Vector2> contact_debug; + int contact_debug_count; + friend class Physics2DDirectSpaceStateSW; public: @@ -169,6 +172,14 @@ public: bool test_body_motion(Body2DSW *p_body, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result); + + void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } + _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } + _FORCE_INLINE_ void add_debug_contact(const Vector2& p_contact) { if (contact_debug_count<contact_debug.size()) contact_debug[contact_debug_count++]=p_contact; } + _FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; } + _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; } + + Physics2DDirectSpaceStateSW *get_direct_state(); Space2DSW(); |