diff options
Diffstat (limited to 'servers')
54 files changed, 2260 insertions, 573 deletions
diff --git a/servers/SCsub b/servers/SCsub index 1a858533b7..3871c30cfa 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -12,7 +12,7 @@ SConscript('audio/SCsub'); SConscript('spatial_sound/SCsub'); SConscript('spatial_sound_2d/SCsub'); -lib = env.Library("servers",env.servers_sources, LIBSUFFIX=env['platform_libsuffix']) +lib = env.Library("servers",env.servers_sources) env.Prepend(LIBS=[lib]) diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp index f50813731e..55dde1b35b 100644 --- a/servers/audio/audio_server_sw.cpp +++ b/servers/audio/audio_server_sw.cpp @@ -332,6 +332,7 @@ void AudioServerSW::driver_process_chunk(int p_frames,int32_t *p_buffer) { void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) { + _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate()); //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE int todo=p_frames; while(todo) { @@ -795,6 +796,8 @@ void AudioServerSW::init() { mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) ); mixer_step_usecs=mixer->get_step_usecs(); + _output_delay=0; + stream_volume=0.3; // start the audio driver if (AudioDriverSW::get_singleton()) @@ -911,6 +914,11 @@ float AudioServerSW::get_event_voice_global_volume_scale() const { return event_voice_volume_scale; } +double AudioServerSW::get_output_delay() const { + + return _output_delay; +} + double AudioServerSW::get_mix_time() const { return AudioDriverSW::get_singleton()->get_mix_time(); diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h index d137c15633..d47c1b4b3f 100644 --- a/servers/audio/audio_server_sw.h +++ b/servers/audio/audio_server_sw.h @@ -92,6 +92,8 @@ class AudioServerSW : public AudioServer { float peak_left,peak_right; uint32_t max_peak; + double _output_delay; + VoiceRBSW voice_rb; bool exit_update_thread; @@ -206,6 +208,9 @@ public: virtual double get_mix_time() const; //useful for video -> audio sync + virtual double get_output_delay() const; + + AudioServerSW(SampleManagerSW *p_sample_manager); ~AudioServerSW(); diff --git a/servers/audio_server.h b/servers/audio_server.h index 85289de58a..511340678a 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -274,6 +274,7 @@ public: static AudioServer *get_singleton(); virtual double get_mix_time() const=0; //useful for video -> audio sync + virtual double get_output_delay() const=0; AudioServer(); virtual ~AudioServer(); diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp index 4a303d3fdd..5938e716e9 100644 --- a/servers/physics/area_pair_sw.cpp +++ b/servers/physics/area_pair_sw.cpp @@ -67,7 +67,6 @@ void AreaPairSW::solve(float p_step) { AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape) { - body=p_body; area=p_area; body_shape=p_body_shape; @@ -75,6 +74,8 @@ AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_are colliding=false; body->add_constraint(this,0); area->add_constraint(this); + if (p_body->get_mode()==PhysicsServer::BODY_MODE_KINEMATIC) + p_body->set_active(true); } diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index 8192a98400..4c9ac814be 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -148,8 +148,6 @@ void AreaSW::call_queries() { return; } - - for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) { if (E->get().state==0) @@ -182,8 +180,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move point_attenuation=1; density=0.1; priority=0; - ray_pickable=false; - + set_ray_pickable(false); + monitor_callback_id=0; } diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index a864055d17..c0c6e5c2ae 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -48,7 +48,6 @@ class AreaSW : public CollisionObjectSW{ float point_attenuation; float density; int priority; - bool ray_pickable; ObjectID monitor_callback_id; StringName monitor_callback_method; @@ -139,8 +138,6 @@ public: _FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; } - _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; } - _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; } diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index d112afa8e2..5847b942fb 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -172,10 +172,57 @@ void BodyPairSW::validate_contacts() { } } + +bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) { + + + + Vector3 motion = p_A->get_linear_velocity()*p_step; + real_t mlen = motion.length(); + if (mlen<CMP_EPSILON) + return false; + + Vector3 mnormal = motion / mlen; + + real_t min,max; + p_A->get_shape(p_shape_A)->project_range(mnormal,p_xform_A,min,max); + bool fast_object = mlen > (max-min)*0.3; //going too fast in that direction + + if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis + return false; + } + + //cast a segment from support in motion normal, in the same direction of motion by motion length + //support is the worst case collision point, so real collision happened before + int a; + Vector3 s=p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized()); + Vector3 from = p_xform_A.xform(s); + Vector3 to = from + motion; + + Transform from_inv = p_xform_B.affine_inverse(); + + Vector3 local_from = from_inv.xform(from-mnormal*mlen*0.1); //start from a little inside the bounding box + Vector3 local_to = from_inv.xform(to); + + Vector3 rpos,rnorm; + if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from,local_to,rpos,rnorm)) { + return false; + } + + //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough + Vector3 hitpos = p_xform_B.xform(rpos); + + float newlen = hitpos.distance_to(from)-(max-min)*0.01; + p_A->set_linear_velocity((mnormal*newlen)/p_step); + + return true; +} + + bool BodyPairSW::setup(float p_step) { //cannot collide - if (A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) { + if ((A->get_layer_mask()&B->get_layer_mask())==0 || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) { collided=false; return false; } @@ -198,8 +245,21 @@ bool BodyPairSW::setup(float p_step) { bool collided = CollisionSolverSW::solve_static(shape_A_ptr,xform_A,shape_B_ptr,xform_B,_contact_added_callback,this,&sep_axis); this->collided=collided; - if (!collided) + + if (!collided) { + + //test ccd (currently just a raycast) + + if (A->is_continuous_collision_detection_enabled() && A->get_mode()>PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC) { + _test_ccd(p_step,A,shape_A,xform_A,B,shape_B,xform_B); + } + + if (B->is_continuous_collision_detection_enabled() && B->get_mode()>PhysicsServer::BODY_MODE_KINEMATIC && A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC) { + _test_ccd(p_step,B,shape_B,xform_B,A,shape_A,xform_A); + } + return false; + } @@ -267,6 +327,14 @@ bool BodyPairSW::setup(float p_step) { B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crA); } + if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) { + c.active=false; + collided=false; + continue; + + } + + c.active=true; // Precompute normal mass, tangent mass, and bias. diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h index 937c295c63..e64464e2c1 100644 --- a/servers/physics/body_pair_sw.h +++ b/servers/physics/body_pair_sw.h @@ -82,6 +82,7 @@ class BodyPairSW : public ConstraintSW { void contact_added_callback(const Vector3& p_point_A,const Vector3& p_point_B); void validate_contacts(); + bool _test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B); SpaceSW *space; diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 0fd754ba25..725a440b59 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -185,6 +185,7 @@ float BodySW::get_param(PhysicsServer::BodyParameter p_param) const { void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { + PhysicsServer::BodyMode prev=mode; mode=p_mode; switch(p_mode) { @@ -196,8 +197,13 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { _inv_mass=0; _set_static(p_mode==PhysicsServer::BODY_MODE_STATIC); //set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC); + set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity=Vector3(); angular_velocity=Vector3(); + if (mode==PhysicsServer::BODY_MODE_KINEMATIC && prev!=mode) { + first_time_kinematic=true; + } + } break; case PhysicsServer::BODY_MODE_RIGID: { @@ -237,6 +243,11 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant& p_varian new_transform=p_variant; //wakeup_neighbours(); set_active(true); + if (first_time_kinematic) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + first_time_kinematic=false; + } } else if (mode==PhysicsServer::BODY_MODE_STATIC) { _set_transform(p_variant); @@ -460,8 +471,8 @@ void BodySW::integrate_velocities(real_t p_step) { if (mode==PhysicsServer::BODY_MODE_KINEMATIC) { _set_transform(new_transform,false); - _set_inv_transform(new_transform.affine_inverse()); ; - if (linear_velocity==Vector3() && angular_velocity==Vector3()) + _set_inv_transform(new_transform.affine_inverse()); + if (contacts.size()==0 && linear_velocity==Vector3() && angular_velocity==Vector3()) set_active(false); //stopped moving, deactivate return; @@ -668,6 +679,7 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda island_step=0; island_next=NULL; island_list_next=NULL; + first_time_kinematic=false; _set_static(false); density=0; contact_count=0; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 6317186d5f..ee3c76e455 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -74,6 +74,7 @@ class BodySW : public CollisionObjectSW { bool continuous_cd; bool can_sleep; + bool first_time_kinematic; void _update_inertia(); virtual void _shapes_changed(); Transform new_transform; @@ -137,7 +138,7 @@ public: _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.insert(AreaCMP(p_area)); } _FORCE_INLINE_ void remove_area(AreaSW *p_area) { areas.erase(AreaCMP(p_area)); } - _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; } + _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; if (mode==PhysicsServer::BODY_MODE_KINEMATIC && p_size) set_active(true);} _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index f34aa19cae..c8e1fc4022 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -217,4 +217,5 @@ CollisionObjectSW::CollisionObjectSW(Type p_type) { space=NULL; instance_id=0; layer_mask=1; + ray_pickable=true; } diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index e717cc257c..788292ad2a 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -59,6 +59,9 @@ private: BroadPhaseSW::ID bpid; AABB aabb_cache; //for rayqueries ShapeSW *shape; + bool trigger; + + Shape() { trigger=false; } }; Vector<Shape> shapes; @@ -94,6 +97,9 @@ protected: virtual void _shapes_changed()=0; void _set_space(SpaceSW *space); + bool ray_pickable; + + CollisionObjectSW(Type p_type); public: @@ -119,6 +125,11 @@ public: _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } _FORCE_INLINE_ SpaceSW* get_space() const { return space; } + _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; } + _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; } + + _FORCE_INLINE_ void set_shape_as_trigger(int p_idx,bool p_enable) { shapes[p_idx].trigger=p_enable; } + _FORCE_INLINE_ bool is_shape_set_as_trigger(int p_idx) const { return shapes[p_idx].trigger; } _FORCE_INLINE_ void set_layer_mask(uint32_t p_mask) { layer_mask=p_mask; } _FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; } diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 56f2784145..86e3b679f2 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -275,6 +275,44 @@ void CollisionSolverSW::concave_distance_callback(void *p_userdata, ShapeSW *p_c } + +bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B) { + + const PlaneShapeSW *plane = static_cast<const PlaneShapeSW*>(p_shape_A); + if (p_shape_B->get_type()==PhysicsServer::SHAPE_PLANE) + return false; + Plane p = p_transform_A.xform(plane->get_plane()); + + static const int max_supports = 16; + Vector3 supports[max_supports]; + int support_count; + + p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(),max_supports,supports,support_count); + + bool collided=false; + Vector3 closest; + float closest_d; + + + for(int i=0;i<support_count;i++) { + + supports[i] = p_transform_B.xform( supports[i] ); + real_t d = p.distance_to(supports[i]); + if (i==0 || d<closest_d) { + closest=supports[i]; + closest_d=d; + if (d<=0) + collided=true; + } + + } + + r_point_A=p.project(closest); + r_point_B=closest; + + return collided; +} + bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis) { if (p_shape_A->is_concave()) @@ -282,7 +320,11 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& if (p_shape_B->get_type()==PhysicsServer::SHAPE_PLANE) { - return false; //unsupported + Vector3 a,b; + bool col = solve_distance_plane(p_shape_B,p_transform_B,p_shape_A,p_transform_A,a,b); + r_point_A=b; + r_point_B=a; + return !col; } else if (p_shape_B->is_concave()) { diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h index 430f057c7c..764c32926c 100644 --- a/servers/physics/collision_solver_sw.h +++ b/servers/physics/collision_solver_sw.h @@ -42,6 +42,7 @@ private: static bool solve_ray(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A=0,float p_margin_B=0); static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex); + static bool solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B); public: diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h index 1be96422e1..5e79c4b54c 100644 --- a/servers/physics/constraint_sw.h +++ b/servers/physics/constraint_sw.h @@ -38,12 +38,13 @@ class ConstraintSW { uint64_t island_step; ConstraintSW *island_next; ConstraintSW *island_list_next; + int priority; RID self; protected: - ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; } + ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; priority=1; } public: _FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; } @@ -62,6 +63,9 @@ public: _FORCE_INLINE_ BodySW **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } + _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } + _FORCE_INLINE_ int get_priority() const { return priority; } + virtual bool setup(float p_step)=0; virtual void solve(float p_step)=0; diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 043d2149fe..cfe5a73ce1 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -540,6 +540,8 @@ void PhysicsServerSW::body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx,body->get_shape_count()); + body->set_shape_as_trigger(p_shape_idx,p_enable); } @@ -547,10 +549,9 @@ bool PhysicsServerSW::body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) BodySW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,false); + ERR_FAIL_INDEX_V(p_shape_idx,body->get_shape_count(),false); - // todo ? - - return false; + body->is_shape_set_as_trigger(p_shape_idx); } @@ -769,7 +770,7 @@ void PhysicsServerSW::body_remove_collision_exception(RID p_body, RID p_body_b) BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->remove_exception(p_body); + body->remove_exception(p_body_b); }; @@ -836,6 +837,22 @@ void PhysicsServerSW::body_set_force_integration_callback(RID p_body,Object *p_r } +void PhysicsServerSW::body_set_ray_pickable(RID p_body,bool p_enable) { + + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_ray_pickable(p_enable); + +} + +bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const{ + + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,false); + return body->is_ray_pickable(); + +} + /* JOINT API */ @@ -1000,6 +1017,21 @@ bool PhysicsServerSW::hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) co return hinge_joint->get_flag(p_flag); } +void PhysicsServerSW::joint_set_solver_priority(RID p_joint,int p_priority) { + + JointSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND(!joint); + joint->set_priority(p_priority); +} + +int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const{ + + JointSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND_V(!joint,0); + return joint->get_priority(); + +} + PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const { JointSW *joint = joint_owner.get(p_joint); diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 76e5aecf55..6609a78662 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -201,6 +201,9 @@ public: virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant()); + virtual void body_set_ray_pickable(RID p_body,bool p_enable); + virtual bool body_is_ray_pickable(RID p_body) const; + /* JOINT API */ virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B); @@ -244,6 +247,9 @@ public: virtual JointType joint_get_type(RID p_joint) const; + virtual void joint_set_solver_priority(RID p_joint,int p_priority); + virtual int joint_get_solver_priority(RID p_joint) const; + #if 0 virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); virtual real_t joint_get_param(RID p_joint,JointParam p_param) const; diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 68d6b464ab..4e8b60b86b 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -71,12 +71,13 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto real_t min_d=1e10;
+
for(int i=0;i<amount;i++) {
if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
continue;
- if (space->intersection_query_results[i]->get_type()==CollisionObjectSW::TYPE_AREA && !(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
@@ -97,6 +98,8 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
+
+
Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);
diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp index 6d95804875..b7d06d207b 100644 --- a/servers/physics/step_sw.cpp +++ b/servers/physics/step_sw.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "step_sw.h" - +#include "joints_sw.h" void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) { @@ -68,14 +68,41 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) { void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){ - for(int i=0;i<p_iterations;i++) { + int at_priority=1; - ConstraintSW *ci=p_island; - while(ci) { - ci->solve(p_delta); - ci=ci->get_island_next(); + while(p_island) { + + for(int i=0;i<p_iterations;i++) { + + ConstraintSW *ci=p_island; + while(ci) { + ci->solve(p_delta); + ci=ci->get_island_next(); + } + } + + at_priority++; + + { + ConstraintSW *ci=p_island; + ConstraintSW *prev=NULL; + while(ci) { + if (ci->get_priority()<at_priority) { + if (prev) { + prev->set_island_next(ci->get_island_next()); //remove + } else { + p_island=ci->get_island_next(); + } + } else { + + prev=ci; + } + + ci=ci->get_island_next(); + } } } + } void StepSW::_check_suspend(BodySW *p_island,float p_delta) { diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 58035eb656..2e911288ae 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -99,7 +99,8 @@ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& 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_POINT_ATTENUATION: point_attenuation=p_value; ; break; - case Physics2DServer::AREA_PARAM_DENSITY: density=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; case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; } @@ -114,7 +115,8 @@ Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { 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_POINT_ATTENUATION: return point_attenuation; - case Physics2DServer::AREA_PARAM_DENSITY: return density; + case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case Physics2DServer::AREA_PARAM_PRIORITY: return priority; } @@ -180,7 +182,9 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), gravity_vector=Vector2(0,-1); gravity_is_point=false; point_attenuation=1; - density=0.1; + + angular_damp=1.0; + linear_damp=0.1; priority=0; monitor_callback_id=0; diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 0eda1050fa..d94b2f9ccf 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -47,7 +47,8 @@ class Area2DSW : public CollisionObject2DSW{ Vector2 gravity_vector; bool gravity_is_point; float point_attenuation; - float density; + float linear_damp; + float angular_damp; int priority; ObjectID monitor_callback_id; @@ -128,8 +129,11 @@ public: _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; } - _FORCE_INLINE_ void set_density(float p_density) { density=p_density; } - _FORCE_INLINE_ float get_density() const { return density; } + _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; } + _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; } + + _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; } + _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; } _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 35286bdb67..1c7f73db5e 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -75,6 +75,8 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,i colliding=false; body->add_constraint(this,0); area->add_constraint(this); + if (p_body->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) //need to be active to process pair + p_body->set_active(true); } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index f10cdadf4e..1cfe9a6ab9 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -65,7 +65,13 @@ void Body2DSW::update_inertias() { float mass = area * this->mass / total_area; - _inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin().length_squared(); + Matrix32 mtx = get_shape_transform(i); + Vector2 scale = mtx.get_scale(); + _inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared(); + //Rect2 ab = get_shape_aabb(i); + //_inertia+=mass*ab.size.dot(ab.size)/12.0f; + + } @@ -150,6 +156,17 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) _update_inertia(); } break; + case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + gravity_scale=p_value; + } break; + case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + + linear_damp=p_value; + } break; + case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + + angular_damp=p_value; + } break; default:{} } } @@ -168,6 +185,17 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { case Physics2DServer::BODY_PARAM_MASS: { return mass; } break; + case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + return gravity_scale; + } break; + case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + + return linear_damp; + } break; + case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + + return angular_damp; + } break; default:{} } @@ -176,6 +204,7 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { + Physics2DServer::BodyMode prev=mode; mode=p_mode; switch(p_mode) { @@ -186,9 +215,12 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { _set_inv_transform(get_transform().affine_inverse()); _inv_mass=0; _set_static(p_mode==Physics2DServer::BODY_MODE_STATIC); - //set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC); + set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity=Vector2(); angular_velocity=0; + if (mode==Physics2DServer::BODY_MODE_KINEMATIC && prev!=mode) { + first_time_kinematic=true; + } } break; case Physics2DServer::BODY_MODE_RIGID: { @@ -226,9 +258,15 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va if (mode==Physics2DServer::BODY_MODE_KINEMATIC) { - new_transform=p_variant; + + new_transform=p_variant; //wakeup_neighbours(); set_active(true); + if (first_time_kinematic) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + first_time_kinematic=false; + } } else if (mode==Physics2DServer::BODY_MODE_STATIC) { _set_transform(p_variant); _set_inv_transform(get_transform().affine_inverse()); @@ -346,6 +384,8 @@ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) { } else { gravity = p_area->get_gravity_vector() * p_area->get_gravity(); } + + gravity*=gravity_scale; } void Body2DSW::integrate_forces(real_t p_step) { @@ -369,7 +409,16 @@ void Body2DSW::integrate_forces(real_t p_step) { } _compute_area_gravity(current_area); - density=current_area->get_density(); + + if (angular_damp>=0) + area_angular_damp=angular_damp; + else + area_angular_damp=current_area->get_angular_damp(); + + if (linear_damp>=0) + area_linear_damp=linear_damp; + else + area_linear_damp=current_area->get_linear_damp(); Vector2 motion; bool do_motion=false; @@ -385,10 +434,10 @@ void Body2DSW::integrate_forces(real_t p_step) { motion = new_transform.elements[2] - get_transform().elements[2]; do_motion=true; - for(int i=0;i<get_shape_count();i++) { - set_shape_kinematic_advance(i,Vector2()); - set_shape_kinematic_retreat(i,0); - } + //for(int i=0;i<get_shape_count();i++) { + // set_shape_kinematic_advance(i,Vector2()); + // set_shape_kinematic_retreat(i,0); + //} } else { if (!omit_force_integration) { @@ -398,12 +447,12 @@ void Body2DSW::integrate_forces(real_t p_step) { force+=applied_force; real_t torque=applied_torque; - real_t damp = 1.0 - p_step * density; + real_t damp = 1.0 - p_step * area_linear_damp; if (damp<0) // reached zero in the given time damp=0; - real_t angular_damp = 1.0 - p_step * density * get_space()->get_body_angular_velocity_damp_ratio(); + real_t angular_damp = 1.0 - p_step * area_angular_damp; if (angular_damp<0) // reached zero in the given time angular_damp=0; @@ -434,7 +483,7 @@ void Body2DSW::integrate_forces(real_t p_step) { } current_area=NULL; // clear the area, so it is set in the next frame - contact_count=0; + contact_count=0; } @@ -449,8 +498,8 @@ void Body2DSW::integrate_velocities(real_t p_step) { if (mode==Physics2DServer::BODY_MODE_KINEMATIC) { _set_transform(new_transform,false); - _set_inv_transform(new_transform.affine_inverse()); ; - if (linear_velocity==Vector2() && angular_velocity==0) + _set_inv_transform(new_transform.affine_inverse()); + if (contacts.size()==0 && linear_velocity==Vector2() && angular_velocity==0) set_active(false); //stopped moving, deactivate return; } @@ -507,6 +556,7 @@ void Body2DSW::call_queries() { Variant v=dbs; const Variant *vp[2]={&v,&fi_callback->callback_udata}; + Object *obj = ObjectDB::get_instance(fi_callback->id); if (!obj) { @@ -590,8 +640,14 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti island_next=NULL; island_list_next=NULL; _set_static(false); - density=0; + first_time_kinematic=false; + linear_damp=-1; + angular_damp=-1; + area_angular_damp=0; + area_linear_damp=0; contact_count=0; + gravity_scale=1.0; + one_way_collision_max_depth=0.1; still_time=0; continuous_cd_mode=Physics2DServer::CCD_MODE_DISABLED; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index ffe47e0267..3b87be2737 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -47,6 +47,10 @@ class Body2DSW : public CollisionObject2DSW { Vector2 linear_velocity; real_t angular_velocity; + real_t linear_damp; + real_t angular_damp; + real_t gravity_scale; + real_t mass; real_t bounce; real_t friction; @@ -55,13 +59,17 @@ class Body2DSW : public CollisionObject2DSW { real_t _inv_inertia; Vector2 gravity; - real_t density; + real_t area_linear_damp; + real_t area_angular_damp; real_t still_time; Vector2 applied_force; real_t applied_torque; + Vector2 one_way_collision_direction; + float one_way_collision_max_depth; + SelfList<Body2DSW> active_list; SelfList<Body2DSW> inertia_update_list; @@ -72,6 +80,7 @@ class Body2DSW : public CollisionObject2DSW { bool omit_force_integration; bool active; bool can_sleep; + bool first_time_kinematic; void _update_inertia(); virtual void _shapes_changed(); Matrix32 new_transform; @@ -134,7 +143,8 @@ public: _FORCE_INLINE_ void add_area(Area2DSW *p_area) { areas.insert(AreaCMP(p_area)); } _FORCE_INLINE_ void remove_area(Area2DSW *p_area) { areas.erase(AreaCMP(p_area)); } - _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; } + _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; if (mode==Physics2DServer::BODY_MODE_KINEMATIC && p_size) set_active(true);} + _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } @@ -209,6 +219,12 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; } _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } + void set_one_way_collision_direction(const Vector2& p_dir) { one_way_collision_direction=p_dir; } + Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; } + + void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; } + float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; } + void set_space(Space2DSW *p_space); void update_inertias(); @@ -217,8 +233,10 @@ public: _FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; } _FORCE_INLINE_ real_t get_friction() const { return friction; } _FORCE_INLINE_ Vector2 get_gravity() const { return gravity; } - _FORCE_INLINE_ real_t get_density() const { return density; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } + _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } + void integrate_forces(real_t p_step); void integrate_velocities(real_t p_step); @@ -304,7 +322,8 @@ public: 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_density() const { return body->get_density(); } // get density of 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 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 @@ -334,6 +353,8 @@ public: virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; } virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; } virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; } + virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Variant()); return body->get_shape_metadata(body->contacts[p_contact_idx].collider_shape); } + virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } virtual Physics2DDirectSpaceState* get_space_state(); diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index ee169cde28..c4d6abe5ac 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -190,7 +190,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat p_A->get_shape(p_shape_A)->project_rangev(mnormal,p_xform_A,min,max); bool fast_object = mlen > (max-min)*0.3; //going too fast in that direction - if (fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis + if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis return false; } @@ -234,7 +234,7 @@ bool BodyPair2DSW::setup(float p_step) { //cannot collide - if ((A->get_layer_mask()&B->get_layer_mask())==0 || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) { + if ((A->get_layer_mask()&B->get_layer_mask())==0 || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) { collided=false; return false; } @@ -343,9 +343,11 @@ bool BodyPair2DSW::setup(float p_step) { } } - if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B)) { + if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) { c.active=false; collided=false; + continue; + } // Precompute normal mass, tangent mass, and bias. @@ -476,6 +478,7 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_sha BodyPair2DSW::~BodyPair2DSW() { + A->remove_constraint(this); B->remove_constraint(this); diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 277a286144..d0443f8110 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -55,6 +55,14 @@ void CollisionObject2DSW::set_shape(int p_index,Shape2DSW *p_shape){ _shapes_changed(); } + +void CollisionObject2DSW::set_shape_metadata(int p_index,const Variant& p_metadata) { + + ERR_FAIL_INDEX(p_index,shapes.size()); + shapes[p_index].metadata=p_metadata; + +} + void CollisionObject2DSW::set_shape_transform(int p_index,const Matrix32& p_transform){ ERR_FAIL_INDEX(p_index,shapes.size()); diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index cc7f8f50bd..00ad361245 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -55,10 +55,9 @@ private: BroadPhase2DSW::ID bpid; Rect2 aabb_cache; //for rayqueries Shape2DSW *shape; - Vector2 kinematic_advance; - float kinematic_retreat; + Variant metadata; bool trigger; - Shape() { trigger=false; kinematic_retreat=0; } + Shape() { trigger=false; } }; Vector<Shape> shapes; @@ -99,17 +98,15 @@ public: void add_shape(Shape2DSW *p_shape,const Matrix32& p_transform=Matrix32()); void set_shape(int p_index,Shape2DSW *p_shape); void set_shape_transform(int p_index,const Matrix32& p_transform); + void set_shape_metadata(int p_index,const Variant& p_metadata); + + _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; } _FORCE_INLINE_ const Matrix32& get_shape_transform(int p_index) const { return shapes[p_index].xform; } _FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } _FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } - - _FORCE_INLINE_ void set_shape_kinematic_advance(int p_index,const Vector2& p_advance) { shapes[p_index].kinematic_advance=p_advance; } - _FORCE_INLINE_ Vector2 get_shape_kinematic_advance(int p_index) const { return shapes[p_index].kinematic_advance; } - - _FORCE_INLINE_ void set_shape_kinematic_retreat(int p_index,float p_retreat) { shapes[p_index].kinematic_retreat=p_retreat; } - _FORCE_INLINE_ float get_shape_kinematic_retreat(int p_index) const { return shapes[p_index].kinematic_retreat; } + _FORCE_INLINE_ const Variant& get_shape_metadata(int p_index) const { return shapes[p_index].metadata; } _FORCE_INLINE_ Matrix32 get_transform() const { return transform; } _FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; } diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index f73ed5732e..9ed594e0eb 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -1086,6 +1086,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW,castA,castB,withMargin> separator(rectangle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B); + if (!separator.test_previous_axis()) return; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 09fa3f9b6a..be49955055 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -138,6 +138,21 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p if (cbk->max==0) return; + if (cbk->valid_dir!=Vector2()) { + if (p_point_A.distance_squared_to(p_point_B)>cbk->valid_depth*cbk->valid_depth) { + return; + } + if (cbk->valid_dir.dot((p_point_A-p_point_B).normalized())<0.7071) { +/* print_line("A: "+p_point_A); + print_line("B: "+p_point_B); + print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B)))); + print_line("resnorm: "+(p_point_A-p_point_B).normalized()); + print_line("distance: "+rtos(p_point_A.distance_to(p_point_B))); +*/ + return; + } + } + if (cbk->amount == cbk->max) { //find least deep float min_depth=1e20; @@ -548,6 +563,22 @@ void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, co body->set_shape_transform(p_shape_idx,p_transform); } +void Physics2DServerSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_shape_metadata(p_shape_idx,p_metadata); +} + + +Variant Physics2DServerSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,Variant()); + return body->get_shape_metadata(p_shape_idx); +} + + int Physics2DServerSW::body_get_shape_count(RID p_body) const { Body2DSW *body = body_owner.get(p_body); @@ -844,6 +875,37 @@ int Physics2DServerSW::body_get_max_contacts_reported(RID p_body) const { return body->get_max_contacts_reported(); } +void Physics2DServerSW::body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_one_way_collision_direction(p_direction); +} + +Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) const{ + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,Vector2()); + return body->get_one_way_collision_direction(); + +} + +void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_max_depth) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_one_way_collision_max_depth(p_max_depth); + +} + +float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,0); + return body->get_one_way_collision_max_depth(); + +} + void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 7ffffe669f..e9c499aaff 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -71,6 +71,8 @@ public: struct CollCbkData { + Vector2 valid_dir; + float valid_depth; int max; int amount; Vector2 *ptr; @@ -149,10 +151,14 @@ public: virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32()); virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape); virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform); + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata); + virtual int body_get_shape_count(RID p_body) const; virtual RID body_get_shape(RID p_body, int p_shape_idx) const; virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const; + virtual void body_remove_shape(RID p_body, int p_shape_idx); virtual void body_clear_shapes(RID p_body); @@ -201,6 +207,13 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); virtual int body_get_max_contacts_reported(RID p_body) const; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction); + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const; + + virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth); + virtual float body_get_one_way_collision_max_depth(RID p_body) const; + + virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant()); virtual 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); diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 012c4ed404..336eec73b5 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -131,7 +131,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en return true; } -real_t LineShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { return 0; } @@ -180,7 +180,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end } -real_t RayShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { return 0; //rays are mass-less } @@ -237,10 +237,12 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return true; } -real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { - real_t l = b.distance_to(a); - Vector2 ofs = (a+b)*0.5; + Vector2 s[2]={a*p_scale,b*p_scale}; + + real_t l = s[1].distance_to(s[0]); + Vector2 ofs = (s[0]+s[1])*0.5; return p_mass*(l*l/12.0f + ofs.length_squared()); } @@ -312,9 +314,10 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_ return true; } -real_t CircleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { + + return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5); - return radius*radius; } void CircleShape2DSW::set_data(const Variant& p_data) { @@ -377,9 +380,9 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal); } -real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { - Vector2 he2=half_extents*2; + Vector2 he2=half_extents*2*p_scale; return p_mass*he2.dot(he2)/12.0f; } @@ -499,9 +502,9 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return collided; //todo } -real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { - Vector2 he2(radius*2,height+radius*2); + Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale; return p_mass*he2.dot(he2)/12.0f; } @@ -610,16 +613,16 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect return inters; //todo } -real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { Rect2 aabb; - aabb.pos=points[0].pos; + aabb.pos=points[0].pos*p_scale; for(int i=0;i<point_count;i++) { - aabb.expand_to(points[i].pos); + aabb.expand_to(points[i].pos*p_scale); } - return p_mass*aabb.size.dot(aabb.size)/12.0f; + return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared(); } void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 8500a6194f..51ece9fc7e 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -84,7 +84,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0; - virtual real_t get_moment_of_inertia(float p_mass) const=0; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0; virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; @@ -173,7 +173,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -215,7 +215,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -262,7 +262,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -299,7 +299,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -338,20 +338,25 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway - Vector2 local_normal=p_transform.basis_xform_inv(p_normal); + r_max=-1e20; + r_min=1e20; + for(int i=0;i<4;i++) { - float length = local_normal.abs().dot(half_extents); - float distance = p_normal.dot( p_transform.get_origin() ); + real_t d=p_normal.dot(p_transform.xform(Vector2( ((i&1)*2-1)*half_extents.x, ((i>>1)*2-1)*half_extents.y ))); - r_min = distance - length; - r_max = distance + length; + if (d>r_max) + r_max=d; + if (d<r_min) + r_min=d; + + } } @@ -420,7 +425,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -482,7 +487,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -570,7 +575,7 @@ public: virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const { return 0; } + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; } virtual void set_data(const Variant& p_data); virtual Variant get_data() const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 21a99cd4b2..f2ed74ffbf 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -98,7 +98,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) { - //print_line("inters sgment!"); + Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point=xform.xform(shape_point); @@ -126,6 +126,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec if (r_result.collider_id!=0) r_result.collider=ObjectDB::get_instance(r_result.collider_id); r_result.normal=res_normal; + r_result.metadata=res_obj->get_shape_metadata(res_shape); r_result.position=res_point; r_result.rid=res_obj->get_self(); r_result.shape=res_shape; @@ -171,6 +172,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); r_results[cc].rid=col_obj->get_self(); r_results[cc].shape=shape_idx; + r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx); cc++; @@ -215,6 +217,16 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 int shape_idx=space->intersection_query_subindex_results[i]; + /*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) { + print_line("failed in motion dir"); + continue; + } + }*/ + + Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) { @@ -225,6 +237,14 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 //test initial overlap if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) { + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + //if one way collision direction ignore initial overlap + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2()) { + continue; + } + } + return false; } @@ -251,6 +271,29 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 } } + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2()) { + + Vector2 cd[2]; + Physics2DServerSW::CollCbkData cbk; + cbk.max=1; + cbk.amount=0; + cbk.ptr=cd; + cbk.valid_dir=body->get_one_way_collision_direction(); + cbk.valid_depth=body->get_one_way_collision_max_depth(); + + Vector2 sep=mnormal; //important optimization for this to work fast enough + bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*(hi+space->contact_max_allowed_penetration),col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),Physics2DServerSW::_shape_col_cbk,&cbk,&sep,p_margin); + if (!collided || cbk.amount==0) { + continue; + } + + } + } + + if (low<best_safe) { best_safe=low; best_unsafe=hi; @@ -309,14 +352,23 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s if (p_exclude.has( col_obj->get_self() )) continue; - + 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(); + cbk.valid_depth=body->get_one_way_collision_max_depth(); + } else { + cbk.valid_dir=Vector2(); + cbk.valid_depth=0; + } if (CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),cbkres,cbkptr,NULL,p_margin)) { - collided=true; + collided=p_result_max==0 || cbk.amount>0; } } + r_result_count=cbk.amount; return collided; @@ -332,6 +384,8 @@ struct _RestCallbackData2D { Vector2 best_contact; Vector2 best_normal; float best_len; + Vector2 valid_dir; + float valid_depth; }; static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) { @@ -339,17 +393,30 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v _RestCallbackData2D *rd=(_RestCallbackData2D*)p_userdata; + if (rd->valid_dir!=Vector2()) { + + if (rd->valid_dir!=Vector2()) { + if (p_point_A.distance_squared_to(p_point_B)>rd->valid_depth*rd->valid_depth) + return; + if (rd->valid_dir.dot((p_point_A-p_point_B).normalized())<Math_PI*0.25) + return; + } + + } + Vector2 contact_rel = p_point_B - p_point_A; float len = contact_rel.length(); if (len <= rd->best_len) return; + rd->best_len=len; rd->best_contact=p_point_B; rd->best_normal=contact_rel/len; rd->best_object=rd->object; rd->best_shape=rd->shape; + } @@ -382,6 +449,17 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape if (p_exclude.has( col_obj->get_self() )) continue; + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + rcd.valid_dir=body->get_one_way_collision_direction(); + rcd.valid_depth=body->get_one_way_collision_max_depth(); + } else { + rcd.valid_dir=Vector2(); + rcd.valid_depth=0; + } + + rcd.object=col_obj; rcd.shape=shape_idx; bool sc = CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_rest_cbk_result,&rcd,NULL,p_margin); @@ -399,6 +477,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape r_info->normal=rcd.best_normal; r_info->point=rcd.best_contact; r_info->rid=rcd.best_object->get_self(); + r_info->metadata=rcd.best_object->get_shape_metadata(rcd.best_shape); if (rcd.best_object->get_type()==CollisionObject2DSW::TYPE_BODY) { const Body2DSW *body = static_cast<const Body2DSW*>(rcd.best_object); @@ -433,6 +512,7 @@ Physics2DDirectSpaceStateSW::Physics2DDirectSpaceStateSW() { void* Space2DSW::_broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_self) { + CollisionObject2DSW::Type type_A=A->get_type(); CollisionObject2DSW::Type type_B=B->get_type(); if (type_A>type_B) { @@ -447,7 +527,6 @@ void* Space2DSW::_broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,Collis if (type_A==CollisionObject2DSW::TYPE_AREA) { - ERR_FAIL_COND_V(type_B!=CollisionObject2DSW::TYPE_BODY,NULL); Area2DSW *area=static_cast<Area2DSW*>(A); Body2DSW *body=static_cast<Body2DSW*>(B); @@ -602,8 +681,7 @@ void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_valu case Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration=p_value; break; case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD: body_linear_velocity_sleep_treshold=p_value; break; case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD: body_angular_velocity_sleep_treshold=p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep=p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio=p_value; break; + case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep=p_value; break; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias=p_value; break; } } @@ -618,7 +696,6 @@ real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const { case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD: return body_linear_velocity_sleep_treshold; case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD: return body_angular_velocity_sleep_treshold; case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; } return 0; @@ -660,7 +737,6 @@ Space2DSW::Space2DSW() { body_linear_velocity_sleep_treshold=0.01; body_angular_velocity_sleep_treshold=(8.0 / 180.0 * Math_PI); body_time_to_sleep=0.5; - body_angular_velocity_damp_ratio=15; broadphase = BroadPhase2DSW::create_func(); diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index c638a0c45b..7977b19063 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -93,7 +93,6 @@ class Space2DSW { float body_linear_velocity_sleep_treshold; float body_angular_velocity_sleep_treshold; float body_time_to_sleep; - float body_angular_velocity_damp_ratio; bool locked; @@ -142,7 +141,7 @@ public: _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_treshold() const { return body_linear_velocity_sleep_treshold; } _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_treshold() const { return body_angular_velocity_sleep_treshold; } _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; } - _FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; } + void update(); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index da8ac5f9c8..07389bc912 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -39,20 +39,24 @@ void Physics2DDirectBodyState::integrate_forces() { real_t av = get_angular_velocity(); - float damp = 1.0 - step * get_total_density(); + float damp = 1.0 - step * get_total_linear_damp(); if (damp<0) // reached zero in the given time damp=0; lv*=damp; + + damp = 1.0 - step * get_total_angular_damp(); + + if (damp<0) // reached zero in the given time + damp=0; + av*=damp; set_linear_velocity(lv); set_angular_velocity(av); - - } Object* Physics2DDirectBodyState::get_contact_collider_object(int p_contact_idx) const { @@ -70,7 +74,8 @@ Physics2DServer * Physics2DServer::get_singleton() { void Physics2DDirectBodyState::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity); - ObjectTypeDB::bind_method(_MD("get_total_density"),&Physics2DDirectBodyState::get_total_density); + ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp); + ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp); ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass); ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia); @@ -97,6 +102,7 @@ void Physics2DDirectBodyState::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id); ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object); ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape); + ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:var","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata); ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos); ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step); ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces); @@ -244,6 +250,7 @@ Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, cons d["collider"]=inters.collider; d["shape"]=inters.shape; d["rid"]=inters.rid; + d["metadata"]=inters.metadata; return d; } @@ -262,6 +269,7 @@ Array Physics2DDirectSpaceState::_intersect_shape(const Ref<Physics2DShapeQueryP d["collider_id"]=sr[i].collider_id; d["collider"]=sr[i].collider; d["shape"]=sr[i].shape; + d["metadata"]=sr[i].metadata; ret[i]=d; } @@ -311,6 +319,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue r["collider_id"]=sri.collider_id; r["shape"]=sri.shape; r["linear_velocity"]=sri.linear_velocity; + r["metadata"]=sri.metadata; return r; } @@ -412,8 +421,8 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_set_shape,DEFVAL(Matrix32())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Matrix32())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count); @@ -446,10 +455,12 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Matrix32())); ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape); ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform); + ObjectTypeDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata); ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count); ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape); ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform); + ObjectTypeDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata); ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape); ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes); @@ -489,6 +500,13 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported); ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported); + ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","normal"),&Physics2DServer::body_set_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction"),&Physics2DServer::body_get_one_way_collision_direction); + + ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","normal"),&Physics2DServer::body_set_one_way_collision_max_depth); + ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth"),&Physics2DServer::body_get_one_way_collision_max_depth); + + ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration); ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration); @@ -508,7 +526,7 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type); - ObjectTypeDB::bind_method(_MD("free","rid"),&Physics2DServer::free); + ObjectTypeDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free); ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active); @@ -532,7 +550,8 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); - BIND_CONSTANT( AREA_PARAM_DENSITY ); + BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP); + BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP); BIND_CONSTANT( AREA_PARAM_PRIORITY ); BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE ); @@ -547,6 +566,9 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( BODY_PARAM_BOUNCE ); BIND_CONSTANT( BODY_PARAM_FRICTION ); BIND_CONSTANT( BODY_PARAM_MASS ); + BIND_CONSTANT( BODY_PARAM_GRAVITY_SCALE ); + BIND_CONSTANT( BODY_PARAM_LINEAR_DAMP); + BIND_CONSTANT( BODY_PARAM_ANGULAR_DAMP); BIND_CONSTANT( BODY_PARAM_MAX ); BIND_CONSTANT( BODY_STATE_TRANSFORM ); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 17a21e46a3..765cebf45f 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -43,7 +43,8 @@ protected: public: virtual Vector2 get_total_gravity() const=0; // get gravity vector working on this body space/area - virtual float get_total_density() const=0; // get density of this body space/area + virtual float get_total_linear_damp() const=0; // get density of this body space/area + virtual float get_total_angular_damp() const=0; // get density of this body space/area virtual float get_inverse_mass() const=0; // get the mass virtual real_t get_inverse_inertia() const=0; // get density of this body space @@ -71,6 +72,7 @@ public: virtual ObjectID get_contact_collider_id(int p_contact_idx) const=0; virtual Object* get_contact_collider_object(int p_contact_idx) const; virtual int get_contact_collider_shape(int p_contact_idx) const=0; + virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const=0; virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const=0; virtual real_t get_step() const=0; @@ -163,6 +165,7 @@ public: ObjectID collider_id; Object *collider; int shape; + Variant metadata; }; virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; @@ -173,6 +176,8 @@ public: ObjectID collider_id; Object *collider; int shape; + Variant metadata; + }; @@ -190,6 +195,7 @@ public: ObjectID collider_id; int shape; Vector2 linear_velocity; //velocity at contact point + Variant metadata; }; @@ -272,7 +278,6 @@ public: SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD, SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD, SPACE_PARAM_BODY_TIME_TO_SLEEP, - SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO, SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, }; @@ -296,7 +301,8 @@ public: AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_POINT_ATTENUATION, - AREA_PARAM_DENSITY, + AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY }; @@ -360,10 +366,12 @@ public: virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0; virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0; virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform)=0; + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata)=0; virtual int body_get_shape_count(RID p_body) const=0; virtual RID body_get_shape(RID p_body, int p_shape_idx) const=0; virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const=0; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const=0; virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool p_enable)=0; virtual bool body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const=0; @@ -394,6 +402,9 @@ public: BODY_PARAM_BOUNCE, BODY_PARAM_FRICTION, BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_GRAVITY_SCALE, + BODY_PARAM_LINEAR_DAMP, + BODY_PARAM_ANGULAR_DAMP, BODY_PARAM_MAX, }; @@ -407,7 +418,7 @@ public: BODY_STATE_LINEAR_VELOCITY, BODY_STATE_ANGULAR_VELOCITY, BODY_STATE_SLEEPING, - BODY_STATE_CAN_SLEEP + BODY_STATE_CAN_SLEEP, }; virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant)=0; @@ -431,6 +442,12 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts)=0; virtual int body_get_max_contacts_reported(RID p_body) const=0; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction)=0; + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const=0; + + virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth)=0; + virtual float body_get_one_way_collision_max_depth(RID p_body) const=0; + //missing remove virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold)=0; virtual float body_get_contacts_reported_depth_treshold(RID p_body) const=0; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index dc8e4cc298..79de253d3b 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -440,8 +440,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_set_shape,DEFVAL(Transform())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count); @@ -452,8 +452,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes); - ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_get_param); - ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_get_transform); + ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param); + ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform); ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param); ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform); @@ -506,7 +506,7 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); - ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_set_axis_lock); + ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock); ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); @@ -520,6 +520,9 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant())); + ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable); + ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable); + /* JOINT API */ BIND_CONSTANT( JOINT_PIN ); @@ -627,6 +630,9 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type); + ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority); + ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority); + ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof); ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param); @@ -649,7 +655,7 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type); */ - ObjectTypeDB::bind_method(_MD("free","rid"),&PhysicsServer::free); + ObjectTypeDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free); ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active); diff --git a/servers/physics_server.h b/servers/physics_server.h index 25a89775a8..0c2542a66c 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -450,6 +450,10 @@ public: virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0; + virtual void body_set_ray_pickable(RID p_body,bool p_enable)=0; + virtual bool body_is_ray_pickable(RID p_body) const=0; + + /* JOINT API */ enum JointType { @@ -464,6 +468,8 @@ public: virtual JointType joint_get_type(RID p_joint) const=0; + virtual void joint_set_solver_priority(RID p_joint,int p_priority)=0; + virtual int joint_get_solver_priority(RID p_joint) const=0; virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B)=0; diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index f8d38d15c0..a2b1b71f99 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -57,6 +57,7 @@ void register_server_types() { ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>(); ObjectTypeDB::register_type<Physics2DShapeQueryParameters>(); + ObjectTypeDB::register_type<PhysicsShapeQueryParameters>(); ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>(); ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>(); ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>(); diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp index 7ec29d32cb..d00deb3912 100644 --- a/servers/spatial_sound/spatial_sound_server_sw.cpp +++ b/servers/spatial_sound/spatial_sound_server_sw.cpp @@ -879,10 +879,13 @@ void SpatialSoundServerSW::update(float p_delta) { float volume_attenuation = 0.0; float air_absorption_hf_cutoff = 0.0; float air_absorption = 0.0; - float pitch_scale=0.0; + float pitch_scale=1.0; Vector3 panning; + //print_line("listeners: "+itos(space->listeners.size())); + + for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { Listener *listener=listener_owner.get(L->get()); @@ -899,9 +902,11 @@ void SpatialSoundServerSW::update(float p_delta) { float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]; float attenuation=1; + //print_line("DIST MIN: "+rtos(distance_min)); + //print_line("DIST MAX: "+rtos(distance_max)); if (distance_max>0) { distance = CLAMP(distance,distance_min,distance_max); - attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16)); + attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16)); } float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]; @@ -945,7 +950,7 @@ void SpatialSoundServerSW::update(float p_delta) { air_absorption+=weight*absorption; air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff; panning+=vpanning*weight; - pitch_scale+=pscale*weight; + //pitch_scale+=pscale*weight; } @@ -991,8 +996,8 @@ void SpatialSoundServerSW::update(float p_delta) { reverb_send*=volume_scale; int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE]; - if (mix_rate<=0) { + if (mix_rate<=0) { ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param."); to_disable.push_back(ActiveVoice(source,voice)); // oh well.. continue; //invalid mix rate, disabling diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp index e3c8aba758..2aab0e7dc9 100644 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp +++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp @@ -904,7 +904,7 @@ void SpatialSound2DServerSW::update(float p_delta) { if (distance_max>0) { distance = CLAMP(distance,distance_min,distance_max); - attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16)); + attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16)); } float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]; diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index e160b4dccc..c3dcd83a31 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -79,7 +79,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { if (texcoords_used&(1<<VS::FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM)) { code+="uniform mat4 fmp_uv_xform;\n"; - code+="vec2 uv_xform = fmp_uv_xform * UV;\n"; + code+="vec2 uv_xform = (fmp_uv_xform * vec4(UV,0,1)).xy;\n"; } /* HANDLE NORMAL MAPPING */ @@ -96,8 +96,14 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { } else { uv_str=_TEXUVSTR(VS::FIXED_MATERIAL_PARAM_NORMAL); } - scode+="vec3 normal=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; - scode+="NORMAL = mix( NORMAL,mat3(TANGENT,BINORMAL,NORMAL) * normal, fmp_normal);\n"; + if (p_key.use_xy_normalmap) { + scode+="vec2 ywnormal=tex( fmp_normal_tex,"+uv_str+").wy * vec2(2.0,2.0) - vec2(1.0,1.0);\n"; + scode+="NORMALMAP=vec3(ywnormal,sqrt(1 - (ywnormal.x * ywnormal.x) - (ywnormal.y * ywnormal.y) ));\n"; + } else { + scode+="NORMALMAP=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; + } + scode+="NORMALMAP_DEPTH=fmp_normal;\n"; + code+=scode; } @@ -323,6 +329,7 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: fm.use_color_array=p_enabled; break; case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: fm.use_pointsize=p_enabled; break; case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: fm.discard_alpha=p_enabled; break; + case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: fm.use_xy_normalmap=p_enabled; break; } if (!fm.dirty_list.in_list()) @@ -341,6 +348,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: return fm.use_color_array;; break; case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: return fm.use_pointsize;; break; case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: return fm.discard_alpha;; break; + case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: return fm.use_xy_normalmap;; break; + } @@ -355,12 +364,13 @@ RID Rasterizer::fixed_material_create() { FixedMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); + material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) { material_set_param(mat,_fixed_material_param_names[i],fm.param[i]); //must be there } fixed_material_dirty_list.add(&fm.dirty_list); - //print_line("FMC: "+itos(mat.get_id())); + //print_line("FMC: "+itos(mat.get_id())); return mat; } @@ -558,8 +568,9 @@ void Rasterizer::_update_fixed_materials() { } material_set_param(fm.self,_fixed_material_uv_xform_name,fm.uv_xform); - if (fm.use_pointsize) + if (fm.use_pointsize) { material_set_param(fm.self,_fixed_material_point_size_name,fm.point_size); + } } fixed_material_dirty_list.remove(fixed_material_dirty_list.first()); @@ -610,6 +621,10 @@ Rasterizer::Rasterizer() { _fixed_material_uv_xform_name="fmp_uv_xform"; _fixed_material_point_size_name="fmp_point_size"; + draw_viewport_func=NULL; + + ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4); + } RID Rasterizer::create_overdraw_debug_material() { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 5b07c633c3..92c7b8ac14 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -40,6 +40,9 @@ class Rasterizer { protected: + + typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); + RID create_default_material(); RID create_overdraw_debug_material(); @@ -56,6 +59,7 @@ protected: bool use_color_array:1; bool use_pointsize:1; bool discard_alpha:1; + bool use_xy_normalmap:1; bool valid:1; }; @@ -83,6 +87,7 @@ protected: bool use_color_array; bool discard_alpha; bool use_pointsize; + bool use_xy_normalmap; float point_size; Transform uv_xform; VS::FixedMaterialLightShader light_shader; @@ -102,6 +107,7 @@ protected: k.use_alpha=use_alpha; k.use_color_array=use_color_array; k.use_pointsize=use_pointsize; + k.use_xy_normalmap=use_xy_normalmap; k.discard_alpha=discard_alpha; k.light_shader=light_shader; k.valid=true; @@ -123,6 +129,7 @@ protected: use_color_array=false; use_pointsize=false; discard_alpha=false; + use_xy_normalmap=false; point_size=1.0; light_shader=VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT; for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) { @@ -183,6 +190,7 @@ public: virtual bool texture_has_alpha(RID p_texture) const=0; virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; + virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0; /* SHADER API */ @@ -199,6 +207,11 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name)=0; + /* COMMON MATERIAL API */ virtual RID material_create()=0; @@ -499,6 +512,7 @@ public: VS::BakedLightMode mode; RID octree_texture; + RID light_texture; float color_multiplier; //used for both lightmaps and octree Transform octree_transform; Map<int,RID> lightmaps; @@ -510,6 +524,7 @@ public: float lightmap_multiplier; int octree_steps; Vector2 octree_tex_pixel_size; + Vector2 light_tex_pixel_size; }; struct InstanceData { @@ -517,6 +532,7 @@ public: Transform transform; RID skeleton; RID material_override; + RID sampled_light; Vector<RID> light_instances; Vector<float> morph_values; BakedLightData *baked_light; @@ -550,7 +566,279 @@ public: CANVAS_RECT_FLIP_H=4, CANVAS_RECT_FLIP_V=8 }; - + + struct CanvasItem { + + struct Command { + + enum Type { + + TYPE_LINE, + TYPE_RECT, + TYPE_STYLE, + TYPE_PRIMITIVE, + TYPE_POLYGON, + TYPE_POLYGON_PTR, + TYPE_CIRCLE, + TYPE_TRANSFORM, + TYPE_BLEND_MODE, + TYPE_CLIP_IGNORE, + }; + + Type type; + }; + + struct CommandLine : public Command { + + Point2 from,to; + Color color; + float width; + CommandLine() { type = TYPE_LINE; } + }; + + struct CommandRect : public Command { + + Rect2 rect; + RID texture; + Color modulate; + Rect2 source; + uint8_t flags; + + CommandRect() { flags=0; type = TYPE_RECT; } + }; + + struct CommandStyle : public Command { + + Rect2 rect; + RID texture; + float margin[4]; + float draw_center; + Color color; + CommandStyle() { draw_center=true; type = TYPE_STYLE; } + }; + + struct CommandPrimitive : public Command { + + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + float width; + + CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} + }; + + struct CommandPolygon : public Command { + + Vector<int> indices; + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + int count; + + CommandPolygon() { type = TYPE_POLYGON; count = 0; } + }; + + struct CommandPolygonPtr : public Command { + + const int* indices; + const Point2* points; + const Point2* uvs; + const Color* colors; + RID texture; + int count; + + CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } + }; + + struct CommandCircle : public Command { + + Point2 pos; + float radius; + Color color; + CommandCircle() { type = TYPE_CIRCLE; } + }; + + struct CommandTransform : public Command { + + Matrix32 xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + struct CommandBlendMode : public Command { + + VS::MaterialBlendMode blend_mode; + CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = VS::MATERIAL_BLEND_MODE_MIX; } + }; + struct CommandClipIgnore : public Command { + + bool ignore; + CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; } + }; + + + struct ViewportRender { + VisualServer*owner; + void* udata; + Rect2 rect; + }; + + Matrix32 xform; + bool clip; + bool visible; + bool ontop; + VS::MaterialBlendMode blend_mode; + Vector<Command*> commands; + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + CanvasItem*next; + RID shader; + Map<StringName,Variant> shader_param; + uint32_t shader_version; + + + float final_opacity; + Matrix32 final_transform; + Rect2 final_clip_rect; + CanvasItem* final_clip_owner; + CanvasItem* shader_owner; + ViewportRender *vp_render; + + const Rect2& get_rect() const { + + if (custom_rect || !rect_dirty) + return rect; + + //must update rect + int s=commands.size(); + if (s==0) { + + rect=Rect2(); + rect_dirty=false; + return rect; + } + + Matrix32 xf; + bool found_xform=false; + bool first=true; + + const CanvasItem::Command * const *cmd = &commands[0]; + + + for (int i=0;i<s;i++) { + + const CanvasItem::Command *c=cmd[i]; + Rect2 r; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); + r.pos=line->from; + r.expand_to(line->to); + } break; + case CanvasItem::Command::TYPE_RECT: { + + const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); + r=crect->rect; + + } break; + case CanvasItem::Command::TYPE_STYLE: { + + const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); + r=style->rect; + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); + r.pos=primitive->points[0]; + for(int i=1;i<primitive->points.size();i++) { + + r.expand_to(primitive->points[i]); + + } + } break; + case CanvasItem::Command::TYPE_POLYGON: { + + const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); + int l = polygon->points.size(); + const Point2*pp=&polygon->points[0]; + r.pos=pp[0]; + for(int i=1;i<l;i++) { + + r.expand_to(pp[i]); + + } + } break; + + case CanvasItem::Command::TYPE_POLYGON_PTR: { + + const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); + int l = polygon->count; + if (polygon->indices != NULL) { + + r.pos=polygon->points[polygon->indices[0]]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[polygon->indices[i]]); + }; + } else { + r.pos=polygon->points[0]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[i]); + }; + }; + } break; + case CanvasItem::Command::TYPE_CIRCLE: { + + const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); + r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; + r.size=Point2(circle->radius*2.0,circle->radius*2.0); + } break; + case CanvasItem::Command::TYPE_TRANSFORM: { + + const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); + xf=transform->xform; + found_xform=true; + continue; + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + } break; + } + + if (found_xform) { + r = xf.xform(r); + found_xform=false; + } + + + if (first) { + rect=r; + first=false; + } else + rect=rect.merge(r); + } + + rect_dirty=false; + return rect; + } + + void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;} + CanvasItem() { vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;} + virtual ~CanvasItem() { clear(); } + }; + + + CanvasItemDrawViewportFunc draw_viewport_func; + + virtual void canvas_begin()=0; virtual void canvas_disable_blending()=0; virtual void canvas_set_opacity(float p_opacity)=0; @@ -564,7 +852,10 @@ public: virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width)=0; virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0; virtual void canvas_set_transform(const Matrix32& p_transform)=0; - + + virtual void canvas_render_items(CanvasItem *p_item_list)=0; + + /* ENVIRONMENT */ @@ -582,6 +873,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0; virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height)=0; + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0; + /*MISC*/ diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 637c251cf1..6c1b6697c1 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -221,6 +221,21 @@ void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } + +void RasterizerDummy::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + +} + +RID RasterizerDummy::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const { + + return RID(); +} + +Variant RasterizerDummy::shader_get_default_param(RID p_shader, const StringName& p_name) { + + return Variant(); +} + /* COMMON MATERIAL API */ @@ -1607,6 +1622,11 @@ void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) { } +void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list) { + + +} + /* ENVIRONMENT */ RID RasterizerDummy::environment_create() { @@ -1679,6 +1699,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + +RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + /*MISC*/ bool RasterizerDummy::is_texture(const RID& p_rid) const { @@ -1816,6 +1848,14 @@ void RasterizerDummy::free(const RID& p_rid) { Environment *env = environment_owner.get( p_rid ); environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + }; } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 373564249e..c72149f88f 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -422,6 +429,12 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -697,6 +710,8 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); virtual void canvas_set_transform(const Matrix32& p_transform); + virtual void canvas_render_items(CanvasItem *p_item_list); + /* ENVIRONMENT */ virtual RID environment_create(); @@ -713,6 +728,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ diff --git a/servers/visual/shader_graph.h b/servers/visual/shader_graph.h index 5c5079202f..fe305f3955 100644 --- a/servers/visual/shader_graph.h +++ b/servers/visual/shader_graph.h @@ -26,8 +26,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_GRAPH_H -#define SHADER_GRAPH_H #if 0 @@ -109,4 +107,3 @@ public: }; #endif -#endif diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 14d35e89b1..9a76a009a9 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -436,7 +436,10 @@ ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_le return Token(TK_INDENTIFIER,str); } - return Token(TK_ERROR,"Unknown character"); + if (GETCHAR(0)>32) + return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); + else + return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); } break; } @@ -463,9 +466,9 @@ Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,Stri if (t.type==TK_ERROR) { if (r_error) { - return ERR_COMPILATION_FAILED; *r_error=t.text; *r_err_line=line; + return ERR_COMPILATION_FAILED; } } @@ -765,16 +768,20 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ //constructors {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, //intrinsics - trigonometry @@ -853,6 +860,9 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, @@ -890,6 +900,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"normalize",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, {"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, //intrinsics - texture {"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}}, {"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}}, @@ -952,10 +963,16 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, @@ -1038,10 +1055,12 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ { "VERTEX", TYPE_VEC3}, - { "POSITION", TYPE_VEC3}, + { "POSITION", TYPE_VEC4}, { "NORMAL", TYPE_VEC3}, { "TANGENT", TYPE_VEC3}, { "BINORMAL", TYPE_VEC3}, + { "NORMALMAP", TYPE_VEC3}, + { "NORMALMAP_DEPTH", TYPE_FLOAT}, { "UV", TYPE_VEC2}, { "UV2", TYPE_VEC2}, { "COLOR", TYPE_VEC4}, @@ -1087,6 +1106,61 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ }; + + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ + + { "SRC_VERTEX", TYPE_VEC2}, + { "VERTEX", TYPE_VEC2}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "POINT_SIZE", TYPE_FLOAT}, + + //builtins + { "WORLD_MATRIX", TYPE_MAT4}, + { "PROJECTION_MATRIX", TYPE_MAT4}, + { "EXTRA_MATRIX", TYPE_MAT4}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID}, +}; +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ + + { "SRC_COLOR", TYPE_VEC4}, + { "POSITION", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "TEXTURE", TYPE_TEXTURE}, + { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "SCREEN_UV", TYPE_VEC2}, + { "POINT_COORD", TYPE_VEC2}, + +// { "SCREEN_POS", TYPE_VEC2}, +// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID} + +}; + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ + + { "COLOR", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "LIGHT_DIR", TYPE_VEC2}, + { "LIGHT_DISTANCE", TYPE_FLOAT}, + { "LIGHT", TYPE_VEC3}, + { "POINT_COORD", TYPE_VEC2}, +// { "SCREEN_POS", TYPE_VEC2}, +// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID} + +}; + const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={ { "IN_COLOR", TYPE_VEC3}, @@ -1199,9 +1273,25 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper Variant data; switch(p_func->return_cache) { case TYPE_FLOAT: data = cdata[0]; break; - case TYPE_VEC2: data = Vector2(cdata[0],cdata[1]); break; - case TYPE_VEC3: data = Vector3(cdata[0],cdata[1],cdata[2]); break; - case TYPE_VEC4: data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); break; + case TYPE_VEC2: + if (cdata.size()==1) + data = Vector2(cdata[0],cdata[0]); + else + data = Vector2(cdata[0],cdata[1]); + + break; + case TYPE_VEC3: + if (cdata.size()==1) + data = Vector3(cdata[0],cdata[0],cdata[0]); + else + data = Vector3(cdata[0],cdata[1],cdata[2]); + break; + case TYPE_VEC4: + if (cdata.size()==1) + data = Plane(cdata[0],cdata[0],cdata[0],cdata[0]); + else + data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); + break; } cn->datatype=p_func->return_cache; @@ -2437,6 +2527,27 @@ Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,Comp idx++; } } break; + case SHADER_CANVAS_ITEM_VERTEX: { + int idx=0; + while (ci_vertex_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_vertex_builtins_defs[idx].name]=ci_vertex_builtins_defs[idx].type; + idx++; + } + } break; + case SHADER_CANVAS_ITEM_FRAGMENT: { + int idx=0; + while (ci_fragment_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_fragment_builtins_defs[idx].name]=ci_fragment_builtins_defs[idx].type; + idx++; + } + } break; + case SHADER_CANVAS_ITEM_LIGHT: { + int idx=0; + while (ci_light_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_light_builtins_defs[idx].name]=ci_light_builtins_defs[idx].type; + idx++; + } + } break; case SHADER_POST_PROCESS: { int idx=0; while (postprocess_fragment_builtins_defs[idx].name) { @@ -2483,6 +2594,9 @@ Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc uint64_t t = OS::get_singleton()->get_ticks_usec(); Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column); + if (err!=OK) { + print_line("tokenizer error!"); + } double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0; //print_line("tokenize time: "+rtos(tf)); @@ -2531,6 +2645,28 @@ void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keyword idx++; } } break; + case SHADER_CANVAS_ITEM_VERTEX: { + idx=0; + while (ci_vertex_builtins_defs[idx].name) { + p_keywords->push_back(ci_vertex_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_CANVAS_ITEM_FRAGMENT: { + idx=0; + while (ci_fragment_builtins_defs[idx].name) { + p_keywords->push_back(ci_fragment_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_CANVAS_ITEM_LIGHT: { + idx=0; + while (ci_light_builtins_defs[idx].name) { + p_keywords->push_back(ci_light_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_POST_PROCESS: { idx=0; while (postprocess_fragment_builtins_defs[idx].name) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 7e01368dd5..f79c219d85 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -105,6 +105,9 @@ public: SHADER_MATERIAL_VERTEX, SHADER_MATERIAL_FRAGMENT, SHADER_MATERIAL_LIGHT, + SHADER_CANVAS_ITEM_VERTEX, + SHADER_CANVAS_ITEM_FRAGMENT, + SHADER_CANVAS_ITEM_LIGHT, SHADER_POST_PROCESS, }; @@ -376,6 +379,12 @@ private: static const BuiltinsDef vertex_builtins_defs[]; static const BuiltinsDef fragment_builtins_defs[]; static const BuiltinsDef light_builtins_defs[]; + + static const BuiltinsDef ci_vertex_builtins_defs[]; + static const BuiltinsDef ci_fragment_builtins_defs[]; + static const BuiltinsDef ci_light_builtins_defs[]; + + static const BuiltinsDef postprocess_fragment_builtins_defs[]; static DataType get_token_datatype(TokenType p_type); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 21ecd4030d..dc0bff4cf4 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -157,6 +157,16 @@ void VisualServerRaster::shader_get_param_list(RID p_shader, List<PropertyInfo> } +void VisualServerRaster::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + rasterizer->shader_set_default_texture_param(p_shader,p_name,p_texture); +} + +RID VisualServerRaster::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + + return rasterizer->shader_get_default_texture_param(p_shader,p_name); +} + /* Material */ @@ -1109,8 +1119,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< int tex_w; int tex_h; + int light_tex_w; + int light_tex_h; bool is16; + bool has_light_tex=false; { + DVector<uint8_t>::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); @@ -1123,7 +1137,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< baked_light->data.octree_steps=decode_uint32(&r[16]); baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + baked_light->data.texture_multiplier=decode_uint32(&r[20]); + light_tex_w=decode_uint16(&r[24]); + light_tex_h=decode_uint16(&r[26]); + print_line("ltexw "+itos(light_tex_w)); + print_line("ltexh "+itos(light_tex_h)); + + if (light_tex_w>0 && light_tex_h>0) { + baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w; + baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h; + has_light_tex=true; + } else { + baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size; + + } + baked_light->octree_aabb.pos.x=decode_float(&r[32]); @@ -1141,12 +1170,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< rasterizer->free(baked_light->data.octree_texture); baked_light->data.octree_texture=RID(); + baked_light->octree_tex_size.x=0; + baked_light->octree_tex_size.y=0; + } + } + + if (baked_light->data.light_texture.is_valid()) { + if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { + rasterizer->free(baked_light->data.light_texture); + baked_light->data.light_texture=RID(); + baked_light->light_tex_size.x=0; + baked_light->light_tex_size.y=0; } } if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->octree_tex_size.x=tex_w; + baked_light->octree_tex_size.y=tex_h; + } + + if (!baked_light->data.light_texture.is_valid() && has_light_tex) { + baked_light->data.light_texture=rasterizer->texture_create(); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->light_tex_size.x=light_tex_w; + baked_light->light_tex_size.y=light_tex_h; + } Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); @@ -1159,6 +1209,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } + DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ @@ -1174,6 +1225,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c } } +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) { + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + ERR_FAIL_COND(p_light.size()==0); + + int tex_w=baked_light->light_tex_size.x; + int tex_h=baked_light->light_tex_size.y; + + ERR_FAIL_COND(tex_w==0 && tex_h==0); + ERR_FAIL_COND(!baked_light->data.light_texture.is_valid()); + + + + print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); + + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + rasterizer->texture_set_data(baked_light->data.light_texture,img); + + + +} + +DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + + if (rasterizer->is_texture(baked_light->data.light_texture)) { + + Image img = rasterizer->texture_get_data(baked_light->data.light_texture); + return img.get_data(); + } else { + return DVector<uint8_t>(); + } +} + + + +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + baked_light->sampler=p_sampler; + + + +} + +DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<int>()); + + return baked_light->sampler; + +} + + void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ VS_CHANGED; @@ -1192,6 +1304,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ } +/* BAKED LIGHT SAMPLER */ + +RID VisualServerRaster::baked_light_sampler_create() { + + BakedLightSampler * blsamp = memnew( BakedLightSampler ); + RID rid = baked_light_sampler_owner.make_rid(blsamp); + _update_baked_light_sampler_dp_cache(blsamp); + return rid; +} + +void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){ + + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX); + blsamp->params[p_param]=p_value; + _dependency_queue_update(p_baked_light_sampler,true); +} + +float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{ + + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0); + return blsamp->params[p_param]; +} + +void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) { + + int res = blsamp->resolution; + blsamp->dp_cache.resize(res*res*2); + Vector3 *dp_normals=blsamp->dp_cache.ptr(); + + for(int p=0;p<2;p++) { + float sign = p==0?1:-1; + int ofs = res*res*p; + for(int i=0;i<res;i++) { + for(int j=0;j<res;j++) { + + Vector2 v( + (i/float(res))*2.0-1.0, + (j/float(res))*2.0-1.0 + ); + + float l=v.length(); + if (l>1.0) { + v/=l; + l=1.0; //clamp to avoid imaginary + } + v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function + Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z + n.y*=sign; + dp_normals[j*res+i+ofs]=n; + } + } + } + +} + +void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + blsamp->resolution=p_resolution; + _update_baked_light_sampler_dp_cache(blsamp); + +} +int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{ + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + return blsamp->resolution; +} + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1202,7 +1392,7 @@ RID VisualServerRaster::camera_create() { } void VisualServerRaster::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) { - VS_CHANGED; + VS_CHANGED Camera *camera = camera_owner.get( p_camera ); ERR_FAIL_COND(!camera); camera->type=Camera::PERSPECTIVE; @@ -1226,7 +1416,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr VS_CHANGED; Camera *camera = camera_owner.get( p_camera ); ERR_FAIL_COND(!camera); - camera->transform=p_transform; + camera->transform=p_transform.orthonormalized(); } @@ -1786,6 +1976,17 @@ void VisualServerRaster::scenario_set_environment(RID p_scenario, RID p_environm } +void VisualServerRaster::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + VS_CHANGED; + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment=p_environment; + + +} + RID VisualServerRaster::scenario_get_environment(RID p_scenario, RID p_environment) const{ const Scenario *scenario = scenario_owner.get(p_scenario); @@ -1932,6 +2133,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_sampler_info) { + + while (instance->baked_light_sampler_info->owned_instances.size()) { + + instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->baked_light_sampler_info->sampled_light); + } + memdelete( instance->baked_light_sampler_info ); + instance->baked_light_sampler_info=NULL; + } + instance->data.morph_values.clear(); } @@ -1981,6 +2196,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { //instance->portal_info = memnew(Instance::PortalInfo); //instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER; + instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else { ERR_EXPLAIN("Invalid base RID for instance!") ERR_FAIL(); @@ -2596,11 +2821,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance,RID() ); if (instance->baked_light) - instance->baked_light->self; + return instance->baked_light->self; return RID(); } + +void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->sampled_light) { + instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); + instance->data.sampled_light=RID(); + } + + if(p_baked_light_sampler.is_valid()) { + Instance *sampler_instance = instance_owner.get( p_baked_light_sampler ); + ERR_FAIL_COND( !sampler_instance ); + ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER ); + instance->sampled_light=sampler_instance; + instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance); + } else { + instance->sampled_light=NULL; + } + + instance->data.sampled_light=RID(); + +} + +RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + + if (instance->sampled_light) + return instance->sampled_light->self; + else + return RID(); + +} + + void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ VS_CHANGED; @@ -2736,6 +3000,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { pairable=true; } + if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) { + + pairable_mask=(1<<INSTANCE_BAKED_LIGHT); + pairable=true; + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { base_type|=INSTANCE_ROOMLESS_MASK; @@ -2848,6 +3119,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { new_aabb=baked_light->octree_aabb; } break; + case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: { + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light_sampler); + float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; + default: {} } @@ -3071,129 +3352,6 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) { canvas_item->clip=p_clip; } -const Rect2& VisualServerRaster::CanvasItem::get_rect() const { - - if (custom_rect || !rect_dirty) - return rect; - - //must update rect - int s=commands.size(); - if (s==0) { - - rect=Rect2(); - rect_dirty=false; - return rect; - } - - Matrix32 xf; - bool found_xform=false; - bool first=true; - - const CanvasItem::Command * const *cmd = &commands[0]; - - - for (int i=0;i<s;i++) { - - const CanvasItem::Command *c=cmd[i]; - Rect2 r; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); - r.pos=line->from; - r.expand_to(line->to); - } break; - case CanvasItem::Command::TYPE_RECT: { - - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); - r=crect->rect; - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); - r=style->rect; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); - r.pos=primitive->points[0]; - for(int i=1;i<primitive->points.size();i++) { - - r.expand_to(primitive->points[i]); - - } - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); - int l = polygon->points.size(); - const Point2*pp=&polygon->points[0]; - r.pos=pp[0]; - for(int i=1;i<l;i++) { - - r.expand_to(pp[i]); - - } - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); - int l = polygon->count; - if (polygon->indices != NULL) { - - r.pos=polygon->points[polygon->indices[0]]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[polygon->indices[i]]); - }; - } else { - r.pos=polygon->points[0]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[i]); - }; - }; - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); - r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; - r.size=Point2(circle->radius*2.0,circle->radius*2.0); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); - xf=transform->xform; - found_xform=true; - continue; - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - } break; - } - - if (found_xform) { - r = xf.xform(r); - found_xform=false; - } - - - if (first) { - rect=r; - first=false; - } else - rect=rect.merge(r); - } - - rect_dirty=false; - return rect; -} void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) { @@ -3531,6 +3689,83 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen canvas_item->commands.push_back(bm); }; +void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { + + ERR_FAIL_COND(p_z<CANVAS_ITEM_Z_MIN || p_z>CANVAS_ITEM_Z_MAX); + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z=p_z; + +} + +void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z_relative=p_enable; + +} + +void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->use_parent_shader=p_enable; + +} + +void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->shader=p_shader; +} + +RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{ + + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND_V(!canvas_item,RID()); + return canvas_item->shader; + +} + +void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){ + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); + ERR_FAIL_COND(!canvas_item); + if (p_value.get_type()==Variant::NIL) + canvas_item->shader_param.erase(p_param); + else + canvas_item->shader_param[p_param]=p_value; + +} +Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{ + + CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); + ERR_FAIL_COND_V(!canvas_item,Variant()); + if (!canvas_item->shader_param.has(p_param)) { + ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant()); + return rasterizer->shader_get_default_param(canvas_item->shader,p_param); + } + + return canvas_item->shader_param[p_param]; +} + + +void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->sort_y=p_enable; +} + + void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { VS_CHANGED; @@ -3742,6 +3977,17 @@ void VisualServerRaster::free( RID p_rid ) { baked_light_owner.free(p_rid); memdelete(baked_light); + } else if (baked_light_sampler_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); + ERR_FAIL_COND(!baked_light_sampler); + //if (baked_light->data.octree_texture.is_valid()) + // rasterizer->free(baked_light->data.octree_texture); + baked_light_sampler_owner.free(p_rid); + memdelete(baked_light_sampler); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3793,7 +4039,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); instance_geometry_set_baked_light(p_rid,RID()); + instance_geometry_set_baked_light_sampler(p_rid,RID()); instance_set_base(p_rid,RID()); + if (instance->data.skeleton.is_valid()) instance_attach_skeleton(p_rid,RID()); @@ -4937,6 +5185,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance //attempt to conncet portal A (will go through B anyway) //this is a little hackish, but works fine in practice + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL); + B->baked_light_sampler_info->baked_lights.insert(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -4986,6 +5243,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance self->_portal_attempt_connect(A); self->_portal_attempt_connect(B); + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER); + B->baked_light_sampler_info->baked_lights.erase(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5177,6 +5443,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance } +void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) { + + + BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler; + int res = sampler_opts->resolution; + int dp_size = res*res*2; + Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors + Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals + const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr(); + + + if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) { + if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light); + } + + p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution; + p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2); + + + } + + + zeromem(dp_map,sizeof(Color)*dp_size); + bool valid=false; + int samples=0; + + + for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) { + + Instance *bl = E->get(); + if (bl->baked_light_info->baked_light->sampler.size()==0) + continue; //not usable + + + Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse(); + for(int i=0;i<dp_size;i++) { + dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized(); + } + + //normals in place + + + //sample octree + + float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION]; + float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH]; + Vector3 s = p_sampled_light->data.transform.basis.get_scale(); + + r*=MAX(MAX(s.x,s.y),s.z); + AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); + //ok got octree local AABB + + DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); + const int *rptr = rp.ptr(); + + int first = rptr[1]; + int depth = rptr[2]; + bool islinear = rptr[3]&1; + depth+=1; + + AABB aabb; + aabb.pos.x=decode_float((const uint8_t*)&rptr[4]); + aabb.pos.y=decode_float((const uint8_t*)&rptr[5]); + aabb.pos.z=decode_float((const uint8_t*)&rptr[6]); + aabb.size.x=decode_float((const uint8_t*)&rptr[7]); + aabb.size.y=decode_float((const uint8_t*)&rptr[8]); + aabb.size.z=decode_float((const uint8_t*)&rptr[9]); + + uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t)); + int *stack_ptr=(int*)alloca(depth*sizeof(int)); + AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB)); + + stack[0]=0; + stack_ptr[0]=first; + aabb_stack[0]=aabb; + Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5; + + + int stack_pos=0; + Color max_col; + + //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]; + + int lalimit = sample_aabb.get_longest_axis_index(); + float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit]; + + + while(true) { + + + bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0; + + if (aabb_stack[stack_pos].size[lalimit]<limit) { + leaf=true; + } + + + if (leaf) { + + Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5; + Vector3 norm = (from-center).normalized(); + + + Color col; + col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0); + col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0); + col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0); + + + max_col.r = MAX(max_col.r,col.r); + max_col.g = MAX(max_col.g,col.g); + max_col.b = MAX(max_col.b,col.b); + + if (!islinear && p_linear_colorspace) { + col=col.to_linear(); + } + + float distance; + + if (aabb_stack[stack_pos].has_point(center)) { + distance=0; + } else { + + Vector3 support = aabb_stack[stack_pos].get_support(norm); + distance = Math::absf(norm.dot(support)-norm.dot(center)); + + } + + if (distance>r) + distance=r; + + float mult = Math::pow(1.0-distance/r,att)*str; + if (mult>0) { + col.r*=mult; + col.g*=mult; + col.b*=mult; + + + + for(int i=0;i<dp_size;i++) { + float mult2 = norm.dot(dp_normals[i]); + if (mult2<0) + mult2=0; + Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0); + dp_map[i].r=MAX(dp_map[i].r,col2.r); + dp_map[i].g=MAX(dp_map[i].g,col2.g); + dp_map[i].b=MAX(dp_map[i].b,col2.b); + } + + } + + samples++; + //nothing is valid unless you hit a leaf + valid=true; + stack_pos--; + } else if ((stack[stack_pos]&0xFF)<8) { + + int i = stack[stack_pos]&0xFF; + int base = (stack[stack_pos]>>8); + + if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) { + //no bit, no test + stack[stack_pos]=(base<<8)+(i+1); + continue; + } + + stack[stack_pos]=((base+1)<<8)+(i+1); + + AABB child_aabb = aabb_stack[stack_pos]; + child_aabb.size*=0.5; + if (i&1) + child_aabb.pos.x+=child_aabb.size.x; + if (i&2) + child_aabb.pos.y+=child_aabb.size.y; + if (i&4) + child_aabb.pos.z+=child_aabb.size.z; + + if (!child_aabb.intersects(sample_aabb)) { + continue; + } + + if (child_aabb.encloses(sample_aabb)) { + stack[stack_pos]=(base<<8)|8; //don't test the rest + } + + stack_pos++; + ERR_FAIL_COND(stack_pos>=depth); + + stack[stack_pos]=0; + stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ]; + aabb_stack[stack_pos]=child_aabb; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + + } + + //print_line("samples "+itos(samples) ); + + if (valid) { + + for(int i=0;i<res;i++) { + //average seams to avoid aliasing + { + //top + int ofs1 = i; + int ofs2 = dp_size-res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //bottom + int ofs1 = res*res-res+i; + int ofs2 = res*res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //left + int ofs1 = i*res; + int ofs2 = res*res+(res-i-1)*res; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //right + int ofs1 = i*res+(res-1); + int ofs2 = res*res+(res-i-1)*res+(res-1); + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + + } + + rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0); + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light; + } + + + } else { + + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=RID(); //do not use because nothing close + } + } + + + + +/* + highp vec3 vtx = vertex_interp; + vtx.z*=dual_paraboloid.y; //side to affect + vtx.z+=0.01; + dp_clip=vtx.z; + highp float len=length( vtx ); + vtx=normalize(vtx); + vtx.xy/=1.0+vtx.z; + vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); + vtx+=normalize(vtx)*0.025; + vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace + vertex_interp=vtx; +*/ + + + + +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5228,6 +5796,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 2 - CULL */ int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); light_cull_count=0; + light_samplers_culled=0; /* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); @@ -5388,6 +5957,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S keep=true; } + + } @@ -5400,6 +5971,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S cull_range.min=min; if (max>cull_range.max) cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) { + if (light_samplers_culled<MAX_LIGHT_SAMPLERS) { + light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light; + ins->sampled_light->baked_light_sampler_info->last_pass=render_pass; + } + } } } @@ -5479,7 +6057,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } - { + { //this should eventually change to //assign shadows by distance to camera SortArray<Instance*,_InstanceLightsort> sorter; sorter.sort(light_cull_result,light_cull_count); @@ -5500,15 +6078,31 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } } + /* ENVIRONMENT */ - - /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/ - RID environment; if (p_camera->env.is_valid()) //camera has more environment priority environment=p_camera->env; - else + else if (p_scenario->environment.is_valid()) environment=p_scenario->environment; + else + environment=p_scenario->fallback_environment; + + + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;i<light_samplers_culled;i++) { + + _process_sampled_light(p_camera->transform,light_sampler_cull_result[i],islinear); + } + + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); @@ -5551,7 +6145,41 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S rasterizer->end_scene(); } -void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity) { + +void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect) { + + + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + + + _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i]); + } + +} + + +void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect) { + + VisualServerRaster *self=(VisualServerRaster*)(p_self); + Viewport *vp=(Viewport*)p_vp; + self->_draw_viewport(vp,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y); + self->rasterizer->canvas_begin(); + +} + +void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) { CanvasItem *ci = p_canvas_item; @@ -5570,200 +6198,100 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (global_rect.intersects(p_clip_rect) && ci->viewport.is_valid() && viewport_owner.owns(ci->viewport)) { - Viewport *vp = viewport_owner.get(ci->viewport); + Viewport *vp = viewport_owner.get(ci->viewport); Point2i from = xform.get_origin() + Point2(viewport_rect.x,viewport_rect.y); Point2i size = rect.size; size.x *= xform[0].length(); size.y *= xform[1].length(); + ci->vp_render = memnew( Rasterizer::CanvasItem::ViewportRender ); + ci->vp_render->owner=this; + ci->vp_render->udata=vp; + ci->vp_render->rect=Rect2(from.x, + from.y, + size.x, + size.y); +/* _draw_viewport(vp, from.x, from.y, size.x, size.y); +*/ + //rasterizer->canvas_begin(); + } else { + ci->vp_render=NULL; + } - rasterizer->canvas_begin(); + if (ci->use_parent_shader && p_shader_owner) + ci->shader_owner=p_shader_owner; + else { + p_shader_owner=ci; + ci->shader_owner=NULL; } - int s = ci->commands.size(); - bool reclip=false; float opacity = ci->opacity * p_opacity; -#ifndef ONTOP_DISABLED - CanvasItem **child_items = ci->child_items.ptr(); + int child_item_count=ci->child_items.size(); - int top_item_count=0; - CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*)); + CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*)); + copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*)); if (ci->clip) { - rasterizer->canvas_set_clip(true,global_rect); - canvas_clip=global_rect; - } - - for(int i=0;i<child_item_count;i++) { + ci->final_clip_rect=global_rect; + ci->final_clip_owner=ci; - if (child_items[i]->ontop) - top_items[top_item_count++]=child_items[i]; - else { - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); - } + } else { + ci->final_clip_owner=p_canvas_clip; } -#endif - - if (s!=0) { - - //Rect2 rect( ci->rect.pos + p_ofs, ci->rect.size); - - if (p_clip_rect.intersects(global_rect)) { - - rasterizer->canvas_begin_rect(xform); - rasterizer->canvas_set_opacity( opacity * ci->self_opacity ); - rasterizer->canvas_set_blend_mode( ci->blend_mode ); - - CanvasItem::Command **commands = &ci->commands[0]; - - for (int i=0;i<s;i++) { - CanvasItem::Command *c=commands[i]; + if (ci->sort_y) { - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); - rasterizer->canvas_draw_line(line->from,line->to,line->color,line->width); - } break; - case CanvasItem::Command::TYPE_RECT: { - - CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); -// rasterizer->canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); -#if 0 - int flags=0; - - if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { - flags|=Rasterizer::CANVAS_RECT_REGION; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { - flags|=Rasterizer::CANVAS_RECT_TILE; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_H; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_V; - } -#else - - int flags=rect->flags; -#endif - rasterizer->canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); - rasterizer->canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); - - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); - rasterizer->canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); - - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); - static const int numpoints=32; - Vector2 points[numpoints+1]; - points[numpoints]=circle->pos; - int indices[numpoints*3]; - - for(int i=0;i<numpoints;i++) { - - points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; - indices[i*3+0]=i; - indices[i*3+1]=(i+1)%numpoints; - indices[i*3+2]=numpoints; - } - rasterizer->canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); - //rasterizer->canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); - rasterizer->canvas_set_transform(transform->xform); - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); - rasterizer->canvas_set_blend_mode(bm->blend_mode); - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); - if (canvas_clip!=Rect2()) { - - if (ci->ignore!=reclip) { - if (ci->ignore) { - - rasterizer->canvas_set_clip(false,Rect2()); - reclip=true; - } else { - rasterizer->canvas_set_clip(true,canvas_clip); - reclip=false; - } - } - } + SortArray<CanvasItem*,CanvasItemPtrSort> sorter; + sorter.sort(child_items,child_item_count); + } + for(int i=0;i<child_item_count;i++) { - } break; - } - } - rasterizer->canvas_end_rect(); - } + if (child_items[i]->ontop) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner); } - if (reclip) { + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) { + //something to draw? + ci->final_transform=xform; + ci->final_opacity=opacity * ci->self_opacity; - rasterizer->canvas_set_clip(true,canvas_clip); - } + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; -#ifndef ONTOP_DISABLED + int zidx = p_z-CANVAS_ITEM_Z_MIN; - for(int i=0;i<top_item_count;i++) { + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; - _render_canvas_item(top_items[i],xform,p_clip_rect,opacity); - } + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } -#else - for(int i=0;i<p_canvas_item->child_items.size();i++) { + ci->next=NULL; - _render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity); } -#endif + for(int i=0;i<child_item_count;i++) { - if (ci->clip) { - rasterizer->canvas_set_clip(false,Rect2()); - canvas_clip=Rect2(); + if (!child_items[i]->ontop) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner); } } @@ -5773,29 +6301,61 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans rasterizer->canvas_begin(); int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); + bool has_mirror=false; for(int i=0;i<l;i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; + } + } - Canvas::ChildItem& ci=p_canvas->child_items[i]; - _render_canvas_item(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height); + if (!has_mirror) { - //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x!=0) { + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; } - if (ci.mirror.y!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); } - if (ci.mirror.y!=0 && ci.mirror.x!=0) { - Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i]); } + } else { + + for(int i=0;i<l;i++) { + + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,clip_rect); + + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + if (ci.mirror.y!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + + } } } @@ -5819,6 +6379,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ desired_rect.x+=p_ofs_x; desired_rect.y+=p_ofs_y; + // if the viewport is different than the actual one, change it if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x || @@ -5828,7 +6389,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ viewport_rect=desired_rect; - rasterizer->set_viewport(viewport_rect); + rasterizer->set_viewport(viewport_rect); } @@ -5876,6 +6437,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ if (p_viewport->queue_capture) { rasterizer->capture_viewport(&p_viewport->capture); + p_viewport->queue_capture = false; } //restore @@ -5956,7 +6518,7 @@ void VisualServerRaster::_draw_viewports() { rasterizer->set_viewport(viewport_rect); } - rasterizer->canvas_begin(); + rasterizer->canvas_begin(); rasterizer->canvas_disable_blending(); rasterizer->canvas_begin_rect(Matrix32()); rasterizer->canvas_draw_rect(E->get()->rt_to_screen_rect,0,Rect2(Point2(),E->get()->rt_to_screen_rect.size),E->get()->render_target_texture,Color(1,1,1)); @@ -5975,7 +6537,14 @@ void VisualServerRaster::_draw_viewports() { int window_w = OS::get_singleton()->get_video_mode(E->get()).width; int window_h = OS::get_singleton()->get_video_mode(E->get()).height; - _draw_viewport(vp,0,0,window_w,window_h); + Rect2 r(0,0,vp->rect.width,vp->rect.height); + if (r.size.width==0) + r.size.width=window_w; + if (r.size.height==0) + r.size.height=window_w; + + + _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); } @@ -6204,6 +6773,7 @@ RID VisualServerRaster::get_test_cube() { VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { rasterizer=p_rasterizer; + rasterizer->draw_viewport_func=_render_canvas_item_viewport; instance_update_list=NULL; render_pass=0; clear_color=Color(0.3,0.3,0.3,1.0); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 49e7996c59..6c4e15827a 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer { MAX_LIGHTS_CULLED=256, MAX_ROOM_CULL=32, MAX_EXTERIOR_PORTALS=128, + MAX_LIGHT_SAMPLERS=256, INSTANCE_ROOMLESS_MASK=(1<<20) @@ -84,18 +85,36 @@ class VisualServerRaster : public VisualServer { Vector<Point2> shape; Rect2 bounds; + Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; } }; struct BakedLight { Rasterizer::BakedLightData data; + DVector<int> sampler; AABB octree_aabb; Size2i octree_tex_size; + Size2i light_tex_size; }; + struct BakedLightSampler { + + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector<Vector3> dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); struct Camera { enum Type { @@ -169,6 +188,7 @@ class VisualServerRaster : public VisualServer { List<Instance*>::Element *RE; Instance *baked_light; List<Instance*>::Element *BLE; + Instance *sampled_light; bool exterior; uint64_t last_render_pass; @@ -179,6 +199,8 @@ class VisualServerRaster : public VisualServer { InstanceSet lights; bool light_cache_dirty; + + struct RoomInfo { Transform affine_inverse; @@ -235,6 +257,23 @@ class VisualServerRaster : public VisualServer { Transform affine_inverse; List<Instance*> owned_instances; }; + + struct BakedLightSamplerInfo { + + Set<Instance*> baked_lights; + Set<Instance*> owned_instances; + BakedLightSampler *sampler; + int resolution; + Vector<Color> light_bufer; + RID sampled_light; + uint64_t last_pass; + Transform xform; // viewspace normal to lightspace, might not use one. + BakedLightSamplerInfo() { + sampler=NULL; + last_pass=0; + resolution=0; + } + }; struct ParticlesInfo { @@ -247,6 +286,7 @@ class VisualServerRaster : public VisualServer { ParticlesInfo *particles_info; PortalInfo * portal_info; BakedLightInfo * baked_light_info; + BakedLightSamplerInfo * baked_light_sampler_info; Instance() { @@ -282,6 +322,8 @@ class VisualServerRaster : public VisualServer { baked_light=NULL; baked_light_info=NULL; + baked_light_sampler_info=NULL; + sampled_light=NULL; BLE=NULL; light_cache_dirty=true; @@ -320,6 +362,7 @@ class VisualServerRaster : public VisualServer { List<RID> directional_lights; RID environment; + RID fallback_environment; Instance *dirty_instances; @@ -328,143 +371,44 @@ class VisualServerRaster : public VisualServer { - - struct CanvasItem { - - struct Command { - - enum Type { - - TYPE_LINE, - TYPE_RECT, - TYPE_STYLE, - TYPE_PRIMITIVE, - TYPE_POLYGON, - TYPE_POLYGON_PTR, - TYPE_CIRCLE, - TYPE_TRANSFORM, - TYPE_BLEND_MODE, - TYPE_CLIP_IGNORE, - }; - - Type type; - }; - - struct CommandLine : public Command { - - Point2 from,to; - Color color; - float width; - CommandLine() { type = TYPE_LINE; } - }; - - struct CommandRect : public Command { - - Rect2 rect; - RID texture; - Color modulate; - Rect2 source; - uint8_t flags; - - CommandRect() { flags=0; type = TYPE_RECT; } - }; - - struct CommandStyle : public Command { - - Rect2 rect; - RID texture; - float margin[4]; - float draw_center; - Color color; - CommandStyle() { draw_center=true; type = TYPE_STYLE; } - }; - - struct CommandPrimitive : public Command { - - Vector<Point2> points; - Vector<Point2> uvs; - Vector<Color> colors; - RID texture; - float width; - - CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} - }; - - struct CommandPolygon : public Command { - - Vector<int> indices; - Vector<Point2> points; - Vector<Point2> uvs; - Vector<Color> colors; - RID texture; - int count; - - CommandPolygon() { type = TYPE_POLYGON; count = 0; } - }; - struct CommandPolygonPtr : public Command { + struct CanvasItem : public Rasterizer::CanvasItem { - const int* indices; - const Point2* points; - const Point2* uvs; - const Color* colors; - RID texture; - int count; - - CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } - }; - - struct CommandCircle : public Command { - - Point2 pos; - float radius; - Color color; - CommandCircle() { type = TYPE_CIRCLE; } - }; - - struct CommandTransform : public Command { - - Matrix32 xform; - CommandTransform() { type = TYPE_TRANSFORM; } - }; - - struct CommandBlendMode : public Command { - - MaterialBlendMode blend_mode; - CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = MATERIAL_BLEND_MODE_MIX; }; - }; - struct CommandClipIgnore : public Command { - - bool ignore; - CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; }; - }; RID parent; // canvas it belongs to List<CanvasItem*>::Element *E; - Matrix32 xform; - bool clip; - bool visible; - bool ontop; + RID viewport; + int z; + bool z_relative; + bool sort_y; float opacity; float self_opacity; - MaterialBlendMode blend_mode; - RID viewport; + bool use_parent_shader; + - mutable bool custom_rect; - mutable bool rect_dirty; - mutable Rect2 rect; - - Vector<Command*> commands; Vector<CanvasItem*> child_items; - const Rect2& get_rect() const; - void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true;}; - CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; } - ~CanvasItem() { clear(); } + + CanvasItem() { + E=NULL; + z=0; + opacity=1; + self_opacity=1; + sort_y=false; + use_parent_shader=false; + z_relative=true; + } }; + struct CanvasItemPtrSort { + + _FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const { + + return p_left->xform.elements[2].y < p_right->xform.elements[2].y; + } + }; struct Canvas { @@ -594,6 +538,9 @@ class VisualServerRaster : public VisualServer { int exterior_portal_cull_count; bool exterior_visited; + Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS]; + int light_samplers_culled; + Instance *room_cull_result[MAX_ROOM_CULL]; int room_cull_count; bool room_cull_enabled; @@ -629,6 +576,7 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Portal> portal_owner; mutable RID_Owner<BakedLight> baked_light_owner; + mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner; mutable RID_Owner<Camera> camera_owner; mutable RID_Owner<Viewport> viewport_owner; @@ -649,8 +597,12 @@ class VisualServerRaster : public VisualServer { bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to); void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal); void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL); + void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace); + void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); - void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity); + static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); + void _render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect); + void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner); void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -700,6 +652,10 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -944,12 +900,28 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree); virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light); + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler); + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); virtual void baked_light_clear_lightmaps(RID p_baked_light); + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create(); + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + /* CAMERA API */ virtual RID camera_create(); @@ -1030,6 +1002,8 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode); virtual void scenario_set_environment(RID p_scenario, RID p_environment); virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const; + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + /* INSTANCING API */ @@ -1085,6 +1059,9 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); virtual RID instance_geometry_get_baked_light(RID p_instance) const; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; @@ -1135,6 +1112,18 @@ public: virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform); virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend); virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); + virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); + virtual void canvas_item_set_z(RID p_item, int p_z); + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); + + virtual void canvas_item_set_shader(RID p_item, RID p_shader); + virtual RID canvas_item_get_shader(RID p_item) const; + + virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable); + + + virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value); + virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const; virtual void canvas_item_clear(RID p_item); virtual void canvas_item_raise(RID p_item); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index f1ba4c453b..b59fdbc66a 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -653,6 +653,10 @@ public: FUNC1RC(String,shader_get_light_code,RID); FUNC2SC(shader_get_param_list,RID,List<PropertyInfo>*); + FUNC3(shader_set_default_texture_param,RID,const StringName&,RID); + FUNC2RC(RID,shader_get_default_texture_param,RID,const StringName&); + + /*virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) { if (Thread::get_caller_ID()!=server_thread) { command_queue.push_and_sync( visual_server, &VisualServer::shader_get_param_list,p_shader,p_param_list); @@ -909,6 +913,12 @@ public: FUNC2(baked_light_set_octree,RID,DVector<uint8_t>); FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID); + FUNC2(baked_light_set_light,RID,DVector<uint8_t>); + FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID); + + FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&); + FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID); + FUNC2(baked_light_set_lightmap_multiplier,RID,float); FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); @@ -916,6 +926,14 @@ public: FUNC1(baked_light_clear_lightmaps,RID); + FUNC0R(RID,baked_light_sampler_create); + + FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); + FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); + + FUNC2(baked_light_sampler_set_resolution,RID,int); + FUNC1RC(int,baked_light_sampler_get_resolution,RID); + /* CAMERA API */ FUNC0R(RID,camera_create); @@ -929,6 +947,7 @@ public: FUNC2(camera_set_environment,RID,RID); FUNC1RC(RID,camera_get_environment,RID); + FUNC2(camera_set_use_vertical_aspect,RID,bool); FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool); @@ -998,6 +1017,7 @@ public: FUNC2(scenario_set_debug,RID,ScenarioDebugMode); FUNC2(scenario_set_environment,RID, RID); FUNC2RC(RID,scenario_get_environment,RID, RID); + FUNC2(scenario_set_fallback_environment,RID, RID); /* INSTANCING API */ @@ -1053,6 +1073,9 @@ public: FUNC2(instance_geometry_set_baked_light,RID, RID ); FUNC1RC(RID,instance_geometry_get_baked_light,RID); + FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); + FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); + FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); @@ -1107,6 +1130,19 @@ public: FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode ); FUNC2(canvas_item_add_clip_ignore,RID, bool ); + FUNC2(canvas_item_set_sort_children_by_y,RID,bool); + FUNC2(canvas_item_set_z,RID,int); + FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool); + + FUNC2(canvas_item_set_shader,RID, RID ); + FUNC1RC(RID,canvas_item_get_shader,RID ); + + FUNC2(canvas_item_set_use_parent_shader,RID, bool ); + + + FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&); + FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&); + FUNC1(canvas_item_clear,RID); FUNC1(canvas_item_raise,RID); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 9abfecaac6..e0238c8042 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -486,7 +486,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb); ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray); - ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_ray); + ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex); diff --git a/servers/visual_server.h b/servers/visual_server.h index 8934fa7903..5721e7acf0 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -86,6 +86,10 @@ public: ARRAY_WEIGHTS_SIZE=4, MAX_PARTICLE_COLOR_PHASES=4, MAX_PARTICLE_ATTRACTORS=4, + CANVAS_ITEM_Z_MIN=-4096, + CANVAS_ITEM_Z_MAX=4096, + + MAX_CURSORS = 8, }; @@ -96,8 +100,10 @@ public: TEXTURE_FLAG_MIPMAPS=1, /// Enable automatic mipmap generation - when available TEXTURE_FLAG_REPEAT=2, /// Repeat texture (Tiling), otherwise Clamping TEXTURE_FLAG_FILTER=4, /// Create texure with linear (or available) filter - TEXTURE_FLAG_CUBEMAP=8, - TEXTURE_FLAG_VIDEO_SURFACE=16, + TEXTURE_FLAG_ANISOTROPIC_FILTER=8, + TEXTURE_FLAG_CONVERT_TO_LINEAR=16, + TEXTURE_FLAG_CUBEMAP=2048, + TEXTURE_FLAG_VIDEO_SURFACE=4096, TEXTURE_FLAGS_DEFAULT=TEXTURE_FLAG_REPEAT|TEXTURE_FLAG_MIPMAPS|TEXTURE_FLAG_FILTER }; @@ -137,6 +143,7 @@ public: SHADER_POST_PROCESS, }; + virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL)=0; virtual void shader_set_mode(RID p_shader,ShaderMode p_mode)=0; @@ -148,6 +155,9 @@ public: virtual String shader_get_light_code(RID p_shader) const=0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + /* COMMON MATERIAL API */ @@ -166,6 +176,7 @@ public: MATERIAL_FLAG_UNSHADED, MATERIAL_FLAG_ONTOP, MATERIAL_FLAG_LIGHTMAP_ON_UV2, + MATERIAL_FLAG_COLOR_ARRAY_SRGB, MATERIAL_FLAG_MAX, }; @@ -229,6 +240,7 @@ public: FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, FIXED_MATERIAL_FLAG_USE_POINT_SIZE, FIXED_MATERIAL_FLAG_DISCARD_ALPHA, + FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP, FIXED_MATERIAL_FLAG_MAX, }; @@ -585,12 +597,35 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0; virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0; + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0; + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create()=0; + + enum BakedLightSamplerParam { + BAKED_LIGHT_SAMPLER_RADIUS, + BAKED_LIGHT_SAMPLER_STRENGTH, + BAKED_LIGHT_SAMPLER_ATTENUATION, + BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + BAKED_LIGHT_SAMPLER_MAX + }; + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; /* CAMERA API */ @@ -803,7 +838,7 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0; virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0; virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0; - + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0; /* INSTANCING API */ @@ -819,7 +854,8 @@ public: INSTANCE_ROOM, INSTANCE_PORTAL, INSTANCE_BAKED_LIGHT, - + INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) }; @@ -893,9 +929,13 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0; virtual RID instance_geometry_get_baked_light(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0; + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0; virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0; + virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0; virtual bool instance_light_is_enabled(RID p_instance) const=0; @@ -944,10 +984,21 @@ public: virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0; virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0; + virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0; + virtual void canvas_item_set_z(RID p_item, int p_z)=0; + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable)=0; virtual void canvas_item_clear(RID p_item)=0; virtual void canvas_item_raise(RID p_item)=0; + virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0; + virtual RID canvas_item_get_shader(RID p_item) const=0; + + virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0; + + virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0; + virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0; + /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0)=0; |