diff options
Diffstat (limited to 'servers')
36 files changed, 1014 insertions, 146 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 1ca2334392..be36c3b748 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -44,7 +44,7 @@ Error AudioDriverDummy::init() { speaker_mode = SPEAKER_MODE_STEREO; channels = 2; - int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); + int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_frames * channels); diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index 9faa4056c3..3414351681 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -100,6 +100,8 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i if (C == 6) { + // FIXME: Lot of unused assignments here, but it seems like intermediate calculations + // should be done as for C == 2 (C == 4 also has some unused assignments). float v0 = rb[(pos * 6) + 0]; float v1 = rb[(pos * 6) + 1]; float v2 = rb[(pos * 6) + 2]; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 8ee43ddc32..ceb843c031 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -117,6 +117,10 @@ AudioDriver::AudioDriver() { _last_mix_time = 0; _mix_amount = 0; + +#ifdef DEBUG_ENABLED + prof_time = 0; +#endif } AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; @@ -184,6 +188,10 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { int todo = p_frames; +#ifdef DEBUG_ENABLED + uint64_t prof_ticks = OS::get_singleton()->get_ticks_usec(); +#endif + if (channel_count != get_channel_count()) { // Amount of channels changed due to a device change // reinitialize the buses channels and buffers @@ -235,27 +243,15 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { to_mix -= to_copy; } -#ifdef DEBUG_ENABLED - if (OS::get_singleton() && OS::get_singleton()->is_stdout_verbose()) { - static uint64_t first_ticks = 0; - static uint64_t last_ticks = 0; - static uint64_t ticks = 0; - static int count = 0; - static int total = 0; - - ticks = OS::get_singleton()->get_ticks_msec(); - if ((ticks - first_ticks) > 10 * 1000 && count > 0) { - print_line("Audio Driver " + String(AudioDriver::get_singleton()->get_name()) + " average latency: " + itos(total / count) + "ms (frame=" + itos(p_frames) + ")"); - first_ticks = ticks; - total = 0; - count = 0; - } - - total += ticks - last_ticks; - count++; - - last_ticks = ticks; + // Calculate latency for Performance.AUDIO_OUTPUT_LATENCY + if (OS::get_singleton()) { + uint64_t ticks = OS::get_singleton()->get_ticks_usec(); + output_latency = (ticks - output_latency_ticks) / 1000000.f; + output_latency_ticks = ticks; } + +#ifdef DEBUG_ENABLED + prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks; #endif } @@ -330,6 +326,10 @@ void AudioServer::_mix_step() { if (!bus->effects[j].enabled) continue; +#ifdef DEBUG_ENABLED + uint64_t ticks = OS::get_singleton()->get_ticks_usec(); +#endif + for (int k = 0; k < bus->channels.size(); k++) { if (!bus->channels[k].active) @@ -344,6 +344,10 @@ void AudioServer::_mix_step() { continue; SWAP(bus->channels[k].buffer, temp_buffer[k]); } + +#ifdef DEBUG_ENABLED + bus->effects[j].prof_time += OS::get_singleton()->get_ticks_usec() - ticks; +#endif } } @@ -784,6 +788,9 @@ void AudioServer::add_bus_effect(int p_bus, const Ref<AudioEffect> &p_effect, in fx.effect = p_effect; //fx.instance=p_effect->instance(); fx.enabled = true; +#ifdef DEBUG_ENABLED + fx.prof_time = 0; +#endif if (p_at_pos >= buses[p_bus]->effects.size() || p_at_pos < 0) { buses[p_bus]->effects.push_back(fx); @@ -896,8 +903,8 @@ void AudioServer::init_channels_and_buffers() { void AudioServer::init() { - channel_disable_threshold_db = GLOBAL_DEF("audio/channel_disable_threshold_db", -60.0); - channel_disable_frames = float(GLOBAL_DEF("audio/channel_disable_time", 2.0)) * get_mix_rate(); + channel_disable_threshold_db = GLOBAL_DEF_RST("audio/channel_disable_threshold_db", -60.0); + channel_disable_frames = float(GLOBAL_DEF_RST("audio/channel_disable_time", 2.0)) * get_mix_rate(); buffer_size = 1024; //hardcoded for now init_channels_and_buffers(); @@ -913,7 +920,69 @@ void AudioServer::init() { set_edited(false); //avoid editors from thinking this was edited #endif - GLOBAL_DEF("audio/video_delay_compensation_ms", 0); + GLOBAL_DEF_RST("audio/video_delay_compensation_ms", 0); +} + +void AudioServer::update() { +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) { + + // Driver time includes server time + effects times + // Server time includes effects times + uint64_t driver_time = AudioDriver::get_singleton()->get_profiling_time(); + uint64_t server_time = prof_time; + + // Substract the server time from the driver time + if (driver_time > server_time) + driver_time -= server_time; + + Array values; + + for (int i = buses.size() - 1; i >= 0; i--) { + Bus *bus = buses[i]; + if (bus->bypass) + continue; + + for (int j = 0; j < bus->effects.size(); j++) { + if (!bus->effects[j].enabled) + continue; + + values.push_back(String(bus->name) + bus->effects[j].effect->get_name()); + values.push_back(USEC_TO_SEC(bus->effects[j].prof_time)); + + // Substract the effect time from the driver and server times + if (driver_time > bus->effects[j].prof_time) + driver_time -= bus->effects[j].prof_time; + if (server_time > bus->effects[j].prof_time) + server_time -= bus->effects[j].prof_time; + } + } + + values.push_back("audio_server"); + values.push_back(USEC_TO_SEC(server_time)); + values.push_back("audio_driver"); + values.push_back(USEC_TO_SEC(driver_time)); + + ScriptDebugger::get_singleton()->add_profiling_frame_data("audio_thread", values); + } + + // Reset profiling times + for (int i = buses.size() - 1; i >= 0; i--) { + Bus *bus = buses[i]; + if (bus->bypass) + continue; + + for (int j = 0; j < bus->effects.size(); j++) { + if (!bus->effects[j].enabled) + continue; + + bus->effects[j].prof_time = 0; + } + } + + AudioDriver::get_singleton()->reset_profiling_time(); + prof_time = 0; +#endif } void AudioServer::load_default_bus_layout() { @@ -1201,6 +1270,11 @@ AudioServer::AudioServer() { mix_frames = 0; channel_count = 0; to_mix = 0; + output_latency = 0; + output_latency_ticks = 0; +#ifdef DEBUG_ENABLED + prof_time = 0; +#endif } AudioServer::~AudioServer() { diff --git a/servers/audio_server.h b/servers/audio_server.h index b7fcd9c093..258fd1d9b0 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -33,6 +33,7 @@ #include "audio_frame.h" #include "object.h" +#include "os/os.h" #include "servers/audio/audio_effect.h" #include "variant.h" @@ -44,10 +45,23 @@ class AudioDriver { uint64_t _last_mix_time; uint64_t _mix_amount; +#ifdef DEBUG_ENABLED + uint64_t prof_ticks; + uint64_t prof_time; +#endif + protected: void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true); void update_mix_time(int p_frames); +#ifdef DEBUG_ENABLED + _FORCE_INLINE_ void start_counting_ticks() { prof_ticks = OS::get_singleton()->get_ticks_usec(); } + _FORCE_INLINE_ void stop_counting_ticks() { prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks; } +#else + _FORCE_INLINE_ void start_counting_ticks() {} + _FORCE_INLINE_ void stop_counting_ticks() {} +#endif + public: double get_mix_time() const; //useful for video -> audio sync @@ -82,6 +96,11 @@ public: SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const; int get_total_channels_by_speaker_mode(SpeakerMode) const; +#ifdef DEBUG_ENABLED + uint64_t get_profiling_time() const { return prof_time; } + void reset_profiling_time() { prof_time = 0; } +#endif + AudioDriver(); virtual ~AudioDriver() {} }; @@ -129,6 +148,9 @@ private: uint32_t buffer_size; uint64_t mix_count; uint64_t mix_frames; +#ifdef DEBUG_ENABLED + uint64_t prof_time; +#endif float channel_disable_threshold_db; uint32_t channel_disable_frames; @@ -166,6 +188,9 @@ private: struct Effect { Ref<AudioEffect> effect; bool enabled; +#ifdef DEBUG_ENABLED + uint64_t prof_time; +#endif }; Vector<Effect> effects; @@ -190,6 +215,9 @@ private: Mutex *audio_data_lock; + float output_latency; + uint64_t output_latency_ticks; + void init_channels_and_buffers(); void _mix_step(); @@ -273,6 +301,7 @@ public: virtual void init(); virtual void finish(); + virtual void update(); virtual void load_default_bus_layout(); /* MISC config */ @@ -306,6 +335,8 @@ public: String get_device(); void set_device(String device); + float get_output_latency() { return output_latency; } + AudioServer(); virtual ~AudioServer(); }; diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index 2a6a9e08ae..5a41b621eb 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -211,6 +211,44 @@ bool BodyPairSW::_test_ccd(real_t p_step, BodySW *p_A, int p_shape_A, const Tran return true; } +real_t combine_bounce(BodySW *A, BodySW *B) { + const PhysicsServer::CombineMode cm = A->get_bounce_combine_mode(); + + switch (cm) { + case PhysicsServer::COMBINE_MODE_INHERIT: + if (B->get_bounce_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT) + return combine_bounce(B, A); + // else use MAX [This is used when the two bodies doesn't use physical material] + case PhysicsServer::COMBINE_MODE_MAX: + return MAX(A->get_bounce(), B->get_bounce()); + case PhysicsServer::COMBINE_MODE_MIN: + return MIN(A->get_bounce(), B->get_bounce()); + case PhysicsServer::COMBINE_MODE_MULTIPLY: + return A->get_bounce() * B->get_bounce(); + default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE: + return (A->get_bounce() + B->get_bounce()) / 2; + } +} + +real_t combine_friction(BodySW *A, BodySW *B) { + const PhysicsServer::CombineMode cm = A->get_friction_combine_mode(); + + switch (cm) { + case PhysicsServer::COMBINE_MODE_INHERIT: + if (B->get_friction_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT) + return combine_friction(B, A); + // else use Multiply [This is used when the two bodies doesn't use physical material] + case PhysicsServer::COMBINE_MODE_MULTIPLY: + return A->get_friction() * B->get_friction(); + case PhysicsServer::COMBINE_MODE_MAX: + return MAX(A->get_friction(), B->get_friction()); + case PhysicsServer::COMBINE_MODE_MIN: + return MIN(A->get_friction(), B->get_friction()); + default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE: + return (A->get_friction() + B->get_friction()) / 2; + } +} + bool BodyPairSW::setup(real_t p_step) { //cannot collide @@ -331,7 +369,7 @@ bool BodyPairSW::setup(real_t p_step) { c.acc_bias_impulse = 0; c.acc_bias_impulse_center_of_mass = 0; - c.bounce = MAX(A->get_bounce(), B->get_bounce()); + c.bounce = combine_bounce(A, B); if (c.bounce) { Vector3 crA = A->get_angular_velocity().cross(c.rA); @@ -421,7 +459,7 @@ void BodyPairSW::solve(real_t p_step) { //friction impulse - real_t friction = A->get_friction() * B->get_friction(); + real_t friction = combine_friction(A, B); Vector3 lvA = A->get_linear_velocity() + A->get_angular_velocity().cross(c.rA); Vector3 lvB = B->get_linear_velocity() + B->get_angular_velocity().cross(c.rB); diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index cc9681193c..59f987fc17 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -423,6 +423,22 @@ void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) { area_angular_damp += p_area->get_angular_damp(); } +void BodySW::set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode) { + if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) { + bounce_combine_mode = p_mode; + } else { + friction_combine_mode = p_mode; + } +} + +PhysicsServer::CombineMode BodySW::get_combine_mode(PhysicsServer::BodyParameter p_param) const { + if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) { + return bounce_combine_mode; + } else { + return friction_combine_mode; + } +} + void BodySW::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index fd2ab16b84..25eb20f5d8 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -49,6 +49,8 @@ class BodySW : public CollisionObjectSW { real_t mass; real_t bounce; real_t friction; + PhysicsServer::CombineMode bounce_combine_mode; + PhysicsServer::CombineMode friction_combine_mode; real_t linear_damp; real_t angular_damp; @@ -298,6 +300,12 @@ public: _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + void set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode); + PhysicsServer::CombineMode get_combine_mode(PhysicsServer::BodyParameter p_param) const; + + _FORCE_INLINE_ PhysicsServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; } + _FORCE_INLINE_ PhysicsServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; } + void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock); bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const; diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp index e587485fcb..44b7c9ac34 100644 --- a/servers/physics/collision_solver_sat.cpp +++ b/servers/physics/collision_solver_sat.cpp @@ -217,8 +217,6 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_ // generate contacts //Plane plane_A(p_points_A[0],p_points_A[1],p_points_A[2]); - int added = 0; - for (int i = 0; i < clipbuf_len; i++) { real_t d = plane_B.distance_to(clipbuf_src[i]); @@ -233,7 +231,6 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_ continue; p_callback->call(clipbuf_src[i], closest_B); - added++; } } diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index f2dbb635f8..f1e0cbef29 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -65,6 +65,11 @@ RID PhysicsServerSW::shape_create(ShapeType p_shape) { shape = memnew(CapsuleShapeSW); } break; + case SHAPE_CYLINDER: { + + ERR_EXPLAIN("CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings."); + ERR_FAIL_V(RID()); + } break; case SHAPE_CONVEX_POLYGON: { shape = memnew(ConvexPolygonShapeSW); @@ -696,6 +701,20 @@ real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const return body->get_param(p_param); }; +void PhysicsServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) { + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_combine_mode(p_param, p_mode); +} + +PhysicsServer::CombineMode PhysicsServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const { + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT); + + return body->get_combine_mode(p_param); +} + void PhysicsServerSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -1362,6 +1381,8 @@ void PhysicsServerSW::init() { void PhysicsServerSW::step(real_t p_step) { +#ifndef _3D_DISABLED + if (!active) return; @@ -1382,6 +1403,7 @@ void PhysicsServerSW::step(real_t p_step) { active_objects += E->get()->get_active_objects(); collision_pairs += E->get()->get_collision_pairs(); } +#endif } void PhysicsServerSW::sync(){ @@ -1390,6 +1412,8 @@ void PhysicsServerSW::sync(){ void PhysicsServerSW::flush_queries() { +#ifndef _3D_DISABLED + if (!active) return; @@ -1436,6 +1460,7 @@ void PhysicsServerSW::flush_queries() { ScriptDebugger::get_singleton()->add_profiling_frame_data("physics", values); } +#endif }; void PhysicsServerSW::finish() { diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 3f56ba26d0..7e9700d026 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -188,6 +188,10 @@ public: virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; + /// p_param accept only Bounce and Friction + virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode); + virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const; + virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin); virtual real_t body_get_kinematic_safe_margin(RID p_body) const; @@ -230,6 +234,72 @@ public: // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); + /* SOFT BODY */ + + virtual RID soft_body_create(bool p_init_sleeping = false) { return RID(); } + + virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) {} + + virtual void soft_body_set_space(RID p_body, RID p_space) {} + virtual RID soft_body_get_space(RID p_body) const { return RID(); } + + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {} + virtual uint32_t soft_body_get_collision_layer(RID p_body) const { return 0; } + + virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {} + virtual uint32_t soft_body_get_collision_mask(RID p_body) const { return 0; } + + virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) {} + virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) {} + virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {} + + virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {} + virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const { return Variant(); } + + virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) {} + virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const { return Vector3(); } + + virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) {} + virtual bool soft_body_is_ray_pickable(RID p_body) const { return false; } + + virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {} + virtual int soft_body_get_simulation_precision(RID p_body) { return 0; } + + virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) {} + virtual real_t soft_body_get_total_mass(RID p_body) { return 0.; } + + virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_linear_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_volume_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {} + virtual real_t soft_body_get_pressure_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) {} + virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {} + virtual real_t soft_body_get_damping_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {} + virtual real_t soft_body_get_drag_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) {} + + virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {} + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) { return Vector3(); } + + virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const { return Vector3(); } + + virtual void soft_body_remove_all_pinned_points(RID p_body) {} + virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {} + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) { return 0; } + /* 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); diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index aa063d6c1e..fcd2a65ee7 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -405,6 +405,22 @@ void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) { area_angular_damp += p_area->get_angular_damp(); } +void Body2DSW::set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode) { + if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) { + bounce_combine_mode = p_mode; + } else { + friction_combine_mode = p_mode; + } +} + +Physics2DServer::CombineMode Body2DSW::get_combine_mode(Physics2DServer::BodyParameter p_param) const { + if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) { + return bounce_combine_mode; + } else { + return friction_combine_mode; + } +} + void Body2DSW::integrate_forces(real_t p_step) { if (mode == Physics2DServer::BODY_MODE_STATIC) diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 782adf3416..301bd6b299 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -54,6 +54,8 @@ class Body2DSW : public CollisionObject2DSW { real_t mass; real_t bounce; real_t friction; + Physics2DServer::CombineMode bounce_combine_mode; + Physics2DServer::CombineMode friction_combine_mode; real_t _inv_mass; real_t _inv_inertia; @@ -256,6 +258,12 @@ public: _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } + void set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode); + Physics2DServer::CombineMode get_combine_mode(Physics2DServer::BodyParameter p_param) const; + + _FORCE_INLINE_ Physics2DServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; } + _FORCE_INLINE_ Physics2DServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; } + void integrate_forces(real_t p_step); void integrate_velocities(real_t p_step); diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 61c0e0063f..be8dcf6fa8 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -219,6 +219,44 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const return true; } +real_t combine_bounce(Body2DSW *A, Body2DSW *B) { + const Physics2DServer::CombineMode cm = A->get_bounce_combine_mode(); + + switch (cm) { + case Physics2DServer::COMBINE_MODE_INHERIT: + if (B->get_bounce_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT) + return combine_bounce(B, A); + // else use MAX [This is used when the two bodies doesn't use physical material] + case Physics2DServer::COMBINE_MODE_MAX: + return MAX(A->get_bounce(), B->get_bounce()); + case Physics2DServer::COMBINE_MODE_MIN: + return MIN(A->get_bounce(), B->get_bounce()); + case Physics2DServer::COMBINE_MODE_MULTIPLY: + return A->get_bounce() * B->get_bounce(); + default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE: + return (A->get_bounce() + B->get_bounce()) / 2; + } +} + +real_t combine_friction(Body2DSW *A, Body2DSW *B) { + const Physics2DServer::CombineMode cm = A->get_friction_combine_mode(); + + switch (cm) { + case Physics2DServer::COMBINE_MODE_INHERIT: + if (B->get_friction_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT) + return combine_friction(B, A); + // else use Multiply [This is used when the two bodies doesn't use physical material] + case Physics2DServer::COMBINE_MODE_MULTIPLY: + return A->get_friction() * B->get_friction(); + case Physics2DServer::COMBINE_MODE_MAX: + return MAX(A->get_friction(), B->get_friction()); + case Physics2DServer::COMBINE_MODE_MIN: + return MIN(A->get_friction(), B->get_friction()); + default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE: + return (A->get_friction() + B->get_friction()) / 2; + } +} + bool BodyPair2DSW::setup(real_t p_step) { //cannot collide @@ -432,7 +470,7 @@ bool BodyPair2DSW::setup(real_t p_step) { #endif - c.bounce = MAX(A->get_bounce(), B->get_bounce()); + c.bounce = combine_bounce(A, B); if (c.bounce) { Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x); @@ -488,7 +526,7 @@ void BodyPair2DSW::solve(real_t p_step) { real_t jnOld = c.acc_normal_impulse; c.acc_normal_impulse = MAX(jnOld + jn, 0.0f); - real_t friction = A->get_friction() * B->get_friction(); + real_t friction = combine_friction(A, B); real_t jtMax = friction * c.acc_normal_impulse; real_t jt = -vt * c.mass_tangent; diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index efee98a35a..6ce019f36e 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -72,7 +72,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Tr return found; } -bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) { +bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) { const RayShape2DSW *ray = static_cast<const RayShape2DSW *>(p_shape_A); if (p_shape_B->get_type() == Physics2DServer::SHAPE_RAY) @@ -80,6 +80,11 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transf Vector2 from = p_transform_A.get_origin(); Vector2 to = from + p_transform_A[1] * ray->get_length(); + if (p_motion_A != Vector2()) { + //not the best but should be enough + Vector2 normal = (to - from).normalized(); + to += normal * MAX(0.0, normal.dot(p_motion_A)); + } Vector2 support_A = to; Transform2D invb = p_transform_B.affine_inverse(); @@ -270,9 +275,9 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p } if (swap) { - return solve_raycast(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis); + return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis); } else { - return solve_raycast(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis); + return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis); } } else if (concave_B) { diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h index e39c41fb75..6faa166115 100644 --- a/servers/physics_2d/collision_solver_2d_sw.h +++ b/servers/physics_2d/collision_solver_2d_sw.h @@ -41,7 +41,7 @@ private: static bool solve_static_line(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); static void concave_callback(void *p_userdata, Shape2DSW *p_convex); static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool solve_raycast(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL); + static bool solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis = NULL); public: static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index a14fed8184..cfcef8cb04 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -789,6 +789,22 @@ real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) cons return body->get_param(p_param); }; +void Physics2DServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_combine_mode(p_param, p_mode); +} + +Physics2DServer::CombineMode Physics2DServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT); + + return body->get_combine_mode(p_param); +} + void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { Body2DSW *body = body_owner.get(p_body); @@ -962,22 +978,40 @@ void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) { body->set_pickable(p_pickable); } -bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result) { +bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); +} + +int Physics2DServerSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result); + return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); } Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) { + if ((using_threads && !doing_sync)) { + ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification."); + ERR_FAIL_V(NULL); + } + + if (!body_owner.owns(p_body)) + return NULL; + Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body, NULL); - if ((using_threads && !doing_sync) || body->get_space()->is_locked()) { + if (body->get_space()->is_locked()) { ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification."); ERR_FAIL_V(NULL); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 036eb934e1..bf00746063 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -200,6 +200,10 @@ public: virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; + /// p_param accept only Bounce and Friction + virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode); + virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const; + virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant); virtual Variant body_get_state(RID p_body, BodyState p_state) const; @@ -232,7 +236,8 @@ public: virtual void body_set_pickable(RID p_body, bool p_pickable); - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL); + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); + virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); // this function only works on physics process, errors and returns null otherwise virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index a15e8bde8b..a85cd5ef8d 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -211,6 +211,9 @@ public: FUNC3(body_set_param, RID, BodyParameter, real_t); FUNC2RC(real_t, body_get_param, RID, BodyParameter); + FUNC3(body_set_combine_mode, RID, BodyParameter, CombineMode); + FUNC2RC(CombineMode, body_get_combine_mode, RID, BodyParameter); + FUNC3(body_set_state, RID, BodyState, const Variant &); FUNC2RC(Variant, body_get_state, RID, BodyState); @@ -245,10 +248,16 @@ public: FUNC2(body_set_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL) { + bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); + } + + int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result); + return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 0e1f74d8d0..6e45951f42 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -487,7 +487,156 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { return amount; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result) { +int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin) { + + Rect2 body_aabb; + + for (int i = 0; i < p_body->get_shape_count(); i++) { + + if (i == 0) + body_aabb = p_body->get_shape_aabb(i); + else + body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); + } + + // Undo the currently transform the physics server is aware of and apply the provided one + body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb)); + body_aabb = body_aabb.grow(p_margin); + + Transform2D body_transform = p_transform; + + for (int i = 0; i < p_result_max; i++) { + //reset results + r_results[i].collision_depth = 0; + } + + int rays_found = 0; + + { + // raycast AND separate + + const int max_results = 32; + int recover_attempts = 4; + Vector2 sr[max_results * 2]; + Physics2DServerSW::CollCbkData cbk; + cbk.max = max_results; + Physics2DServerSW::CollCbkData *cbkptr = &cbk; + CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk; + + do { + + Vector2 recover_motion; + + bool collided = false; + + int amount = _cull_aabb_for_body(p_body, body_aabb); + int ray_index = 0; + + for (int j = 0; j < p_body->get_shape_count(); j++) { + if (p_body->is_shape_set_as_disabled(j)) + continue; + + Shape2DSW *body_shape = p_body->get_shape(j); + + if (body_shape->get_type() != Physics2DServer::SHAPE_RAY) + continue; + + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); + + for (int i = 0; i < amount; i++) { + + const CollisionObject2DSW *col_obj = intersection_query_results[i]; + int shape_idx = intersection_query_subindex_results[i]; + + cbk.amount = 0; + cbk.ptr = sr; + cbk.invalid_by_dir = 0; + + if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { + const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + continue; + } + } + + if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { + + cbk.valid_dir = body_shape_xform.get_axis(1).normalized(); + cbk.valid_depth = p_margin; //only valid depth is the collision margin + cbk.invalid_by_dir = 0; + + } else { + cbk.valid_dir = Vector2(); + cbk.valid_depth = 0; + cbk.invalid_by_dir = 0; + } + + Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) { + if (cbk.amount > 0) { + collided = true; + } + + if (ray_index < p_result_max) { + Physics2DServer::SeparationResult &result = r_results[ray_index]; + + for (int k = 0; k < cbk.amount; k++) { + Vector2 a = sr[k * 2 + 0]; + Vector2 b = sr[k * 2 + 1]; + + recover_motion += (b - a) * 0.4; + + float depth = a.distance_to(b); + if (depth > result.collision_depth) { + + result.collision_depth = depth; + result.collision_point = b; + result.collision_normal = (b - a).normalized(); + result.collision_local_shape = shape_idx; + result.collider = col_obj->get_self(); + result.collider_id = col_obj->get_instance_id(); + result.collider_metadata = col_obj->get_shape_metadata(shape_idx); + if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { + Body2DSW *body = (Body2DSW *)col_obj; + + Vector2 rel_vec = b - body->get_transform().get_origin(); + result.collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); + } + } + } + } + } + } + + ray_index++; + } + + rays_found = MAX(ray_index, rays_found); + + if (!collided || recover_motion == Vector2()) { + break; + } + + body_transform.elements[2] += recover_motion; + body_aabb.position += recover_motion; + + recover_attempts--; + } while (recover_attempts); + } + + //optimize results (remove non colliding) + for (int i = 0; i < rays_found; i++) { + if (r_results[i].collision_depth == 0) { + rays_found--; + SWAP(r_results[i], r_results[rays_found]); + } + } + + r_recover_motion = body_transform.elements[2] - p_transform.elements[2]; + return rays_found; +} + +bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes) { //give me back regular physics engine logic //this is madness @@ -547,8 +696,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (p_body->is_shape_set_as_disabled(j)) continue; - Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); + if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + continue; + } + + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); for (int i = 0; i < amount; i++) { const CollisionObject2DSW *col_obj = intersection_query_results[i]; @@ -635,8 +788,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (p_body->is_shape_set_as_disabled(body_shape_idx)) continue; - Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx); Shape2DSW *body_shape = p_body->get_shape(body_shape_idx); + if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + continue; + } + + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx); bool stuck = false; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 79349c46f3..959e15e12d 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -182,7 +182,8 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result); + bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes = true); + int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index ba5232f7fe..89c649af49 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -416,6 +416,19 @@ public: virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; + enum CombineMode { + COMBINE_MODE_MAX, + COMBINE_MODE_MIN, + COMBINE_MODE_MULTIPLY, + COMBINE_MODE_AVERAGE, + + COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction) + }; + + /// p_param accept only Bounce and Friction + virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0; + virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0; + //state enum BodyState { BODY_STATE_TRANSFORM, @@ -479,7 +492,22 @@ public: Variant collider_metadata; }; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL) = 0; + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; + + struct SeparationResult { + + float collision_depth; + Vector2 collision_point; + Vector2 collision_normal; + Vector2 collider_velocity; + int collision_local_shape; + ObjectID collider_id; + RID collider; + int collider_shape; + Variant collider_metadata; + }; + + virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; /* JOINT API */ diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 82c4eb2e13..b4bd4cb35f 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -400,6 +400,8 @@ void PhysicsShapeQueryResult::_bind_methods() { void PhysicsServer::_bind_methods() { +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("shape_create", "type"), &PhysicsServer::shape_create); ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer::shape_set_data); @@ -664,6 +666,7 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_SPHERE); BIND_ENUM_CONSTANT(SHAPE_BOX); BIND_ENUM_CONSTANT(SHAPE_CAPSULE); + BIND_ENUM_CONSTANT(SHAPE_CYLINDER); BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP); @@ -736,6 +739,8 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_X); BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Y); BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Z); + +#endif } PhysicsServer::PhysicsServer() { diff --git a/servers/physics_server.h b/servers/physics_server.h index 6712bee8dc..497d23c555 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -228,6 +228,7 @@ public: SHAPE_SPHERE, ///< float:"radius" SHAPE_BOX, ///< vec3:"extents" SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule + SHAPE_CYLINDER, ///< dict( float:"radius", float:"height"):cylinder SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" @@ -398,6 +399,19 @@ public: virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; + enum CombineMode { + COMBINE_MODE_MAX, + COMBINE_MODE_MIN, + COMBINE_MODE_MULTIPLY, + COMBINE_MODE_AVERAGE, + + COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction) + }; + + /// p_param accept only Bounce and Friction + virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0; + virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0; + virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0; virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0; @@ -476,6 +490,72 @@ public: virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL) = 0; + /* SOFT BODY */ + + virtual RID soft_body_create(bool p_init_sleeping = false) = 0; + + virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) = 0; + + virtual void soft_body_set_space(RID p_body, RID p_space) = 0; + virtual RID soft_body_get_space(RID p_body) const = 0; + + virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0; + + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; + virtual uint32_t soft_body_get_collision_layer(RID p_body) const = 0; + + virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; + virtual uint32_t soft_body_get_collision_mask(RID p_body) const = 0; + + virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) = 0; + + virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; + virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0; + + virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0; + virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0; + + virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0; + virtual bool soft_body_is_ray_pickable(RID p_body) const = 0; + + virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) = 0; + virtual int soft_body_get_simulation_precision(RID p_body) = 0; + + virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) = 0; + virtual real_t soft_body_get_total_mass(RID p_body) = 0; + + virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_linear_stiffness(RID p_body) = 0; + + virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) = 0; + + virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_volume_stiffness(RID p_body) = 0; + + virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0; + virtual real_t soft_body_get_pressure_coefficient(RID p_body) = 0; + + virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0; + virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) = 0; + + virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0; + virtual real_t soft_body_get_damping_coefficient(RID p_body) = 0; + + virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) = 0; + virtual real_t soft_body_get_drag_coefficient(RID p_body) = 0; + + virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0; + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) = 0; + + virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0; + + virtual void soft_body_remove_all_pinned_points(RID p_body) = 0; + virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0; + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) = 0; + /* JOINT API */ enum JointType { diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h index 4681dd46f0..611e25af2a 100644 --- a/servers/server_wrap_mt_common.h +++ b/servers/server_wrap_mt_common.h @@ -810,3 +810,12 @@ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \ } \ } + +#define FUNC13(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13) \ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12, m_arg13 p13) { \ + if (Thread::get_caller_id() != server_thread) { \ + command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \ + } else { \ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \ + } \ + } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8d8e9e693e..a8f4377ce7 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -66,7 +66,7 @@ public: virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0; virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; @@ -104,10 +104,12 @@ public: VS::ShadowCastingSetting cast_shadows; + //fit in 32 bits bool mirror : 8; bool receive_shadows : 8; bool visible : 8; - bool baked_light : 8; //this flag is only to know if it actually did use baked light + bool baked_light : 4; //this flag is only to know if it actually did use baked light + bool redraw_if_visible : 4; float depth; //used for sorting @@ -131,6 +133,7 @@ public: depth_layer = 0; layer_mask = 1; baked_light = false; + redraw_if_visible = false; lightmap_capture = NULL; } }; @@ -201,6 +204,7 @@ public: virtual void textures_keep_original(bool p_enable) = 0; virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0; + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; /* SKY API */ @@ -276,25 +280,30 @@ public: virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const = 0; + virtual void mesh_clear(RID p_mesh) = 0; /* MULTIMESH API */ virtual RID multimesh_create() = 0; - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) = 0; + virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) = 0; virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0; virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 2069e64c43..fd1eb77143 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2545,7 +2545,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons TkPos pos = _get_tkpos(); tk = _get_token(); - if (tk.type == TK_PERIOD) { + if (tk.type == TK_CURSOR) { + //do nothing + } else if (tk.type == TK_PERIOD) { StringName identifier; if (_get_completable_identifier(p_block, COMPLETION_INDEX, identifier)) { @@ -3583,7 +3585,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { Token tk = _get_token(); @@ -3642,7 +3644,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (!p_render_modes.has(mode)) { + if (p_render_modes.find(mode) == -1) { _set_error("Invalid render mode: '" + String(mode) + "'"); return ERR_PARSE_ERROR; } @@ -4097,7 +4099,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) { return String(); } -Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { clear(); @@ -4114,7 +4116,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi return OK; } -Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { clear(); @@ -4130,13 +4132,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct switch (completion_type) { case COMPLETION_NONE: { - //do none - return ERR_PARSE_ERROR; + //do nothing + return OK; } break; case COMPLETION_RENDER_MODE: { - for (const Set<String>::Element *E = p_render_modes.front(); E; E = E->next()) { + for (int i = 0; i < p_render_modes.size(); i++) { - r_options->push_back(E->get()); + r_options->push_back(p_render_modes[i]); } return OK; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 720511e18d..9b84c5f195 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -650,7 +650,7 @@ private: Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types); + Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); public: //static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); @@ -658,8 +658,8 @@ public: void clear(); static String get_shader_type(const String &p_code); - Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types); - Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint); + Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); + Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint); String get_error_text(); int get_error_line(); diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 95193f7a8f..0de8676f32 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -35,7 +35,7 @@ const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions( return shader_modes[p_mode].functions; } -const Set<String> &ShaderTypes::get_modes(VS::ShaderMode p_mode) { +const Vector<StringName> &ShaderTypes::get_modes(VS::ShaderMode p_mode) { return shader_modes[p_mode].modes; } @@ -140,42 +140,45 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true; - shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul"); + //order used puts first enum mode (default) first + shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mix"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_add"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_sub"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mul"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_opaque"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_always"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_always"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_never"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_alpha_prepass"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_test_disable"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_test_disable"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_back"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_front"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_disabled"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("unshaded"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert_wrap"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_oren_nayar"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_burley"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_toon"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_burley"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_toon"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_schlick_ggx"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_blinn"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_phong"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_toon"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("specular_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_blinn"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_phong"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_toon"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_disabled"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_vertex_transform"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("world_vertex_coords"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("world_vertex_coords"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("shadows_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_lighting"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); /************ CANVAS ITEM **************************/ @@ -226,17 +229,17 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_vertex_transform"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mix"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_add"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_disabled"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_add"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("unshaded"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("light_only"); /************ PARTICLES **************************/ @@ -256,9 +259,9 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[VS::SHADER_PARTICLES].functions["vertex"].can_discard = false; - shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force"); - shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity"); - shader_modes[VS::SHADER_PARTICLES].modes.insert("keep_data"); + shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_force"); + shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_velocity"); + shader_modes[VS::SHADER_PARTICLES].modes.push_back("keep_data"); shader_types.insert("spatial"); shader_types.insert("canvas_item"); diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h index 1f43ff9c92..0680ec8242 100644 --- a/servers/visual/shader_types.h +++ b/servers/visual/shader_types.h @@ -31,14 +31,16 @@ #ifndef SHADERTYPES_H #define SHADERTYPES_H +#include "ordered_hash_map.h" #include "servers/visual_server.h" #include "shader_language.h" + class ShaderTypes { struct Type { Map<StringName, ShaderLanguage::FunctionInfo> functions; - Set<String> modes; + Vector<StringName> modes; }; Map<VS::ShaderMode, Type> shader_modes; @@ -51,7 +53,7 @@ public: static ShaderTypes *get_singleton() { return singleton; } const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(VS::ShaderMode p_mode); - const Set<String> &get_modes(VS::ShaderMode p_mode); + const Vector<StringName> &get_modes(VS::ShaderMode p_mode); const Set<String> &get_types(); ShaderTypes(); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index fca3126604..5f207b1d3f 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -95,6 +95,9 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str void VisualServerRaster::draw(bool p_swap_buffers) { + //needs to be done before changes is reset to 0, to not force the editor to redraw + VS::get_singleton()->emit_signal("frame_pre_draw"); + changes = 0; VSG::rasterizer->begin_frame(); @@ -122,7 +125,7 @@ void VisualServerRaster::draw(bool p_swap_buffers) { frame_drawn_callbacks.pop_front(); } - emit_signal("frame_drawn_in_thread"); + VS::get_singleton()->emit_signal("frame_post_draw"); } void VisualServerRaster::sync() { } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 8f19de9f8b..ec0d02ed2a 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -139,6 +139,8 @@ public: void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } #define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \ void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } +#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } //from now on, calls forwarded to this singleton #define BINDBASE VSG::storage @@ -171,6 +173,8 @@ public: BIND2(texture_set_proxy, RID, RID) + BIND2(texture_set_force_redraw_if_visible, RID, bool) + /* SKY API */ BIND0R(RID, sky_create) @@ -244,13 +248,14 @@ public: BIND0R(RID, multimesh_create) - BIND4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat) + BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat) BIND1RC(int, multimesh_get_instance_count, RID) BIND2(multimesh_set_mesh, RID, RID) BIND3(multimesh_instance_set_transform, RID, int, const Transform &) BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) BIND3(multimesh_instance_set_color, RID, int, const Color &) + BIND3(multimesh_instance_set_custom_data, RID, int, const Color &) BIND1RC(RID, multimesh_get_mesh, RID) BIND1RC(AABB, multimesh_get_aabb, RID) @@ -258,6 +263,9 @@ public: BIND2RC(Transform, multimesh_instance_get_transform, RID, int) BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) BIND2RC(Color, multimesh_instance_get_color, RID, int) + BIND2RC(Color, multimesh_instance_get_custom_data, RID, int) + + BIND2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &) BIND2(multimesh_set_visible_instances, RID, int) BIND1RC(int, multimesh_get_visible_instances, RID) @@ -489,7 +497,7 @@ public: BIND2(environment_set_canvas_max_layer, RID, int) BIND4(environment_set_ambient_light, RID, const Color &, float, float) BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool) - BIND12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) + BIND13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index b7abb07f43..887cd7429a 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -820,6 +820,11 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF instance->baked_light = p_enabled; } break; + case VS::INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE: { + + instance->redraw_if_visible = p_enabled; + + } break; } } void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { @@ -1257,6 +1262,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); + Transform light_transform = p_instance->transform; + light_transform.orthonormalize(); //scale does not count on lights + switch (VSG::storage->light_get_type(p_instance->base)) { case VS::LIGHT_DIRECTIONAL: { @@ -1359,7 +1367,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons // obtain the light frustm ranges (given endpoints) - Transform transform = p_instance->transform.orthonormalized(); //discard scale and stabilize light + Transform transform = light_transform; //discard scale and stabilize light Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized(); Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized(); @@ -1469,7 +1477,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons // a pre pass will need to be needed to determine the actual z-near to be used - Plane near_plane(p_instance->transform.origin, -p_instance->transform.basis.get_axis(2)); + Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); for (int j = 0; j < cull_count; j++) { @@ -1524,14 +1532,14 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons float z = i == 0 ? -1 : 1; Vector<Plane> planes; planes.resize(5); - planes[0] = p_instance->transform.xform(Plane(Vector3(0, 0, z), radius)); - planes[1] = p_instance->transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); - planes[2] = p_instance->transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); - planes[3] = p_instance->transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); - planes[4] = p_instance->transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); + planes[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius)); + planes[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); + planes[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); + planes[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); + planes[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - Plane near_plane(p_instance->transform.origin, p_instance->transform.basis.get_axis(2) * z); + Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z); for (int j = 0; j < cull_count; j++) { @@ -1546,7 +1554,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } } - VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), p_instance->transform, radius, 0, i); + VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i); VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); } } break; @@ -1577,7 +1585,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons Vector3(0, -1, 0) }; - Transform xform = p_instance->transform * Transform().looking_at(view_normals[i], view_up[i]); + Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]); Vector<Plane> planes = cm.get_projection_planes(xform); @@ -1602,7 +1610,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } //restore the regular DP matrix - VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), p_instance->transform, radius, 0, 0); + VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0); } break; } @@ -1616,10 +1624,10 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons CameraMatrix cm; cm.set_perspective(angle * 2.0, 1.0, 0.01, radius); - Vector<Plane> planes = cm.get_projection_planes(p_instance->transform); + Vector<Plane> planes = cm.get_projection_planes(light_transform); int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - Plane near_plane(p_instance->transform.origin, -p_instance->transform.basis.get_axis(2)); + Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); for (int j = 0; j < cull_count; j++) { Instance *instance = instance_shadow_cull_result[j]; @@ -1633,7 +1641,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } } - VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, p_instance->transform, radius, 0, 0); + VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0); VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); } break; @@ -1641,7 +1649,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { - // render to mono camera +// render to mono camera +#ifndef _3D_DISABLED Camera *camera = camera_owner.getornull(p_camera); ERR_FAIL_COND(!camera); @@ -1676,6 +1685,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); _render_scene(camera->transform, camera_matrix, ortho, camera->env, p_scenario, p_shadow_atlas, RID(), -1); +#endif } void VisualServerScene::render_camera(Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { @@ -1868,6 +1878,10 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data); + if (ins->redraw_if_visible) { + VisualServerRaster::redraw_request(); + } + if (ins->base_type == VS::INSTANCE_PARTICLES) { //particles visible? process them VSG::storage->particles_request_process(ins->base); @@ -2099,6 +2113,8 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) { +#ifndef _3D_DISABLED + Scenario *scenario = scenario_owner.getornull(p_scenario); RID environment; @@ -2107,6 +2123,7 @@ void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) { else environment = scenario->fallback_environment; VSG::scene_render->render_scene(Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0); +#endif } bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index dcc270ca5e..dd6bc3cf26 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -268,7 +268,7 @@ void VisualServerViewport::draw_viewports() { ERR_CONTINUE(!vp->render_target.is_valid()); bool visible = vp->viewport_to_screen_rect != Rect2() || vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE || (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)); - visible = visible && vp->size.x > 0 && vp->size.y > 0; + visible = visible && vp->size.x > 1 && vp->size.y > 1; if (!visible) continue; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 19bb58f3ad..48f0ec46f3 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -107,6 +107,8 @@ public: FUNC2(texture_set_proxy, RID, RID) + FUNC2(texture_set_force_redraw_if_visible, RID, bool) + /* SKY API */ FUNCRID(sky) @@ -180,13 +182,14 @@ public: FUNCRID(multimesh) - FUNC4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat) + FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat) FUNC1RC(int, multimesh_get_instance_count, RID) FUNC2(multimesh_set_mesh, RID, RID) FUNC3(multimesh_instance_set_transform, RID, int, const Transform &) FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) FUNC3(multimesh_instance_set_color, RID, int, const Color &) + FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &) FUNC1RC(RID, multimesh_get_mesh, RID) FUNC1RC(AABB, multimesh_get_aabb, RID) @@ -194,6 +197,9 @@ public: FUNC2RC(Transform, multimesh_instance_get_transform, RID, int) FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) FUNC2RC(Color, multimesh_instance_get_color, RID, int) + FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int) + + FUNC2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &) FUNC2(multimesh_set_visible_instances, RID, int) FUNC1RC(int, multimesh_get_visible_instances, RID) @@ -416,7 +422,7 @@ public: FUNC2(environment_set_canvas_max_layer, RID, int) FUNC4(environment_set_ambient_light, RID, const Color &, float, float) FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool) - FUNC12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) + FUNC13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 21745e87a8..1f3319dc04 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -187,16 +187,14 @@ RID VisualServer::_make_test_cube() { PoolVector<float> tangents; PoolVector<Vector3> uvs; - int vtx_idx = 0; -#define ADD_VTX(m_idx) \ - vertices.push_back(face_points[m_idx]); \ - normals.push_back(normal_points[m_idx]); \ - tangents.push_back(normal_points[m_idx][1]); \ - tangents.push_back(normal_points[m_idx][2]); \ - tangents.push_back(normal_points[m_idx][0]); \ - tangents.push_back(1.0); \ - uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); \ - vtx_idx++; +#define ADD_VTX(m_idx) \ + vertices.push_back(face_points[m_idx]); \ + normals.push_back(normal_points[m_idx]); \ + tangents.push_back(normal_points[m_idx][1]); \ + tangents.push_back(normal_points[m_idx][2]); \ + tangents.push_back(normal_points[m_idx][0]); \ + tangents.push_back(1.0); \ + uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); for (int i = 0; i < 6; i++) { @@ -795,6 +793,140 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_ return OK; } +uint32_t VisualServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const { + uint32_t offsets[ARRAY_MAX]; + mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); + return offsets[p_array_index]; +} + +uint32_t VisualServer::mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const { + uint32_t offsets[ARRAY_MAX]; + return mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); +} + +uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const { + + int total_elem_size = 0; + + for (int i = 0; i < VS::ARRAY_MAX; i++) { + + r_offsets[i] = 0; //reset + + if (!(p_format & (1 << i))) // no array + continue; + + int elem_size = 0; + + switch (i) { + + case VS::ARRAY_VERTEX: { + + if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { + elem_size = 2; + } else { + elem_size = 3; + } + + if (p_format & ARRAY_COMPRESS_VERTEX) { + elem_size *= sizeof(int16_t); + } else { + elem_size *= sizeof(float); + } + + if (elem_size == 6) { + elem_size = 8; + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_format & ARRAY_COMPRESS_NORMAL) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 3; + } + + } break; + + case VS::ARRAY_TANGENT: { + if (p_format & ARRAY_COMPRESS_TANGENT) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_format & ARRAY_COMPRESS_COLOR) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + } break; + case VS::ARRAY_TEX_UV: { + if (p_format & ARRAY_COMPRESS_TEX_UV) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + + case VS::ARRAY_TEX_UV2: { + if (p_format & ARRAY_COMPRESS_TEX_UV2) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_format & ARRAY_COMPRESS_WEIGHTS) { + elem_size = sizeof(uint16_t) * 4; + } else { + elem_size = sizeof(float) * 4; + } + + } break; + case VS::ARRAY_BONES: { + + if (p_format & ARRAY_FLAG_USE_16_BIT_BONES) { + elem_size = sizeof(uint16_t) * 4; + } else { + elem_size = sizeof(uint32_t); + } + + } break; + case VS::ARRAY_INDEX: { + + if (p_index_len <= 0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine whether using 16 or 32 bits indices */ + if (p_vertex_len >= (1 << 16)) { + + elem_size = 4; + + } else { + elem_size = 2; + } + r_offsets[i] = elem_size; + continue; + } break; + default: { + ERR_FAIL_V(0); + } + } + + r_offsets[i] = total_elem_size; + total_elem_size += elem_size; + } + return total_elem_size; +} + void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_compress_format) { ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX); @@ -1543,10 +1675,10 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_debug_usage"), &VisualServer::_texture_debug_usage_bind); ClassDB::bind_method(D_METHOD("textures_keep_original", "enable"), &VisualServer::textures_keep_original); - +#ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create); ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "cube_map", "radiance_size"), &VisualServer::sky_set_texture); - +#endif ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create); ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code); ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &VisualServer::shader_get_code); @@ -1564,11 +1696,14 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &VisualServer::material_set_next_pass); ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_offset); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len"), &VisualServer::mesh_surface_get_format_stride); ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primtive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count); ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count); ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode); ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &VisualServer::mesh_surface_update_region); ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material); ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material); ClassDB::bind_method(D_METHOD("mesh_surface_get_array_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_len); @@ -1587,20 +1722,23 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb); ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); - ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format"), &VisualServer::multimesh_allocate); + ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(MULTIMESH_CUSTOM_DATA_NONE)); ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count); ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh); ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform); ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform_2d", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform_2d); ClassDB::bind_method(D_METHOD("multimesh_instance_set_color", "multimesh", "index", "color"), &VisualServer::multimesh_instance_set_color); + ClassDB::bind_method(D_METHOD("multimesh_instance_set_custom_data", "multimesh", "index", "custom_data"), &VisualServer::multimesh_instance_set_custom_data); ClassDB::bind_method(D_METHOD("multimesh_get_mesh", "multimesh"), &VisualServer::multimesh_get_mesh); ClassDB::bind_method(D_METHOD("multimesh_get_aabb", "multimesh"), &VisualServer::multimesh_get_aabb); ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform); ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform_2d", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform_2d); ClassDB::bind_method(D_METHOD("multimesh_instance_get_color", "multimesh", "index"), &VisualServer::multimesh_instance_get_color); + ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &VisualServer::multimesh_instance_get_custom_data); ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances); ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances); - + ClassDB::bind_method(D_METHOD("multimesh_set_as_bulk_array", "multimesh", "array"), &VisualServer::multimesh_set_as_bulk_array); +#ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create); ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("immediate_vertex", "immediate", "vertex"), &VisualServer::immediate_vertex); @@ -1614,6 +1752,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("immediate_clear", "immediate"), &VisualServer::immediate_clear); ClassDB::bind_method(D_METHOD("immediate_set_material", "immediate", "material"), &VisualServer::immediate_set_material); ClassDB::bind_method(D_METHOD("immediate_get_material", "immediate"), &VisualServer::immediate_get_material); +#endif ClassDB::bind_method(D_METHOD("skeleton_create"), &VisualServer::skeleton_create); ClassDB::bind_method(D_METHOD("skeleton_allocate", "skeleton", "bones", "is_2d_skeleton"), &VisualServer::skeleton_allocate, DEFVAL(false)); @@ -1623,6 +1762,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform_2d", "skeleton", "bone", "transform"), &VisualServer::skeleton_bone_set_transform_2d); ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform_2d", "skeleton", "bone"), &VisualServer::skeleton_bone_get_transform_2d); +#ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("directional_light_create"), &VisualServer::directional_light_create); ClassDB::bind_method(D_METHOD("omni_light_create"), &VisualServer::omni_light_create); ClassDB::bind_method(D_METHOD("spot_light_create"), &VisualServer::spot_light_create); @@ -1692,7 +1832,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &VisualServer::lightmap_capture_get_octree); ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &VisualServer::lightmap_capture_set_energy); ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &VisualServer::lightmap_capture_get_energy); - +#endif ClassDB::bind_method(D_METHOD("particles_create"), &VisualServer::particles_create); ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &VisualServer::particles_set_emitting); ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &VisualServer::particles_get_emitting); @@ -1779,6 +1919,8 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "p_size", "subdiv"), &VisualServer::scenario_set_reflection_atlas_size); ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &VisualServer::scenario_set_fallback_environment); +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("instance_create2", "base", "scenario"), &VisualServer::instance_create2); ClassDB::bind_method(D_METHOD("instance_create"), &VisualServer::instance_create); ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &VisualServer::instance_set_base); @@ -1803,7 +1945,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &VisualServer::_instances_cull_aabb_bind, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &VisualServer::_instances_cull_ray_bind, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("instances_cull_convex", "convex", "scenario"), &VisualServer::_instances_cull_convex_bind, DEFVAL(RID())); - +#endif ClassDB::bind_method(D_METHOD("canvas_create"), &VisualServer::canvas_create); ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &VisualServer::canvas_set_item_mirroring); ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &VisualServer::canvas_set_modulate); @@ -1886,13 +2028,14 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("init"), &VisualServer::init); ClassDB::bind_method(D_METHOD("finish"), &VisualServer::finish); ClassDB::bind_method(D_METHOD("get_render_info", "info"), &VisualServer::get_render_info); +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh); ClassDB::bind_method(D_METHOD("get_test_cube"), &VisualServer::get_test_cube); +#endif ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture); ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture); - ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh); - ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale"), &VisualServer::set_boot_image); ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color); @@ -2058,6 +2201,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT); + BIND_ENUM_CONSTANT(INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE); BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX); BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); @@ -2143,7 +2287,8 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_2x2); BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_3x3); - ADD_SIGNAL(MethodInfo("frame_drawn_in_thread")); + ADD_SIGNAL(MethodInfo("frame_pre_draw")); + ADD_SIGNAL(MethodInfo("frame_post_draw")); } void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) { diff --git a/servers/visual_server.h b/servers/visual_server.h index 65d0f07a43..367642b7d4 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -144,6 +144,7 @@ public: virtual void textures_keep_original(bool p_enable) = 0; virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0; + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; /* SKY API */ @@ -233,7 +234,7 @@ public: ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2, ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, - ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_VERTEX | ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS + ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS }; @@ -250,6 +251,10 @@ public: virtual RID mesh_create() = 0; + virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const; + virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const; + /// Returns stride + virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const; virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT); virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0; @@ -309,13 +314,20 @@ public: MULTIMESH_COLOR_FLOAT, }; - virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format) = 0; + enum MultimeshCustomDataFormat { + MULTIMESH_CUSTOM_DATA_NONE, + MULTIMESH_CUSTOM_DATA_8BIT, + MULTIMESH_CUSTOM_DATA_FLOAT, + }; + + virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format, MultimeshCustomDataFormat p_data_format = MULTIMESH_CUSTOM_DATA_NONE) = 0; virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; @@ -323,6 +335,9 @@ public: virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0; virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; @@ -719,7 +734,7 @@ public: ENV_SSAO_BLUR_3x3, }; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; @@ -794,6 +809,7 @@ public: enum InstanceFlags { INSTANCE_FLAG_USE_BAKED_LIGHT, + INSTANCE_FLAG_REDRAW_FRAME_IF_VISIBLE, INSTANCE_FLAG_MAX }; @@ -1023,6 +1039,7 @@ VARIANT_ENUM_CAST(VisualServer::RenderInfo); VARIANT_ENUM_CAST(VisualServer::Features); VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat); VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat); +VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat); VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode); VARIANT_ENUM_CAST(VisualServer::LightOmniShadowDetail); VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode); |