summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub2
-rw-r--r--servers/audio/audio_server_sw.cpp8
-rw-r--r--servers/audio/audio_server_sw.h5
-rw-r--r--servers/audio_server.h1
-rw-r--r--servers/physics/area_pair_sw.cpp3
-rw-r--r--servers/physics/area_sw.cpp6
-rw-r--r--servers/physics/area_sw.h3
-rw-r--r--servers/physics/body_pair_sw.cpp72
-rw-r--r--servers/physics/body_pair_sw.h1
-rw-r--r--servers/physics/body_sw.cpp16
-rw-r--r--servers/physics/body_sw.h3
-rw-r--r--servers/physics/collision_object_sw.cpp1
-rw-r--r--servers/physics/collision_object_sw.h11
-rw-r--r--servers/physics/collision_solver_sw.cpp44
-rw-r--r--servers/physics/collision_solver_sw.h1
-rw-r--r--servers/physics/constraint_sw.h6
-rw-r--r--servers/physics/physics_server_sw.cpp40
-rw-r--r--servers/physics/physics_server_sw.h6
-rw-r--r--servers/physics/space_sw.cpp5
-rw-r--r--servers/physics/step_sw.cpp39
-rw-r--r--servers/physics_2d/area_2d_sw.cpp10
-rw-r--r--servers/physics_2d/area_2d_sw.h10
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp84
-rw-r--r--servers/physics_2d/body_2d_sw.h29
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp9
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp8
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h15
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp1
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp62
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h13
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp33
-rw-r--r--servers/physics_2d/shape_2d_sw.h33
-rw-r--r--servers/physics_2d/space_2d_sw.cpp92
-rw-r--r--servers/physics_2d/space_2d_sw.h3
-rw-r--r--servers/physics_2d_server.cpp38
-rw-r--r--servers/physics_2d_server.h25
-rw-r--r--servers/physics_server.cpp18
-rw-r--r--servers/physics_server.h6
-rw-r--r--servers/register_server_types.cpp1
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.cpp13
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp2
-rw-r--r--servers/visual/rasterizer.cpp25
-rw-r--r--servers/visual/rasterizer.h299
-rw-r--r--servers/visual/rasterizer_dummy.cpp40
-rw-r--r--servers/visual/rasterizer_dummy.h19
-rw-r--r--servers/visual/shader_graph.h3
-rw-r--r--servers/visual/shader_language.cpp148
-rw-r--r--servers/visual/shader_language.h9
-rw-r--r--servers/visual/visual_server_raster.cpp1176
-rw-r--r--servers/visual/visual_server_raster.h237
-rw-r--r--servers/visual/visual_server_wrap_mt.h36
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h59
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;