summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/area.cpp52
-rw-r--r--scene/3d/area.h4
-rw-r--r--scene/3d/arvr_nodes.cpp4
-rw-r--r--scene/3d/audio_stream_player_3d.cpp56
-rw-r--r--scene/3d/baked_lightmap.cpp58
-rw-r--r--scene/3d/baked_lightmap.h14
-rw-r--r--scene/3d/bone_attachment.cpp2
-rw-r--r--scene/3d/camera.cpp32
-rw-r--r--scene/3d/camera.h4
-rw-r--r--scene/3d/collision_polygon.cpp8
-rw-r--r--scene/3d/collision_shape.cpp11
-rw-r--r--scene/3d/cpu_particles.cpp311
-rw-r--r--scene/3d/cpu_particles.h28
-rw-r--r--scene/3d/gi_probe.cpp432
-rw-r--r--scene/3d/gi_probe.h88
-rw-r--r--scene/3d/immediate_geometry.cpp8
-rw-r--r--scene/3d/immediate_geometry.h6
-rw-r--r--scene/3d/interpolated_camera.cpp2
-rw-r--r--scene/3d/light.cpp61
-rw-r--r--scene/3d/light.h14
-rw-r--r--scene/3d/mesh_instance.cpp26
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/3d/multimesh_instance.cpp4
-rw-r--r--scene/3d/multimesh_instance.h2
-rw-r--r--scene/3d/navigation.cpp706
-rw-r--r--scene/3d/navigation.h153
-rw-r--r--scene/3d/navigation_agent.cpp361
-rw-r--r--scene/3d/navigation_agent.h162
-rw-r--r--scene/3d/navigation_mesh.cpp744
-rw-r--r--scene/3d/navigation_mesh.h227
-rw-r--r--scene/3d/navigation_obstacle.cpp163
-rw-r--r--scene/3d/navigation_obstacle.h71
-rw-r--r--scene/3d/navigation_region.cpp258
-rw-r--r--scene/3d/navigation_region.h75
-rw-r--r--scene/3d/particles.cpp24
-rw-r--r--scene/3d/particles.h2
-rw-r--r--scene/3d/path.cpp13
-rw-r--r--scene/3d/physics_body.cpp421
-rw-r--r--scene/3d/physics_body.h37
-rw-r--r--scene/3d/physics_joint.cpp210
-rw-r--r--scene/3d/ray_cast.cpp18
-rw-r--r--scene/3d/reflection_probe.cpp12
-rw-r--r--scene/3d/reflection_probe.h2
-rw-r--r--scene/3d/remote_transform.cpp7
-rw-r--r--scene/3d/skeleton.cpp131
-rw-r--r--scene/3d/skeleton.h11
-rw-r--r--scene/3d/soft_body.cpp110
-rw-r--r--scene/3d/soft_body.h13
-rw-r--r--scene/3d/spring_arm.cpp4
-rw-r--r--scene/3d/sprite_3d.cpp82
-rw-r--r--scene/3d/sprite_3d.h16
-rw-r--r--scene/3d/vehicle_body.cpp33
-rw-r--r--scene/3d/visibility_notifier.cpp5
-rw-r--r--scene/3d/visual_instance.cpp6
-rw-r--r--scene/3d/visual_instance.h3
-rw-r--r--scene/3d/voxel_light_baker.cpp2486
-rw-r--r--scene/3d/voxelizer.cpp1224
-rw-r--r--scene/3d/voxelizer.h (renamed from scene/3d/voxel_light_baker.h)118
-rw-r--r--scene/3d/world_environment.cpp49
-rw-r--r--scene/3d/world_environment.h4
60 files changed, 3619 insertions, 5571 deletions
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 67f57a1aa3..321926d841 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "area.h"
+
#include "scene/scene_string_names.h"
#include "servers/audio_server.h"
#include "servers/physics_server.h"
@@ -147,7 +148,7 @@ void Area::_body_exit_tree(ObjectID p_id) {
}
}
-void Area::_body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape) {
+void Area::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) {
bool body_in = p_status == PhysicsServer::AREA_BODY_ADDED;
ObjectID objid = p_instance;
@@ -170,8 +171,8 @@ void Area::_body_inout(int p_status, const RID &p_body, int p_instance, int p_bo
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree, make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree, make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree), make_binds(objid));
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
@@ -197,8 +198,8 @@ void Area::_body_inout(int p_status, const RID &p_body, int p_instance, int p_bo
if (E->get().rc == 0) {
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree));
if (E->get().in_tree)
emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
}
@@ -244,8 +245,8 @@ void Area::_clear_monitoring() {
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree));
}
}
@@ -274,8 +275,8 @@ void Area::_clear_monitoring() {
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_area_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_area_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree));
}
}
}
@@ -340,7 +341,7 @@ void Area::_area_exit_tree(ObjectID p_id) {
}
}
-void Area::_area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape) {
+void Area::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) {
bool area_in = p_status == PhysicsServer::AREA_BODY_ADDED;
ObjectID objid = p_instance;
@@ -363,8 +364,8 @@ void Area::_area_inout(int p_status, const RID &p_area, int p_instance, int p_ar
E->get().rc = 0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_area_enter_tree, make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_area_exit_tree, make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree), make_binds(objid));
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
}
@@ -390,8 +391,8 @@ void Area::_area_inout(int p_status, const RID &p_area, int p_instance, int p_ar
if (E->get().rc == 0) {
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_area_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_area_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree));
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
}
@@ -618,13 +619,6 @@ void Area::_validate_property(PropertyInfo &property) const {
}
void Area::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_body_enter_tree", "id"), &Area::_body_enter_tree);
- ClassDB::bind_method(D_METHOD("_body_exit_tree", "id"), &Area::_body_exit_tree);
-
- ClassDB::bind_method(D_METHOD("_area_enter_tree", "id"), &Area::_area_enter_tree);
- ClassDB::bind_method(D_METHOD("_area_exit_tree", "id"), &Area::_area_exit_tree);
-
ClassDB::bind_method(D_METHOD("set_space_override_mode", "enable"), &Area::set_space_override_mode);
ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area::get_space_override_mode);
@@ -706,11 +700,11 @@ void Area::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable");
@@ -719,12 +713,12 @@ void Area::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_GROUP("Audio Bus", "audio_bus_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus");
ADD_GROUP("Reverb Bus", "reverb_bus_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity");
BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED);
BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE);
diff --git a/scene/3d/area.h b/scene/3d/area.h
index ca66f41f60..7fe61430fa 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -62,7 +62,7 @@ private:
bool monitorable;
bool locked;
- void _body_inout(int p_status, const RID &p_body, int p_instance, int p_body_shape, int p_area_shape);
+ void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape);
void _body_enter_tree(ObjectID p_id);
void _body_exit_tree(ObjectID p_id);
@@ -94,7 +94,7 @@ private:
Map<ObjectID, BodyState> body_map;
- void _area_inout(int p_status, const RID &p_area, int p_instance, int p_area_shape, int p_self_shape);
+ void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape);
void _area_enter_tree(ObjectID p_id);
void _area_exit_tree(ObjectID p_id);
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index 8d1556ef1c..bf85a8bd53 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -252,7 +252,7 @@ void ARVRController::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRController::get_rumble);
ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRController::set_rumble);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble");
ADD_PROPERTY_DEFAULT("rumble", 0.0);
ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRController::get_mesh);
@@ -544,7 +544,7 @@ String ARVROrigin::get_configuration_warning() const {
void ARVROrigin::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &ARVROrigin::set_world_scale);
ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVROrigin::get_world_scale);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
};
void ARVROrigin::set_tracked_camera(ARVRCamera *p_tracked_camera) {
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 596ef78fb5..855d254bd6 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -45,12 +45,12 @@ private:
mutable real_t squared_gain; // temporary
};
- PoolVector<Speaker> speakers;
+ Vector<Speaker> speakers;
public:
Spcap(unsigned int speaker_count, const Vector3 *speaker_directions) {
this->speakers.resize(speaker_count);
- PoolVector<Speaker>::Write w = this->speakers.write();
+ Speaker *w = this->speakers.ptrw();
for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) {
w[speaker_num].direction = speaker_directions[speaker_num];
w[speaker_num].squared_gain = 0.0;
@@ -66,11 +66,11 @@ public:
}
Vector3 get_speaker_direction(unsigned int index) const {
- return this->speakers.read()[index].direction;
+ return this->speakers.ptr()[index].direction;
}
void calculate(const Vector3 &source_direction, real_t tightness, unsigned int volume_count, real_t *volumes) const {
- PoolVector<Speaker>::Read r = this->speakers.read();
+ const Speaker *r = this->speakers.ptr();
real_t sum_squared_gains = 0.0;
for (unsigned int speaker_num = 0; speaker_num < (unsigned int)this->speakers.size(); speaker_num++) {
real_t initial_gain = 0.5 * powf(1.0 + r[speaker_num].direction.dot(source_direction), tightness) / r[speaker_num].effective_number_of_speakers;
@@ -98,11 +98,18 @@ static const Vector3 speaker_directions[7] = {
void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tightness, AudioStreamPlayer3D::Output &output) {
unsigned int speaker_count; // only main speakers (no LFE)
switch (AudioServer::get_singleton()->get_speaker_mode()) {
- default: //fallthrough
- case AudioServer::SPEAKER_MODE_STEREO: speaker_count = 2; break;
- case AudioServer::SPEAKER_SURROUND_31: speaker_count = 3; break;
- case AudioServer::SPEAKER_SURROUND_51: speaker_count = 5; break;
- case AudioServer::SPEAKER_SURROUND_71: speaker_count = 7; break;
+ case AudioServer::SPEAKER_MODE_STEREO:
+ speaker_count = 2;
+ break;
+ case AudioServer::SPEAKER_SURROUND_31:
+ speaker_count = 3;
+ break;
+ case AudioServer::SPEAKER_SURROUND_51:
+ speaker_count = 5;
+ break;
+ case AudioServer::SPEAKER_SURROUND_71:
+ speaker_count = 7;
+ break;
}
Spcap spcap(speaker_count, speaker_directions); //TODO: should only be created/recreated once the speaker mode / speaker positions changes
@@ -113,18 +120,19 @@ void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tig
case AudioServer::SPEAKER_SURROUND_71:
output.vol[3].l = volumes[5]; // side-left
output.vol[3].r = volumes[6]; // side-right
- //fallthrough
+ [[fallthrough]];
case AudioServer::SPEAKER_SURROUND_51:
output.vol[2].l = volumes[3]; // rear-left
output.vol[2].r = volumes[4]; // rear-right
- //fallthrough
+ [[fallthrough]];
case AudioServer::SPEAKER_SURROUND_31:
output.vol[1].r = 1.0; // LFE - always full power
output.vol[1].l = volumes[2]; // center
- //fallthrough
+ [[fallthrough]];
case AudioServer::SPEAKER_MODE_STEREO:
output.vol[0].r = volumes[1]; // front-right
output.vol[0].l = volumes[0]; // front-left
+ break;
}
}
@@ -1000,28 +1008,26 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stream_playback"), &AudioStreamPlayer3D::get_stream_playback);
- ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed);
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,4096,1,or_greater"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,4096,1,or_greater"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask");
ADD_GROUP("Emission Angle", "emission_angle");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");
ADD_GROUP("Attenuation Filter", "attenuation_filter_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db");
ADD_GROUP("Doppler", "doppler_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
@@ -1068,7 +1074,7 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() {
stream_paused_fade_out = false;
velocity_tracker.instance();
- AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed");
+ AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer3D::_bus_layout_changed));
set_disable_scale(true);
}
AudioStreamPlayer3D::~AudioStreamPlayer3D() {
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 071afd1a69..73b1d450f0 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#if 0
#include "baked_lightmap.h"
#include "core/io/config_file.h"
#include "core/io/resource_saver.h"
@@ -46,12 +47,12 @@ AABB BakedLightmapData::get_bounds() const {
return bounds;
}
-void BakedLightmapData::set_octree(const PoolVector<uint8_t> &p_octree) {
+void BakedLightmapData::set_octree(const Vector<uint8_t> &p_octree) {
VS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree);
}
-PoolVector<uint8_t> BakedLightmapData::get_octree() const {
+Vector<uint8_t> BakedLightmapData::get_octree() const {
return VS::get_singleton()->lightmap_capture_get_octree(baked_light);
}
@@ -86,7 +87,7 @@ float BakedLightmapData::get_energy() const {
return energy;
}
-void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap, int p_instance) {
+void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Texture2D> &p_lightmap, int p_instance) {
ERR_FAIL_COND_MSG(p_lightmap.is_null(), "It's not a reference to a valid Texture object.");
User user;
@@ -105,9 +106,9 @@ NodePath BakedLightmapData::get_user_path(int p_user) const {
ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
return users[p_user].path;
}
-Ref<Texture> BakedLightmapData::get_user_lightmap(int p_user) const {
+Ref<Texture2D> BakedLightmapData::get_user_lightmap(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), Ref<Texture>());
+ ERR_FAIL_INDEX_V(p_user, users.size(), Ref<Texture2D>());
return users[p_user].lightmap;
}
@@ -173,8 +174,8 @@ void BakedLightmapData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_subdiv", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_subdiv", "get_cell_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "octree", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_octree", "get_octree");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "octree", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_octree", "get_octree");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
}
@@ -368,7 +369,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
Ref<BakedLightmapData> new_light_data;
new_light_data.instance();
- VoxelLightBaker baker;
+ Voxelizer baker;
int bake_subdiv;
int capture_subdiv;
@@ -413,7 +414,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
}
pmc = 0;
- baker.begin_bake_light(VoxelLightBaker::BakeQuality(bake_quality), VoxelLightBaker::BakeMode(bake_mode), propagation, energy);
+ baker.begin_bake_light(Voxelizer::BakeQuality(bake_quality), Voxelizer::BakeMode(bake_mode), propagation, energy);
for (List<PlotLight>::Element *E = light_list.front(); E; E = E->next()) {
@@ -465,7 +466,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
used_mesh_names.insert(mesh_name);
pmc++;
- VoxelLightBaker::LightMapData lm;
+ Voxelizer::LightMapData lm;
Error err;
if (bake_step_function) {
@@ -491,17 +492,16 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
Ref<Image> image;
image.instance();
- uint32_t tex_flags = Texture::FLAGS_DEFAULT;
if (hdr) {
//just save a regular image
- PoolVector<uint8_t> data;
+ Vector<uint8_t> data;
int s = lm.light.size();
data.resize(lm.light.size() * 2);
{
- PoolVector<uint8_t>::Write w = data.write();
- PoolVector<float>::Read r = lm.light.read();
+ uint8_t* w = data.ptrw();
+ const float* r = lm.light.ptr();
uint16_t *hfw = (uint16_t *)w.ptr();
for (int i = 0; i < s; i++) {
hfw[i] = Math::make_half_float(r[i]);
@@ -513,13 +513,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
} else {
//just save a regular image
- PoolVector<uint8_t> data;
+ Vector<uint8_t> data;
int s = lm.light.size();
data.resize(lm.light.size());
{
- PoolVector<uint8_t>::Write w = data.write();
- PoolVector<float>::Read r = lm.light.read();
+ uint8_t* w = data.ptrw();
+ const float* r = lm.light.ptr();
for (int i = 0; i < s; i += 3) {
Color c(r[i + 0], r[i + 1], r[i + 2]);
c = c.to_srgb();
@@ -534,11 +534,10 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
//This texture is saved to SRGB for two reasons:
// 1) first is so it looks better when doing the LINEAR->SRGB conversion (more accurate)
// 2) So it can be used in the GLES2 backend, which does not support linkear workflow
- tex_flags |= Texture::FLAG_CONVERT_TO_LINEAR;
}
String image_path = save_path.plus_file(mesh_name);
- Ref<Texture> texture;
+ Ref<Texture2D> texture;
if (ResourceLoader::import) {
@@ -583,7 +582,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
tex.instance();
}
- tex->create_from_image(image, tex_flags);
+ tex->create_from_image(image);
err = ResourceSaver::save(image_path, tex, ResourceSaver::FLAG_CHANGE_PATH);
if (set_path) {
@@ -628,7 +627,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
if (p_create_visual_debug) {
MultiMeshInstance *mmi = memnew(MultiMeshInstance);
- mmi->set_multimesh(baker.create_debug_multimesh(VoxelLightBaker::DEBUG_LIGHT));
+ mmi->set_multimesh(baker.create_debug_multimesh(Voxelizer::DEBUG_LIGHT));
add_child(mmi);
#ifdef TOOLS_ENABLED
if (get_tree()->get_edited_scene_root() == this) {
@@ -668,7 +667,7 @@ void BakedLightmap::_assign_lightmaps() {
ERR_FAIL_COND(!light_data.is_valid());
for (int i = 0; i < light_data->get_user_count(); i++) {
- Ref<Texture> lightmap = light_data->get_user_lightmap(i);
+ Ref<Texture2D> lightmap = light_data->get_user_lightmap(i);
ERR_CONTINUE(!lightmap.is_valid());
Node *node = get_node(light_data->get_user_path(i));
@@ -776,8 +775,8 @@ String BakedLightmap::get_image_path() const {
AABB BakedLightmap::get_aabb() const {
return AABB(-extents, extents * 2);
}
-PoolVector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+Vector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
+ return Vector<Face3>();
}
void BakedLightmap::_bind_methods() {
@@ -820,16 +819,16 @@ void BakedLightmap::_bind_methods() {
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_GROUP("Bake", "bake_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_bake_cell_size", "get_bake_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_bake_cell_size", "get_bake_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_bake_quality", "get_bake_quality");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mode", PROPERTY_HINT_ENUM, "ConeTrace,RayTrace"), "set_bake_mode", "get_bake_mode");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_hdr"), "set_hdr", "is_hdr");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bake_extents"), "set_extents", "get_extents");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_default_texels_per_unit"), "set_bake_default_texels_per_unit", "get_bake_default_texels_per_unit");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_default_texels_per_unit"), "set_bake_default_texels_per_unit", "get_bake_default_texels_per_unit");
ADD_GROUP("Capture", "capture_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
ADD_GROUP("Data", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR), "set_image_path", "get_image_path");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data");
@@ -862,3 +861,4 @@ BakedLightmap::BakedLightmap() {
image_path = ".";
set_disable_scale(true);
}
+#endif
diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h
index 82354cc9f0..bc9e3f55ea 100644
--- a/scene/3d/baked_lightmap.h
+++ b/scene/3d/baked_lightmap.h
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#if 0
#ifndef BAKED_INDIRECT_LIGHT_H
#define BAKED_INDIRECT_LIGHT_H
@@ -47,7 +48,7 @@ class BakedLightmapData : public Resource {
struct User {
NodePath path;
- Ref<Texture> lightmap;
+ Ref<Texture2D> lightmap;
int instance_index;
};
@@ -63,8 +64,8 @@ public:
void set_bounds(const AABB &p_bounds);
AABB get_bounds() const;
- void set_octree(const PoolVector<uint8_t> &p_octree);
- PoolVector<uint8_t> get_octree() const;
+ void set_octree(const Vector<uint8_t> &p_octree);
+ Vector<uint8_t> get_octree() const;
void set_cell_space_transform(const Transform &p_xform);
Transform get_cell_space_transform() const;
@@ -75,10 +76,10 @@ public:
void set_energy(float p_energy);
float get_energy() const;
- void add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap, int p_instance = -1);
+ void add_user(const NodePath &p_path, const Ref<Texture2D> &p_lightmap, int p_instance = -1);
int get_user_count() const;
NodePath get_user_path(int p_user) const;
- Ref<Texture> get_user_lightmap(int p_user) const;
+ Ref<Texture2D> get_user_lightmap(int p_user) const;
int get_user_instance(int p_user) const;
void clear_users();
@@ -201,7 +202,7 @@ public:
String get_image_path() const;
AABB get_aabb() const;
- PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const;
BakeError bake(Node *p_from_node, bool p_create_visual_debug = false);
BakedLightmap();
@@ -211,4 +212,5 @@ VARIANT_ENUM_CAST(BakedLightmap::BakeQuality);
VARIANT_ENUM_CAST(BakedLightmap::BakeMode);
VARIANT_ENUM_CAST(BakedLightmap::BakeError);
+#endif
#endif // BAKED_INDIRECT_LIGHT_H
diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp
index e94e174b92..b1cd9bfe8b 100644
--- a/scene/3d/bone_attachment.cpp
+++ b/scene/3d/bone_attachment.cpp
@@ -123,5 +123,5 @@ void BoneAttachment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_name", "bone_name"), &BoneAttachment::set_bone_name);
ClassDB::bind_method(D_METHOD("get_bone_name"), &BoneAttachment::get_bone_name);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "bone_name"), "set_bone_name", "get_bone_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name");
}
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 640189a26e..741712025c 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -445,6 +445,21 @@ Ref<Environment> Camera::get_environment() const {
return environment;
}
+void Camera::set_effects(const Ref<CameraEffects> &p_effects) {
+
+ effects = p_effects;
+ if (effects.is_valid())
+ VS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid());
+ else
+ VS::get_singleton()->camera_set_camera_effects(camera, RID());
+ _update_camera_mode();
+}
+
+Ref<CameraEffects> Camera::get_effects() const {
+
+ return effects;
+}
+
void Camera::set_keep_aspect_mode(KeepAspect p_aspect) {
keep_aspect = p_aspect;
VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH);
@@ -512,6 +527,8 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera::get_cull_mask);
ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment);
+ ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera::set_effects);
+ ClassDB::bind_method(D_METHOD("get_effects"), &Camera::get_effects);
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking);
@@ -527,16 +544,17 @@ void Camera::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
@@ -908,7 +926,7 @@ void ClippedCamera::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_exceptions"), &ClippedCamera::clear_exceptions);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index e215783a58..6ac3ece798 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -82,6 +82,7 @@ private:
uint32_t layers;
Ref<Environment> environment;
+ Ref<CameraEffects> effects;
virtual bool _can_gizmo_scale() const;
@@ -157,6 +158,9 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
+ void set_effects(const Ref<CameraEffects> &p_effects);
+ Ref<CameraEffects> get_effects() const;
+
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index cc07072962..636b859477 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -53,11 +53,11 @@ void CollisionPolygon::_build_polygon() {
for (int i = 0; i < decomp.size(); i++) {
Ref<ConvexPolygonShape> convex = memnew(ConvexPolygonShape);
- PoolVector<Vector3> cp;
+ Vector<Vector3> cp;
int cs = decomp[i].size();
cp.resize(cs * 2);
{
- PoolVector<Vector3>::Write w = cp.write();
+ Vector3 *w = cp.ptrw();
int idx = 0;
for (int j = 0; j < cs; j++) {
@@ -191,9 +191,9 @@ void CollisionPolygon::_bind_methods() {
ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CollisionPolygon::_is_editable_3d_polygon);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
}
CollisionPolygon::CollisionPolygon() {
diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp
index bf2816fd41..35e4a61cd6 100644
--- a/scene/3d/collision_shape.cpp
+++ b/scene/3d/collision_shape.cpp
@@ -33,9 +33,9 @@
#include "scene/resources/capsule_shape.h"
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
-#include "scene/resources/plane_shape.h"
#include "scene/resources/ray_shape.h"
#include "scene/resources/sphere_shape.h"
+#include "scene/resources/world_margin_shape.h"
#include "servers/visual_server.h"
//TODO: Implement CylinderShape and HeightMapShape?
#include "core/math/quick_hull.h"
@@ -123,10 +123,6 @@ String CollisionShape::get_configuration_warning() const {
return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it.");
}
- if (shape->is_class("PlaneShape")) {
- return TTR("Plane shapes don't work well and will be removed in future versions. Please don't use them.");
- }
-
return String();
}
@@ -141,7 +137,6 @@ void CollisionShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
- ClassDB::bind_method(D_METHOD("_shape_changed"), &CollisionShape::_shape_changed);
ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape::_update_debug_shape);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
@@ -152,12 +147,12 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
if (!shape.is_null()) {
shape->unregister_owner(this);
- shape->disconnect("changed", this, "_shape_changed");
+ shape->disconnect("changed", callable_mp(this, &CollisionShape::_shape_changed));
}
shape = p_shape;
if (!shape.is_null()) {
shape->register_owner(this);
- shape->connect("changed", this, "_shape_changed");
+ shape->connect("changed", callable_mp(this, &CollisionShape::_shape_changed));
}
update_gizmo();
if (parent) {
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index aa7a413548..bde578d0af 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -39,9 +39,9 @@ AABB CPUParticles::get_aabb() const {
return AABB();
}
-PoolVector<Face3> CPUParticles::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> CPUParticles::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
void CPUParticles::set_emitting(bool p_emitting) {
@@ -65,15 +65,15 @@ void CPUParticles::set_amount(int p_amount) {
particles.resize(p_amount);
{
- PoolVector<Particle>::Write w = particles.write();
+ Particle *w = particles.ptrw();
for (int i = 0; i < p_amount; i++) {
w[i].active = false;
}
}
- particle_data.resize((12 + 4 + 1) * p_amount);
- VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT);
+ particle_data.resize((12 + 4 + 4) * p_amount);
+ VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true);
particle_order.resize(p_amount);
}
@@ -209,14 +209,14 @@ String CPUParticles::get_configuration_warning() const {
mesh_found = true;
for (int j = 0; j < get_mesh()->get_surface_count(); j++) {
anim_material_found = Object::cast_to<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != NULL;
- SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_mesh()->surface_get_material(j).ptr());
- anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
+ StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_mesh()->surface_get_material(j).ptr());
+ anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
}
}
anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL;
- SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_material_override().ptr());
- anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
+ StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_material_override().ptr());
+ anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
if (!mesh_found) {
if (warnings != String())
@@ -228,7 +228,7 @@ String CPUParticles::get_configuration_warning() const {
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
- warnings += "- " + TTR("CPUParticles animation requires the usage of a SpatialMaterial whose Billboard Mode is set to \"Particle Billboard\".");
+ warnings += "- " + TTR("CPUParticles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".");
}
return warnings;
@@ -244,7 +244,7 @@ void CPUParticles::restart() {
{
int pc = particles.size();
- PoolVector<Particle>::Write w = particles.write();
+ Particle *w = particles.ptrw();
for (int i = 0; i < pc; i++) {
w[i].active = false;
@@ -419,17 +419,17 @@ void CPUParticles::set_emission_box_extents(Vector3 p_extents) {
emission_box_extents = p_extents;
}
-void CPUParticles::set_emission_points(const PoolVector<Vector3> &p_points) {
+void CPUParticles::set_emission_points(const Vector<Vector3> &p_points) {
emission_points = p_points;
}
-void CPUParticles::set_emission_normals(const PoolVector<Vector3> &p_normals) {
+void CPUParticles::set_emission_normals(const Vector<Vector3> &p_normals) {
emission_normals = p_normals;
}
-void CPUParticles::set_emission_colors(const PoolVector<Color> &p_colors) {
+void CPUParticles::set_emission_colors(const Vector<Color> &p_colors) {
emission_colors = p_colors;
}
@@ -442,16 +442,16 @@ Vector3 CPUParticles::get_emission_box_extents() const {
return emission_box_extents;
}
-PoolVector<Vector3> CPUParticles::get_emission_points() const {
+Vector<Vector3> CPUParticles::get_emission_points() const {
return emission_points;
}
-PoolVector<Vector3> CPUParticles::get_emission_normals() const {
+Vector<Vector3> CPUParticles::get_emission_normals() const {
return emission_normals;
}
-PoolVector<Color> CPUParticles::get_emission_colors() const {
+Vector<Color> CPUParticles::get_emission_colors() const {
return emission_colors;
}
@@ -597,9 +597,9 @@ void CPUParticles::_particles_process(float p_delta) {
p_delta *= speed_scale;
int pcount = particles.size();
- PoolVector<Particle>::Write w = particles.write();
+ Particle *w = particles.ptrw();
- Particle *parray = w.ptr();
+ Particle *parray = w;
float prev_time = time;
time += p_delta;
@@ -1017,140 +1017,125 @@ void CPUParticles::_particles_process(float p_delta) {
}
void CPUParticles::_update_particle_data_buffer() {
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
+ MutexLock lock(update_mutex);
- {
+ int pc = particles.size();
- int pc = particles.size();
+ int *ow;
+ int *order = NULL;
- PoolVector<int>::Write ow;
- int *order = NULL;
+ float *w = particle_data.ptrw();
+ const Particle *r = particles.ptr();
+ float *ptr = w;
- PoolVector<float>::Write w = particle_data.write();
- PoolVector<Particle>::Read r = particles.read();
- float *ptr = w.ptr();
+ if (draw_order != DRAW_ORDER_INDEX) {
+ ow = particle_order.ptrw();
+ order = ow;
- if (draw_order != DRAW_ORDER_INDEX) {
- ow = particle_order.write();
- order = ow.ptr();
+ for (int i = 0; i < pc; i++) {
+ order[i] = i;
+ }
+ if (draw_order == DRAW_ORDER_LIFETIME) {
+ SortArray<int, SortLifetime> sorter;
+ sorter.compare.particles = r;
+ sorter.sort(order, pc);
+ } else if (draw_order == DRAW_ORDER_VIEW_DEPTH) {
+ Camera *c = get_viewport()->get_camera();
+ if (c) {
+ Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
+
+ if (local_coords) {
+
+ // will look different from Particles in editor as this is based on the camera in the scenetree
+ // and not the editor camera
+ dir = inv_emission_transform.xform(dir).normalized();
+ } else {
+ dir = dir.normalized();
+ }
- for (int i = 0; i < pc; i++) {
- order[i] = i;
- }
- if (draw_order == DRAW_ORDER_LIFETIME) {
- SortArray<int, SortLifetime> sorter;
- sorter.compare.particles = r.ptr();
+ SortArray<int, SortAxis> sorter;
+ sorter.compare.particles = r;
+ sorter.compare.axis = dir;
sorter.sort(order, pc);
- } else if (draw_order == DRAW_ORDER_VIEW_DEPTH) {
- Camera *c = get_viewport()->get_camera();
- if (c) {
- Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close
-
- if (local_coords) {
-
- // will look different from Particles in editor as this is based on the camera in the scenetree
- // and not the editor camera
- dir = inv_emission_transform.xform(dir).normalized();
- } else {
- dir = dir.normalized();
- }
-
- SortArray<int, SortAxis> sorter;
- sorter.compare.particles = r.ptr();
- sorter.compare.axis = dir;
- sorter.sort(order, pc);
- }
}
}
+ }
- for (int i = 0; i < pc; i++) {
+ for (int i = 0; i < pc; i++) {
- int idx = order ? order[i] : i;
+ int idx = order ? order[i] : i;
- Transform t = r[idx].transform;
+ Transform t = r[idx].transform;
- if (!local_coords) {
- t = inv_emission_transform * t;
- }
+ if (!local_coords) {
+ t = inv_emission_transform * t;
+ }
- if (r[idx].active) {
- ptr[0] = t.basis.elements[0][0];
- ptr[1] = t.basis.elements[0][1];
- ptr[2] = t.basis.elements[0][2];
- ptr[3] = t.origin.x;
- ptr[4] = t.basis.elements[1][0];
- ptr[5] = t.basis.elements[1][1];
- ptr[6] = t.basis.elements[1][2];
- ptr[7] = t.origin.y;
- ptr[8] = t.basis.elements[2][0];
- ptr[9] = t.basis.elements[2][1];
- ptr[10] = t.basis.elements[2][2];
- ptr[11] = t.origin.z;
- } else {
- zeromem(ptr, sizeof(float) * 12);
- }
+ if (r[idx].active) {
+ ptr[0] = t.basis.elements[0][0];
+ ptr[1] = t.basis.elements[0][1];
+ ptr[2] = t.basis.elements[0][2];
+ ptr[3] = t.origin.x;
+ ptr[4] = t.basis.elements[1][0];
+ ptr[5] = t.basis.elements[1][1];
+ ptr[6] = t.basis.elements[1][2];
+ ptr[7] = t.origin.y;
+ ptr[8] = t.basis.elements[2][0];
+ ptr[9] = t.basis.elements[2][1];
+ ptr[10] = t.basis.elements[2][2];
+ ptr[11] = t.origin.z;
+ } else {
+ zeromem(ptr, sizeof(float) * 12);
+ }
- Color c = r[idx].color;
- uint8_t *data8 = (uint8_t *)&ptr[12];
- data8[0] = CLAMP(c.r * 255.0, 0, 255);
- data8[1] = CLAMP(c.g * 255.0, 0, 255);
- data8[2] = CLAMP(c.b * 255.0, 0, 255);
- data8[3] = CLAMP(c.a * 255.0, 0, 255);
+ Color c = r[idx].color;
- ptr[13] = r[idx].custom[0];
- ptr[14] = r[idx].custom[1];
- ptr[15] = r[idx].custom[2];
- ptr[16] = r[idx].custom[3];
+ ptr[12] = c.r;
+ ptr[13] = c.g;
+ ptr[14] = c.b;
+ ptr[15] = c.a;
- ptr += 17;
- }
+ ptr[16] = r[idx].custom[0];
+ ptr[17] = r[idx].custom[1];
+ ptr[18] = r[idx].custom[2];
+ ptr[19] = r[idx].custom[3];
- can_update = true;
+ ptr += 20;
}
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
+ can_update = true;
}
void CPUParticles::_set_redraw(bool p_redraw) {
if (redraw == p_redraw)
return;
redraw = p_redraw;
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
- if (redraw) {
- VS::get_singleton()->connect("frame_pre_draw", this, "_update_render_thread");
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
- VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1);
- } else {
- if (VS::get_singleton()->is_connected("frame_pre_draw", this, "_update_render_thread")) {
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_update_render_thread");
+
+ {
+ MutexLock lock(update_mutex);
+
+ if (redraw) {
+ VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread));
+ VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
+ VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1);
+ } else {
+ if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread))) {
+ VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread));
+ }
+ VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
+ VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
}
- VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false);
- VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
}
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
}
void CPUParticles::_update_render_thread() {
-#ifndef NO_THREADS
- update_mutex->lock();
-#endif
+ MutexLock lock(update_mutex);
+
if (can_update) {
- VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
+ VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data);
can_update = false; //wait for next time
}
-
-#ifndef NO_THREADS
- update_mutex->unlock();
-#endif
}
void CPUParticles::_notification(int p_what) {
@@ -1185,9 +1170,9 @@ void CPUParticles::_notification(int p_what) {
int pc = particles.size();
- PoolVector<float>::Write w = particle_data.write();
- PoolVector<Particle>::Read r = particles.read();
- float *ptr = w.ptr();
+ float *w = particle_data.ptrw();
+ const Particle *r = particles.ptr();
+ float *ptr = w;
for (int i = 0; i < pc; i++) {
@@ -1210,7 +1195,7 @@ void CPUParticles::_notification(int p_what) {
zeromem(ptr, sizeof(float) * 12);
}
- ptr += 17;
+ ptr += 20;
}
can_update = true;
@@ -1327,13 +1312,13 @@ void CPUParticles::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_GROUP("Drawing", "");
@@ -1397,74 +1382,72 @@ void CPUParticles::_bind_methods() {
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles::convert_from_particles);
- ClassDB::bind_method(D_METHOD("_update_render_thread"), &CPUParticles::_update_render_thread);
-
ADD_GROUP("Emission Shape", "emission_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
ADD_GROUP("Flags", "flag_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_particle_flag", "get_particle_flag", FLAG_ROTATE_Y);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_particle_flag", "get_particle_flag", FLAG_DISABLE_Z);
ADD_GROUP("Direction", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness");
ADD_GROUP("Gravity", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
ADD_GROUP("Initial Velocity", "initial_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY);
ADD_GROUP("Angular Velocity", "angular_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY);
ADD_GROUP("Orbit Velocity", "orbit_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY);
ADD_GROUP("Linear Accel", "linear_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_LINEAR_ACCEL);
ADD_GROUP("Radial Accel", "radial_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_RADIAL_ACCEL);
ADD_GROUP("Tangential Accel", "tangential_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL);
ADD_GROUP("Damping", "");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
ADD_GROUP("Angle", "");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE);
ADD_GROUP("Scale", "");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_amount", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_amount_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_amount_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_SCALE);
ADD_GROUP("Color", "");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp");
ADD_GROUP("Hue Variation", "hue_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION);
ADD_GROUP("Animation", "anim_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_SPEED);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_OFFSET);
BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY);
@@ -1556,16 +1539,8 @@ CPUParticles::CPUParticles() {
can_update = false;
set_color(Color(1, 1, 1, 1));
-
-#ifndef NO_THREADS
- update_mutex = Mutex::create();
-#endif
}
CPUParticles::~CPUParticles() {
VS::get_singleton()->free(multimesh);
-
-#ifndef NO_THREADS
- memdelete(update_mutex);
-#endif
}
diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h
index d5a549b976..231e1f1ad9 100644
--- a/scene/3d/cpu_particles.h
+++ b/scene/3d/cpu_particles.h
@@ -106,9 +106,9 @@ private:
RID multimesh;
- PoolVector<Particle> particles;
- PoolVector<float> particle_data;
- PoolVector<int> particle_order;
+ Vector<Particle> particles;
+ Vector<float> particle_data;
+ Vector<int> particle_order;
struct SortLifetime {
const Particle *particles;
@@ -167,9 +167,9 @@ private:
EmissionShape emission_shape;
float emission_sphere_radius;
Vector3 emission_box_extents;
- PoolVector<Vector3> emission_points;
- PoolVector<Vector3> emission_normals;
- PoolVector<Color> emission_colors;
+ Vector<Vector3> emission_points;
+ Vector<Vector3> emission_normals;
+ Vector<Color> emission_colors;
int emission_point_count;
Vector3 gravity;
@@ -178,7 +178,7 @@ private:
void _particles_process(float p_delta);
void _update_particle_data_buffer();
- Mutex *update_mutex;
+ Mutex update_mutex;
void _update_render_thread();
@@ -191,7 +191,7 @@ protected:
public:
AABB get_aabb() const;
- PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
@@ -264,17 +264,17 @@ public:
void set_emission_shape(EmissionShape p_shape);
void set_emission_sphere_radius(float p_radius);
void set_emission_box_extents(Vector3 p_extents);
- void set_emission_points(const PoolVector<Vector3> &p_points);
- void set_emission_normals(const PoolVector<Vector3> &p_normals);
- void set_emission_colors(const PoolVector<Color> &p_colors);
+ void set_emission_points(const Vector<Vector3> &p_points);
+ void set_emission_normals(const Vector<Vector3> &p_normals);
+ void set_emission_colors(const Vector<Color> &p_colors);
void set_emission_point_count(int p_count);
EmissionShape get_emission_shape() const;
float get_emission_sphere_radius() const;
Vector3 get_emission_box_extents() const;
- PoolVector<Vector3> get_emission_points() const;
- PoolVector<Vector3> get_emission_normals() const;
- PoolVector<Color> get_emission_colors() const;
+ Vector<Vector3> get_emission_points() const;
+ Vector<Vector3> get_emission_normals() const;
+ Vector<Color> get_emission_colors() const;
int get_emission_point_count() const;
void set_gravity(const Vector3 &p_gravity);
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 99bc78f5d2..c3f039ae85 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -32,116 +32,183 @@
#include "core/os/os.h"
+#include "core/method_bind_ext.gen.inc"
#include "mesh_instance.h"
-#include "voxel_light_baker.h"
+#include "voxelizer.h"
+
+void GIProbeData::_set_data(const Dictionary &p_data) {
+ ERR_FAIL_COND(!p_data.has("bounds"));
+ ERR_FAIL_COND(!p_data.has("octree_size"));
+ ERR_FAIL_COND(!p_data.has("octree_cells"));
+ ERR_FAIL_COND(!p_data.has("octree_data"));
+ ERR_FAIL_COND(!p_data.has("octree_df") && !p_data.has("octree_df_png"));
+ ERR_FAIL_COND(!p_data.has("level_counts"));
+ ERR_FAIL_COND(!p_data.has("to_cell_xform"));
+
+ AABB bounds = p_data["bounds"];
+ Vector3 octree_size = p_data["octree_size"];
+ Vector<uint8_t> octree_cells = p_data["octree_cells"];
+ Vector<uint8_t> octree_data = p_data["octree_data"];
+
+ Vector<uint8_t> octree_df;
+ if (p_data.has("octree_df")) {
+ octree_df = p_data["octree_df"];
+ } else if (p_data.has("octree_df_png")) {
+ Vector<uint8_t> octree_df_png = p_data["octree_df_png"];
+ Ref<Image> img;
+ img.instance();
+ Error err = img->load_png_from_buffer(octree_df_png);
+ ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND(img->get_format() != Image::FORMAT_L8);
+ octree_df = img->get_data();
+ }
+ Vector<int> octree_levels = p_data["level_counts"];
+ Transform to_cell_xform = p_data["to_cell_xform"];
+
+ allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels);
+}
+
+Dictionary GIProbeData::_get_data() const {
+ Dictionary d;
+ d["bounds"] = get_bounds();
+ Vector3i otsize = get_octree_size();
+ d["octree_size"] = Vector3(otsize);
+ d["octree_cells"] = get_octree_cells();
+ d["octree_data"] = get_data_cells();
+ if (otsize != Vector3i()) {
+ Ref<Image> img;
+ img.instance();
+ img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field());
+ Vector<uint8_t> df_png = img->save_png_to_buffer();
+ ERR_FAIL_COND_V(df_png.size() == 0, Dictionary());
+ d["octree_df_png"] = df_png;
+ } else {
+ d["octree_df"] = Vector<uint8_t>();
+ }
-void GIProbeData::set_bounds(const AABB &p_bounds) {
+ d["level_counts"] = get_level_counts();
+ d["to_cell_xform"] = get_to_cell_xform();
+ return d;
+}
- VS::get_singleton()->gi_probe_set_bounds(probe, p_bounds);
+void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+ VS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
+ bounds = p_aabb;
+ to_cell_xform = p_to_cell_xform;
+ octree_size = p_octree_size;
}
AABB GIProbeData::get_bounds() const {
-
- return VS::get_singleton()->gi_probe_get_bounds(probe);
+ return bounds;
}
-
-void GIProbeData::set_cell_size(float p_size) {
-
- VS::get_singleton()->gi_probe_set_cell_size(probe, p_size);
+Vector3 GIProbeData::get_octree_size() const {
+ return octree_size;
}
-
-float GIProbeData::get_cell_size() const {
-
- return VS::get_singleton()->gi_probe_get_cell_size(probe);
+Vector<uint8_t> GIProbeData::get_octree_cells() const {
+ return VS::get_singleton()->gi_probe_get_octree_cells(probe);
}
-
-void GIProbeData::set_to_cell_xform(const Transform &p_xform) {
-
- VS::get_singleton()->gi_probe_set_to_cell_xform(probe, p_xform);
+Vector<uint8_t> GIProbeData::get_data_cells() const {
+ return VS::get_singleton()->gi_probe_get_data_cells(probe);
+}
+Vector<uint8_t> GIProbeData::get_distance_field() const {
+ return VS::get_singleton()->gi_probe_get_distance_field(probe);
}
+Vector<int> GIProbeData::get_level_counts() const {
+ return VS::get_singleton()->gi_probe_get_level_counts(probe);
+}
Transform GIProbeData::get_to_cell_xform() const {
-
- return VS::get_singleton()->gi_probe_get_to_cell_xform(probe);
+ return to_cell_xform;
}
-void GIProbeData::set_dynamic_data(const PoolVector<int> &p_data) {
+void GIProbeData::set_dynamic_range(float p_range) {
+ VS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range);
+ dynamic_range = p_range;
+}
- VS::get_singleton()->gi_probe_set_dynamic_data(probe, p_data);
+float GIProbeData::get_dynamic_range() const {
+ return dynamic_range;
}
-PoolVector<int> GIProbeData::get_dynamic_data() const {
- return VS::get_singleton()->gi_probe_get_dynamic_data(probe);
+void GIProbeData::set_propagation(float p_propagation) {
+ VS::get_singleton()->gi_probe_set_propagation(probe, p_propagation);
+ propagation = p_propagation;
}
-void GIProbeData::set_dynamic_range(int p_range) {
+float GIProbeData::get_propagation() const {
+ return propagation;
+}
- VS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range);
+void GIProbeData::set_anisotropy_strength(float p_anisotropy_strength) {
+ VS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength);
+ anisotropy_strength = p_anisotropy_strength;
}
-void GIProbeData::set_energy(float p_range) {
+float GIProbeData::get_anisotropy_strength() const {
+ return anisotropy_strength;
+}
- VS::get_singleton()->gi_probe_set_energy(probe, p_range);
+void GIProbeData::set_energy(float p_energy) {
+ VS::get_singleton()->gi_probe_set_energy(probe, p_energy);
+ energy = p_energy;
}
float GIProbeData::get_energy() const {
-
- return VS::get_singleton()->gi_probe_get_energy(probe);
+ return energy;
}
-void GIProbeData::set_bias(float p_range) {
-
- VS::get_singleton()->gi_probe_set_bias(probe, p_range);
+void GIProbeData::set_ao(float p_ao) {
+ VS::get_singleton()->gi_probe_set_ao(probe, p_ao);
+ ao = p_ao;
}
-float GIProbeData::get_bias() const {
-
- return VS::get_singleton()->gi_probe_get_bias(probe);
+float GIProbeData::get_ao() const {
+ return ao;
}
-void GIProbeData::set_normal_bias(float p_range) {
-
- VS::get_singleton()->gi_probe_set_normal_bias(probe, p_range);
+void GIProbeData::set_ao_size(float p_ao_size) {
+ VS::get_singleton()->gi_probe_set_ao_size(probe, p_ao_size);
+ ao_size = p_ao_size;
}
-float GIProbeData::get_normal_bias() const {
-
- return VS::get_singleton()->gi_probe_get_normal_bias(probe);
+float GIProbeData::get_ao_size() const {
+ return ao_size;
}
-void GIProbeData::set_propagation(float p_range) {
+void GIProbeData::set_bias(float p_bias) {
+ VS::get_singleton()->gi_probe_set_bias(probe, p_bias);
+ bias = p_bias;
+}
- VS::get_singleton()->gi_probe_set_propagation(probe, p_range);
+float GIProbeData::get_bias() const {
+ return bias;
}
-float GIProbeData::get_propagation() const {
+void GIProbeData::set_normal_bias(float p_normal_bias) {
+ VS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias);
+ normal_bias = p_normal_bias;
+}
- return VS::get_singleton()->gi_probe_get_propagation(probe);
+float GIProbeData::get_normal_bias() const {
+ return normal_bias;
}
void GIProbeData::set_interior(bool p_enable) {
-
VS::get_singleton()->gi_probe_set_interior(probe, p_enable);
+ interior = p_enable;
}
bool GIProbeData::is_interior() const {
-
- return VS::get_singleton()->gi_probe_is_interior(probe);
+ return interior;
}
-bool GIProbeData::is_compressed() const {
-
- return VS::get_singleton()->gi_probe_is_compressed(probe);
+void GIProbeData::set_use_two_bounces(bool p_enable) {
+ VS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable);
+ use_two_bounces = p_enable;
}
-void GIProbeData::set_compress(bool p_enable) {
-
- VS::get_singleton()->gi_probe_set_compress(probe, p_enable);
-}
-
-int GIProbeData::get_dynamic_range() const {
-
- return VS::get_singleton()->gi_probe_get_dynamic_range(probe);
+bool GIProbeData::is_using_two_bounces() const {
+ return use_two_bounces;
}
RID GIProbeData::get_rid() const {
@@ -149,19 +216,24 @@ RID GIProbeData::get_rid() const {
return probe;
}
+void GIProbeData::_validate_property(PropertyInfo &property) const {
+ if (property.name == "anisotropy_strength") {
+ bool anisotropy_enabled = ProjectSettings::get_singleton()->get("rendering/quality/gi_probes/anisotropic");
+ if (!anisotropy_enabled) {
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+ }
+}
+
void GIProbeData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("allocate", "to_cell_xform", "aabb", "octree_size", "octree_cells", "data_cells", "distance_field", "level_counts"), &GIProbeData::allocate);
- ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &GIProbeData::set_bounds);
ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds);
-
- ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &GIProbeData::set_cell_size);
- ClassDB::bind_method(D_METHOD("get_cell_size"), &GIProbeData::get_cell_size);
-
- ClassDB::bind_method(D_METHOD("set_to_cell_xform", "to_cell_xform"), &GIProbeData::set_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("get_octree_size"), &GIProbeData::get_octree_size);
ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform);
-
- ClassDB::bind_method(D_METHOD("set_dynamic_data", "dynamic_data"), &GIProbeData::set_dynamic_data);
- ClassDB::bind_method(D_METHOD("get_dynamic_data"), &GIProbeData::get_dynamic_data);
+ ClassDB::bind_method(D_METHOD("get_octree_cells"), &GIProbeData::get_octree_cells);
+ ClassDB::bind_method(D_METHOD("get_data_cells"), &GIProbeData::get_data_cells);
+ ClassDB::bind_method(D_METHOD("get_level_counts"), &GIProbeData::get_level_counts);
ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range);
ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range);
@@ -178,28 +250,50 @@ void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation);
+ ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &GIProbeData::set_anisotropy_strength);
+ ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &GIProbeData::get_anisotropy_strength);
+
+ ClassDB::bind_method(D_METHOD("set_ao", "ao"), &GIProbeData::set_ao);
+ ClassDB::bind_method(D_METHOD("get_ao"), &GIProbeData::get_ao);
+
+ ClassDB::bind_method(D_METHOD("set_ao_size", "strength"), &GIProbeData::set_ao_size);
+ ClassDB::bind_method(D_METHOD("get_ao_size"), &GIProbeData::get_ao_size);
+
ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior);
- ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress);
- ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed);
+ ClassDB::bind_method(D_METHOD("set_use_two_bounces", "enable"), &GIProbeData::set_use_two_bounces);
+ ClassDB::bind_method(D_METHOD("is_using_two_bounces"), &GIProbeData::is_using_two_bounces);
+
+ ClassDB::bind_method(D_METHOD("_set_data", "data"), &GIProbeData::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"), &GIProbeData::_get_data);
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "dynamic_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_data", "get_dynamic_data");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_dynamic_range", "get_dynamic_range");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_energy", "get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_size", "get_ao_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
}
GIProbeData::GIProbeData() {
+ ao = 0.0;
+ ao_size = 0.5;
+ dynamic_range = 4;
+ energy = 1.0;
+ bias = 1.5;
+ normal_bias = 0.0;
+ propagation = 0.7;
+ anisotropy_strength = 0.5;
+ interior = false;
+
probe = VS::get_singleton()->gi_probe_create();
}
@@ -251,89 +345,6 @@ Vector3 GIProbe::get_extents() const {
return extents;
}
-void GIProbe::set_dynamic_range(int p_dynamic_range) {
-
- dynamic_range = p_dynamic_range;
-}
-int GIProbe::get_dynamic_range() const {
-
- return dynamic_range;
-}
-
-void GIProbe::set_energy(float p_energy) {
-
- energy = p_energy;
- if (probe_data.is_valid()) {
- probe_data->set_energy(energy);
- }
-}
-float GIProbe::get_energy() const {
-
- return energy;
-}
-
-void GIProbe::set_bias(float p_bias) {
-
- bias = p_bias;
- if (probe_data.is_valid()) {
- probe_data->set_bias(bias);
- }
-}
-float GIProbe::get_bias() const {
-
- return bias;
-}
-
-void GIProbe::set_normal_bias(float p_normal_bias) {
-
- normal_bias = p_normal_bias;
- if (probe_data.is_valid()) {
- probe_data->set_normal_bias(normal_bias);
- }
-}
-float GIProbe::get_normal_bias() const {
-
- return normal_bias;
-}
-
-void GIProbe::set_propagation(float p_propagation) {
-
- propagation = p_propagation;
- if (probe_data.is_valid()) {
- probe_data->set_propagation(propagation);
- }
-}
-float GIProbe::get_propagation() const {
-
- return propagation;
-}
-
-void GIProbe::set_interior(bool p_enable) {
-
- interior = p_enable;
- if (probe_data.is_valid()) {
- probe_data->set_interior(p_enable);
- }
-}
-
-bool GIProbe::is_interior() const {
-
- return interior;
-}
-
-void GIProbe::set_compress(bool p_enable) {
-
- compress = p_enable;
- if (probe_data.is_valid()) {
- probe_data->set_compress(p_enable);
- }
-}
-
-bool GIProbe::is_compressed() const {
-
- return compress;
-}
-
void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
@@ -395,11 +406,36 @@ GIProbe::BakeBeginFunc GIProbe::bake_begin_function = NULL;
GIProbe::BakeStepFunc GIProbe::bake_step_function = NULL;
GIProbe::BakeEndFunc GIProbe::bake_end_function = NULL;
+Vector3i GIProbe::get_estimated_cell_size() const {
+ static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
+ int cell_subdiv = subdiv_value[subdiv];
+ int axis_cell_size[3];
+ AABB bounds = AABB(-extents, extents * 2.0);
+ int longest_axis = bounds.get_longest_axis_index();
+ axis_cell_size[longest_axis] = 1 << cell_subdiv;
+
+ for (int i = 0; i < 3; i++) {
+
+ if (i == longest_axis)
+ continue;
+
+ axis_cell_size[i] = axis_cell_size[longest_axis];
+ float axis_size = bounds.size[longest_axis];
+
+ //shrink until fit subdiv
+ while (axis_size / 2.0 >= bounds.size[i]) {
+ axis_size /= 2.0;
+ axis_cell_size[i] >>= 1;
+ }
+ }
+
+ return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
+}
void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
- static const int subdiv_value[SUBDIV_MAX] = { 7, 8, 9, 10 };
+ static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 };
- VoxelLightBaker baker;
+ Voxelizer baker;
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
@@ -431,8 +467,6 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
//create the data for visual server
- PoolVector<int> data = baker.create_gi_probe_data();
-
if (p_create_visual_debug) {
MultiMeshInstance *mmi = memnew(MultiMeshInstance);
mmi->set_multimesh(baker.create_debug_multimesh());
@@ -454,24 +488,25 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
if (probe_data.is_null())
probe_data.instance();
- probe_data->set_bounds(AABB(-extents, extents * 2.0));
- probe_data->set_cell_size(baker.get_cell_size());
- probe_data->set_dynamic_data(data);
- probe_data->set_dynamic_range(dynamic_range);
- probe_data->set_energy(energy);
- probe_data->set_bias(bias);
- probe_data->set_normal_bias(normal_bias);
- probe_data->set_propagation(propagation);
- probe_data->set_interior(interior);
- probe_data->set_compress(compress);
- probe_data->set_to_cell_xform(baker.get_to_cell_space_xform());
+ if (bake_step_function) {
+ bake_step_function(pmc++, RTR("Generating Distance Field"));
+ }
+
+ Vector<uint8_t> df = baker.get_sdf_3d_image();
+
+ probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), df, baker.get_giprobe_level_cell_count());
set_probe_data(probe_data);
+#ifdef TOOLS_ENABLED
+ probe_data->set_edited(true); //so it gets saved
+#endif
}
if (bake_end_function) {
bake_end_function();
}
+
+ _change_notify(); //bake property may have changed
}
void GIProbe::_debug_bake() {
@@ -484,9 +519,9 @@ AABB GIProbe::get_aabb() const {
return AABB(-extents, extents * 2);
}
-PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
String GIProbe::get_configuration_warning() const {
@@ -508,40 +543,12 @@ void GIProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents);
- ClassDB::bind_method(D_METHOD("set_dynamic_range", "max"), &GIProbe::set_dynamic_range);
- ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbe::get_dynamic_range);
-
- ClassDB::bind_method(D_METHOD("set_energy", "max"), &GIProbe::set_energy);
- ClassDB::bind_method(D_METHOD("get_energy"), &GIProbe::get_energy);
-
- ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias);
- ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias);
-
- ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias);
- ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias);
-
- ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation);
- ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation);
-
- ClassDB::bind_method(D_METHOD("set_interior", "enable"), &GIProbe::set_interior);
- ClassDB::bind_method(D_METHOD("is_interior"), &GIProbe::is_interior);
-
- ClassDB::bind_method(D_METHOD("set_compress", "enable"), &GIProbe::set_compress);
- ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbe::is_compressed);
-
ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "1,16,1"), "set_dynamic_range", "get_dynamic_range");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);
@@ -554,14 +561,7 @@ void GIProbe::_bind_methods() {
GIProbe::GIProbe() {
subdiv = SUBDIV_128;
- dynamic_range = 4;
- energy = 1.0;
- bias = 1.5;
- normal_bias = 0.0;
- propagation = 0.7;
extents = Vector3(10, 10, 10);
- interior = false;
- compress = false;
gi_probe = VS::get_singleton()->gi_probe_create();
set_disable_scale(true);
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index 7c58f862e4..354eaad7c0 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -40,42 +40,67 @@ class GIProbeData : public Resource {
RID probe;
+ void _set_data(const Dictionary &p_data);
+ Dictionary _get_data() const;
+
+ Transform to_cell_xform;
+ AABB bounds;
+ Vector3 octree_size;
+
+ float dynamic_range;
+ float energy;
+ float bias;
+ float normal_bias;
+ float propagation;
+ float anisotropy_strength;
+ float ao;
+ float ao_size;
+ bool interior;
+ bool use_two_bounces;
+
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
public:
- void set_bounds(const AABB &p_bounds);
+ void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
AABB get_bounds() const;
+ Vector3 get_octree_size() const;
+ Vector<uint8_t> get_octree_cells() const;
+ Vector<uint8_t> get_data_cells() const;
+ Vector<uint8_t> get_distance_field() const;
+ Vector<int> get_level_counts() const;
+ Transform get_to_cell_xform() const;
- void set_cell_size(float p_size);
- float get_cell_size() const;
+ void set_dynamic_range(float p_range);
+ float get_dynamic_range() const;
- void set_to_cell_xform(const Transform &p_xform);
- Transform get_to_cell_xform() const;
+ void set_propagation(float p_propagation);
+ float get_propagation() const;
- void set_dynamic_data(const PoolVector<int> &p_data);
- PoolVector<int> get_dynamic_data() const;
+ void set_anisotropy_strength(float p_anisotropy_strength);
+ float get_anisotropy_strength() const;
- void set_dynamic_range(int p_range);
- int get_dynamic_range() const;
+ void set_ao(float p_ao);
+ float get_ao() const;
- void set_propagation(float p_range);
- float get_propagation() const;
+ void set_ao_size(float p_ao_size);
+ float get_ao_size() const;
- void set_energy(float p_range);
+ void set_energy(float p_energy);
float get_energy() const;
- void set_bias(float p_range);
+ void set_bias(float p_bias);
float get_bias() const;
- void set_normal_bias(float p_range);
+ void set_normal_bias(float p_normal_bias);
float get_normal_bias() const;
void set_interior(bool p_enable);
bool is_interior() const;
- void set_compress(bool p_enable);
- bool is_compressed() const;
+ void set_use_two_bounces(bool p_enable);
+ bool is_using_two_bounces() const;
virtual RID get_rid() const;
@@ -107,13 +132,6 @@ private:
Subdiv subdiv;
Vector3 extents;
- int dynamic_range;
- float energy;
- float bias;
- float normal_bias;
- float propagation;
- bool interior;
- bool compress;
struct PlotMesh {
Ref<Material> override_material;
@@ -141,32 +159,12 @@ public:
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
-
- void set_dynamic_range(int p_dynamic_range);
- int get_dynamic_range() const;
-
- void set_energy(float p_energy);
- float get_energy() const;
-
- void set_bias(float p_bias);
- float get_bias() const;
-
- void set_normal_bias(float p_normal_bias);
- float get_normal_bias() const;
-
- void set_propagation(float p_propagation);
- float get_propagation() const;
-
- void set_interior(bool p_enable);
- bool is_interior() const;
-
- void set_compress(bool p_enable);
- bool is_compressed() const;
+ Vector3i get_estimated_cell_size() const;
void bake(Node *p_from_node = NULL, bool p_create_visual_debug = false);
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
virtual String get_configuration_warning() const;
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
index 0a1beaf3f4..f5b08b86e1 100644
--- a/scene/3d/immediate_geometry.cpp
+++ b/scene/3d/immediate_geometry.cpp
@@ -30,7 +30,7 @@
#include "immediate_geometry.h"
-void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture> &p_texture) {
+void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) {
VS::get_singleton()->immediate_begin(im, (VS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID());
if (p_texture.is_valid())
@@ -90,9 +90,9 @@ AABB ImmediateGeometry::get_aabb() const {
return aabb;
}
-PoolVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) {
@@ -144,7 +144,7 @@ void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool
void ImmediateGeometry::_bind_methods() {
- ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry::begin, DEFVAL(Ref<Texture>()));
+ ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry::begin, DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry::set_normal);
ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry::set_tangent);
ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry::set_color);
diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h
index f45ebd6724..77a20e8d4d 100644
--- a/scene/3d/immediate_geometry.h
+++ b/scene/3d/immediate_geometry.h
@@ -41,7 +41,7 @@ class ImmediateGeometry : public GeometryInstance {
RID im;
//a list of textures drawn need to be kept, to avoid references
// in VisualServer from becoming invalid if the texture is no longer used
- List<Ref<Texture> > cached_textures;
+ List<Ref<Texture2D> > cached_textures;
bool empty;
AABB aabb;
@@ -49,7 +49,7 @@ protected:
static void _bind_methods();
public:
- void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture> &p_texture = Ref<Texture>());
+ void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture = Ref<Texture2D>());
void set_normal(const Vector3 &p_normal);
void set_tangent(const Plane &p_tangent);
void set_color(const Color &p_color);
@@ -64,7 +64,7 @@ public:
void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
ImmediateGeometry();
~ImmediateGeometry();
diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp
index baf5ac4be6..592d592a38 100644
--- a/scene/3d/interpolated_camera.cpp
+++ b/scene/3d/interpolated_camera.cpp
@@ -144,7 +144,7 @@ void InterpolatedCamera::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_interpolation_enabled"), &InterpolatedCamera::is_interpolation_enabled);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target"), "set_target_path", "get_target_path");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed"), "set_speed", "get_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed"), "set_speed", "get_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_interpolation_enabled", "is_interpolation_enabled");
}
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 593d0b95b7..7c922ce1cd 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -152,9 +152,9 @@ AABB Light::get_aabb() const {
return AABB();
}
-PoolVector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
void Light::set_bake_mode(BakeMode p_mode) {
@@ -253,17 +253,17 @@ void Light::_bind_methods() {
ADD_GROUP("Light", "light_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
ADD_GROUP("Editor", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
@@ -281,6 +281,7 @@ void Light::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
+ BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
@@ -325,8 +326,10 @@ Light::Light(VisualServer::LightType p_type) {
set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
+ set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
set_param(PARAM_SHADOW_BIAS, 0.15);
+ set_param(PARAM_SHADOW_FADE_START, 1);
set_disable_scale(true);
}
@@ -390,14 +393,15 @@ void DirectionalLight::_bind_methods() {
ADD_GROUP("Directional Shadow", "directional_shadow_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), "set_shadow_mode", "get_shadow_mode");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
@@ -413,6 +417,7 @@ DirectionalLight::DirectionalLight() :
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
set_param(PARAM_SHADOW_BIAS, 0.1);
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
+ set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
@@ -431,42 +436,24 @@ OmniLight::ShadowMode OmniLight::get_shadow_mode() const {
return shadow_mode;
}
-void OmniLight::set_shadow_detail(ShadowDetail p_detail) {
-
- shadow_detail = p_detail;
- VS::get_singleton()->light_omni_set_shadow_detail(light, VS::LightOmniShadowDetail(p_detail));
-}
-OmniLight::ShadowDetail OmniLight::get_shadow_detail() const {
-
- return shadow_detail;
-}
-
void OmniLight::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight::get_shadow_mode);
- ClassDB::bind_method(D_METHOD("set_shadow_detail", "detail"), &OmniLight::set_shadow_detail);
- ClassDB::bind_method(D_METHOD("get_shadow_detail"), &OmniLight::get_shadow_detail);
-
ADD_GROUP("Omni", "omni_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_detail", PROPERTY_HINT_ENUM, "Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail");
BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID);
BIND_ENUM_CONSTANT(SHADOW_CUBE);
-
- BIND_ENUM_CONSTANT(SHADOW_DETAIL_VERTICAL);
- BIND_ENUM_CONSTANT(SHADOW_DETAIL_HORIZONTAL);
}
OmniLight::OmniLight() :
Light(VisualServer::LIGHT_OMNI) {
set_shadow_mode(SHADOW_CUBE);
- set_shadow_detail(SHADOW_DETAIL_HORIZONTAL);
}
String SpotLight::get_configuration_warning() const {
@@ -486,8 +473,8 @@ String SpotLight::get_configuration_warning() const {
void SpotLight::_bind_methods() {
ADD_GROUP("Spot", "spot_");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 272ee8d7a9..16e0c47083 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -54,6 +54,7 @@ public:
PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
+ PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START,
PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
@@ -123,7 +124,7 @@ public:
BakeMode get_bake_mode() const;
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
Light();
~Light();
@@ -183,15 +184,8 @@ public:
SHADOW_CUBE,
};
- // omni light
- enum ShadowDetail {
- SHADOW_DETAIL_VERTICAL,
- SHADOW_DETAIL_HORIZONTAL
- };
-
private:
ShadowMode shadow_mode;
- ShadowDetail shadow_detail;
protected:
static void _bind_methods();
@@ -200,14 +194,10 @@ public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
- void set_shadow_detail(ShadowDetail p_detail);
- ShadowDetail get_shadow_detail() const;
-
OmniLight();
};
VARIANT_ENUM_CAST(OmniLight::ShadowMode)
-VARIANT_ENUM_CAST(OmniLight::ShadowDetail)
class SpotLight : public Light {
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index e14fa9e9af..4ca139ebbc 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -34,7 +34,6 @@
#include "core/core_string_names.h"
#include "physics_body.h"
#include "scene/resources/material.h"
-#include "scene/scene_string_names.h"
#include "skeleton.h"
bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) {
@@ -96,12 +95,12 @@ void MeshInstance::_get_property_list(List<PropertyInfo> *p_list) const {
ls.sort();
for (List<String>::Element *E = ls.front(); E; E = E->next()) {
- p_list->push_back(PropertyInfo(Variant::REAL, E->get(), PROPERTY_HINT_RANGE, "0,1,0.00001"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "0,1,0.00001"));
}
if (mesh.is_valid()) {
for (int i = 0; i < mesh->get_surface_count(); i++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
}
}
}
@@ -112,7 +111,7 @@ void MeshInstance::set_mesh(const Ref<Mesh> &p_mesh) {
return;
if (mesh.is_valid()) {
- mesh->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_mesh_changed);
+ mesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance::_mesh_changed));
materials.clear();
}
@@ -129,7 +128,7 @@ void MeshInstance::set_mesh(const Ref<Mesh> &p_mesh) {
blend_shape_tracks["blend_shapes/" + String(mesh->get_blend_shape_name(i))] = mt;
}
- mesh->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_mesh_changed);
+ mesh->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance::_mesh_changed));
materials.resize(mesh->get_surface_count());
set_base(mesh->get_rid());
@@ -204,13 +203,13 @@ AABB MeshInstance::get_aabb() const {
return AABB();
}
-PoolVector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const {
if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING)))
- return PoolVector<Face3>();
+ return Vector<Face3>();
if (mesh.is_null())
- return PoolVector<Face3>();
+ return Vector<Face3>();
return mesh->get_faces();
}
@@ -355,12 +354,12 @@ void MeshInstance::create_debug_tangents() {
if (lines.size()) {
- Ref<SpatialMaterial> sm;
+ Ref<StandardMaterial3D> sm;
sm.instance();
- sm->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
- sm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
- sm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ sm->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ sm->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ sm->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
Ref<ArrayMesh> am;
am.instance();
@@ -403,14 +402,15 @@ void MeshInstance::_bind_methods() {
ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance::create_convex_collision);
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents);
ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
+ ADD_GROUP("Skeleton", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
+ ADD_GROUP("", "");
}
MeshInstance::MeshInstance() {
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index fd5f60a5d7..d49d9ed98f 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -94,7 +94,7 @@ public:
void create_debug_tangents();
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
MeshInstance();
~MeshInstance();
diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp
index 245dbdaf58..075eb0a1ec 100644
--- a/scene/3d/multimesh_instance.cpp
+++ b/scene/3d/multimesh_instance.cpp
@@ -51,9 +51,9 @@ Ref<MultiMesh> MultiMeshInstance::get_multimesh() const {
return multimesh;
}
-PoolVector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
AABB MultiMeshInstance::get_aabb() const {
diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h
index 855bd54910..2b59c3b96c 100644
--- a/scene/3d/multimesh_instance.h
+++ b/scene/3d/multimesh_instance.h
@@ -44,7 +44,7 @@ protected:
// bind helpers
public:
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
index 4a82fe0080..8c543bc97f 100644
--- a/scene/3d/navigation.cpp
+++ b/scene/3d/navigation.cpp
@@ -30,669 +30,33 @@
#include "navigation.h"
-#define USE_ENTRY_POINT
+#include "servers/navigation_server.h"
-void Navigation::_navmesh_link(int p_id) {
+Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const {
- ERR_FAIL_COND(!navmesh_map.has(p_id));
- NavMesh &nm = navmesh_map[p_id];
- ERR_FAIL_COND(nm.linked);
- ERR_FAIL_COND(nm.navmesh.is_null());
-
- PoolVector<Vector3> vertices = nm.navmesh->get_vertices();
- int len = vertices.size();
- if (len == 0)
- return;
-
- PoolVector<Vector3>::Read r = vertices.read();
-
- for (int i = 0; i < nm.navmesh->get_polygon_count(); i++) {
-
- //build
-
- List<Polygon>::Element *P = nm.polygons.push_back(Polygon());
- Polygon &p = P->get();
- p.owner = &nm;
-
- Vector<int> poly = nm.navmesh->get_polygon(i);
- int plen = poly.size();
- const int *indices = poly.ptr();
- bool valid = true;
- p.edges.resize(plen);
-
- Vector3 center;
- float sum = 0;
-
- for (int j = 0; j < plen; j++) {
-
- int idx = indices[j];
- if (idx < 0 || idx >= len) {
- valid = false;
- break;
- }
-
- Polygon::Edge e;
- Vector3 ep = nm.xform.xform(r[idx]);
- center += ep;
- e.point = _get_point(ep);
- p.edges.write[j] = e;
-
- if (j >= 2) {
- Vector3 epa = nm.xform.xform(r[indices[j - 2]]);
- Vector3 epb = nm.xform.xform(r[indices[j - 1]]);
-
- sum += up.dot((epb - epa).cross(ep - epa));
- }
- }
-
- p.clockwise = sum > 0;
-
- if (!valid) {
- nm.polygons.pop_back();
- ERR_CONTINUE(!valid);
- }
-
- p.center = center;
- if (plen != 0) {
- p.center /= plen;
- }
-
- //connect
-
- for (int j = 0; j < plen; j++) {
-
- int next = (j + 1) % plen;
- EdgeKey ek(p.edges[j].point, p.edges[next].point);
-
- Map<EdgeKey, Connection>::Element *C = connections.find(ek);
- if (!C) {
-
- Connection c;
- c.A = &p;
- c.A_edge = j;
- c.B = NULL;
- c.B_edge = -1;
- connections[ek] = c;
- } else {
-
- if (C->get().B != NULL) {
- ConnectionPending pending;
- pending.polygon = &p;
- pending.edge = j;
- p.edges.write[j].P = C->get().pending.push_back(pending);
- continue;
- }
-
- C->get().B = &p;
- C->get().B_edge = j;
- C->get().A->edges.write[C->get().A_edge].C = &p;
- C->get().A->edges.write[C->get().A_edge].C_edge = j;
- p.edges.write[j].C = C->get().A;
- p.edges.write[j].C_edge = C->get().A_edge;
- //connection successful.
- }
- }
- }
-
- nm.linked = true;
+ return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
}
-void Navigation::_navmesh_unlink(int p_id) {
-
- ERR_FAIL_COND(!navmesh_map.has(p_id));
- NavMesh &nm = navmesh_map[p_id];
- ERR_FAIL_COND(!nm.linked);
-
- for (List<Polygon>::Element *E = nm.polygons.front(); E; E = E->next()) {
-
- Polygon &p = E->get();
-
- int ec = p.edges.size();
- Polygon::Edge *edges = p.edges.ptrw();
-
- for (int i = 0; i < ec; i++) {
- int next = (i + 1) % ec;
-
- EdgeKey ek(edges[i].point, edges[next].point);
- Map<EdgeKey, Connection>::Element *C = connections.find(ek);
-
- ERR_CONTINUE(!C);
-
- if (edges[i].P) {
- C->get().pending.erase(edges[i].P);
- edges[i].P = NULL;
- } else if (C->get().B) {
- //disconnect
-
- C->get().B->edges.write[C->get().B_edge].C = NULL;
- C->get().B->edges.write[C->get().B_edge].C_edge = -1;
- C->get().A->edges.write[C->get().A_edge].C = NULL;
- C->get().A->edges.write[C->get().A_edge].C_edge = -1;
-
- if (C->get().A == &E->get()) {
-
- C->get().A = C->get().B;
- C->get().A_edge = C->get().B_edge;
- }
- C->get().B = NULL;
- C->get().B_edge = -1;
-
- if (C->get().pending.size()) {
- //reconnect if something is pending
- ConnectionPending cp = C->get().pending.front()->get();
- C->get().pending.pop_front();
-
- C->get().B = cp.polygon;
- C->get().B_edge = cp.edge;
- C->get().A->edges.write[C->get().A_edge].C = cp.polygon;
- C->get().A->edges.write[C->get().A_edge].C_edge = cp.edge;
- cp.polygon->edges.write[cp.edge].C = C->get().A;
- cp.polygon->edges.write[cp.edge].C_edge = C->get().A_edge;
- cp.polygon->edges.write[cp.edge].P = NULL;
- }
-
- } else {
- connections.erase(C);
- //erase
- }
- }
- }
-
- nm.polygons.clear();
-
- nm.linked = false;
+Vector3 Navigation::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const {
+ return NavigationServer::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision);
}
-int Navigation::navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner) {
-
- int id = last_id++;
- NavMesh nm;
- nm.linked = false;
- nm.navmesh = p_mesh;
- nm.xform = p_xform;
- nm.owner = p_owner;
- navmesh_map[id] = nm;
-
- _navmesh_link(id);
-
- return id;
+Vector3 Navigation::get_closest_point(const Vector3 &p_point) const {
+ return NavigationServer::get_singleton()->map_get_closest_point(map, p_point);
}
-void Navigation::navmesh_set_transform(int p_id, const Transform &p_xform) {
-
- ERR_FAIL_COND(!navmesh_map.has(p_id));
- NavMesh &nm = navmesh_map[p_id];
- if (nm.xform == p_xform)
- return; //bleh
- _navmesh_unlink(p_id);
- nm.xform = p_xform;
- _navmesh_link(p_id);
+Vector3 Navigation::get_closest_point_normal(const Vector3 &p_point) const {
+ return NavigationServer::get_singleton()->map_get_closest_point_normal(map, p_point);
}
-void Navigation::navmesh_remove(int p_id) {
- ERR_FAIL_COND_MSG(!navmesh_map.has(p_id), "Trying to remove nonexisting navmesh with id: " + itos(p_id));
- _navmesh_unlink(p_id);
- navmesh_map.erase(p_id);
-}
-
-void Navigation::_clip_path(Vector<Vector3> &path, Polygon *from_poly, const Vector3 &p_to_point, Polygon *p_to_poly) {
-
- Vector3 from = path[path.size() - 1];
-
- if (from.distance_to(p_to_point) < CMP_EPSILON)
- return;
- Plane cut_plane;
- cut_plane.normal = (from - p_to_point).cross(up);
- if (cut_plane.normal == Vector3())
- return;
- cut_plane.normal.normalize();
- cut_plane.d = cut_plane.normal.dot(from);
-
- while (from_poly != p_to_poly) {
-
- int pe = from_poly->prev_edge;
- Vector3 a = _get_vertex(from_poly->edges[pe].point);
- Vector3 b = _get_vertex(from_poly->edges[(pe + 1) % from_poly->edges.size()].point);
-
- from_poly = from_poly->edges[pe].C;
- ERR_FAIL_COND(!from_poly);
-
- if (a.distance_to(b) > CMP_EPSILON) {
-
- Vector3 inters;
- if (cut_plane.intersects_segment(a, b, &inters)) {
- if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) {
- path.push_back(inters);
- }
- }
- }
- }
-}
-
-Vector<Vector3> Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) {
-
- Polygon *begin_poly = NULL;
- Polygon *end_poly = NULL;
- Vector3 begin_point;
- Vector3 end_point;
- float begin_d = 1e20;
- float end_d = 1e20;
-
- for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) {
-
- if (!E->get().linked)
- continue;
- for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) {
-
- Polygon &p = F->get();
- for (int i = 2; i < p.edges.size(); i++) {
-
- Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point));
- Vector3 spoint = f.get_closest_point_to(p_start);
- float dpoint = spoint.distance_to(p_start);
- if (dpoint < begin_d) {
- begin_d = dpoint;
- begin_poly = &p;
- begin_point = spoint;
- }
-
- spoint = f.get_closest_point_to(p_end);
- dpoint = spoint.distance_to(p_end);
- if (dpoint < end_d) {
- end_d = dpoint;
- end_poly = &p;
- end_point = spoint;
- }
- }
-
- p.prev_edge = -1;
- }
- }
-
- if (!begin_poly || !end_poly) {
-
- return Vector<Vector3>(); //no path
- }
-
- if (begin_poly == end_poly) {
-
- Vector<Vector3> path;
- path.resize(2);
- path.write[0] = begin_point;
- path.write[1] = end_point;
- return path;
- }
-
- bool found_route = false;
-
- List<Polygon *> open_list;
-
- for (int i = 0; i < begin_poly->edges.size(); i++) {
-
- if (begin_poly->edges[i].C) {
-
- begin_poly->edges[i].C->prev_edge = begin_poly->edges[i].C_edge;
-#ifdef USE_ENTRY_POINT
- Vector3 edge[2] = {
- _get_vertex(begin_poly->edges[i].point),
- _get_vertex(begin_poly->edges[(i + 1) % begin_poly->edges.size()].point)
- };
-
- Vector3 entry = Geometry::get_closest_point_to_segment(begin_poly->entry, edge);
- begin_poly->edges[i].C->distance = begin_point.distance_to(entry);
- begin_poly->edges[i].C->entry = entry;
-#else
- begin_poly->edges[i].C->distance = begin_poly->center.distance_to(begin_poly->edges[i].C->center);
-#endif
- open_list.push_back(begin_poly->edges[i].C);
- }
- }
-
- while (!found_route) {
-
- if (open_list.size() == 0) {
- break;
- }
- //check open list
-
- List<Polygon *>::Element *least_cost_poly = NULL;
- float least_cost = 1e30;
-
- //this could be faster (cache previous results)
- for (List<Polygon *>::Element *E = open_list.front(); E; E = E->next()) {
-
- Polygon *p = E->get();
-
- float cost = p->distance;
-#ifdef USE_ENTRY_POINT
- cost += p->entry.distance_to(end_point);
-#else
- cost += p->center.distance_to(end_point);
-#endif
- if (cost < least_cost) {
- least_cost_poly = E;
- least_cost = cost;
- }
- }
-
- Polygon *p = least_cost_poly->get();
- //open the neighbours for search
-
- if (p == end_poly) {
- //oh my reached end! stop algorithm
- found_route = true;
- break;
- }
-
- for (int i = 0; i < p->edges.size(); i++) {
-
- Polygon::Edge &e = p->edges.write[i];
-
- if (!e.C)
- continue;
-
-#ifdef USE_ENTRY_POINT
- Vector3 edge[2] = {
- _get_vertex(p->edges[i].point),
- _get_vertex(p->edges[(i + 1) % p->edges.size()].point)
- };
-
- Vector3 entry = Geometry::get_closest_point_to_segment(p->entry, edge);
- float distance = p->entry.distance_to(entry) + p->distance;
-#else
- float distance = p->center.distance_to(e.C->center) + p->distance;
-#endif
-
- if (e.C->prev_edge != -1) {
- //oh this was visited already, can we win the cost?
-
- if (e.C->distance > distance) {
-
- e.C->prev_edge = e.C_edge;
- e.C->distance = distance;
-#ifdef USE_ENTRY_POINT
- e.C->entry = entry;
-#endif
- }
- } else {
- //add to open neighbours
-
- e.C->prev_edge = e.C_edge;
- e.C->distance = distance;
-#ifdef USE_ENTRY_POINT
- e.C->entry = entry;
-#endif
- open_list.push_back(e.C);
- }
- }
-
- open_list.erase(least_cost_poly);
- }
-
- if (found_route) {
-
- Vector<Vector3> path;
-
- if (p_optimize) {
- //string pulling
-
- Polygon *apex_poly = end_poly;
- Vector3 apex_point = end_point;
- Vector3 portal_left = apex_point;
- Vector3 portal_right = apex_point;
- Polygon *left_poly = end_poly;
- Polygon *right_poly = end_poly;
- Polygon *p = end_poly;
- path.push_back(end_point);
-
- while (p) {
-
- Vector3 left;
- Vector3 right;
-
-#define CLOCK_TANGENT(m_a, m_b, m_c) (((m_a) - (m_c)).cross((m_a) - (m_b)))
-
- if (p == begin_poly) {
- left = begin_point;
- right = begin_point;
- } else {
- int prev = p->prev_edge;
- int prev_n = (p->prev_edge + 1) % p->edges.size();
- left = _get_vertex(p->edges[prev].point);
- right = _get_vertex(p->edges[prev_n].point);
-
- //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){
- if (p->clockwise) {
- SWAP(left, right);
- }
- }
-
- bool skip = false;
-
- if (CLOCK_TANGENT(apex_point, portal_left, left).dot(up) >= 0) {
- //process
- if (portal_left == apex_point || CLOCK_TANGENT(apex_point, left, portal_right).dot(up) > 0) {
- left_poly = p;
- portal_left = left;
- } else {
-
- _clip_path(path, apex_poly, portal_right, right_poly);
-
- apex_point = portal_right;
- p = right_poly;
- left_poly = p;
- apex_poly = p;
- portal_left = apex_point;
- portal_right = apex_point;
- path.push_back(apex_point);
- skip = true;
- }
- }
-
- if (!skip && CLOCK_TANGENT(apex_point, portal_right, right).dot(up) <= 0) {
- //process
- if (portal_right == apex_point || CLOCK_TANGENT(apex_point, right, portal_left).dot(up) < 0) {
- right_poly = p;
- portal_right = right;
- } else {
-
- _clip_path(path, apex_poly, portal_left, left_poly);
-
- apex_point = portal_left;
- p = left_poly;
- right_poly = p;
- apex_poly = p;
- portal_right = apex_point;
- portal_left = apex_point;
- path.push_back(apex_point);
- }
- }
-
- if (p != begin_poly)
- p = p->edges[p->prev_edge].C;
- else
- p = NULL;
- }
-
- if (path[path.size() - 1] != begin_point)
- path.push_back(begin_point);
-
- path.invert();
-
- } else {
- //midpoints
- Polygon *p = end_poly;
-
- path.push_back(end_point);
- while (true) {
- int prev = p->prev_edge;
-#ifdef USE_ENTRY_POINT
- Vector3 point = p->entry;
-#else
- int prev_n = (p->prev_edge + 1) % p->edges.size();
- Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point)) * 0.5;
-#endif
- path.push_back(point);
- p = p->edges[prev].C;
- if (p == begin_poly)
- break;
- }
-
- path.push_back(begin_point);
-
- path.invert();
- }
-
- return path;
- }
-
- return Vector<Vector3>();
-}
-
-Vector3 Navigation::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool &p_use_collision) {
-
- bool use_collision = p_use_collision;
- Vector3 closest_point;
- float closest_point_d = 1e20;
-
- for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) {
-
- if (!E->get().linked)
- continue;
- for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) {
-
- Polygon &p = F->get();
- for (int i = 2; i < p.edges.size(); i++) {
-
- Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point));
- Vector3 inters;
- if (f.intersects_segment(p_from, p_to, &inters)) {
-
- if (!use_collision) {
- closest_point = inters;
- use_collision = true;
- closest_point_d = p_from.distance_to(inters);
- } else if (closest_point_d > inters.distance_to(p_from)) {
-
- closest_point = inters;
- closest_point_d = p_from.distance_to(inters);
- }
- }
- }
-
- if (!use_collision) {
-
- for (int i = 0; i < p.edges.size(); i++) {
-
- Vector3 a, b;
-
- Geometry::get_closest_points_between_segments(p_from, p_to, _get_vertex(p.edges[i].point), _get_vertex(p.edges[(i + 1) % p.edges.size()].point), a, b);
-
- float d = a.distance_to(b);
- if (d < closest_point_d) {
-
- closest_point_d = d;
- closest_point = b;
- }
- }
- }
- }
- }
-
- return closest_point;
-}
-
-Vector3 Navigation::get_closest_point(const Vector3 &p_point) {
-
- Vector3 closest_point;
- float closest_point_d = 1e20;
-
- for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) {
-
- if (!E->get().linked)
- continue;
- for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) {
-
- Polygon &p = F->get();
- for (int i = 2; i < p.edges.size(); i++) {
-
- Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point));
- Vector3 inters = f.get_closest_point_to(p_point);
- float d = inters.distance_to(p_point);
- if (d < closest_point_d) {
- closest_point = inters;
- closest_point_d = d;
- }
- }
- }
- }
-
- return closest_point;
-}
-
-Vector3 Navigation::get_closest_point_normal(const Vector3 &p_point) {
-
- Vector3 closest_point;
- Vector3 closest_normal;
- float closest_point_d = 1e20;
-
- for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) {
-
- if (!E->get().linked)
- continue;
- for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) {
-
- Polygon &p = F->get();
- for (int i = 2; i < p.edges.size(); i++) {
-
- Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point));
- Vector3 inters = f.get_closest_point_to(p_point);
- float d = inters.distance_to(p_point);
- if (d < closest_point_d) {
- closest_point = inters;
- closest_point_d = d;
- closest_normal = f.get_plane().normal;
- }
- }
- }
- }
-
- return closest_normal;
-}
-
-Object *Navigation::get_closest_point_owner(const Vector3 &p_point) {
-
- Vector3 closest_point;
- Object *owner = NULL;
- float closest_point_d = 1e20;
-
- for (Map<int, NavMesh>::Element *E = navmesh_map.front(); E; E = E->next()) {
-
- if (!E->get().linked)
- continue;
- for (List<Polygon>::Element *F = E->get().polygons.front(); F; F = F->next()) {
-
- Polygon &p = F->get();
- for (int i = 2; i < p.edges.size(); i++) {
-
- Face3 f(_get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point));
- Vector3 inters = f.get_closest_point_to(p_point);
- float d = inters.distance_to(p_point);
- if (d < closest_point_d) {
- closest_point = inters;
- closest_point_d = d;
- owner = E->get().owner;
- }
- }
- }
- }
-
- return owner;
+RID Navigation::get_closest_point_owner(const Vector3 &p_point) const {
+ return NavigationServer::get_singleton()->map_get_closest_point_owner(map, p_point);
}
void Navigation::set_up_vector(const Vector3 &p_up) {
up = p_up;
+ NavigationServer::get_singleton()->map_set_up(map, up);
}
Vector3 Navigation::get_up_vector() const {
@@ -700,11 +64,19 @@ Vector3 Navigation::get_up_vector() const {
return up;
}
+void Navigation::set_cell_size(float p_cell_size) {
+ cell_size = p_cell_size;
+ NavigationServer::get_singleton()->map_set_cell_size(map, cell_size);
+}
+
+void Navigation::set_edge_connection_margin(float p_edge_connection_margin) {
+ edge_connection_margin = p_edge_connection_margin;
+ NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
+}
+
void Navigation::_bind_methods() {
- ClassDB::bind_method(D_METHOD("navmesh_add", "mesh", "xform", "owner"), &Navigation::navmesh_add, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("navmesh_set_transform", "id", "xform"), &Navigation::navmesh_set_transform);
- ClassDB::bind_method(D_METHOD("navmesh_remove", "id"), &Navigation::navmesh_remove);
+ ClassDB::bind_method(D_METHOD("get_rid"), &Navigation::get_rid);
ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation::get_simple_path, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation::get_closest_point_to_segment, DEFVAL(false));
@@ -715,13 +87,39 @@ void Navigation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation::set_up_vector);
ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation::get_up_vector);
+ ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation::set_cell_size);
+ ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation::get_cell_size);
+
+ ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation::set_edge_connection_margin);
+ ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation::get_edge_connection_margin);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
+}
+
+void Navigation::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ NavigationServer::get_singleton()->map_set_active(map, true);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+
+ NavigationServer::get_singleton()->map_set_active(map, false);
+ } break;
+ }
}
Navigation::Navigation() {
- ERR_FAIL_COND(sizeof(Point) != 8);
- cell_size = 0.01; //one centimeter
- last_id = 1;
+ map = NavigationServer::get_singleton()->map_create();
+
+ set_cell_size(0.3);
+ set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius
+
up = Vector3(0, 1, 0);
}
+
+Navigation::~Navigation() {
+ NavigationServer::get_singleton()->free(map);
+}
diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h
index 31dbc9d4b5..08f306611f 100644
--- a/scene/3d/navigation.h
+++ b/scene/3d/navigation.h
@@ -31,154 +31,49 @@
#ifndef NAVIGATION_H
#define NAVIGATION_H
-#include "scene/3d/navigation_mesh.h"
+#include "scene/3d/navigation_region.h"
#include "scene/3d/spatial.h"
class Navigation : public Spatial {
GDCLASS(Navigation, Spatial);
- union Point {
-
- struct {
- int64_t x : 21;
- int64_t y : 22;
- int64_t z : 21;
- };
-
- uint64_t key;
- bool operator<(const Point &p_key) const { return key < p_key.key; }
- };
-
- struct EdgeKey {
-
- Point a;
- Point b;
-
- bool operator<(const EdgeKey &p_key) const {
- return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key);
- };
-
- EdgeKey(const Point &p_a = Point(), const Point &p_b = Point()) :
- a(p_a),
- b(p_b) {
- if (a.key > b.key) {
- SWAP(a, b);
- }
- }
- };
-
- struct NavMesh;
- struct Polygon;
-
- struct ConnectionPending {
-
- Polygon *polygon;
- int edge;
- };
-
- struct Polygon {
-
- struct Edge {
- Point point;
- Polygon *C; //connection
- int C_edge;
- List<ConnectionPending>::Element *P;
- Edge() {
- C = NULL;
- C_edge = -1;
- P = NULL;
- }
- };
-
- Vector<Edge> edges;
-
- Vector3 center;
- Vector3 entry;
-
- float distance;
- int prev_edge;
- bool clockwise;
-
- NavMesh *owner;
- };
-
- struct Connection {
-
- Polygon *A;
- int A_edge;
- Polygon *B;
- int B_edge;
-
- List<ConnectionPending> pending;
-
- Connection() {
- A = NULL;
- B = NULL;
- A_edge = -1;
- B_edge = -1;
- }
- };
-
- Map<EdgeKey, Connection> connections;
-
- struct NavMesh {
-
- Object *owner;
- Transform xform;
- bool linked;
- Ref<NavigationMesh> navmesh;
- List<Polygon> polygons;
- };
-
- _FORCE_INLINE_ Point _get_point(const Vector3 &p_pos) const {
-
- int x = int(Math::floor(p_pos.x / cell_size));
- int y = int(Math::floor(p_pos.y / cell_size));
- int z = int(Math::floor(p_pos.z / cell_size));
-
- Point p;
- p.key = 0;
- p.x = x;
- p.y = y;
- p.z = z;
- return p;
- }
-
- _FORCE_INLINE_ Vector3 _get_vertex(const Point &p_point) const {
-
- return Vector3(p_point.x, p_point.y, p_point.z) * cell_size;
- }
-
- void _navmesh_link(int p_id);
- void _navmesh_unlink(int p_id);
-
- float cell_size;
- Map<int, NavMesh> navmesh_map;
- int last_id;
+ RID map;
Vector3 up;
- void _clip_path(Vector<Vector3> &path, Polygon *from_poly, const Vector3 &p_to_point, Polygon *p_to_poly);
+ real_t cell_size;
+ real_t edge_connection_margin;
protected:
static void _bind_methods();
+ void _notification(int p_what);
public:
+ RID get_rid() const {
+ return map;
+ }
+
void set_up_vector(const Vector3 &p_up);
Vector3 get_up_vector() const;
- //API should be as dynamic as possible
- int navmesh_add(const Ref<NavigationMesh> &p_mesh, const Transform &p_xform, Object *p_owner = NULL);
- void navmesh_set_transform(int p_id, const Transform &p_xform);
- void navmesh_remove(int p_id);
+ void set_cell_size(float p_cell_size);
+ float get_cell_size() const {
+ return cell_size;
+ }
+
+ void set_edge_connection_margin(float p_edge_connection_margin);
+ float get_edge_connection_margin() const {
+ return edge_connection_margin;
+ }
- Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true);
- Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool &p_use_collision = false);
- Vector3 get_closest_point(const Vector3 &p_point);
- Vector3 get_closest_point_normal(const Vector3 &p_point);
- Object *get_closest_point_owner(const Vector3 &p_point);
+ Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const;
+ Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const;
+ Vector3 get_closest_point(const Vector3 &p_point) const;
+ Vector3 get_closest_point_normal(const Vector3 &p_point) const;
+ RID get_closest_point_owner(const Vector3 &p_point) const;
Navigation();
+ ~Navigation();
};
#endif // NAVIGATION_H
diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp
new file mode 100644
index 0000000000..728fc947e9
--- /dev/null
+++ b/scene/3d/navigation_agent.cpp
@@ -0,0 +1,361 @@
+/*************************************************************************/
+/* navigation_agent.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_agent.h"
+
+#include "core/engine.h"
+#include "scene/3d/navigation.h"
+#include "servers/navigation_server.h"
+
+void NavigationAgent::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent::set_target_desired_distance);
+ ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent::get_target_desired_distance);
+
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent::get_radius);
+
+ ClassDB::bind_method(D_METHOD("set_agent_height_offset", "agent_height_offset"), &NavigationAgent::set_agent_height_offset);
+ ClassDB::bind_method(D_METHOD("get_agent_height_offset"), &NavigationAgent::get_agent_height_offset);
+
+ ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent::set_ignore_y);
+ ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent::get_ignore_y);
+
+ ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent::set_navigation_node);
+ ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent::get_navigation_node);
+
+ ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent::set_neighbor_dist);
+ ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent::get_neighbor_dist);
+
+ ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent::set_max_neighbors);
+ ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent::get_max_neighbors);
+
+ ClassDB::bind_method(D_METHOD("set_time_horizon", "time_horizon"), &NavigationAgent::set_time_horizon);
+ ClassDB::bind_method(D_METHOD("get_time_horizon"), &NavigationAgent::get_time_horizon);
+
+ ClassDB::bind_method(D_METHOD("set_max_speed", "max_speed"), &NavigationAgent::set_max_speed);
+ ClassDB::bind_method(D_METHOD("get_max_speed"), &NavigationAgent::get_max_speed);
+
+ ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent::set_path_max_distance);
+ ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent::get_path_max_distance);
+
+ ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent::set_target_location);
+ ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent::get_target_location);
+ ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent::get_next_location);
+ ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent::distance_to_target);
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent::get_nav_path);
+ ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent::get_nav_path_index);
+ ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent::is_target_reached);
+ ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent::is_target_reachable);
+ ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent::is_navigation_finished);
+ ClassDB::bind_method(D_METHOD("get_final_location"), &NavigationAgent::get_final_location);
+
+ ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent::_avoidance_done);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_target_desired_distance", "get_target_desired_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01"), "set_agent_height_offset", "get_agent_height_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_neighbor_dist", "get_neighbor_dist");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_time_horizon", "get_time_horizon");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_max_speed", "get_max_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1"), "set_path_max_distance", "get_path_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
+
+ ADD_SIGNAL(MethodInfo("path_changed"));
+ ADD_SIGNAL(MethodInfo("target_reached"));
+ ADD_SIGNAL(MethodInfo("navigation_finished"));
+ ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity")));
+}
+
+void NavigationAgent::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+
+ agent_parent = Object::cast_to<Spatial>(get_parent());
+
+ NavigationServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+
+ // Search the navigation node and set it
+ {
+ Navigation *nav = NULL;
+ Node *p = get_parent();
+ while (p != NULL) {
+ nav = Object::cast_to<Navigation>(p);
+ if (nav != NULL)
+ p = NULL;
+ else
+ p = p->get_parent();
+ }
+
+ set_navigation(nav);
+ }
+
+ set_physics_process_internal(true);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ agent_parent = NULL;
+ set_navigation(NULL);
+ set_physics_process_internal(false);
+ } break;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (agent_parent) {
+
+ NavigationServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin);
+ if (!target_reached) {
+ if (distance_to_target() < target_desired_distance) {
+ emit_signal("target_reached");
+ target_reached = true;
+ }
+ }
+ }
+ } break;
+ }
+}
+
+NavigationAgent::NavigationAgent() :
+ agent_parent(NULL),
+ navigation(NULL),
+ agent(RID()),
+ target_desired_distance(1.0),
+ navigation_height_offset(0.0),
+ path_max_distance(3.0),
+ velocity_submitted(false),
+ target_reached(false),
+ navigation_finished(true) {
+ agent = NavigationServer::get_singleton()->agent_create();
+ set_neighbor_dist(50.0);
+ set_max_neighbors(10);
+ set_time_horizon(5.0);
+ set_radius(1.0);
+ set_max_speed(10.0);
+ set_ignore_y(true);
+}
+
+NavigationAgent::~NavigationAgent() {
+ NavigationServer::get_singleton()->free(agent);
+ agent = RID(); // Pointless
+}
+
+void NavigationAgent::set_navigation(Navigation *p_nav) {
+ if (navigation == p_nav)
+ return; // Pointless
+
+ navigation = p_nav;
+ NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid());
+}
+
+void NavigationAgent::set_navigation_node(Node *p_nav) {
+ Navigation *nav = Object::cast_to<Navigation>(p_nav);
+ ERR_FAIL_COND(nav == NULL);
+ set_navigation(nav);
+}
+
+Node *NavigationAgent::get_navigation_node() const {
+ return Object::cast_to<Node>(navigation);
+}
+
+void NavigationAgent::set_target_desired_distance(real_t p_dd) {
+ target_desired_distance = p_dd;
+}
+
+void NavigationAgent::set_radius(real_t p_radius) {
+ radius = p_radius;
+ NavigationServer::get_singleton()->agent_set_radius(agent, radius);
+}
+
+void NavigationAgent::set_agent_height_offset(real_t p_hh) {
+ navigation_height_offset = p_hh;
+}
+
+void NavigationAgent::set_ignore_y(bool p_ignore_y) {
+ ignore_y = p_ignore_y;
+ NavigationServer::get_singleton()->agent_set_ignore_y(agent, ignore_y);
+}
+
+void NavigationAgent::set_neighbor_dist(real_t p_dist) {
+ neighbor_dist = p_dist;
+ NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist);
+}
+
+void NavigationAgent::set_max_neighbors(int p_count) {
+ max_neighbors = p_count;
+ NavigationServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors);
+}
+
+void NavigationAgent::set_time_horizon(real_t p_time) {
+ time_horizon = p_time;
+ NavigationServer::get_singleton()->agent_set_time_horizon(agent, time_horizon);
+}
+
+void NavigationAgent::set_max_speed(real_t p_max_speed) {
+ max_speed = p_max_speed;
+ NavigationServer::get_singleton()->agent_set_max_speed(agent, max_speed);
+}
+
+void NavigationAgent::set_path_max_distance(real_t p_pmd) {
+ path_max_distance = p_pmd;
+}
+
+real_t NavigationAgent::get_path_max_distance() {
+ return path_max_distance;
+}
+
+void NavigationAgent::set_target_location(Vector3 p_location) {
+ target_location = p_location;
+ navigation_path.clear();
+ target_reached = false;
+ navigation_finished = false;
+}
+
+Vector3 NavigationAgent::get_target_location() const {
+ return target_location;
+}
+
+Vector3 NavigationAgent::get_next_location() {
+ update_navigation();
+ if (navigation_path.size() == 0) {
+ ERR_FAIL_COND_V(agent_parent == NULL, Vector3());
+ return agent_parent->get_global_transform().origin;
+ } else {
+ return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0);
+ }
+}
+
+real_t NavigationAgent::distance_to_target() const {
+ ERR_FAIL_COND_V(agent_parent == NULL, 0.0);
+ return agent_parent->get_global_transform().origin.distance_to(target_location);
+}
+
+bool NavigationAgent::is_target_reached() const {
+ return target_reached;
+}
+
+bool NavigationAgent::is_target_reachable() {
+ return target_desired_distance >= get_final_location().distance_to(target_location);
+}
+
+bool NavigationAgent::is_navigation_finished() {
+ update_navigation();
+ return navigation_finished;
+}
+
+Vector3 NavigationAgent::get_final_location() {
+ update_navigation();
+ if (navigation_path.size() == 0) {
+ return Vector3();
+ }
+ return navigation_path[navigation_path.size() - 1];
+}
+
+void NavigationAgent::set_velocity(Vector3 p_velocity) {
+ target_velocity = p_velocity;
+ NavigationServer::get_singleton()->agent_set_target_velocity(agent, target_velocity);
+ NavigationServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity);
+ velocity_submitted = true;
+}
+
+void NavigationAgent::_avoidance_done(Vector3 p_new_velocity) {
+ prev_safe_velocity = p_new_velocity;
+
+ if (!velocity_submitted) {
+ target_velocity = Vector3();
+ return;
+ }
+ velocity_submitted = false;
+
+ emit_signal("velocity_computed", p_new_velocity);
+}
+
+String NavigationAgent::get_configuration_warning() const {
+ if (!Object::cast_to<Spatial>(get_parent())) {
+ return TTR("The NavigationAgent can be used only under a spatial node.");
+ }
+
+ return String();
+}
+
+void NavigationAgent::update_navigation() {
+
+ if (agent_parent == NULL) return;
+ if (navigation == NULL) return;
+ if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return;
+
+ update_frame_id = Engine::get_singleton()->get_physics_frames();
+
+ Vector3 o = agent_parent->get_global_transform().origin;
+
+ bool reload_path = false;
+
+ if (NavigationServer::get_singleton()->agent_is_map_changed(agent)) {
+ reload_path = true;
+ } else if (navigation_path.size() == 0) {
+ reload_path = true;
+ } else {
+ // Check if too far from the navigation path
+ if (nav_path_index > 0) {
+ Vector3 segment[2];
+ segment[0] = navigation_path[nav_path_index - 1];
+ segment[1] = navigation_path[nav_path_index];
+ segment[0].y -= navigation_height_offset;
+ segment[1].y -= navigation_height_offset;
+ Vector3 p = Geometry::get_closest_point_to_segment(o, segment);
+ if (o.distance_to(p) >= path_max_distance) {
+ // To faraway, reload path
+ reload_path = true;
+ }
+ }
+ }
+
+ if (reload_path) {
+ navigation_path = NavigationServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true);
+ navigation_finished = false;
+ nav_path_index = 0;
+ emit_signal("path_changed");
+ }
+
+ if (navigation_path.size() == 0)
+ return;
+
+ // Check if we can advance the navigation path
+ if (navigation_finished == false) {
+ // Advances to the next far away location.
+ while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < target_desired_distance) {
+ nav_path_index += 1;
+ if (nav_path_index == navigation_path.size()) {
+ nav_path_index -= 1;
+ navigation_finished = true;
+ emit_signal("navigation_finished");
+ break;
+ }
+ }
+ }
+}
diff --git a/scene/3d/navigation_agent.h b/scene/3d/navigation_agent.h
new file mode 100644
index 0000000000..200d5db475
--- /dev/null
+++ b/scene/3d/navigation_agent.h
@@ -0,0 +1,162 @@
+/*************************************************************************/
+/* navigation_agent.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_AGENT_H
+#define NAVIGATION_AGENT_H
+
+#include "core/vector.h"
+#include "scene/main/node.h"
+
+class Spatial;
+class Navigation;
+
+class NavigationAgent : public Node {
+ GDCLASS(NavigationAgent, Node);
+
+ Spatial *agent_parent;
+ Navigation *navigation;
+
+ RID agent;
+
+ real_t target_desired_distance;
+ real_t radius;
+ real_t navigation_height_offset;
+ bool ignore_y;
+ real_t neighbor_dist;
+ int max_neighbors;
+ real_t time_horizon;
+ real_t max_speed;
+
+ real_t path_max_distance;
+
+ Vector3 target_location;
+ Vector<Vector3> navigation_path;
+ int nav_path_index;
+ bool velocity_submitted;
+ Vector3 prev_safe_velocity;
+ /// The submitted target velocity
+ Vector3 target_velocity;
+ bool target_reached;
+ bool navigation_finished;
+ // No initialized on purpose
+ uint32_t update_frame_id;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ NavigationAgent();
+ virtual ~NavigationAgent();
+
+ void set_navigation(Navigation *p_nav);
+ const Navigation *get_navigation() const {
+ return navigation;
+ }
+
+ void set_navigation_node(Node *p_nav);
+ Node *get_navigation_node() const;
+
+ RID get_rid() const {
+ return agent;
+ }
+
+ void set_target_desired_distance(real_t p_dd);
+ real_t get_target_desired_distance() const {
+ return target_desired_distance;
+ }
+
+ void set_radius(real_t p_radius);
+ real_t get_radius() const {
+ return radius;
+ }
+
+ void set_agent_height_offset(real_t p_hh);
+ real_t get_agent_height_offset() const {
+ return navigation_height_offset;
+ }
+
+ void set_ignore_y(bool p_ignore_y);
+ bool get_ignore_y() const {
+ return ignore_y;
+ }
+
+ void set_neighbor_dist(real_t p_dist);
+ real_t get_neighbor_dist() const {
+ return neighbor_dist;
+ }
+
+ void set_max_neighbors(int p_count);
+ int get_max_neighbors() const {
+ return max_neighbors;
+ }
+
+ void set_time_horizon(real_t p_time);
+ real_t get_time_horizon() const {
+ return time_horizon;
+ }
+
+ void set_max_speed(real_t p_max_speed);
+ real_t get_max_speed() const {
+ return max_speed;
+ }
+
+ void set_path_max_distance(real_t p_pmd);
+ real_t get_path_max_distance();
+
+ void set_target_location(Vector3 p_location);
+ Vector3 get_target_location() const;
+
+ Vector3 get_next_location();
+
+ Vector<Vector3> get_nav_path() const {
+ return navigation_path;
+ }
+
+ int get_nav_path_index() const {
+ return nav_path_index;
+ }
+
+ real_t distance_to_target() const;
+ bool is_target_reached() const;
+ bool is_target_reachable();
+ bool is_navigation_finished();
+ Vector3 get_final_location();
+
+ void set_velocity(Vector3 p_velocity);
+ void _avoidance_done(Vector3 p_new_velocity);
+
+ virtual String get_configuration_warning() const;
+
+private:
+ void update_navigation();
+};
+
+#endif
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
deleted file mode 100644
index aaba91125e..0000000000
--- a/scene/3d/navigation_mesh.cpp
+++ /dev/null
@@ -1,744 +0,0 @@
-/*************************************************************************/
-/* navigation_mesh.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "navigation_mesh.h"
-#include "mesh_instance.h"
-#include "navigation.h"
-
-void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) {
-
- vertices = PoolVector<Vector3>();
- clear_polygons();
-
- for (int i = 0; i < p_mesh->get_surface_count(); i++) {
-
- if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
- continue;
- Array arr = p_mesh->surface_get_arrays(i);
- PoolVector<Vector3> varr = arr[Mesh::ARRAY_VERTEX];
- PoolVector<int> iarr = arr[Mesh::ARRAY_INDEX];
- if (varr.size() == 0 || iarr.size() == 0)
- continue;
-
- int from = vertices.size();
- vertices.append_array(varr);
- int rlen = iarr.size();
- PoolVector<int>::Read r = iarr.read();
-
- for (int j = 0; j < rlen; j += 3) {
- Vector<int> vi;
- vi.resize(3);
- vi.write[0] = r[j + 0] + from;
- vi.write[1] = r[j + 1] + from;
- vi.write[2] = r[j + 2] + from;
-
- add_polygon(vi);
- }
- }
-}
-
-void NavigationMesh::set_sample_partition_type(int p_value) {
- ERR_FAIL_COND(p_value >= SAMPLE_PARTITION_MAX);
- partition_type = static_cast<SamplePartitionType>(p_value);
-}
-
-int NavigationMesh::get_sample_partition_type() const {
- return static_cast<int>(partition_type);
-}
-
-void NavigationMesh::set_parsed_geometry_type(int p_value) {
- ERR_FAIL_COND(p_value >= PARSED_GEOMETRY_MAX);
- parsed_geometry_type = static_cast<ParsedGeometryType>(p_value);
- _change_notify();
-}
-
-int NavigationMesh::get_parsed_geometry_type() const {
- return parsed_geometry_type;
-}
-
-void NavigationMesh::set_collision_mask(uint32_t p_mask) {
-
- collision_mask = p_mask;
-}
-
-uint32_t NavigationMesh::get_collision_mask() const {
-
- return collision_mask;
-}
-
-void NavigationMesh::set_collision_mask_bit(int p_bit, bool p_value) {
-
- uint32_t mask = get_collision_mask();
- if (p_value)
- mask |= 1 << p_bit;
- else
- mask &= ~(1 << p_bit);
- set_collision_mask(mask);
-}
-
-bool NavigationMesh::get_collision_mask_bit(int p_bit) const {
-
- return get_collision_mask() & (1 << p_bit);
-}
-
-void NavigationMesh::set_source_geometry_mode(int p_geometry_mode) {
- ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX);
- source_geometry_mode = static_cast<SourceGeometryMode>(p_geometry_mode);
- _change_notify();
-}
-
-int NavigationMesh::get_source_geometry_mode() const {
- return source_geometry_mode;
-}
-
-void NavigationMesh::set_source_group_name(StringName p_group_name) {
- source_group_name = p_group_name;
-}
-
-StringName NavigationMesh::get_source_group_name() const {
- return source_group_name;
-}
-
-void NavigationMesh::set_cell_size(float p_value) {
- cell_size = p_value;
-}
-
-float NavigationMesh::get_cell_size() const {
- return cell_size;
-}
-
-void NavigationMesh::set_cell_height(float p_value) {
- cell_height = p_value;
-}
-
-float NavigationMesh::get_cell_height() const {
- return cell_height;
-}
-
-void NavigationMesh::set_agent_height(float p_value) {
- agent_height = p_value;
-}
-
-float NavigationMesh::get_agent_height() const {
- return agent_height;
-}
-
-void NavigationMesh::set_agent_radius(float p_value) {
- agent_radius = p_value;
-}
-
-float NavigationMesh::get_agent_radius() {
- return agent_radius;
-}
-
-void NavigationMesh::set_agent_max_climb(float p_value) {
- agent_max_climb = p_value;
-}
-
-float NavigationMesh::get_agent_max_climb() const {
- return agent_max_climb;
-}
-
-void NavigationMesh::set_agent_max_slope(float p_value) {
- agent_max_slope = p_value;
-}
-
-float NavigationMesh::get_agent_max_slope() const {
- return agent_max_slope;
-}
-
-void NavigationMesh::set_region_min_size(float p_value) {
- region_min_size = p_value;
-}
-
-float NavigationMesh::get_region_min_size() const {
- return region_min_size;
-}
-
-void NavigationMesh::set_region_merge_size(float p_value) {
- region_merge_size = p_value;
-}
-
-float NavigationMesh::get_region_merge_size() const {
- return region_merge_size;
-}
-
-void NavigationMesh::set_edge_max_length(float p_value) {
- edge_max_length = p_value;
-}
-
-float NavigationMesh::get_edge_max_length() const {
- return edge_max_length;
-}
-
-void NavigationMesh::set_edge_max_error(float p_value) {
- edge_max_error = p_value;
-}
-
-float NavigationMesh::get_edge_max_error() const {
- return edge_max_error;
-}
-
-void NavigationMesh::set_verts_per_poly(float p_value) {
- verts_per_poly = p_value;
-}
-
-float NavigationMesh::get_verts_per_poly() const {
- return verts_per_poly;
-}
-
-void NavigationMesh::set_detail_sample_distance(float p_value) {
- detail_sample_distance = p_value;
-}
-
-float NavigationMesh::get_detail_sample_distance() const {
- return detail_sample_distance;
-}
-
-void NavigationMesh::set_detail_sample_max_error(float p_value) {
- detail_sample_max_error = p_value;
-}
-
-float NavigationMesh::get_detail_sample_max_error() const {
- return detail_sample_max_error;
-}
-
-void NavigationMesh::set_filter_low_hanging_obstacles(bool p_value) {
- filter_low_hanging_obstacles = p_value;
-}
-
-bool NavigationMesh::get_filter_low_hanging_obstacles() const {
- return filter_low_hanging_obstacles;
-}
-
-void NavigationMesh::set_filter_ledge_spans(bool p_value) {
- filter_ledge_spans = p_value;
-}
-
-bool NavigationMesh::get_filter_ledge_spans() const {
- return filter_ledge_spans;
-}
-
-void NavigationMesh::set_filter_walkable_low_height_spans(bool p_value) {
- filter_walkable_low_height_spans = p_value;
-}
-
-bool NavigationMesh::get_filter_walkable_low_height_spans() const {
- return filter_walkable_low_height_spans;
-}
-
-void NavigationMesh::set_vertices(const PoolVector<Vector3> &p_vertices) {
-
- vertices = p_vertices;
- _change_notify();
-}
-
-PoolVector<Vector3> NavigationMesh::get_vertices() const {
-
- return vertices;
-}
-
-void NavigationMesh::_set_polygons(const Array &p_array) {
-
- polygons.resize(p_array.size());
- for (int i = 0; i < p_array.size(); i++) {
- polygons.write[i].indices = p_array[i];
- }
- _change_notify();
-}
-
-Array NavigationMesh::_get_polygons() const {
-
- Array ret;
- ret.resize(polygons.size());
- for (int i = 0; i < ret.size(); i++) {
- ret[i] = polygons[i].indices;
- }
-
- return ret;
-}
-
-void NavigationMesh::add_polygon(const Vector<int> &p_polygon) {
-
- Polygon polygon;
- polygon.indices = p_polygon;
- polygons.push_back(polygon);
- _change_notify();
-}
-int NavigationMesh::get_polygon_count() const {
-
- return polygons.size();
-}
-Vector<int> NavigationMesh::get_polygon(int p_idx) {
-
- ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
- return polygons[p_idx].indices;
-}
-void NavigationMesh::clear_polygons() {
-
- polygons.clear();
-}
-
-Ref<Mesh> NavigationMesh::get_debug_mesh() {
-
- if (debug_mesh.is_valid())
- return debug_mesh;
-
- PoolVector<Vector3> vertices = get_vertices();
- PoolVector<Vector3>::Read vr = vertices.read();
- List<Face3> faces;
- for (int i = 0; i < get_polygon_count(); i++) {
- Vector<int> p = get_polygon(i);
-
- for (int j = 2; j < p.size(); j++) {
- Face3 f;
- f.vertex[0] = vr[p[0]];
- f.vertex[1] = vr[p[j - 1]];
- f.vertex[2] = vr[p[j]];
-
- faces.push_back(f);
- }
- }
-
- Map<_EdgeKey, bool> edge_map;
- PoolVector<Vector3> tmeshfaces;
- tmeshfaces.resize(faces.size() * 3);
-
- {
- PoolVector<Vector3>::Write tw = tmeshfaces.write();
- int tidx = 0;
-
- for (List<Face3>::Element *E = faces.front(); E; E = E->next()) {
-
- const Face3 &f = E->get();
-
- for (int j = 0; j < 3; j++) {
-
- tw[tidx++] = f.vertex[j];
- _EdgeKey ek;
- ek.from = f.vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON));
- ek.to = f.vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON));
- if (ek.from < ek.to)
- SWAP(ek.from, ek.to);
-
- Map<_EdgeKey, bool>::Element *F = edge_map.find(ek);
-
- if (F) {
-
- F->get() = false;
-
- } else {
-
- edge_map[ek] = true;
- }
- }
- }
- }
- List<Vector3> lines;
-
- for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) {
-
- if (E->get()) {
- lines.push_back(E->key().from);
- lines.push_back(E->key().to);
- }
- }
-
- PoolVector<Vector3> varr;
- varr.resize(lines.size());
- {
- PoolVector<Vector3>::Write w = varr.write();
- int idx = 0;
- for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) {
- w[idx++] = E->get();
- }
- }
-
- debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
-
- Array arr;
- arr.resize(Mesh::ARRAY_MAX);
- arr[Mesh::ARRAY_VERTEX] = varr;
-
- debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr);
-
- return debug_mesh;
-}
-
-void NavigationMesh::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type);
- ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationMesh::get_sample_partition_type);
-
- ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationMesh::set_parsed_geometry_type);
- ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationMesh::get_parsed_geometry_type);
-
- ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &NavigationMesh::set_collision_mask);
- ClassDB::bind_method(D_METHOD("get_collision_mask"), &NavigationMesh::get_collision_mask);
-
- ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &NavigationMesh::set_collision_mask_bit);
- ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &NavigationMesh::get_collision_mask_bit);
-
- ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "mask"), &NavigationMesh::set_source_geometry_mode);
- ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationMesh::get_source_geometry_mode);
-
- ClassDB::bind_method(D_METHOD("set_source_group_name", "mask"), &NavigationMesh::set_source_group_name);
- ClassDB::bind_method(D_METHOD("get_source_group_name"), &NavigationMesh::get_source_group_name);
-
- ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationMesh::set_cell_size);
- ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationMesh::get_cell_size);
-
- ClassDB::bind_method(D_METHOD("set_cell_height", "cell_height"), &NavigationMesh::set_cell_height);
- ClassDB::bind_method(D_METHOD("get_cell_height"), &NavigationMesh::get_cell_height);
-
- ClassDB::bind_method(D_METHOD("set_agent_height", "agent_height"), &NavigationMesh::set_agent_height);
- ClassDB::bind_method(D_METHOD("get_agent_height"), &NavigationMesh::get_agent_height);
-
- ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationMesh::set_agent_radius);
- ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationMesh::get_agent_radius);
-
- ClassDB::bind_method(D_METHOD("set_agent_max_climb", "agent_max_climb"), &NavigationMesh::set_agent_max_climb);
- ClassDB::bind_method(D_METHOD("get_agent_max_climb"), &NavigationMesh::get_agent_max_climb);
-
- ClassDB::bind_method(D_METHOD("set_agent_max_slope", "agent_max_slope"), &NavigationMesh::set_agent_max_slope);
- ClassDB::bind_method(D_METHOD("get_agent_max_slope"), &NavigationMesh::get_agent_max_slope);
-
- ClassDB::bind_method(D_METHOD("set_region_min_size", "region_min_size"), &NavigationMesh::set_region_min_size);
- ClassDB::bind_method(D_METHOD("get_region_min_size"), &NavigationMesh::get_region_min_size);
-
- ClassDB::bind_method(D_METHOD("set_region_merge_size", "region_merge_size"), &NavigationMesh::set_region_merge_size);
- ClassDB::bind_method(D_METHOD("get_region_merge_size"), &NavigationMesh::get_region_merge_size);
-
- ClassDB::bind_method(D_METHOD("set_edge_max_length", "edge_max_length"), &NavigationMesh::set_edge_max_length);
- ClassDB::bind_method(D_METHOD("get_edge_max_length"), &NavigationMesh::get_edge_max_length);
-
- ClassDB::bind_method(D_METHOD("set_edge_max_error", "edge_max_error"), &NavigationMesh::set_edge_max_error);
- ClassDB::bind_method(D_METHOD("get_edge_max_error"), &NavigationMesh::get_edge_max_error);
-
- ClassDB::bind_method(D_METHOD("set_verts_per_poly", "verts_per_poly"), &NavigationMesh::set_verts_per_poly);
- ClassDB::bind_method(D_METHOD("get_verts_per_poly"), &NavigationMesh::get_verts_per_poly);
-
- ClassDB::bind_method(D_METHOD("set_detail_sample_distance", "detail_sample_dist"), &NavigationMesh::set_detail_sample_distance);
- ClassDB::bind_method(D_METHOD("get_detail_sample_distance"), &NavigationMesh::get_detail_sample_distance);
-
- ClassDB::bind_method(D_METHOD("set_detail_sample_max_error", "detail_sample_max_error"), &NavigationMesh::set_detail_sample_max_error);
- ClassDB::bind_method(D_METHOD("get_detail_sample_max_error"), &NavigationMesh::get_detail_sample_max_error);
-
- ClassDB::bind_method(D_METHOD("set_filter_low_hanging_obstacles", "filter_low_hanging_obstacles"), &NavigationMesh::set_filter_low_hanging_obstacles);
- ClassDB::bind_method(D_METHOD("get_filter_low_hanging_obstacles"), &NavigationMesh::get_filter_low_hanging_obstacles);
-
- ClassDB::bind_method(D_METHOD("set_filter_ledge_spans", "filter_ledge_spans"), &NavigationMesh::set_filter_ledge_spans);
- ClassDB::bind_method(D_METHOD("get_filter_ledge_spans"), &NavigationMesh::get_filter_ledge_spans);
-
- ClassDB::bind_method(D_METHOD("set_filter_walkable_low_height_spans", "filter_walkable_low_height_spans"), &NavigationMesh::set_filter_walkable_low_height_spans);
- ClassDB::bind_method(D_METHOD("get_filter_walkable_low_height_spans"), &NavigationMesh::get_filter_walkable_low_height_spans);
-
- ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationMesh::set_vertices);
- ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationMesh::get_vertices);
-
- ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationMesh::add_polygon);
- ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationMesh::get_polygon_count);
- ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationMesh::get_polygon);
- ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationMesh::clear_polygons);
-
- ClassDB::bind_method(D_METHOD("create_from_mesh", "mesh"), &NavigationMesh::create_from_mesh);
-
- ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationMesh::_set_polygons);
- ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationMesh::_get_polygons);
-
- BIND_CONSTANT(SAMPLE_PARTITION_WATERSHED);
- BIND_CONSTANT(SAMPLE_PARTITION_MONOTONE);
- BIND_CONSTANT(SAMPLE_PARTITION_LAYERS);
-
- BIND_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);
- BIND_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);
- BIND_CONSTANT(PARSED_GEOMETRY_BOTH);
-
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type/sample_partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_sample_partition_type", "get_sample_partition_type");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/source_geometry_mode", PROPERTY_HINT_ENUM, "Navmesh Children, Group With Children, Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry/source_group_name"), "set_source_group_name", "get_source_group_name");
-
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/size", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_size", "get_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell/height", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_height", "get_cell_height");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "agent/height", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_height", "get_agent_height");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "agent/radius", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_radius", "get_agent_radius");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "agent/max_climb", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_max_climb", "get_agent_max_climb");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "agent/max_slope", PROPERTY_HINT_RANGE, "0.0,90.0,0.1"), "set_agent_max_slope", "get_agent_max_slope");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "region/min_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_min_size", "get_region_min_size");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "region/merge_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_merge_size", "get_region_merge_size");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge/max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater"), "set_edge_max_length", "get_edge_max_length");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge/max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater"), "set_edge_max_error", "get_edge_max_error");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "polygon/verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "detail/sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_max_error", "get_detail_sample_max_error");
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/low_hanging_obstacles"), "set_filter_low_hanging_obstacles", "get_filter_low_hanging_obstacles");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/ledge_spans"), "set_filter_ledge_spans", "get_filter_ledge_spans");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/filter_walkable_low_height_spans"), "set_filter_walkable_low_height_spans", "get_filter_walkable_low_height_spans");
-}
-
-void NavigationMesh::_validate_property(PropertyInfo &property) const {
- if (property.name == "geometry/collision_mask") {
- if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) {
- property.usage = 0;
- return;
- }
- }
-
- if (property.name == "geometry/source_group_name") {
- if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
- property.usage = 0;
- return;
- }
- }
-}
-
-NavigationMesh::NavigationMesh() {
- cell_size = 0.3f;
- cell_height = 0.2f;
- agent_height = 2.0f;
- agent_radius = 0.6f;
- agent_max_climb = 0.9f;
- agent_max_slope = 45.0f;
- region_min_size = 8.0f;
- region_merge_size = 20.0f;
- edge_max_length = 12.0f;
- edge_max_error = 1.3f;
- verts_per_poly = 6.0f;
- detail_sample_distance = 6.0f;
- detail_sample_max_error = 1.0f;
-
- partition_type = SAMPLE_PARTITION_WATERSHED;
- parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
- collision_mask = 0xFFFFFFFF;
- source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN;
- source_group_name = "navmesh";
- filter_low_hanging_obstacles = false;
- filter_ledge_spans = false;
- filter_walkable_low_height_spans = false;
-}
-
-void NavigationMeshInstance::set_enabled(bool p_enabled) {
-
- if (enabled == p_enabled)
- return;
- enabled = p_enabled;
-
- if (!is_inside_tree())
- return;
-
- if (!enabled) {
-
- if (nav_id != -1) {
- navigation->navmesh_remove(nav_id);
- nav_id = -1;
- }
- } else {
-
- if (navigation) {
-
- if (navmesh.is_valid()) {
-
- nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this);
- }
- }
- }
-
- if (debug_view) {
- MeshInstance *dm = Object::cast_to<MeshInstance>(debug_view);
- if (is_enabled()) {
- dm->set_material_override(get_tree()->get_debug_navigation_material());
- } else {
- dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
- }
- }
-
- update_gizmo();
-}
-
-bool NavigationMeshInstance::is_enabled() const {
-
- return enabled;
-}
-
-/////////////////////////////
-
-void NavigationMeshInstance::_notification(int p_what) {
-
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
-
- Spatial *c = this;
- while (c) {
-
- navigation = Object::cast_to<Navigation>(c);
- if (navigation) {
-
- if (enabled && navmesh.is_valid()) {
-
- nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this);
- }
- break;
- }
-
- c = c->get_parent_spatial();
- }
-
- if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
-
- MeshInstance *dm = memnew(MeshInstance);
- dm->set_mesh(navmesh->get_debug_mesh());
- if (is_enabled()) {
- dm->set_material_override(get_tree()->get_debug_navigation_material());
- } else {
- dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
- }
- add_child(dm);
- debug_view = dm;
- }
-
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- if (navigation && nav_id != -1) {
- navigation->navmesh_set_transform(nav_id, get_relative_transform(navigation));
- }
-
- } break;
- case NOTIFICATION_EXIT_TREE: {
-
- if (navigation) {
-
- if (nav_id != -1) {
- navigation->navmesh_remove(nav_id);
- nav_id = -1;
- }
- }
-
- if (debug_view) {
- debug_view->queue_delete();
- debug_view = NULL;
- }
- navigation = NULL;
- } break;
- }
-}
-
-void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) {
-
- if (p_navmesh == navmesh)
- return;
-
- if (navigation && nav_id != -1) {
- navigation->navmesh_remove(nav_id);
- nav_id = -1;
- }
-
- if (navmesh.is_valid()) {
- navmesh->remove_change_receptor(this);
- }
-
- navmesh = p_navmesh;
-
- if (navmesh.is_valid()) {
- navmesh->add_change_receptor(this);
- }
-
- if (navigation && navmesh.is_valid() && enabled) {
- nav_id = navigation->navmesh_add(navmesh, get_relative_transform(navigation), this);
- }
-
- if (debug_view && navmesh.is_valid()) {
- Object::cast_to<MeshInstance>(debug_view)->set_mesh(navmesh->get_debug_mesh());
- }
-
- update_gizmo();
- update_configuration_warning();
-}
-
-Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const {
-
- return navmesh;
-}
-
-String NavigationMeshInstance::get_configuration_warning() const {
-
- if (!is_visible_in_tree() || !is_inside_tree())
- return String();
-
- if (!navmesh.is_valid()) {
- return TTR("A NavigationMesh resource must be set or created for this node to work.");
- }
- const Spatial *c = this;
- while (c) {
-
- if (Object::cast_to<Navigation>(c))
- return String();
-
- c = Object::cast_to<Spatial>(c->get_parent());
- }
-
- return TTR("NavigationMeshInstance must be a child or grandchild to a Navigation node. It only provides navigation data.");
-}
-
-void NavigationMeshInstance::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationMeshInstance::set_navigation_mesh);
- ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh);
-
- ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled);
- ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
-}
-
-void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) {
- update_gizmo();
- update_configuration_warning();
-}
-
-NavigationMeshInstance::NavigationMeshInstance() {
-
- debug_view = NULL;
- navigation = NULL;
- nav_id = -1;
- enabled = true;
- set_notify_transform(true);
-}
-
-NavigationMeshInstance::~NavigationMeshInstance() {
- if (navmesh.is_valid())
- navmesh->remove_change_receptor(this);
-}
diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h
deleted file mode 100644
index f9ab911bea..0000000000
--- a/scene/3d/navigation_mesh.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*************************************************************************/
-/* navigation_mesh.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef NAVIGATION_MESH_H
-#define NAVIGATION_MESH_H
-
-#include "scene/3d/spatial.h"
-#include "scene/resources/mesh.h"
-
-class Mesh;
-
-class NavigationMesh : public Resource {
-
- GDCLASS(NavigationMesh, Resource);
-
- PoolVector<Vector3> vertices;
- struct Polygon {
- Vector<int> indices;
- };
- Vector<Polygon> polygons;
- Ref<ArrayMesh> debug_mesh;
-
- struct _EdgeKey {
-
- Vector3 from;
- Vector3 to;
-
- bool operator<(const _EdgeKey &p_with) const { return from == p_with.from ? to < p_with.to : from < p_with.from; }
- };
-
-protected:
- static void _bind_methods();
- virtual void _validate_property(PropertyInfo &property) const;
-
- void _set_polygons(const Array &p_array);
- Array _get_polygons() const;
-
-public:
- enum SamplePartitionType {
- SAMPLE_PARTITION_WATERSHED = 0,
- SAMPLE_PARTITION_MONOTONE,
- SAMPLE_PARTITION_LAYERS,
- SAMPLE_PARTITION_MAX
- };
-
- enum ParsedGeometryType {
- PARSED_GEOMETRY_MESH_INSTANCES = 0,
- PARSED_GEOMETRY_STATIC_COLLIDERS,
- PARSED_GEOMETRY_BOTH,
- PARSED_GEOMETRY_MAX
- };
-
- enum SourceGeometryMode {
- SOURCE_GEOMETRY_NAVMESH_CHILDREN = 0,
- SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN,
- SOURCE_GEOMETRY_GROUPS_EXPLICIT,
- SOURCE_GEOMETRY_MAX
- };
-
-protected:
- float cell_size;
- float cell_height;
- float agent_height;
- float agent_radius;
- float agent_max_climb;
- float agent_max_slope;
- float region_min_size;
- float region_merge_size;
- float edge_max_length;
- float edge_max_error;
- float verts_per_poly;
- float detail_sample_distance;
- float detail_sample_max_error;
-
- SamplePartitionType partition_type;
- ParsedGeometryType parsed_geometry_type;
- uint32_t collision_mask;
-
- SourceGeometryMode source_geometry_mode;
- StringName source_group_name;
-
- bool filter_low_hanging_obstacles;
- bool filter_ledge_spans;
- bool filter_walkable_low_height_spans;
-
-public:
- // Recast settings
- void set_sample_partition_type(int p_value);
- int get_sample_partition_type() const;
-
- void set_parsed_geometry_type(int p_value);
- int get_parsed_geometry_type() const;
-
- void set_collision_mask(uint32_t p_mask);
- uint32_t get_collision_mask() const;
-
- void set_collision_mask_bit(int p_bit, bool p_value);
- bool get_collision_mask_bit(int p_bit) const;
-
- void set_source_geometry_mode(int p_geometry_mode);
- int get_source_geometry_mode() const;
-
- void set_source_group_name(StringName p_group_name);
- StringName get_source_group_name() const;
-
- void set_cell_size(float p_value);
- float get_cell_size() const;
-
- void set_cell_height(float p_value);
- float get_cell_height() const;
-
- void set_agent_height(float p_value);
- float get_agent_height() const;
-
- void set_agent_radius(float p_value);
- float get_agent_radius();
-
- void set_agent_max_climb(float p_value);
- float get_agent_max_climb() const;
-
- void set_agent_max_slope(float p_value);
- float get_agent_max_slope() const;
-
- void set_region_min_size(float p_value);
- float get_region_min_size() const;
-
- void set_region_merge_size(float p_value);
- float get_region_merge_size() const;
-
- void set_edge_max_length(float p_value);
- float get_edge_max_length() const;
-
- void set_edge_max_error(float p_value);
- float get_edge_max_error() const;
-
- void set_verts_per_poly(float p_value);
- float get_verts_per_poly() const;
-
- void set_detail_sample_distance(float p_value);
- float get_detail_sample_distance() const;
-
- void set_detail_sample_max_error(float p_value);
- float get_detail_sample_max_error() const;
-
- void set_filter_low_hanging_obstacles(bool p_value);
- bool get_filter_low_hanging_obstacles() const;
-
- void set_filter_ledge_spans(bool p_value);
- bool get_filter_ledge_spans() const;
-
- void set_filter_walkable_low_height_spans(bool p_value);
- bool get_filter_walkable_low_height_spans() const;
-
- void create_from_mesh(const Ref<Mesh> &p_mesh);
-
- void set_vertices(const PoolVector<Vector3> &p_vertices);
- PoolVector<Vector3> get_vertices() const;
-
- void add_polygon(const Vector<int> &p_polygon);
- int get_polygon_count() const;
- Vector<int> get_polygon(int p_idx);
- void clear_polygons();
-
- Ref<Mesh> get_debug_mesh();
-
- NavigationMesh();
-};
-
-class Navigation;
-
-class NavigationMeshInstance : public Spatial {
-
- GDCLASS(NavigationMeshInstance, Spatial);
-
- bool enabled;
- int nav_id;
- Navigation *navigation;
- Ref<NavigationMesh> navmesh;
-
- Node *debug_view;
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
- void _changed_callback(Object *p_changed, const char *p_prop);
-
-public:
- void set_enabled(bool p_enabled);
- bool is_enabled() const;
-
- void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
- Ref<NavigationMesh> get_navigation_mesh() const;
-
- String get_configuration_warning() const;
-
- NavigationMeshInstance();
- ~NavigationMeshInstance();
-};
-
-#endif // NAVIGATION_MESH_H
diff --git a/scene/3d/navigation_obstacle.cpp b/scene/3d/navigation_obstacle.cpp
new file mode 100644
index 0000000000..befc41eee5
--- /dev/null
+++ b/scene/3d/navigation_obstacle.cpp
@@ -0,0 +1,163 @@
+/*************************************************************************/
+/* navigation_obstacle.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_obstacle.h"
+
+#include "scene/3d/collision_shape.h"
+#include "scene/3d/navigation.h"
+#include "scene/3d/physics_body.h"
+#include "servers/navigation_server.h"
+
+void NavigationObstacle::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle::set_navigation_node);
+ ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle::get_navigation_node);
+}
+
+void NavigationObstacle::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+
+ update_agent_shape();
+
+ // Search the navigation node and set it
+ {
+ Navigation *nav = NULL;
+ Node *p = get_parent();
+ while (p != NULL) {
+ nav = Object::cast_to<Navigation>(p);
+ if (nav != NULL)
+ p = NULL;
+ else
+ p = p->get_parent();
+ }
+
+ set_navigation(nav);
+ }
+
+ set_physics_process_internal(true);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ set_navigation(NULL);
+ set_physics_process_internal(false);
+ } break;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ Spatial *spatial = Object::cast_to<Spatial>(get_parent());
+ if (spatial) {
+ NavigationServer::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin);
+ }
+
+ PhysicsBody *rigid = Object::cast_to<PhysicsBody>(get_parent());
+ if (rigid) {
+
+ Vector3 v = rigid->get_linear_velocity();
+ NavigationServer::get_singleton()->agent_set_velocity(agent, v);
+ NavigationServer::get_singleton()->agent_set_target_velocity(agent, v);
+ }
+
+ } break;
+ }
+}
+
+NavigationObstacle::NavigationObstacle() :
+ navigation(NULL),
+ agent(RID()) {
+ agent = NavigationServer::get_singleton()->agent_create();
+}
+
+NavigationObstacle::~NavigationObstacle() {
+ NavigationServer::get_singleton()->free(agent);
+ agent = RID(); // Pointless
+}
+
+void NavigationObstacle::set_navigation(Navigation *p_nav) {
+ if (navigation == p_nav)
+ return; // Pointless
+
+ navigation = p_nav;
+ NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid());
+}
+
+void NavigationObstacle::set_navigation_node(Node *p_nav) {
+ Navigation *nav = Object::cast_to<Navigation>(p_nav);
+ ERR_FAIL_COND(nav == NULL);
+ set_navigation(nav);
+}
+
+Node *NavigationObstacle::get_navigation_node() const {
+ return Object::cast_to<Node>(navigation);
+}
+
+String NavigationObstacle::get_configuration_warning() const {
+ if (!Object::cast_to<Spatial>(get_parent())) {
+
+ return TTR("The NavigationObstacle only serves to provide collision avoidance to a spatial object.");
+ }
+
+ return String();
+}
+
+void NavigationObstacle::update_agent_shape() {
+ Node *node = get_parent();
+
+ // Estimate the radius of this physics body
+ real_t radius = 0.0;
+ for (int i(0); i < node->get_child_count(); i++) {
+ // For each collision shape
+ CollisionShape *cs = Object::cast_to<CollisionShape>(node->get_child(i));
+ if (cs) {
+ // Take the distance between the Body center to the shape center
+ real_t r = cs->get_transform().origin.length();
+ if (cs->get_shape().is_valid()) {
+ // and add the enclosing shape radius
+ r += cs->get_shape()->get_enclosing_radius();
+ }
+ Vector3 s = cs->get_global_transform().basis.get_scale();
+ r *= MAX(s.x, MAX(s.y, s.z));
+ // Takes the biggest radius
+ radius = MAX(radius, r);
+ }
+ }
+ Spatial *spa = Object::cast_to<Spatial>(node);
+ if (spa) {
+ Vector3 s = spa->get_global_transform().basis.get_scale();
+ radius *= MAX(s.x, MAX(s.y, s.z));
+ }
+
+ if (radius == 0.0)
+ radius = 1.0; // Never a 0 radius
+
+ // Initialize the Agent as an object
+ NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
+ NavigationServer::get_singleton()->agent_set_max_neighbors(agent, 0);
+ NavigationServer::get_singleton()->agent_set_time_horizon(agent, 0.0);
+ NavigationServer::get_singleton()->agent_set_radius(agent, radius);
+ NavigationServer::get_singleton()->agent_set_max_speed(agent, 0.0);
+}
diff --git a/scene/3d/navigation_obstacle.h b/scene/3d/navigation_obstacle.h
new file mode 100644
index 0000000000..7257a43150
--- /dev/null
+++ b/scene/3d/navigation_obstacle.h
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* navigation_obstacle.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_OBSTACLE_H
+#define NAVIGATION_OBSTACLE_H
+
+#include "scene/main/node.h"
+
+class Navigation;
+
+class NavigationObstacle : public Node {
+ GDCLASS(NavigationObstacle, Node);
+
+ Navigation *navigation;
+
+ RID agent;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ NavigationObstacle();
+ virtual ~NavigationObstacle();
+
+ void set_navigation(Navigation *p_nav);
+ const Navigation *get_navigation() const {
+ return navigation;
+ }
+
+ void set_navigation_node(Node *p_nav);
+ Node *get_navigation_node() const;
+
+ RID get_rid() const {
+ return agent;
+ }
+
+ virtual String get_configuration_warning() const;
+
+private:
+ void update_agent_shape();
+};
+
+#endif
diff --git a/scene/3d/navigation_region.cpp b/scene/3d/navigation_region.cpp
new file mode 100644
index 0000000000..d96d095797
--- /dev/null
+++ b/scene/3d/navigation_region.cpp
@@ -0,0 +1,258 @@
+/*************************************************************************/
+/* navigation_region.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_region.h"
+#include "core/os/thread.h"
+#include "mesh_instance.h"
+#include "navigation.h"
+#include "servers/navigation_server.h"
+
+void NavigationRegion::set_enabled(bool p_enabled) {
+
+ if (enabled == p_enabled)
+ return;
+ enabled = p_enabled;
+
+ if (!is_inside_tree())
+ return;
+
+ if (!enabled) {
+
+ NavigationServer::get_singleton()->region_set_map(region, RID());
+ } else {
+
+ if (navigation) {
+
+ NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid());
+ }
+ }
+
+ if (debug_view) {
+ MeshInstance *dm = Object::cast_to<MeshInstance>(debug_view);
+ if (is_enabled()) {
+ dm->set_material_override(get_tree()->get_debug_navigation_material());
+ } else {
+ dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
+ }
+ }
+
+ update_gizmo();
+}
+
+bool NavigationRegion::is_enabled() const {
+
+ return enabled;
+}
+
+/////////////////////////////
+
+void NavigationRegion::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+
+ Spatial *c = this;
+ while (c) {
+
+ navigation = Object::cast_to<Navigation>(c);
+ if (navigation) {
+
+ if (enabled) {
+
+ NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid());
+ }
+ break;
+ }
+
+ c = c->get_parent_spatial();
+ }
+
+ if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
+
+ MeshInstance *dm = memnew(MeshInstance);
+ dm->set_mesh(navmesh->get_debug_mesh());
+ if (is_enabled()) {
+ dm->set_material_override(get_tree()->get_debug_navigation_material());
+ } else {
+ dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
+ }
+ add_child(dm);
+ debug_view = dm;
+ }
+
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+
+ NavigationServer::get_singleton()->region_set_transform(region, get_global_transform());
+
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+
+ if (navigation) {
+
+ NavigationServer::get_singleton()->region_set_map(region, RID());
+ }
+
+ if (debug_view) {
+ debug_view->queue_delete();
+ debug_view = NULL;
+ }
+ navigation = NULL;
+ } break;
+ }
+}
+
+void NavigationRegion::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) {
+
+ if (p_navmesh == navmesh)
+ return;
+
+ if (navmesh.is_valid()) {
+ navmesh->remove_change_receptor(this);
+ }
+
+ navmesh = p_navmesh;
+
+ if (navmesh.is_valid()) {
+ navmesh->add_change_receptor(this);
+ }
+
+ NavigationServer::get_singleton()->region_set_navmesh(region, p_navmesh);
+
+ if (debug_view && navmesh.is_valid()) {
+ Object::cast_to<MeshInstance>(debug_view)->set_mesh(navmesh->get_debug_mesh());
+ }
+
+ emit_signal("navigation_mesh_changed");
+
+ update_gizmo();
+ update_configuration_warning();
+}
+
+Ref<NavigationMesh> NavigationRegion::get_navigation_mesh() const {
+
+ return navmesh;
+}
+
+struct BakeThreadsArgs {
+ NavigationRegion *nav_mesh_instance;
+};
+
+void _bake_navigation_mesh(void *p_user_data) {
+ BakeThreadsArgs *args = static_cast<BakeThreadsArgs *>(p_user_data);
+
+ if (args->nav_mesh_instance->get_navigation_mesh().is_valid()) {
+ Ref<NavigationMesh> nav_mesh = args->nav_mesh_instance->get_navigation_mesh()->duplicate();
+
+ NavigationServer::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_mesh_instance);
+ args->nav_mesh_instance->call_deferred("_bake_finished", nav_mesh);
+ memdelete(args);
+ } else {
+
+ ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist");
+ args->nav_mesh_instance->call_deferred("_bake_finished", Ref<NavigationMesh>());
+ memdelete(args);
+ }
+}
+
+void NavigationRegion::bake_navigation_mesh() {
+ ERR_FAIL_COND(bake_thread != NULL);
+
+ BakeThreadsArgs *args = memnew(BakeThreadsArgs);
+ args->nav_mesh_instance = this;
+
+ bake_thread = Thread::create(_bake_navigation_mesh, args);
+ ERR_FAIL_COND(bake_thread == NULL);
+}
+
+void NavigationRegion::_bake_finished(Ref<NavigationMesh> p_nav_mesh) {
+ set_navigation_mesh(p_nav_mesh);
+ bake_thread = NULL;
+}
+
+String NavigationRegion::get_configuration_warning() const {
+
+ if (!is_visible_in_tree() || !is_inside_tree())
+ return String();
+
+ if (!navmesh.is_valid()) {
+ return TTR("A NavigationMesh resource must be set or created for this node to work.");
+ }
+ const Spatial *c = this;
+ while (c) {
+
+ if (Object::cast_to<Navigation>(c))
+ return String();
+
+ c = Object::cast_to<Spatial>(c->get_parent());
+ }
+
+ return TTR("NavigationRegion must be a child or grandchild to a Navigation node. It only provides navigation data.");
+}
+
+void NavigationRegion::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion::set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion::get_navigation_mesh);
+
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion::is_enabled);
+
+ ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion::bake_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion::_bake_finished);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+
+ ADD_SIGNAL(MethodInfo("navigation_mesh_changed"));
+ ADD_SIGNAL(MethodInfo("bake_finished"));
+}
+
+void NavigationRegion::_changed_callback(Object *p_changed, const char *p_prop) {
+ update_gizmo();
+ update_configuration_warning();
+}
+
+NavigationRegion::NavigationRegion() {
+
+ enabled = true;
+ set_notify_transform(true);
+ region = NavigationServer::get_singleton()->region_create();
+
+ navigation = NULL;
+ debug_view = NULL;
+ bake_thread = NULL;
+}
+
+NavigationRegion::~NavigationRegion() {
+ if (navmesh.is_valid())
+ navmesh->remove_change_receptor(this);
+ NavigationServer::get_singleton()->free(region);
+}
diff --git a/scene/3d/navigation_region.h b/scene/3d/navigation_region.h
new file mode 100644
index 0000000000..f215e92c97
--- /dev/null
+++ b/scene/3d/navigation_region.h
@@ -0,0 +1,75 @@
+/*************************************************************************/
+/* navigation_region.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_REGION_H
+#define NAVIGATION_REGION_H
+
+#include "scene/3d/spatial.h"
+#include "scene/resources/mesh.h"
+#include "scene/resources/navigation_mesh.h"
+
+class Navigation;
+
+class NavigationRegion : public Spatial {
+
+ GDCLASS(NavigationRegion, Spatial);
+
+ bool enabled;
+ RID region;
+ Ref<NavigationMesh> navmesh;
+
+ Navigation *navigation;
+ Node *debug_view;
+ Thread *bake_thread;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ void _changed_callback(Object *p_changed, const char *p_prop);
+
+public:
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const;
+
+ void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
+ Ref<NavigationMesh> get_navigation_mesh() const;
+
+ /// Bakes the navigation mesh in a dedicated thread; once done, automatically
+ /// sets the new navigation mesh and emits a signal
+ void bake_navigation_mesh();
+ void _bake_finished(Ref<NavigationMesh> p_nav_mesh);
+
+ String get_configuration_warning() const;
+
+ NavigationRegion();
+ ~NavigationRegion();
+};
+
+#endif // NAVIGATION_REGION_H
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index add563d991..e502b0c037 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -39,9 +39,9 @@ AABB Particles::get_aabb() const {
return AABB();
}
-PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
void Particles::set_emitting(bool p_emitting) {
@@ -254,16 +254,16 @@ String Particles::get_configuration_warning() const {
meshes_found = true;
for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) {
anim_material_found = Object::cast_to<ShaderMaterial>(draw_passes[i]->surface_get_material(j).ptr()) != NULL;
- SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(draw_passes[i]->surface_get_material(j).ptr());
- anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
+ StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(draw_passes[i]->surface_get_material(j).ptr());
+ anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
}
if (anim_material_found) break;
}
}
anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL;
- SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_material_override().ptr());
- anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
+ StandardMaterial3D *spat = Object::cast_to<StandardMaterial3D>(get_material_override().ptr());
+ anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES);
if (!meshes_found) {
if (warnings != String())
@@ -282,7 +282,7 @@ String Particles::get_configuration_warning() const {
process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
- warnings += "- " + TTR("Particles animation requires the usage of a SpatialMaterial whose Billboard Mode is set to \"Particle Billboard\".");
+ warnings += "- " + TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".");
}
}
@@ -386,12 +386,12 @@ void Particles::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
ADD_GROUP("Drawing", "");
diff --git a/scene/3d/particles.h b/scene/3d/particles.h
index 69be7da29a..95c6de15ec 100644
--- a/scene/3d/particles.h
+++ b/scene/3d/particles.h
@@ -78,7 +78,7 @@ protected:
public:
AABB get_aabb() const;
- PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ Vector<Face3> get_faces(uint32_t p_usage_flags) const;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index ac012de1ab..f93485d79f 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -59,13 +59,13 @@ void Path::_curve_changed() {
void Path::set_curve(const Ref<Curve3D> &p_curve) {
if (curve.is_valid()) {
- curve->disconnect("changed", this, "_curve_changed");
+ curve->disconnect("changed", callable_mp(this, &Path::_curve_changed));
}
curve = p_curve;
if (curve.is_valid()) {
- curve->connect("changed", this, "_curve_changed");
+ curve->connect("changed", callable_mp(this, &Path::_curve_changed));
}
_curve_changed();
}
@@ -79,7 +79,6 @@ void Path::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &Path::get_curve);
- ClassDB::bind_method(D_METHOD("_curve_changed"), &Path::_curve_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve");
@@ -297,10 +296,10 @@ void PathFollow::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow::has_loop);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index caeae90238..eba45a5604 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -36,15 +36,14 @@
#include "core/method_bind_ext.gen.inc"
#include "core/object.h"
#include "core/rid.h"
+#include "scene/3d/collision_shape.h"
#include "scene/scene_string_names.h"
+#include "servers/navigation_server.h"
#ifdef TOOLS_ENABLED
#include "editor/plugins/spatial_editor_plugin.h"
#endif
-void PhysicsBody::_notification(int p_what) {
-}
-
Vector3 PhysicsBody::get_linear_velocity() const {
return Vector3();
@@ -179,74 +178,17 @@ PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) :
collision_mask = 1;
}
-#ifndef DISABLE_DEPRECATED
-void StaticBody::set_friction(real_t p_friction) {
-
- if (p_friction == 1.0 && physics_material_override.is_null()) { // default value, don't create an override for that
- return;
- }
-
- WARN_DEPRECATED_MSG("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
-
- ERR_FAIL_COND_MSG(p_friction < 0 || p_friction > 1, "Friction must be between 0 and 1.");
-
- if (physics_material_override.is_null()) {
- physics_material_override.instance();
- set_physics_material_override(physics_material_override);
- }
- physics_material_override->set_friction(p_friction);
-}
-
-real_t StaticBody::get_friction() const {
-
- WARN_DEPRECATED_MSG("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
-
- if (physics_material_override.is_null()) {
- return 1;
- }
-
- return physics_material_override->get_friction();
-}
-
-void StaticBody::set_bounce(real_t p_bounce) {
-
- if (p_bounce == 0.0 && physics_material_override.is_null()) { // default value, don't create an override for that
- return;
- }
-
- WARN_DEPRECATED_MSG("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
-
- ERR_FAIL_COND_MSG(p_bounce < 0 || p_bounce > 1, "Bounce must be between 0 and 1.");
-
- if (physics_material_override.is_null()) {
- physics_material_override.instance();
- set_physics_material_override(physics_material_override);
- }
- physics_material_override->set_bounce(p_bounce);
-}
-
-real_t StaticBody::get_bounce() const {
-
- WARN_DEPRECATED_MSG("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
-
- if (physics_material_override.is_null()) {
- return 0;
- }
-
- return physics_material_override->get_bounce();
-}
-#endif
-
void StaticBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"))
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics))) {
+ physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics));
+ }
}
physics_material_override = p_physics_material_override;
if (physics_material_override.is_valid()) {
- physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics));
}
_reload_physics_characteristics();
}
@@ -283,27 +225,13 @@ void StaticBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody::get_constant_angular_velocity);
-#ifndef DISABLE_DEPRECATED
- ClassDB::bind_method(D_METHOD("set_friction", "friction"), &StaticBody::set_friction);
- ClassDB::bind_method(D_METHOD("get_friction"), &StaticBody::get_friction);
-
- ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &StaticBody::set_bounce);
- ClassDB::bind_method(D_METHOD("get_bounce"), &StaticBody::get_bounce);
-#endif // DISABLE_DEPRECATED
-
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody::get_physics_material_override);
- ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &StaticBody::_reload_physics_characteristics);
-
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with);
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with);
-#ifndef DISABLE_DEPRECATED
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce");
-#endif // DISABLE_DEPRECATED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
@@ -393,8 +321,8 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,
//E->get().rc=0;
E->get().in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree, make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree, make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree), make_binds(objid));
if (E->get().in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
@@ -420,8 +348,8 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,
if (E->get().shapes.empty()) {
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree));
if (in_tree)
emit_signal(SceneStringNames::get_singleton()->body_exited, node);
}
@@ -619,70 +547,17 @@ real_t RigidBody::get_weight() const {
return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8));
}
-#ifndef DISABLE_DEPRECATED
-void RigidBody::set_friction(real_t p_friction) {
-
- if (p_friction == 1.0 && physics_material_override.is_null()) { // default value, don't create an override for that
- return;
- }
-
- WARN_DEPRECATED_MSG("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
-
- ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
-
- if (physics_material_override.is_null()) {
- physics_material_override.instance();
- set_physics_material_override(physics_material_override);
- }
- physics_material_override->set_friction(p_friction);
-}
-real_t RigidBody::get_friction() const {
-
- WARN_DEPRECATED_MSG("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
-
- if (physics_material_override.is_null()) {
- return 1;
- }
-
- return physics_material_override->get_friction();
-}
-
-void RigidBody::set_bounce(real_t p_bounce) {
-
- if (p_bounce == 0.0 && physics_material_override.is_null()) { // default value, don't create an override for that
- return;
- }
-
- WARN_DEPRECATED_MSG("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
-
- ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
-
- if (physics_material_override.is_null()) {
- physics_material_override.instance();
- set_physics_material_override(physics_material_override);
- }
- physics_material_override->set_bounce(p_bounce);
-}
-real_t RigidBody::get_bounce() const {
- WARN_DEPRECATED_MSG("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
- if (physics_material_override.is_null()) {
- return 0;
- }
-
- return physics_material_override->get_bounce();
-}
-#endif // DISABLE_DEPRECATED
-
void RigidBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"))
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics))) {
+ physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics));
+ }
}
physics_material_override = p_physics_material_override;
if (physics_material_override.is_valid()) {
- physics_material_override->connect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics));
}
_reload_physics_characteristics();
}
@@ -862,9 +737,8 @@ void RigidBody::set_contact_monitor(bool p_enabled) {
Node *node = Object::cast_to<Node>(obj);
if (node) {
-
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree));
}
}
@@ -936,19 +810,9 @@ void RigidBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_weight", "weight"), &RigidBody::set_weight);
ClassDB::bind_method(D_METHOD("get_weight"), &RigidBody::get_weight);
-#ifndef DISABLE_DEPRECATED
- ClassDB::bind_method(D_METHOD("set_friction", "friction"), &RigidBody::set_friction);
- ClassDB::bind_method(D_METHOD("get_friction"), &RigidBody::get_friction);
-
- ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &RigidBody::set_bounce);
- ClassDB::bind_method(D_METHOD("get_bounce"), &RigidBody::get_bounce);
-#endif // DISABLE_DEPRECATED
-
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody::get_physics_material_override);
- ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &RigidBody::_reload_physics_characteristics);
-
ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody::set_linear_velocity);
ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody::get_linear_velocity);
@@ -993,8 +857,6 @@ void RigidBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody::is_able_to_sleep);
ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody::_direct_state_changed);
- ClassDB::bind_method(D_METHOD("_body_enter_tree"), &RigidBody::_body_enter_tree);
- ClassDB::bind_method(D_METHOD("_body_exit_tree"), &RigidBody::_body_exit_tree);
ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody::set_axis_lock);
ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody::get_axis_lock);
@@ -1004,14 +866,10 @@ void RigidBody::_bind_methods() {
BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight");
-#ifndef DISABLE_DEPRECATED
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce");
-#endif // DISABLE_DEPRECATED
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection");
ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
@@ -1027,10 +885,10 @@ void RigidBody::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z);
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_GROUP("Angular", "angular_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
@@ -1104,6 +962,14 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_inf
return Ref<KinematicCollision>();
}
+Vector3 KinematicBody::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+Vector3 KinematicBody::get_angular_velocity() const {
+ return angular_velocity;
+}
+
bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
Transform gt = get_global_transform();
@@ -1399,6 +1265,8 @@ void KinematicBody::_notification(int p_what) {
void KinematicBody::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody::_direct_state_changed);
+
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
@@ -1424,7 +1292,18 @@ void KinematicBody::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
+}
+
+void KinematicBody::_direct_state_changed(Object *p_state) {
+#ifdef DEBUG_ENABLED
+ PhysicsDirectBodyState *state = Object::cast_to<PhysicsDirectBodyState>(p_state);
+#else
+ PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it
+#endif
+
+ linear_velocity = state->get_linear_velocity();
+ angular_velocity = state->get_angular_velocity();
}
KinematicBody::KinematicBody() :
@@ -1435,6 +1314,8 @@ KinematicBody::KinematicBody() :
on_floor = false;
on_ceiling = false;
on_wall = false;
+
+ PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
}
KinematicBody::~KinematicBody() {
@@ -1471,7 +1352,7 @@ Object *KinematicCollision::get_local_shape() const {
Object *KinematicCollision::get_collider() const {
- if (collision.collider) {
+ if (collision.collider.is_valid()) {
return ObjectDB::get_instance(collision.collider);
}
@@ -1535,7 +1416,7 @@ void KinematicCollision::_bind_methods() {
}
KinematicCollision::KinematicCollision() {
- collision.collider = 0;
+
collision.collider_shape = 0;
collision.local_shape = 0;
owner = NULL;
@@ -1562,6 +1443,24 @@ void PhysicalBone::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse)
PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse);
}
+void PhysicalBone::reset_physics_simulation_state() {
+ if (simulate_physics) {
+ _start_physics_simulation();
+ } else {
+ _stop_physics_simulation();
+ }
+}
+
+void PhysicalBone::reset_to_rest_position() {
+ if (parent_skeleton) {
+ if (-1 == bone_id) {
+ set_global_transform(parent_skeleton->get_global_transform() * body_offset);
+ } else {
+ set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset);
+ }
+ }
+}
+
bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
if (JointData::_set(p_name, p_value, j)) {
return true;
@@ -1610,9 +1509,9 @@ bool PhysicalBone::PinJointData::_get(const StringName &p_name, Variant &r_ret)
void PhysicalBone::PinJointData::_get_property_list(List<PropertyInfo> *p_list) const {
JointData::_get_property_list(p_list);
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"));
}
bool PhysicalBone::ConeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
@@ -1677,11 +1576,11 @@ bool PhysicalBone::ConeJointData::_get(const StringName &p_name, Variant &r_ret)
void PhysicalBone::ConeJointData::_get_property_list(List<PropertyInfo> *p_list) const {
JointData::_get_property_list(p_list);
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/swing_span", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_lesser,or_greater"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/swing_span", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_lesser,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
}
bool PhysicalBone::HingeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
@@ -1754,11 +1653,11 @@ void PhysicalBone::HingeJointData::_get_property_list(List<PropertyInfo> *p_list
JointData::_get_property_list(p_list);
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/angular_limit_enabled"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
}
bool PhysicalBone::SliderJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
@@ -1858,17 +1757,17 @@ bool PhysicalBone::SliderJointData::_get(const StringName &p_name, Variant &r_re
void PhysicalBone::SliderJointData::_get_property_list(List<PropertyInfo> *p_list) const {
JointData::_get_property_list(p_list);
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_upper"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_lower"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_upper"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_lower"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"));
}
bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
@@ -2082,26 +1981,26 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
const StringName axis_names[] = { "x", "y", "z" };
for (int i = 0; i < 3; ++i) {
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_limit_enabled"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_upper"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_lower"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_upper"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_lower"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_damping"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/erp"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/erp"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_damping"));
- p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point"));
}
}
@@ -2150,10 +2049,10 @@ void PhysicalBone::_get_property_list(List<PropertyInfo> *p_list) const {
names += parent->get_bone_name(i);
}
- p_list->push_back(PropertyInfo(Variant::STRING, "bone_name", PROPERTY_HINT_ENUM, names));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_name", PROPERTY_HINT_ENUM, names));
} else {
- p_list->push_back(PropertyInfo(Variant::STRING, "bone_name"));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_name"));
}
if (joint_data) {
@@ -2167,7 +2066,7 @@ void PhysicalBone::_notification(int p_what) {
parent_skeleton = find_skeleton_parent(get_parent());
update_bone_id();
reset_to_rest_position();
- _reset_physics_simulation_state();
+ reset_physics_simulation_state();
if (!joint.is_valid() && joint_data) {
_reload_joint();
}
@@ -2238,8 +2137,6 @@ void PhysicalBone::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset);
ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset);
- ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body);
-
ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics);
ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics);
@@ -2267,11 +2164,11 @@ void PhysicalBone::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale");
BIND_ENUM_CONSTANT(JOINT_TYPE_NONE);
BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
@@ -2508,26 +2405,13 @@ const Transform &PhysicalBone::get_joint_offset() const {
return joint_offset;
}
-void PhysicalBone::set_static_body(bool p_static) {
-
- static_body = p_static;
-
- set_as_toplevel(!static_body);
-
- _reset_physics_simulation_state();
-}
-
-bool PhysicalBone::is_static_body() {
- return static_body;
-}
-
void PhysicalBone::set_simulate_physics(bool p_simulate) {
if (simulate_physics == p_simulate) {
return;
}
simulate_physics = p_simulate;
- _reset_physics_simulation_state();
+ reset_physics_simulation_state();
}
bool PhysicalBone::get_simulate_physics() {
@@ -2535,7 +2419,7 @@ bool PhysicalBone::get_simulate_physics() {
}
bool PhysicalBone::is_simulating_physics() {
- return _internal_simulate_physics && !_internal_static_body;
+ return _internal_simulate_physics;
}
void PhysicalBone::set_bone_name(const String &p_name) {
@@ -2618,8 +2502,6 @@ PhysicalBone::PhysicalBone() :
#endif
joint_data(NULL),
parent_skeleton(NULL),
- static_body(false),
- _internal_static_body(false),
simulate_physics(false),
_internal_simulate_physics(false),
bone_id(-1),
@@ -2629,8 +2511,7 @@ PhysicalBone::PhysicalBone() :
friction(1),
gravity_scale(1) {
- set_static_body(static_body);
- _reset_physics_simulation_state();
+ reset_physics_simulation_state();
}
PhysicalBone::~PhysicalBone() {
@@ -2657,8 +2538,7 @@ void PhysicalBone::update_bone_id() {
parent_skeleton->bind_physical_bone_to_bone(bone_id, this);
_fix_joint_offset();
- _internal_static_body = !static_body; // Force staticness reset
- _reset_staticness_state();
+ reset_physics_simulation_state();
}
}
@@ -2680,49 +2560,6 @@ void PhysicalBone::update_offset() {
#endif
}
-void PhysicalBone::reset_to_rest_position() {
- if (parent_skeleton) {
- if (-1 == bone_id) {
- set_global_transform(parent_skeleton->get_global_transform() * body_offset);
- } else {
- set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset);
- }
- }
-}
-
-void PhysicalBone::_reset_physics_simulation_state() {
- if (simulate_physics && !static_body) {
- _start_physics_simulation();
- } else {
- _stop_physics_simulation();
- }
-
- _reset_staticness_state();
-}
-
-void PhysicalBone::_reset_staticness_state() {
-
- if (parent_skeleton && -1 != bone_id) {
- if (static_body && simulate_physics) { // With this check I'm sure the position of this body is updated only when it's necessary
-
- if (_internal_static_body) {
- return;
- }
-
- parent_skeleton->bind_child_node_to_bone(bone_id, this);
- _internal_static_body = true;
- } else {
-
- if (!_internal_static_body) {
- return;
- }
-
- parent_skeleton->unbind_child_node_from_bone(bone_id, this);
- _internal_static_body = false;
- }
- }
-}
-
void PhysicalBone::_start_physics_simulation() {
if (_internal_simulate_physics || !parent_skeleton) {
return;
@@ -2732,17 +2569,27 @@ void PhysicalBone::_start_physics_simulation() {
PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+ set_as_toplevel(true);
_internal_simulate_physics = true;
}
void PhysicalBone::_stop_physics_simulation() {
- if (!_internal_simulate_physics || !parent_skeleton) {
+ if (!parent_skeleton) {
return;
}
- PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC);
- PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0);
- PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0);
- PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, "");
- parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
- _internal_simulate_physics = false;
+ if (parent_skeleton->get_animate_physical_bones()) {
+ PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC);
+ PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
+ PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
+ } else {
+ PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC);
+ PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0);
+ PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0);
+ }
+ if (_internal_simulate_physics) {
+ PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, "");
+ parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
+ set_as_toplevel(false);
+ _internal_simulate_physics = false;
+ }
}
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 05bcbe22f0..5362baf8ee 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -49,7 +49,6 @@ class PhysicsBody : public CollisionObject {
protected:
static void _bind_methods();
- void _notification(int p_what);
PhysicsBody(PhysicsServer::BodyMode p_mode);
public:
@@ -89,14 +88,6 @@ protected:
static void _bind_methods();
public:
-#ifndef DISABLE_DEPRECATED
- void set_friction(real_t p_friction);
- real_t get_friction() const;
-
- void set_bounce(real_t p_bounce);
- real_t get_bounce() const;
-#endif
-
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -205,14 +196,6 @@ public:
void set_weight(real_t p_weight);
real_t get_weight() const;
-#ifndef DISABLE_DEPRECATED
- void set_friction(real_t p_friction);
- real_t get_friction() const;
-
- void set_bounce(real_t p_bounce);
- real_t get_bounce() const;
-#endif
-
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -296,6 +279,9 @@ public:
};
private:
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+
uint16_t locked_axis;
float margin;
@@ -319,7 +305,12 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _direct_state_changed(Object *p_state);
+
public:
+ virtual Vector3 get_linear_velocity() const;
+ virtual Vector3 get_angular_velocity() const;
+
bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false);
bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
@@ -562,8 +553,6 @@ private:
Skeleton *parent_skeleton;
Transform body_offset;
Transform body_offset_inverse;
- bool static_body;
- bool _internal_static_body;
bool simulate_physics;
bool _internal_simulate_physics;
int bone_id;
@@ -613,9 +602,6 @@ public:
void set_body_offset(const Transform &p_offset);
const Transform &get_body_offset() const;
- void set_static_body(bool p_static);
- bool is_static_body();
-
void set_simulate_physics(bool p_simulate);
bool get_simulate_physics();
bool is_simulating_physics();
@@ -641,16 +627,15 @@ public:
void apply_central_impulse(const Vector3 &p_impulse);
void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
+ void reset_physics_simulation_state();
+ void reset_to_rest_position();
+
PhysicalBone();
~PhysicalBone();
private:
void update_bone_id();
void update_offset();
- void reset_to_rest_position();
-
- void _reset_physics_simulation_state();
- void _reset_staticness_state();
void _start_physics_simulation();
void _stop_physics_simulation();
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index eacc6bcc0f..0699e366e0 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -172,9 +172,9 @@ void PinJoint::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &PinJoint::set_param);
ClassDB::bind_method(D_METHOD("get_param", "param"), &PinJoint::get_param);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"), "set_param", "get_param", PARAM_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"), "set_param", "get_param", PARAM_IMPULSE_CLAMP);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"), "set_param", "get_param", PARAM_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"), "set_param", "get_param", PARAM_IMPULSE_CLAMP);
BIND_ENUM_CONSTANT(PARAM_BIAS);
BIND_ENUM_CONSTANT(PARAM_DAMPING);
@@ -257,18 +257,18 @@ void HingeJoint::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_lower_limit", "lower_limit"), &HingeJoint::_set_lower_limit);
ClassDB::bind_method(D_METHOD("_get_lower_limit"), &HingeJoint::_get_lower_limit);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/bias", PROPERTY_HINT_RANGE, "0.00,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.00,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit/enable"), "set_flag", "get_flag", FLAG_USE_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit", "_get_upper_limit");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit", "_get_lower_limit");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_LIMIT_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit", "_get_upper_limit");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit", "_get_lower_limit");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_LIMIT_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "motor/enable"), "set_flag", "get_flag", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "motor/target_velocity", PROPERTY_HINT_RANGE, "-200,200,0.01,or_greater,or_lesser"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/target_velocity", PROPERTY_HINT_RANGE, "-200,200,0.01,or_greater,or_lesser"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE);
BIND_ENUM_CONSTANT(PARAM_BIAS);
BIND_ENUM_CONSTANT(PARAM_LIMIT_UPPER);
@@ -392,29 +392,29 @@ void SliderJoint::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_lower_limit_angular", "lower_limit_angular"), &SliderJoint::_set_lower_limit_angular);
ClassDB::bind_method(D_METHOD("_get_lower_limit_angular"), &SliderJoint::_get_lower_limit_angular);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_DAMPING);
-
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit_angular", "_get_upper_limit_angular");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit_angular", "_get_lower_limit_angular");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_DAMPING);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit_angular", "_get_upper_limit_angular");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit_angular", "_get_lower_limit_angular");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_DAMPING);
BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_UPPER);
BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_LOWER);
@@ -541,12 +541,12 @@ void ConeTwistJoint::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_twist_span", "twist_span"), &ConeTwistJoint::_set_twist_span);
ClassDB::bind_method(D_METHOD("_get_twist_span"), &ConeTwistJoint::_get_twist_span);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_swing_span", "_get_swing_span");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1"), "_set_twist_span", "_get_twist_span");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_swing_span", "_get_swing_span");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1"), "_set_twist_span", "_get_twist_span");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_RELAXATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_RELAXATION);
BIND_ENUM_CONSTANT(PARAM_SWING_SPAN);
BIND_ENUM_CONSTANT(PARAM_TWIST_SPAN);
@@ -711,92 +711,92 @@ void Generic6DOFJoint::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_precision"), &Generic6DOFJoint::get_precision);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/upper_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/lower_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/lower_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/lower_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
ADD_PROPERTY(PropertyInfo(Variant::INT, "precision", PROPERTY_HINT_RANGE, "1,99999,1"), "set_precision", "get_precision");
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index fbe3cd7a3e..be1426f13c 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -80,7 +80,7 @@ bool RayCast::is_colliding() const {
}
Object *RayCast::get_collider() const {
- if (against == 0)
+ if (against.is_null())
return NULL;
return ObjectDB::get_instance(against);
@@ -186,7 +186,7 @@ void RayCast::_notification(int p_what) {
_update_raycast_state();
if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) {
if (debug_material.is_valid()) {
- Ref<SpatialMaterial> line_material = static_cast<Ref<SpatialMaterial> >(debug_material);
+ Ref<StandardMaterial3D> line_material = static_cast<Ref<StandardMaterial3D> >(debug_material);
line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6));
}
}
@@ -219,7 +219,7 @@ void RayCast::_update_raycast_state() {
against_shape = rr.shape;
} else {
collided = false;
- against = 0;
+ against = ObjectID();
against_shape = 0;
}
}
@@ -333,11 +333,10 @@ void RayCast::_bind_methods() {
void RayCast::_create_debug_shape() {
if (!debug_material.is_valid()) {
- debug_material = Ref<SpatialMaterial>(memnew(SpatialMaterial));
+ debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
- Ref<SpatialMaterial> line_material = static_cast<Ref<SpatialMaterial> >(debug_material);
- line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
- line_material->set_line_width(3.0);
+ Ref<StandardMaterial3D> line_material = static_cast<Ref<StandardMaterial3D> >(debug_material);
+ line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
line_material->set_albedo(Color(1.0, 0.8, 0.6));
}
@@ -363,8 +362,7 @@ void RayCast::_update_debug_shape() {
return;
Ref<ArrayMesh> mesh = mi->get_mesh();
- if (mesh->get_surface_count() > 0)
- mesh->surface_remove(0);
+ mesh->clear_surfaces();
Array a;
a.resize(Mesh::ARRAY_MAX);
@@ -395,7 +393,7 @@ void RayCast::_clear_debug_shape() {
RayCast::RayCast() {
enabled = false;
- against = 0;
+
collided = false;
against_shape = 0;
collision_mask = 1;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 2a5a84741f..3cf8e43ec2 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -186,9 +186,9 @@ AABB ReflectionProbe::get_aabb() const {
aabb.size = origin_offset + extents;
return aabb;
}
-PoolVector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
@@ -239,8 +239,8 @@ void ReflectionProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_update_mode"), &ReflectionProbe::get_update_mode);
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once,Always"), "set_update_mode", "get_update_mode");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled");
@@ -250,8 +250,8 @@ void ReflectionProbe::_bind_methods() {
ADD_GROUP("Interior", "interior_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior_enable"), "set_as_interior", "is_set_as_interior");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "interior_ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_interior_ambient", "get_interior_ambient");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution");
BIND_ENUM_CONSTANT(UPDATE_ONCE);
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 28ca680e9f..57c1b0a320 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -103,7 +103,7 @@ public:
UpdateMode get_update_mode() const;
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
ReflectionProbe();
~ReflectionProbe();
diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp
index 983af7a9ec..9ef43647ba 100644
--- a/scene/3d/remote_transform.cpp
+++ b/scene/3d/remote_transform.cpp
@@ -31,7 +31,7 @@
#include "remote_transform.h"
void RemoteTransform::_update_cache() {
- cache = 0;
+ cache = ObjectID();
if (has_node(remote_node)) {
Node *node = get_node(remote_node);
if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) {
@@ -47,7 +47,7 @@ void RemoteTransform::_update_remote() {
if (!is_inside_tree())
return;
- if (!cache)
+ if (cache.is_null())
return;
Spatial *n = Object::cast_to<Spatial>(ObjectDB::get_instance(cache));
@@ -114,7 +114,7 @@ void RemoteTransform::_notification(int p_what) {
if (!is_inside_tree())
break;
- if (cache) {
+ if (cache.is_valid()) {
_update_remote();
}
@@ -219,6 +219,5 @@ RemoteTransform::RemoteTransform() {
update_remote_rotation = true;
update_remote_scale = true;
- cache = 0;
set_notify_transform(true);
}
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index 17e67c47d1..b2252bcb04 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -30,8 +30,8 @@
#include "skeleton.h"
+#include "core/engine.h"
#include "core/message_queue.h"
-
#include "core/project_settings.h"
#include "scene/3d/physics_body.h"
#include "scene/resources/surface_tool.h"
@@ -40,6 +40,7 @@ void SkinReference::_skin_changed() {
if (skeleton_node) {
skeleton_node->_make_dirty();
}
+ skeleton_version = 0;
}
void SkinReference::_bind_methods() {
@@ -137,7 +138,7 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const {
else if (what == "bound_children") {
Array children;
- for (const List<uint32_t>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -301,7 +302,7 @@ void Skeleton::_notification(int p_what) {
b.global_pose_override_amount = 0.0;
}
- for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
+ for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -321,10 +322,49 @@ void Skeleton::_notification(int p_what) {
if (E->get()->bind_count != bind_count) {
VS::get_singleton()->skeleton_allocate(skeleton, bind_count);
E->get()->bind_count = bind_count;
+ E->get()->skin_bone_indices.resize(bind_count);
+ E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw();
+ }
+
+ if (E->get()->skeleton_version != version) {
+
+ for (uint32_t i = 0; i < bind_count; i++) {
+ StringName bind_name = skin->get_bind_name(i);
+
+ if (bind_name != StringName()) {
+ //bind name used, use this
+ bool found = false;
+ for (int j = 0; j < len; j++) {
+ if (bonesptr[j].name == bind_name) {
+ E->get()->skin_bone_indices_ptrs[i] = j;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name.");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ }
+ } else if (skin->get_bind_bone(i) >= 0) {
+ int bind_index = skin->get_bind_bone(i);
+ if (bind_index >= len) {
+ ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + ".");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ } else {
+ E->get()->skin_bone_indices_ptrs[i] = bind_index;
+ }
+ } else {
+ ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index.");
+ E->get()->skin_bone_indices_ptrs[i] = 0;
+ }
+ }
+
+ E->get()->skeleton_version = version;
}
for (uint32_t i = 0; i < bind_count; i++) {
- uint32_t bone_index = skin->get_bind_bone(i);
+ uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i];
ERR_CONTINUE(bone_index >= (uint32_t)len);
vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
}
@@ -332,6 +372,27 @@ void Skeleton::_notification(int p_what) {
dirty = false;
} break;
+
+#ifndef _3D_DISABLED
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ // This is active only if the skeleton animates the physical bones
+ // and the state of the bone is not active.
+ if (animate_physical_bones) {
+ for (int i = 0; i < bones.size(); i += 1) {
+ if (bones[i].physical_bone) {
+ if (bones[i].physical_bone->is_simulating_physics() == false) {
+ bones[i].physical_bone->reset_to_rest_position();
+ }
+ }
+ }
+ }
+ } break;
+ case NOTIFICATION_READY: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_physics_process_internal(true);
+ }
+ } break;
+#endif
}
}
@@ -366,6 +427,7 @@ void Skeleton::add_bone(const String &p_name) {
b.name = p_name;
bones.push_back(b);
process_order_dirty = true;
+ version++;
_make_dirty();
update_gizmo();
}
@@ -483,9 +545,9 @@ void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
- uint32_t id = p_node->get_instance_id();
+ ObjectID id = p_node->get_instance_id();
- for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
if (E->get() == id)
return; // already here
@@ -498,14 +560,14 @@ void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_INDEX(p_bone, bones.size());
- uint32_t id = p_node->get_instance_id();
+ ObjectID id = p_node->get_instance_id();
bones.write[p_bone].nodes_bound.erase(id);
}
void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const {
ERR_FAIL_INDEX(p_bone, bones.size());
- for (const List<uint32_t>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
+ for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE(!obj);
@@ -517,7 +579,7 @@ void Skeleton::clear_bones() {
bones.clear();
process_order_dirty = true;
-
+ version++;
_make_dirty();
}
@@ -584,6 +646,27 @@ void Skeleton::localize_rests() {
#ifndef _3D_DISABLED
+void Skeleton::set_animate_physical_bones(bool p_animate) {
+ animate_physical_bones = p_animate;
+
+ if (Engine::get_singleton()->is_editor_hint() == false) {
+ bool sim = false;
+ for (int i = 0; i < bones.size(); i += 1) {
+ if (bones[i].physical_bone) {
+ bones[i].physical_bone->reset_physics_simulation_state();
+ if (bones[i].physical_bone->is_simulating_physics()) {
+ sim = true;
+ }
+ }
+ }
+ set_physics_process_internal(sim == false && p_animate);
+ }
+}
+
+bool Skeleton::get_animate_physical_bones() const {
+ return animate_physical_bones;
+}
+
void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) {
ERR_FAIL_INDEX(p_bone, bones.size());
ERR_FAIL_COND(bones[p_bone].physical_bone);
@@ -653,12 +736,14 @@ void _pb_stop_simulation(Node *p_node) {
PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node);
if (pb) {
pb->set_simulate_physics(false);
- pb->set_static_body(false);
}
}
void Skeleton::physical_bones_stop_simulation() {
_pb_stop_simulation(this);
+ if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) {
+ set_physics_process_internal(true);
+ }
}
void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) {
@@ -669,24 +754,17 @@ void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector
PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node);
if (pb) {
- bool sim = false;
for (int i = p_sim_bones.size() - 1; 0 <= i; --i) {
if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
- sim = true;
+ pb->set_simulate_physics(true);
break;
}
}
-
- pb->set_simulate_physics(true);
- if (sim) {
- pb->set_static_body(false);
- } else {
- pb->set_static_body(true);
- }
}
}
void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) {
+ set_physics_process_internal(false);
Vector<int> sim_bones;
if (p_bones.size() <= 0) {
@@ -695,7 +773,8 @@ void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) {
sim_bones.resize(p_bones.size());
int c = 0;
for (int i = sim_bones.size() - 1; 0 <= i; --i) {
- if (Variant::STRING == p_bones.get(i).get_type()) {
+ Variant::Type type = p_bones.get(i).get_type();
+ if (Variant::STRING == type || Variant::STRING_NAME == type) {
int bone_id = find_bone(p_bones.get(i));
if (bone_id != -1)
sim_bones.write[c++] = bone_id;
@@ -791,8 +870,10 @@ Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) {
skin_bindings.insert(skin_ref.operator->());
- skin->connect("changed", skin_ref.operator->(), "_skin_changed");
- _make_dirty();
+ skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed");
+
+ _make_dirty(); //skin needs to be updated, so update skeleton
+
return skin_ref;
}
@@ -836,11 +917,15 @@ void Skeleton::_bind_methods() {
#ifndef _3D_DISABLED
+ ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones);
+ ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones);
+
ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation);
ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception);
ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones");
#endif // _3D_DISABLED
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
@@ -848,7 +933,9 @@ void Skeleton::_bind_methods() {
Skeleton::Skeleton() {
+ animate_physical_bones = true;
dirty = false;
+ version = 1;
process_order_dirty = true;
}
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index 056f70e22b..76fd96f30a 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -51,6 +51,9 @@ class SkinReference : public Reference {
RID skeleton;
Ref<Skin> skin;
uint32_t bind_count = 0;
+ uint64_t skeleton_version = 0;
+ Vector<uint32_t> skin_bone_indices;
+ uint32_t *skin_bone_indices_ptrs;
void _skin_changed();
protected:
@@ -99,7 +102,7 @@ private:
PhysicalBone *cache_parent_physical_bone;
#endif // _3D_DISABLED
- List<uint32_t> nodes_bound;
+ List<ObjectID> nodes_bound;
Bone() {
parent = -1;
@@ -115,6 +118,7 @@ private:
}
};
+ bool animate_physical_bones;
Vector<Bone> bones;
Vector<int> process_order;
bool process_order_dirty;
@@ -122,6 +126,8 @@ private:
void _make_dirty();
bool dirty;
+ uint64_t version;
+
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
@@ -199,6 +205,9 @@ public:
#ifndef _3D_DISABLED
// Physical bone API
+ void set_animate_physical_bones(bool p_animate);
+ bool get_animate_physical_bones() const;
+
void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone);
void unbind_physical_bone_from_bone(int p_bone);
diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp
index ef13985bf4..3859a278ef 100644
--- a/scene/3d/soft_body.cpp
+++ b/scene/3d/soft_body.cpp
@@ -47,7 +47,10 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) {
mesh = p_mesh;
surface = p_surface;
-
+#ifndef _MSC_VER
+#warning Softbody is not working, needs to be redone considering that these functions no longer exist
+#endif
+#if 0
const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface);
const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface);
const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface);
@@ -57,6 +60,7 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) {
stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets);
offset_vertices = surface_offsets[VS::ARRAY_VERTEX];
offset_normal = surface_offsets[VS::ARRAY_NORMAL];
+#endif
}
void SoftBodyVisualServerHandler::clear() {
@@ -69,11 +73,11 @@ void SoftBodyVisualServerHandler::clear() {
}
void SoftBodyVisualServerHandler::open() {
- write_buffer = buffer.write();
+ write_buffer = buffer.ptrw();
}
void SoftBodyVisualServerHandler::close() {
- write_buffer.release();
+ //write_buffer.release();
}
void SoftBodyVisualServerHandler::commit_changes() {
@@ -145,7 +149,7 @@ bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const {
if ("pinned_points" == which) {
Array arr_ret;
const int pinned_points_indices_size = pinned_points.size();
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ const PinnedPoint *r = pinned_points.ptr();
arr_ret.resize(pinned_points_indices_size);
for (int i = 0; i < pinned_points_indices_size; ++i) {
@@ -170,7 +174,7 @@ void SoftBody::_get_property_list(List<PropertyInfo> *p_list) const {
const int pinned_points_indices_size = pinned_points.size();
- p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "pinned_points"));
+ p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "pinned_points"));
for (int i = 0; i < pinned_points_indices_size; ++i) {
p_list->push_back(PropertyInfo(Variant::INT, "attachments/" + itos(i) + "/point_index"));
@@ -184,7 +188,7 @@ bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) {
const int p_indices_size = p_indices.size();
{ // Remove the pined points on physics server that will be removed by resize
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ const PinnedPoint *r = pinned_points.ptr();
if (p_indices_size < pinned_points.size()) {
for (int i = pinned_points.size() - 1; i >= p_indices_size; --i) {
pin_point(r[i].point_index, false);
@@ -194,7 +198,7 @@ bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) {
pinned_points.resize(p_indices_size);
- PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ PinnedPoint *w = pinned_points.ptrw();
int point_index;
for (int i = 0; i < p_indices_size; ++i) {
point_index = p_indices.get(i);
@@ -214,11 +218,11 @@ bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &
}
if ("spatial_attachment_path" == p_what) {
- PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ PinnedPoint *w = pinned_points.ptrw();
pin_point(w[p_item].point_index, true, p_value);
_make_cache_dirty();
} else if ("offset" == p_what) {
- PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ PinnedPoint *w = pinned_points.ptrw();
w[p_item].offset = p_value;
} else {
return false;
@@ -231,7 +235,7 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var
if (pinned_points.size() <= p_item) {
return false;
}
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ const PinnedPoint *r = pinned_points.ptr();
if ("point_index" == p_what) {
r_ret = r[p_item].point_index;
@@ -247,7 +251,7 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var
}
void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) {
- update_physics_server();
+ prepare_physics_server();
_reset_points_offsets();
#ifdef TOOLS_ENABLED
if (p_changed == this) {
@@ -267,7 +271,7 @@ void SoftBody::_notification(int p_what) {
RID space = get_world()->get_space();
PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space);
- update_physics_server();
+ prepare_physics_server();
} break;
case NOTIFICATION_READY: {
if (!parent_collision_ignore.is_empty())
@@ -290,21 +294,6 @@ void SoftBody::_notification(int p_what) {
set_notify_transform(true);
} break;
- case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-
- if (!simulation_started)
- return;
-
- _update_cache_pin_points_datas();
- // Submit bone attachment
- const int pinned_points_indices_size = pinned_points.size();
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
- for (int i = 0; i < pinned_points_indices_size; ++i) {
- if (r[i].spatial_attachment) {
- PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset));
- }
- }
- } break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
@@ -330,8 +319,6 @@ void SoftBody::_notification(int p_what) {
void SoftBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_draw_soft_mesh"), &SoftBody::_draw_soft_mesh);
-
ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody::set_collision_mask);
ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody::get_collision_mask);
@@ -387,14 +374,14 @@ void SoftBody::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "parent_collision_ignore", PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, "Parent collision object"), "set_parent_collision_ignore", "get_parent_collision_ignore");
ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable");
}
@@ -421,6 +408,21 @@ String SoftBody::get_configuration_warning() const {
return warning;
}
+void SoftBody::_update_physics_server() {
+ if (!simulation_started)
+ return;
+
+ _update_cache_pin_points_datas();
+ // Submit bone attachment
+ const int pinned_points_indices_size = pinned_points.size();
+ const PinnedPoint *r = pinned_points.ptr();
+ for (int i = 0; i < pinned_points_indices_size; ++i) {
+ if (r[i].spatial_attachment) {
+ PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset));
+ }
+ }
+}
+
void SoftBody::_draw_soft_mesh() {
if (get_mesh().is_null())
return;
@@ -435,6 +437,8 @@ void SoftBody::_draw_soft_mesh() {
call_deferred("set_transform", Transform());
}
+ _update_physics_server();
+
visual_server_handler.open();
PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler);
visual_server_handler.close();
@@ -442,7 +446,7 @@ void SoftBody::_draw_soft_mesh() {
visual_server_handler.commit_changes();
}
-void SoftBody::update_physics_server() {
+void SoftBody::prepare_physics_server() {
if (Engine::get_singleton()->is_editor_hint()) {
@@ -458,12 +462,12 @@ void SoftBody::update_physics_server() {
become_mesh_owner();
PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
- VS::get_singleton()->connect("frame_pre_draw", this, "_draw_soft_mesh");
+ VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh));
} else {
PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL);
- if (VS::get_singleton()->is_connected("frame_pre_draw", this, "_draw_soft_mesh")) {
- VS::get_singleton()->disconnect("frame_pre_draw", this, "_draw_soft_mesh");
+ if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh))) {
+ VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh));
}
}
}
@@ -483,14 +487,15 @@ void SoftBody::become_mesh_owner() {
// Get current mesh array and create new mesh array with necessary flag for softbody
Array surface_arrays = mesh->surface_get_arrays(0);
Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0);
+ Dictionary surface_lods = mesh->surface_get_lods(0);
uint32_t surface_format = mesh->surface_get_format(0);
- surface_format &= ~(Mesh::ARRAY_COMPRESS_VERTEX | Mesh::ARRAY_COMPRESS_NORMAL);
+ surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL);
surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
Ref<ArrayMesh> soft_mesh;
soft_mesh.instance();
- soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_format);
+ soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format);
soft_mesh->surface_set_material(0, mesh->surface_get_material(0));
set_mesh(soft_mesh);
@@ -552,15 +557,14 @@ const NodePath &SoftBody::get_parent_collision_ignore() const {
return parent_collision_ignore;
}
-void SoftBody::set_pinned_points_indices(PoolVector<SoftBody::PinnedPoint> p_pinned_points_indices) {
+void SoftBody::set_pinned_points_indices(Vector<SoftBody::PinnedPoint> p_pinned_points_indices) {
pinned_points = p_pinned_points_indices;
- PoolVector<PinnedPoint>::Read w = pinned_points.read();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
pin_point(p_pinned_points_indices[i].point_index, true);
}
}
-PoolVector<SoftBody::PinnedPoint> SoftBody::get_pinned_points_indices() {
+Vector<SoftBody::PinnedPoint> SoftBody::get_pinned_points_indices() {
return pinned_points;
}
@@ -706,8 +710,6 @@ SoftBody::SoftBody() :
ray_pickable(true) {
PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
- //set_notify_transform(true);
- set_physics_process_internal(true);
}
SoftBody::~SoftBody() {
@@ -716,7 +718,7 @@ SoftBody::~SoftBody() {
void SoftBody::reset_softbody_pin() {
PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid);
- PoolVector<PinnedPoint>::Read pps = pinned_points.read();
+ const PinnedPoint *pps = pinned_points.ptr();
for (int i = pinned_points.size() - 1; 0 < i; --i) {
PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true);
}
@@ -732,7 +734,7 @@ void SoftBody::_update_cache_pin_points_datas() {
pinned_points_cache_dirty = false;
- PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ PinnedPoint *w = pinned_points.ptrw();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
if (!w[i].spatial_attachment_path.is_empty()) {
@@ -781,8 +783,8 @@ void SoftBody::_reset_points_offsets() {
if (!Engine::get_singleton()->is_editor_hint())
return;
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
- PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ const PinnedPoint *r = pinned_points.ptr();
+ PinnedPoint *w = pinned_points.ptrw();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
if (!r[i].spatial_attachment)
@@ -808,13 +810,13 @@ int SoftBody::_get_pinned_point(int p_point_index, SoftBody::PinnedPoint *&r_poi
r_point = NULL;
return -1;
} else {
- r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points.read()[id]);
+ r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points.ptr()[id]);
return id;
}
}
int SoftBody::_has_pinned_point(int p_point_index) const {
- PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ const PinnedPoint *r = pinned_points.ptr();
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
if (p_point_index == r[i].point_index) {
return i;
diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h
index 629c2e42a5..d6c35a5989 100644
--- a/scene/3d/soft_body.h
+++ b/scene/3d/soft_body.h
@@ -41,12 +41,12 @@ class SoftBodyVisualServerHandler {
RID mesh;
int surface;
- PoolVector<uint8_t> buffer;
+ Vector<uint8_t> buffer;
uint32_t stride;
uint32_t offset_vertices;
uint32_t offset_normal;
- PoolVector<uint8_t>::Write write_buffer;
+ uint8_t *write_buffer;
private:
SoftBodyVisualServerHandler();
@@ -87,7 +87,7 @@ private:
uint32_t collision_mask;
uint32_t collision_layer;
NodePath parent_collision_ignore;
- PoolVector<PinnedPoint> pinned_points;
+ Vector<PinnedPoint> pinned_points;
bool simulation_started;
bool pinned_points_cache_dirty;
@@ -116,10 +116,11 @@ protected:
virtual String get_configuration_warning() const;
protected:
+ void _update_physics_server();
void _draw_soft_mesh();
public:
- void update_physics_server();
+ void prepare_physics_server();
void become_mesh_owner();
void set_collision_mask(uint32_t p_mask);
@@ -137,8 +138,8 @@ public:
void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore);
const NodePath &get_parent_collision_ignore() const;
- void set_pinned_points_indices(PoolVector<PinnedPoint> p_pinned_points_indices);
- PoolVector<PinnedPoint> get_pinned_points_indices();
+ void set_pinned_points_indices(Vector<PinnedPoint> p_pinned_points_indices);
+ Vector<PinnedPoint> get_pinned_points_indices();
void set_simulation_precision(int p_simulation_precision);
int get_simulation_precision();
diff --git a/scene/3d/spring_arm.cpp b/scene/3d/spring_arm.cpp
index bce0535d64..ce277dae5b 100644
--- a/scene/3d/spring_arm.cpp
+++ b/scene/3d/spring_arm.cpp
@@ -81,8 +81,8 @@ void SpringArm::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "spring_length"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spring_length"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
}
float SpringArm::get_length() const {
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index a4c81b864d..fd22076091 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "sprite_3d.h"
+
#include "core/core_string_names.h"
#include "scene/scene_string_names.h"
@@ -177,8 +178,6 @@ void SpriteBase3D::_im_update() {
_draw();
pending_update = false;
-
- //texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
}
void SpriteBase3D::_queue_update() {
@@ -197,18 +196,18 @@ AABB SpriteBase3D::get_aabb() const {
return aabb;
}
-PoolVector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
+Vector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
+ return Vector<Face3>();
}
Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
if (triangle_mesh.is_valid())
return triangle_mesh;
- PoolVector<Vector3> faces;
+ Vector<Vector3> faces;
faces.resize(6);
- PoolVector<Vector3>::Write facesw = faces.write();
+ Vector3 *facesw = faces.ptrw();
Rect2 final_rect = get_item_rect();
@@ -254,8 +253,6 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
facesw[j] = vtx;
}
- facesw.release();
-
triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh));
triangle_mesh->create(faces);
@@ -286,14 +283,14 @@ SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const {
return alpha_cut;
}
-void SpriteBase3D::set_billboard_mode(SpatialMaterial::BillboardMode p_mode) {
+void SpriteBase3D::set_billboard_mode(StandardMaterial3D::BillboardMode p_mode) {
ERR_FAIL_INDEX(p_mode, 3);
billboard_mode = p_mode;
_queue_update();
}
-SpatialMaterial::BillboardMode SpriteBase3D::get_billboard_mode() const {
+StandardMaterial3D::BillboardMode SpriteBase3D::get_billboard_mode() const {
return billboard_mode;
}
@@ -336,16 +333,13 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
- ClassDB::bind_method(D_METHOD("_queue_update"), &SpriteBase3D::_queue_update);
- ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update);
-
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_opacity", "get_opacity");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_opacity", "get_opacity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X-Axis,Y-Axis,Z-Axis"), "set_axis", "get_axis");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode");
@@ -377,7 +371,7 @@ SpriteBase3D::SpriteBase3D() {
flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
alpha_cut = ALPHA_CUT_DISABLED;
- billboard_mode = SpatialMaterial::BILLBOARD_DISABLED;
+ billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
axis = Vector3::AXIS_Z;
pixel_size = 0.01;
modulate = Color(1, 1, 1, 1);
@@ -480,10 +474,10 @@ void Sprite3D::_draw() {
tangent = Plane(1, 0, 0, 1);
}
- RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
+ RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y);
VS::get_singleton()->immediate_set_material(immediate, mat);
- VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
+ VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLES, texture->get_rid());
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -504,15 +498,18 @@ void Sprite3D::_draw() {
AABB aabb;
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 6; i++) {
+
+ static const int index[6] = { 0, 1, 2, 0, 2, 3 };
+
VS::get_singleton()->immediate_normal(immediate, normal);
VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
Vector3 vtx;
- vtx[x_axis] = vertices[i][0];
- vtx[y_axis] = vertices[i][1];
+ vtx[x_axis] = vertices[index[i]][0];
+ vtx[y_axis] = vertices[index[i]][1];
VS::get_singleton()->immediate_vertex(immediate, vtx);
if (i == 0) {
aabb.position = vtx;
@@ -525,22 +522,25 @@ void Sprite3D::_draw() {
VS::get_singleton()->immediate_end(immediate);
}
-void Sprite3D::set_texture(const Ref<Texture> &p_texture) {
+void Sprite3D::_texture_changed() {
+ _queue_update();
+}
+
+void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
if (p_texture == texture)
return;
if (texture.is_valid()) {
- texture->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_queue_update);
+ texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
}
texture = p_texture;
if (texture.is_valid()) {
- texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
- texture->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_queue_update);
+ texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
}
_queue_update();
}
-Ref<Texture> Sprite3D::get_texture() const {
+Ref<Texture2D> Sprite3D::get_texture() const {
return texture;
}
@@ -691,7 +691,7 @@ void Sprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite3D::set_hframes);
ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_GROUP("Animation", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
@@ -731,7 +731,7 @@ void AnimatedSprite3D::_draw() {
return;
}
- Ref<Texture> texture = frames->get_frame(animation, frame);
+ Ref<Texture2D> texture = frames->get_frame(animation, frame);
if (!texture.is_valid())
return; //no texuture no life
Vector2 tsize = texture->get_size();
@@ -808,11 +808,11 @@ void AnimatedSprite3D::_draw() {
tangent = Plane(1, 0, 0, -1);
}
- RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
+ RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y);
VS::get_singleton()->immediate_set_material(immediate, mat);
- VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
+ VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLES, texture->get_rid());
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -833,15 +833,21 @@ void AnimatedSprite3D::_draw() {
AABB aabb;
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 6; i++) {
+
+ static const int indices[6] = {
+ 0, 1, 2,
+ 0, 2, 3
+ };
+
VS::get_singleton()->immediate_normal(immediate, normal);
VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
Vector3 vtx;
- vtx[x_axis] = vertices[i][0];
- vtx[y_axis] = vertices[i][1];
+ vtx[x_axis] = vertices[indices[i]][0];
+ vtx[y_axis] = vertices[indices[i]][1];
VS::get_singleton()->immediate_vertex(immediate, vtx);
if (i == 0) {
aabb.position = vtx;
@@ -946,10 +952,10 @@ void AnimatedSprite3D::_notification(int p_what) {
void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
if (frames.is_valid())
- frames->disconnect("changed", this, "_res_changed");
+ frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
frames = p_frames;
if (frames.is_valid())
- frames->connect("changed", this, "_res_changed");
+ frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
if (!frames.is_valid()) {
frame = 0;
@@ -1003,7 +1009,7 @@ Rect2 AnimatedSprite3D::get_item_rect() const {
return Rect2(0, 0, 1, 1);
}
- Ref<Texture> t;
+ Ref<Texture2D> t;
if (animation)
t = frames->get_frame(animation, frame);
if (t.is_null())
@@ -1119,12 +1125,10 @@ void AnimatedSprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame);
- ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite3D::_res_changed);
-
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing");
}
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index ddbade147c..082884c83b 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -80,7 +80,7 @@ private:
bool flags[FLAG_MAX];
AlphaCutMode alpha_cut;
- SpatialMaterial::BillboardMode billboard_mode;
+ StandardMaterial3D::BillboardMode billboard_mode;
bool pending_update;
void _im_update();
@@ -131,13 +131,13 @@ public:
void set_alpha_cut_mode(AlphaCutMode p_mode);
AlphaCutMode get_alpha_cut_mode() const;
- void set_billboard_mode(SpatialMaterial::BillboardMode p_mode);
- SpatialMaterial::BillboardMode get_billboard_mode() const;
+ void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode);
+ StandardMaterial3D::BillboardMode get_billboard_mode() const;
virtual Rect2 get_item_rect() const = 0;
virtual AABB get_aabb() const;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const;
Ref<TriangleMesh> generate_triangle_mesh() const;
SpriteBase3D();
@@ -147,7 +147,7 @@ public:
class Sprite3D : public SpriteBase3D {
GDCLASS(Sprite3D, SpriteBase3D);
- Ref<Texture> texture;
+ Ref<Texture2D> texture;
bool region;
Rect2 region_rect;
@@ -157,6 +157,8 @@ class Sprite3D : public SpriteBase3D {
int vframes;
int hframes;
+ void _texture_changed();
+
protected:
virtual void _draw();
static void _bind_methods();
@@ -164,8 +166,8 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
- void set_texture(const Ref<Texture> &p_texture);
- Ref<Texture> get_texture() const;
+ void set_texture(const Ref<Texture2D> &p_texture);
+ Ref<Texture2D> get_texture() const;
void set_region(bool p_region);
bool is_region() const;
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index 92b17d5056..c249d844d1 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -282,24 +282,24 @@ void VehicleWheel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_steering"), &VehicleWheel::get_steering);
ADD_GROUP("Per-Wheel Motion", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
ADD_GROUP("VehicleBody Motion", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering");
ADD_GROUP("Wheel", "wheel_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_roll_influence"), "set_roll_influence", "get_roll_influence");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_radius"), "set_radius", "get_radius");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_rest_length"), "set_suspension_rest_length", "get_suspension_rest_length");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel_friction_slip"), "set_friction_slip", "get_friction_slip");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_roll_influence"), "set_roll_influence", "get_roll_influence");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_radius"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_rest_length"), "set_suspension_rest_length", "get_suspension_rest_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_friction_slip"), "set_friction_slip", "get_friction_slip");
ADD_GROUP("Suspension", "suspension_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension_travel"), "set_suspension_travel", "get_suspension_travel");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension_stiffness"), "set_suspension_stiffness", "get_suspension_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension_max_force"), "set_suspension_max_force", "get_suspension_max_force");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_travel"), "set_suspension_travel", "get_suspension_travel");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_stiffness"), "set_suspension_stiffness", "get_suspension_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_max_force"), "set_suspension_max_force", "get_suspension_max_force");
ADD_GROUP("Damping", "damping_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_compression"), "set_damping_compression", "get_damping_compression");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_relaxation"), "set_damping_relaxation", "get_damping_relaxation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_compression"), "set_damping_compression", "get_damping_compression");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_relaxation"), "set_damping_relaxation", "get_damping_relaxation");
}
void VehicleWheel::set_engine_force(float p_engine_force) {
@@ -364,9 +364,8 @@ VehicleWheel::VehicleWheel() {
steers = false;
engine_traction = false;
-
m_steering = real_t(0.);
- //m_engineForce = real_t(0.);
+ m_engineForce = real_t(0.);
m_rotation = real_t(0.);
m_deltaRotation = real_t(0.);
m_brake = real_t(0.);
@@ -975,9 +974,9 @@ void VehicleBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_steering"), &VehicleBody::get_steering);
ADD_GROUP("Motion", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
}
VehicleBody::VehicleBody() {
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index 510442dc1c..986607f18d 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -170,7 +170,7 @@ void VisibilityEnabler::_find_nodes(Node *p_node) {
if (add) {
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, this, "_node_removed", varray(p_node), CONNECT_ONESHOT);
+ p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler::_node_removed), varray(p_node), CONNECT_ONESHOT);
nodes[p_node] = meta;
_change_node_state(p_node, false);
}
@@ -208,7 +208,7 @@ void VisibilityEnabler::_notification(int p_what) {
if (!visible)
_change_node_state(E->key(), true);
- E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, "_node_removed");
+ E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler::_node_removed));
}
nodes.clear();
@@ -247,7 +247,6 @@ void VisibilityEnabler::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler::set_enabler);
ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler::is_enabler_enabled);
- ClassDB::bind_method(D_METHOD("_node_removed"), &VisibilityEnabler::_node_removed);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES);
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index 4574dfac5f..105ce9ca74 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -294,10 +294,11 @@ void GeometryInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance::get_aabb);
ADD_GROUP("Geometry", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_override", "get_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_dynamic_gi"), "set_flag", "get_flag", FLAG_USE_DYNAMIC_GI);
ADD_GROUP("LOD", "lod_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
@@ -313,6 +314,7 @@ void GeometryInstance::_bind_methods() {
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT);
+ BIND_ENUM_CONSTANT(FLAG_USE_DYNAMIC_GI);
BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
BIND_ENUM_CONSTANT(FLAG_MAX);
}
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index f115748952..fee6787c87 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -63,7 +63,7 @@ public:
RID get_instance() const;
virtual AABB get_aabb() const = 0;
- virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
virtual AABB get_transformed_aabb() const; // helper
@@ -87,6 +87,7 @@ class GeometryInstance : public VisualInstance {
public:
enum Flags {
FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT,
+ FLAG_USE_DYNAMIC_GI = VS::INSTANCE_FLAG_USE_DYNAMIC_GI,
FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
FLAG_MAX = VS::INSTANCE_FLAG_MAX,
};
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
deleted file mode 100644
index c1ec59d49f..0000000000
--- a/scene/3d/voxel_light_baker.cpp
+++ /dev/null
@@ -1,2486 +0,0 @@
-/*************************************************************************/
-/* voxel_light_baker.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "voxel_light_baker.h"
-
-#include "core/os/os.h"
-#include "core/os/threaded_array_processor.h"
-
-#include <stdlib.h>
-
-#define FINDMINMAX(x0, x1, x2, min, max) \
- min = max = x0; \
- if (x1 < min) min = x1; \
- if (x1 > max) max = x1; \
- if (x2 < min) min = x2; \
- if (x2 > max) max = x2;
-
-static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) {
- int q;
- Vector3 vmin, vmax;
- for (q = 0; q <= 2; q++) {
- if (normal[q] > 0.0f) {
- vmin[q] = -maxbox[q];
- vmax[q] = maxbox[q];
- } else {
- vmin[q] = maxbox[q];
- vmax[q] = -maxbox[q];
- }
- }
- if (normal.dot(vmin) + d > 0.0f) return false;
- if (normal.dot(vmax) + d >= 0.0f) return true;
-
- return false;
-}
-
-/*======================== X-tests ========================*/
-#define AXISTEST_X01(a, b, fa, fb) \
- p0 = a * v0.y - b * v0.z; \
- p2 = a * v2.y - b * v2.z; \
- if (p0 < p2) { \
- min = p0; \
- max = p2; \
- } else { \
- min = p2; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_X2(a, b, fa, fb) \
- p0 = a * v0.y - b * v0.z; \
- p1 = a * v1.y - b * v1.z; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-/*======================== Y-tests ========================*/
-#define AXISTEST_Y02(a, b, fa, fb) \
- p0 = -a * v0.x + b * v0.z; \
- p2 = -a * v2.x + b * v2.z; \
- if (p0 < p2) { \
- min = p0; \
- max = p2; \
- } else { \
- min = p2; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_Y1(a, b, fa, fb) \
- p0 = -a * v0.x + b * v0.z; \
- p1 = -a * v1.x + b * v1.z; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
- if (min > rad || max < -rad) return false;
-
-/*======================== Z-tests ========================*/
-
-#define AXISTEST_Z12(a, b, fa, fb) \
- p1 = a * v1.x - b * v1.y; \
- p2 = a * v2.x - b * v2.y; \
- if (p2 < p1) { \
- min = p2; \
- max = p1; \
- } else { \
- min = p1; \
- max = p2; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
- if (min > rad || max < -rad) return false;
-
-#define AXISTEST_Z0(a, b, fa, fb) \
- p0 = a * v0.x - b * v0.y; \
- p1 = a * v1.x - b * v1.y; \
- if (p0 < p1) { \
- min = p0; \
- max = p1; \
- } else { \
- min = p1; \
- max = p0; \
- } \
- rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
- if (min > rad || max < -rad) return false;
-
-static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) {
-
- /* use separating axis theorem to test overlap between triangle and box */
- /* need to test for overlap in these directions: */
- /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
- /* we do not even need to test these) */
- /* 2) normal of the triangle */
- /* 3) crossproduct(edge from tri, {x,y,z}-directin) */
- /* this gives 3x3=9 more tests */
- Vector3 v0, v1, v2;
- float min, max, d, p0, p1, p2, rad, fex, fey, fez;
- Vector3 normal, e0, e1, e2;
-
- /* This is the fastest branch on Sun */
- /* move everything so that the boxcenter is in (0,0,0) */
-
- v0 = triverts[0] - boxcenter;
- v1 = triverts[1] - boxcenter;
- v2 = triverts[2] - boxcenter;
-
- /* compute triangle edges */
- e0 = v1 - v0; /* tri edge 0 */
- e1 = v2 - v1; /* tri edge 1 */
- e2 = v0 - v2; /* tri edge 2 */
-
- /* Bullet 3: */
- /* test the 9 tests first (this was faster) */
- fex = Math::abs(e0.x);
- fey = Math::abs(e0.y);
- fez = Math::abs(e0.z);
- AXISTEST_X01(e0.z, e0.y, fez, fey);
- AXISTEST_Y02(e0.z, e0.x, fez, fex);
- AXISTEST_Z12(e0.y, e0.x, fey, fex);
-
- fex = Math::abs(e1.x);
- fey = Math::abs(e1.y);
- fez = Math::abs(e1.z);
- AXISTEST_X01(e1.z, e1.y, fez, fey);
- AXISTEST_Y02(e1.z, e1.x, fez, fex);
- AXISTEST_Z0(e1.y, e1.x, fey, fex);
-
- fex = Math::abs(e2.x);
- fey = Math::abs(e2.y);
- fez = Math::abs(e2.z);
- AXISTEST_X2(e2.z, e2.y, fez, fey);
- AXISTEST_Y1(e2.z, e2.x, fez, fex);
- AXISTEST_Z12(e2.y, e2.x, fey, fex);
-
- /* Bullet 1: */
- /* first test overlap in the {x,y,z}-directions */
- /* find min, max of the triangle each direction, and test for overlap in */
- /* that direction -- this is equivalent to testing a minimal AABB around */
- /* the triangle against the AABB */
-
- /* test in X-direction */
- FINDMINMAX(v0.x, v1.x, v2.x, min, max);
- if (min > boxhalfsize.x || max < -boxhalfsize.x) return false;
-
- /* test in Y-direction */
- FINDMINMAX(v0.y, v1.y, v2.y, min, max);
- if (min > boxhalfsize.y || max < -boxhalfsize.y) return false;
-
- /* test in Z-direction */
- FINDMINMAX(v0.z, v1.z, v2.z, min, max);
- if (min > boxhalfsize.z || max < -boxhalfsize.z) return false;
-
- /* Bullet 2: */
- /* test if the box intersects the plane of the triangle */
- /* compute plane equation of triangle: normal*x+d=0 */
- normal = e0.cross(e1);
- d = -normal.dot(v0); /* plane eq: normal.x+d=0 */
- return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */
-}
-
-static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
-
- if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
- r_uv = p_uv[0];
- r_normal = p_normal[0];
- return;
- }
- if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) {
- r_uv = p_uv[1];
- r_normal = p_normal[1];
- return;
- }
- if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) {
- r_uv = p_uv[2];
- r_normal = p_normal[2];
- return;
- }
-
- Vector3 v0 = p_vtx[1] - p_vtx[0];
- Vector3 v1 = p_vtx[2] - p_vtx[0];
- Vector3 v2 = p_pos - p_vtx[0];
-
- float d00 = v0.dot(v0);
- float d01 = v0.dot(v1);
- float d11 = v1.dot(v1);
- float d20 = v2.dot(v0);
- float d21 = v2.dot(v1);
- float denom = (d00 * d11 - d01 * d01);
- if (denom == 0) {
- r_uv = p_uv[0];
- r_normal = p_normal[0];
- return;
- }
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
-
- r_uv = p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
- r_normal = (p_normal[0] * u + p_normal[1] * v + p_normal[2] * w).normalized();
-}
-
-void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) {
-
- if (p_level == cell_subdiv - 1) {
- //plot the face by guessing its albedo and emission value
-
- //find best axis to map to, for scanning values
- int closest_axis = 0;
- float closest_dot = 0;
-
- Plane plane = Plane(p_vtx[0], p_vtx[1], p_vtx[2]);
- Vector3 normal = plane.normal;
-
- for (int i = 0; i < 3; i++) {
-
- Vector3 axis;
- axis[i] = 1.0;
- float dot = ABS(normal.dot(axis));
- if (i == 0 || dot > closest_dot) {
- closest_axis = i;
- closest_dot = dot;
- }
- }
-
- Vector3 axis;
- axis[closest_axis] = 1.0;
- Vector3 t1;
- t1[(closest_axis + 1) % 3] = 1.0;
- Vector3 t2;
- t2[(closest_axis + 2) % 3] = 1.0;
-
- t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width);
- t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width);
-
- Color albedo_accum;
- Color emission_accum;
- Vector3 normal_accum;
-
- float alpha = 0.0;
-
- //map to a grid average in the best axis for this face
- for (int i = 0; i < color_scan_cell_width; i++) {
-
- Vector3 ofs_i = float(i) * t1;
-
- for (int j = 0; j < color_scan_cell_width; j++) {
-
- Vector3 ofs_j = float(j) * t2;
-
- Vector3 from = p_aabb.position + ofs_i + ofs_j;
- Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis];
- Vector3 half = (to - from) * 0.5;
-
- //is in this cell?
- if (!fast_tri_box_overlap(from + half, half, p_vtx)) {
- continue; //face does not span this cell
- }
-
- //go from -size to +size*2 to avoid skipping collisions
- Vector3 ray_from = from + (t1 + t2) * 0.5 - axis * p_aabb.size[closest_axis];
- Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis] * 2;
-
- if (normal.dot(ray_from - ray_to) < 0) {
- SWAP(ray_from, ray_to);
- }
-
- Vector3 intersection;
-
- if (!plane.intersects_segment(ray_from, ray_to, &intersection)) {
- if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) {
- intersection = plane.project(ray_from);
- } else {
-
- intersection = plane.project(ray_to);
- }
- }
-
- intersection = Face3(p_vtx[0], p_vtx[1], p_vtx[2]).get_closest_point_to(intersection);
-
- Vector2 uv;
- Vector3 lnormal;
- get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal);
- if (lnormal == Vector3()) //just in case normal as nor provided
- lnormal = normal;
-
- int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
- int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
-
- int ofs = uv_y * bake_texture_size + uv_x;
- albedo_accum.r += p_material.albedo[ofs].r;
- albedo_accum.g += p_material.albedo[ofs].g;
- albedo_accum.b += p_material.albedo[ofs].b;
- albedo_accum.a += p_material.albedo[ofs].a;
-
- emission_accum.r += p_material.emission[ofs].r;
- emission_accum.g += p_material.emission[ofs].g;
- emission_accum.b += p_material.emission[ofs].b;
-
- normal_accum += lnormal;
-
- alpha += 1.0;
- }
- }
-
- if (alpha == 0) {
- //could not in any way get texture information.. so use closest point to center
-
- Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]);
- Vector3 inters = f.get_closest_point_to(p_aabb.position + p_aabb.size * 0.5);
-
- Vector3 lnormal;
- Vector2 uv;
- get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal);
- if (lnormal == Vector3()) //just in case normal as nor provided
- lnormal = normal;
-
- int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
- int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
-
- int ofs = uv_y * bake_texture_size + uv_x;
-
- alpha = 1.0 / (color_scan_cell_width * color_scan_cell_width);
-
- albedo_accum.r = p_material.albedo[ofs].r * alpha;
- albedo_accum.g = p_material.albedo[ofs].g * alpha;
- albedo_accum.b = p_material.albedo[ofs].b * alpha;
- albedo_accum.a = p_material.albedo[ofs].a * alpha;
-
- emission_accum.r = p_material.emission[ofs].r * alpha;
- emission_accum.g = p_material.emission[ofs].g * alpha;
- emission_accum.b = p_material.emission[ofs].b * alpha;
-
- normal_accum = lnormal * alpha;
-
- } else {
-
- float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width);
- alpha *= accdiv;
-
- albedo_accum.r *= accdiv;
- albedo_accum.g *= accdiv;
- albedo_accum.b *= accdiv;
- albedo_accum.a *= accdiv;
-
- emission_accum.r *= accdiv;
- emission_accum.g *= accdiv;
- emission_accum.b *= accdiv;
-
- normal_accum *= accdiv;
- }
-
- //put this temporarily here, corrected in a later step
- bake_cells.write[p_idx].albedo[0] += albedo_accum.r;
- bake_cells.write[p_idx].albedo[1] += albedo_accum.g;
- bake_cells.write[p_idx].albedo[2] += albedo_accum.b;
- bake_cells.write[p_idx].emission[0] += emission_accum.r;
- bake_cells.write[p_idx].emission[1] += emission_accum.g;
- bake_cells.write[p_idx].emission[2] += emission_accum.b;
- bake_cells.write[p_idx].normal[0] += normal_accum.x;
- bake_cells.write[p_idx].normal[1] += normal_accum.y;
- bake_cells.write[p_idx].normal[2] += normal_accum.z;
- bake_cells.write[p_idx].alpha += alpha;
-
- } else {
- //go down
-
- int half = (1 << (cell_subdiv - 1)) >> (p_level + 1);
- for (int i = 0; i < 8; i++) {
-
- AABB aabb = p_aabb;
- aabb.size *= 0.5;
-
- int nx = p_x;
- int ny = p_y;
- int nz = p_z;
-
- if (i & 1) {
- aabb.position.x += aabb.size.x;
- nx += half;
- }
- if (i & 2) {
- aabb.position.y += aabb.size.y;
- ny += half;
- }
- if (i & 4) {
- aabb.position.z += aabb.size.z;
- nz += half;
- }
- //make sure to not plot beyond limits
- if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2])
- continue;
-
- {
- AABB test_aabb = aabb;
- //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
- Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
-
- if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
- //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) {
- //does not fit in child, go on
- continue;
- }
- }
-
- if (bake_cells[p_idx].children[i] == CHILD_EMPTY) {
- //sub cell must be created
-
- uint32_t child_idx = bake_cells.size();
- bake_cells.write[p_idx].children[i] = child_idx;
- bake_cells.resize(bake_cells.size() + 1);
- bake_cells.write[child_idx].level = p_level + 1;
- }
-
- _plot_face(bake_cells[p_idx].children[i], p_level + 1, nx, ny, nz, p_vtx, p_normal, p_uv, p_material, aabb);
- }
- }
-}
-
-Vector<Color> VoxelLightBaker::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) {
-
- Vector<Color> ret;
-
- if (p_image.is_null() || p_image->empty()) {
-
- ret.resize(bake_texture_size * bake_texture_size);
- for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
- ret.write[i] = p_color_add;
- }
-
- return ret;
- }
- p_image = p_image->duplicate();
-
- if (p_image->is_compressed()) {
- p_image->decompress();
- }
- p_image->convert(Image::FORMAT_RGBA8);
- p_image->resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC);
-
- PoolVector<uint8_t>::Read r = p_image->get_data().read();
- ret.resize(bake_texture_size * bake_texture_size);
-
- for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
- Color c;
- c.r = (r[i * 4 + 0] / 255.0) * p_color_mul.r + p_color_add.r;
- c.g = (r[i * 4 + 1] / 255.0) * p_color_mul.g + p_color_add.g;
- c.b = (r[i * 4 + 2] / 255.0) * p_color_mul.b + p_color_add.b;
-
- c.a = r[i * 4 + 3] / 255.0;
-
- ret.write[i] = c;
- }
-
- return ret;
-}
-
-VoxelLightBaker::MaterialCache VoxelLightBaker::_get_material_cache(Ref<Material> p_material) {
-
- //this way of obtaining materials is inaccurate and also does not support some compressed formats very well
- Ref<SpatialMaterial> mat = p_material;
-
- Ref<Material> material = mat; //hack for now
-
- if (material_cache.has(material)) {
- return material_cache[material];
- }
-
- MaterialCache mc;
-
- if (mat.is_valid()) {
-
- Ref<Texture> albedo_tex = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO);
-
- Ref<Image> img_albedo;
- if (albedo_tex.is_valid()) {
-
- img_albedo = albedo_tex->get_data();
- mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative
- } else {
- mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive
- }
-
- Ref<Texture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION);
-
- Color emission_col = mat->get_emission();
- float emission_energy = mat->get_emission_energy();
-
- Ref<Image> img_emission;
-
- if (emission_tex.is_valid()) {
-
- img_emission = emission_tex->get_data();
- }
-
- if (mat->get_emission_operator() == SpatialMaterial::EMISSION_OP_ADD) {
- mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy);
- } else {
- mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0));
- }
-
- } else {
- Ref<Image> empty;
-
- mc.albedo = _get_bake_texture(empty, Color(0, 0, 0), Color(1, 1, 1));
- mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0));
- }
-
- material_cache[p_material] = mc;
- return mc;
-}
-
-void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) {
-
- for (int i = 0; i < p_mesh->get_surface_count(); i++) {
-
- if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
- continue; //only triangles
-
- Ref<Material> src_material;
-
- if (p_override_material.is_valid()) {
- src_material = p_override_material;
- } else if (i < p_materials.size() && p_materials[i].is_valid()) {
- src_material = p_materials[i];
- } else {
- src_material = p_mesh->surface_get_material(i);
- }
- MaterialCache material = _get_material_cache(src_material);
-
- Array a = p_mesh->surface_get_arrays(i);
-
- PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
- PoolVector<Vector3>::Read vr = vertices.read();
- PoolVector<Vector2> uv = a[Mesh::ARRAY_TEX_UV];
- PoolVector<Vector2>::Read uvr;
- PoolVector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
- PoolVector<Vector3>::Read nr;
- PoolVector<int> index = a[Mesh::ARRAY_INDEX];
-
- bool read_uv = false;
- bool read_normals = false;
-
- if (uv.size()) {
-
- uvr = uv.read();
- read_uv = true;
- }
-
- if (normals.size()) {
- read_normals = true;
- nr = normals.read();
- }
-
- if (index.size()) {
-
- int facecount = index.size() / 3;
- PoolVector<int>::Read ir = index.read();
-
- for (int j = 0; j < facecount; j++) {
-
- Vector3 vtxs[3];
- Vector2 uvs[3];
- Vector3 normal[3];
-
- for (int k = 0; k < 3; k++) {
- vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]);
- }
-
- if (read_uv) {
- for (int k = 0; k < 3; k++) {
- uvs[k] = uvr[ir[j * 3 + k]];
- }
- }
-
- if (read_normals) {
- for (int k = 0; k < 3; k++) {
- normal[k] = nr[ir[j * 3 + k]];
- }
- }
-
- //test against original bounds
- if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
- continue;
- //plot
- _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
- }
-
- } else {
-
- int facecount = vertices.size() / 3;
-
- for (int j = 0; j < facecount; j++) {
-
- Vector3 vtxs[3];
- Vector2 uvs[3];
- Vector3 normal[3];
-
- for (int k = 0; k < 3; k++) {
- vtxs[k] = p_xform.xform(vr[j * 3 + k]);
- }
-
- if (read_uv) {
- for (int k = 0; k < 3; k++) {
- uvs[k] = uvr[j * 3 + k];
- }
- }
-
- if (read_normals) {
- for (int k = 0; k < 3; k++) {
- normal[k] = nr[j * 3 + k];
- }
- }
-
- //test against original bounds
- if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
- continue;
- //plot face
- _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
- }
- }
- }
-
- max_original_cells = bake_cells.size();
-}
-
-void VoxelLightBaker::_init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent) {
-
- bake_light.write[p_idx].x = p_x;
- bake_light.write[p_idx].y = p_y;
- bake_light.write[p_idx].z = p_z;
-
- if (p_level == cell_subdiv - 1) {
-
- bake_light.write[p_idx].next_leaf = first_leaf;
- first_leaf = p_idx;
- } else {
-
- //go down
- int half = (1 << (cell_subdiv - 1)) >> (p_level + 1);
- for (int i = 0; i < 8; i++) {
-
- uint32_t child = bake_cells[p_idx].children[i];
-
- if (child == CHILD_EMPTY)
- continue;
-
- int nx = p_x;
- int ny = p_y;
- int nz = p_z;
-
- if (i & 1)
- nx += half;
- if (i & 2)
- ny += half;
- if (i & 4)
- nz += half;
-
- _init_light_plot(child, p_level + 1, nx, ny, nz, p_idx);
- }
- }
-}
-
-void VoxelLightBaker::begin_bake_light(BakeQuality p_quality, BakeMode p_bake_mode, float p_propagation, float p_energy) {
- _check_init_light();
- propagation = p_propagation;
- bake_quality = p_quality;
- bake_mode = p_bake_mode;
- energy = p_energy;
-}
-
-void VoxelLightBaker::_check_init_light() {
- if (bake_light.size() == 0) {
-
- direct_lights_baked = false;
- leaf_voxel_count = 0;
- _fixup_plot(0, 0); //pre fixup, so normal, albedo, emission, etc. work for lighting.
- bake_light.resize(bake_cells.size());
- print_line("bake light size: " + itos(bake_light.size()));
- //zeromem(bake_light.ptrw(), bake_light.size() * sizeof(Light));
- first_leaf = -1;
- _init_light_plot(0, 0, 0, 0, 0, CHILD_EMPTY);
- }
-}
-
-static float _get_normal_advance(const Vector3 &p_normal) {
-
- Vector3 normal = p_normal;
- Vector3 unorm = normal.abs();
-
- if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
- // x code
- unorm = normal.x > 0.0 ? Vector3(1.0, 0.0, 0.0) : Vector3(-1.0, 0.0, 0.0);
- } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
- // y code
- unorm = normal.y > 0.0 ? Vector3(0.0, 1.0, 0.0) : Vector3(0.0, -1.0, 0.0);
- } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
- // z code
- unorm = normal.z > 0.0 ? Vector3(0.0, 0.0, 1.0) : Vector3(0.0, 0.0, -1.0);
- } else {
- // oh-no we messed up code
- // has to be
- unorm = Vector3(1.0, 0.0, 0.0);
- }
-
- return 1.0 / normal.dot(unorm);
-}
-
-static const Vector3 aniso_normal[6] = {
- Vector3(-1, 0, 0),
- Vector3(1, 0, 0),
- Vector3(0, -1, 0),
- Vector3(0, 1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, 1)
-};
-
-uint32_t VoxelLightBaker::_find_cell_at_pos(const Cell *cells, int x, int y, int z) {
-
- uint32_t cell = 0;
-
- int ofs_x = 0;
- int ofs_y = 0;
- int ofs_z = 0;
- int size = 1 << (cell_subdiv - 1);
- int half = size / 2;
-
- if (x < 0 || x >= size)
- return -1;
- if (y < 0 || y >= size)
- return -1;
- if (z < 0 || z >= size)
- return -1;
-
- for (int i = 0; i < cell_subdiv - 1; i++) {
-
- const Cell *bc = &cells[cell];
-
- int child = 0;
- if (x >= ofs_x + half) {
- child |= 1;
- ofs_x += half;
- }
- if (y >= ofs_y + half) {
- child |= 2;
- ofs_y += half;
- }
- if (z >= ofs_z + half) {
- child |= 4;
- ofs_z += half;
- }
-
- cell = bc->children[child];
- if (cell == CHILD_EMPTY)
- return CHILD_EMPTY;
-
- half >>= 1;
- }
-
- return cell;
-}
-void VoxelLightBaker::plot_light_directional(const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, bool p_direct) {
-
- _check_init_light();
-
- float max_len = Vector3(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]).length() * 1.1;
-
- if (p_direct)
- direct_lights_baked = true;
-
- Vector3 light_axis = p_direction;
- Plane clip[3];
- int clip_planes = 0;
-
- Light *light_data = bake_light.ptrw();
- const Cell *cells = bake_cells.ptr();
-
- for (int i = 0; i < 3; i++) {
-
- if (Math::is_zero_approx(light_axis[i]))
- continue;
- clip[clip_planes].normal[i] = 1.0;
-
- if (light_axis[i] < 0) {
-
- clip[clip_planes].d = axis_cell_size[i] + 1;
- } else {
- clip[clip_planes].d -= 1.0;
- }
-
- clip_planes++;
- }
-
- float distance_adv = _get_normal_advance(light_axis);
-
- int success_count = 0;
-
- Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy;
-
- int idx = first_leaf;
- while (idx >= 0) {
-
- Light *light = &light_data[idx];
-
- Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5);
- to += -light_axis.sign() * 0.47; //make it more likely to receive a ray
-
- Vector3 from = to - max_len * light_axis;
-
- for (int j = 0; j < clip_planes; j++) {
-
- clip[j].intersects_segment(from, to, &from);
- }
-
- float distance = (to - from).length();
- distance += distance_adv - Math::fmod(distance, distance_adv); //make it reach the center of the box always
- from = to - light_axis * distance;
-
- uint32_t result = 0xFFFFFFFF;
-
- while (distance > -distance_adv) { //use this to avoid precision errors
-
- result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z)));
- if (result != 0xFFFFFFFF) {
- break;
- }
-
- from += light_axis * distance_adv;
- distance -= distance_adv;
- }
-
- if (result == (uint32_t)idx) {
- //cell hit itself! hooray!
-
- Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]);
- if (normal == Vector3()) {
- for (int i = 0; i < 6; i++) {
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0];
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1];
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2];
- }
-
- } else {
-
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-normal));
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s;
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s;
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s;
- }
- }
-
- if (p_direct) {
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
- light->direct_accum[i][0] += light_energy.x * s;
- light->direct_accum[i][1] += light_energy.y * s;
- light->direct_accum[i][2] += light_energy.z * s;
- }
- }
- success_count++;
- }
-
- idx = light_data[idx].next_leaf;
- }
-}
-
-void VoxelLightBaker::plot_light_omni(const Vector3 &p_pos, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, bool p_direct) {
-
- _check_init_light();
-
- if (p_direct)
- direct_lights_baked = true;
-
- Plane clip[3];
- int clip_planes = 0;
-
- // uint64_t us = OS::get_singleton()->get_ticks_usec();
-
- Vector3 light_pos = to_cell_space.xform(p_pos) + Vector3(0.5, 0.5, 0.5);
- //Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized();
-
- float local_radius = to_cell_space.basis.xform(Vector3(0, 0, 1)).length() * p_radius;
-
- Light *light_data = bake_light.ptrw();
- const Cell *cells = bake_cells.ptr();
- Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy;
-
- int idx = first_leaf;
- while (idx >= 0) {
-
- Light *light = &light_data[idx];
-
- Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5);
- to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray
-
- Vector3 light_axis = (to - light_pos).normalized();
- float distance_adv = _get_normal_advance(light_axis);
-
- Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]);
-
- if (normal != Vector3() && normal.dot(-light_axis) < 0.001) {
- idx = light_data[idx].next_leaf;
- continue;
- }
-
- float att = 1.0;
- {
- float d = light_pos.distance_to(to);
- if (d + distance_adv > local_radius) {
- idx = light_data[idx].next_leaf;
- continue; // too far away
- }
-
- float dt = CLAMP((d + distance_adv) / local_radius, 0, 1);
- att *= powf(1.0 - dt, p_attenutation);
- }
-
- clip_planes = 0;
-
- for (int c = 0; c < 3; c++) {
-
- if (Math::is_zero_approx(light_axis[c]))
- continue;
- clip[clip_planes].normal[c] = 1.0;
-
- if (light_axis[c] < 0) {
-
- clip[clip_planes].d = (1 << (cell_subdiv - 1)) + 1;
- } else {
- clip[clip_planes].d -= 1.0;
- }
-
- clip_planes++;
- }
-
- Vector3 from = light_pos;
-
- for (int j = 0; j < clip_planes; j++) {
-
- clip[j].intersects_segment(from, to, &from);
- }
-
- float distance = (to - from).length();
-
- distance -= Math::fmod(distance, distance_adv); //make it reach the center of the box always, but this tame make it closer
- from = to - light_axis * distance;
- to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray
-
- uint32_t result = 0xFFFFFFFF;
-
- while (distance > -distance_adv) { //use this to avoid precision errors
-
- result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z)));
- if (result != 0xFFFFFFFF) {
- break;
- }
-
- from += light_axis * distance_adv;
- distance -= distance_adv;
- }
-
- if (result == (uint32_t)idx) {
- //cell hit itself! hooray!
-
- if (normal == Vector3()) {
- for (int i = 0; i < 6; i++) {
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * att;
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * att;
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * att;
- }
-
- } else {
-
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-normal));
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s * att;
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s * att;
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s * att;
- }
- }
-
- if (p_direct) {
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
- light->direct_accum[i][0] += light_energy.x * s * att;
- light->direct_accum[i][1] += light_energy.y * s * att;
- light->direct_accum[i][2] += light_energy.z * s * att;
- }
- }
- }
-
- idx = light_data[idx].next_leaf;
- }
-}
-
-void VoxelLightBaker::plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axis, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, float p_spot_angle, float p_spot_attenuation, bool p_direct) {
-
- _check_init_light();
-
- if (p_direct)
- direct_lights_baked = true;
-
- Plane clip[3];
- int clip_planes = 0;
-
- // uint64_t us = OS::get_singleton()->get_ticks_usec();
-
- Vector3 light_pos = to_cell_space.xform(p_pos) + Vector3(0.5, 0.5, 0.5);
- Vector3 spot_axis = to_cell_space.basis.xform(p_axis).normalized();
-
- float local_radius = to_cell_space.basis.xform(Vector3(0, 0, 1)).length() * p_radius;
-
- Light *light_data = bake_light.ptrw();
- const Cell *cells = bake_cells.ptr();
- Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy;
-
- int idx = first_leaf;
- while (idx >= 0) {
-
- Light *light = &light_data[idx];
-
- Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5);
-
- Vector3 light_axis = (to - light_pos).normalized();
- float distance_adv = _get_normal_advance(light_axis);
-
- Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]);
-
- if (normal != Vector3() && normal.dot(-light_axis) < 0.001) {
- idx = light_data[idx].next_leaf;
- continue;
- }
-
- float angle = Math::rad2deg(Math::acos(light_axis.dot(-spot_axis)));
- if (angle > p_spot_angle) {
- idx = light_data[idx].next_leaf;
- continue; // too far away
- }
-
- float att = Math::pow(1.0f - angle / p_spot_angle, p_spot_attenuation);
-
- {
- float d = light_pos.distance_to(to);
- if (d + distance_adv > local_radius) {
- idx = light_data[idx].next_leaf;
- continue; // too far away
- }
-
- float dt = CLAMP((d + distance_adv) / local_radius, 0, 1);
- att *= powf(1.0 - dt, p_attenutation);
- }
-
- clip_planes = 0;
-
- for (int c = 0; c < 3; c++) {
-
- if (Math::is_zero_approx(light_axis[c]))
- continue;
- clip[clip_planes].normal[c] = 1.0;
-
- if (light_axis[c] < 0) {
-
- clip[clip_planes].d = (1 << (cell_subdiv - 1)) + 1;
- } else {
- clip[clip_planes].d -= 1.0;
- }
-
- clip_planes++;
- }
-
- Vector3 from = light_pos;
-
- for (int j = 0; j < clip_planes; j++) {
-
- clip[j].intersects_segment(from, to, &from);
- }
-
- float distance = (to - from).length();
-
- distance -= Math::fmod(distance, distance_adv); //make it reach the center of the box always, but this tame make it closer
- from = to - light_axis * distance;
-
- uint32_t result = 0xFFFFFFFF;
-
- while (distance > -distance_adv) { //use this to avoid precision errors
-
- result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z)));
- if (result != 0xFFFFFFFF) {
- break;
- }
-
- from += light_axis * distance_adv;
- distance -= distance_adv;
- }
-
- if (result == (uint32_t)idx) {
- //cell hit itself! hooray!
-
- if (normal == Vector3()) {
- for (int i = 0; i < 6; i++) {
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * att;
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * att;
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * att;
- }
-
- } else {
-
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-normal));
- light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s * att;
- light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s * att;
- light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s * att;
- }
- }
-
- if (p_direct) {
- for (int i = 0; i < 6; i++) {
- float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
- light->direct_accum[i][0] += light_energy.x * s * att;
- light->direct_accum[i][1] += light_energy.y * s * att;
- light->direct_accum[i][2] += light_energy.z * s * att;
- }
- }
- }
-
- idx = light_data[idx].next_leaf;
- }
-}
-
-void VoxelLightBaker::_fixup_plot(int p_idx, int p_level) {
-
- if (p_level == cell_subdiv - 1) {
-
- leaf_voxel_count++;
- float alpha = bake_cells[p_idx].alpha;
-
- bake_cells.write[p_idx].albedo[0] /= alpha;
- bake_cells.write[p_idx].albedo[1] /= alpha;
- bake_cells.write[p_idx].albedo[2] /= alpha;
-
- //transfer emission to light
- bake_cells.write[p_idx].emission[0] /= alpha;
- bake_cells.write[p_idx].emission[1] /= alpha;
- bake_cells.write[p_idx].emission[2] /= alpha;
-
- bake_cells.write[p_idx].normal[0] /= alpha;
- bake_cells.write[p_idx].normal[1] /= alpha;
- bake_cells.write[p_idx].normal[2] /= alpha;
-
- Vector3 n(bake_cells[p_idx].normal[0], bake_cells[p_idx].normal[1], bake_cells[p_idx].normal[2]);
- if (n.length() < 0.01) {
- //too much fight over normal, zero it
- bake_cells.write[p_idx].normal[0] = 0;
- bake_cells.write[p_idx].normal[1] = 0;
- bake_cells.write[p_idx].normal[2] = 0;
- } else {
- n.normalize();
- bake_cells.write[p_idx].normal[0] = n.x;
- bake_cells.write[p_idx].normal[1] = n.y;
- bake_cells.write[p_idx].normal[2] = n.z;
- }
-
- bake_cells.write[p_idx].alpha = 1.0;
-
- /*if (bake_light.size()) {
- for(int i=0;i<6;i++) {
-
- }
- }*/
-
- } else {
-
- //go down
-
- bake_cells.write[p_idx].emission[0] = 0;
- bake_cells.write[p_idx].emission[1] = 0;
- bake_cells.write[p_idx].emission[2] = 0;
- bake_cells.write[p_idx].normal[0] = 0;
- bake_cells.write[p_idx].normal[1] = 0;
- bake_cells.write[p_idx].normal[2] = 0;
- bake_cells.write[p_idx].albedo[0] = 0;
- bake_cells.write[p_idx].albedo[1] = 0;
- bake_cells.write[p_idx].albedo[2] = 0;
- if (bake_light.size()) {
- for (int j = 0; j < 6; j++) {
- bake_light.write[p_idx].accum[j][0] = 0;
- bake_light.write[p_idx].accum[j][1] = 0;
- bake_light.write[p_idx].accum[j][2] = 0;
- }
- }
-
- float alpha_average = 0;
- int children_found = 0;
-
- for (int i = 0; i < 8; i++) {
-
- uint32_t child = bake_cells[p_idx].children[i];
-
- if (child == CHILD_EMPTY)
- continue;
-
- _fixup_plot(child, p_level + 1);
- alpha_average += bake_cells[child].alpha;
-
- if (bake_light.size() > 0) {
- for (int j = 0; j < 6; j++) {
- bake_light.write[p_idx].accum[j][0] += bake_light[child].accum[j][0];
- bake_light.write[p_idx].accum[j][1] += bake_light[child].accum[j][1];
- bake_light.write[p_idx].accum[j][2] += bake_light[child].accum[j][2];
- }
- bake_cells.write[p_idx].emission[0] += bake_cells[child].emission[0];
- bake_cells.write[p_idx].emission[1] += bake_cells[child].emission[1];
- bake_cells.write[p_idx].emission[2] += bake_cells[child].emission[2];
- }
-
- children_found++;
- }
-
- bake_cells.write[p_idx].alpha = alpha_average / 8.0;
- if (bake_light.size() && children_found) {
- float divisor = Math::lerp(8, children_found, propagation);
- for (int j = 0; j < 6; j++) {
- bake_light.write[p_idx].accum[j][0] /= divisor;
- bake_light.write[p_idx].accum[j][1] /= divisor;
- bake_light.write[p_idx].accum[j][2] /= divisor;
- }
- bake_cells.write[p_idx].emission[0] /= divisor;
- bake_cells.write[p_idx].emission[1] /= divisor;
- bake_cells.write[p_idx].emission[2] /= divisor;
- }
- }
-}
-
-//make sure any cell (save for the root) has an empty cell previous to it, so it can be interpolated into
-
-void VoxelLightBaker::_plot_triangle(Vector2 *vertices, Vector3 *positions, Vector3 *normals, LightMap *pixels, int width, int height) {
-
- int x[3];
- int y[3];
-
- for (int j = 0; j < 3; j++) {
-
- x[j] = vertices[j].x * width;
- y[j] = vertices[j].y * height;
- //x[j] = CLAMP(x[j], 0, bt.width - 1);
- //y[j] = CLAMP(y[j], 0, bt.height - 1);
- }
-
- // sort the points vertically
- if (y[1] > y[2]) {
- SWAP(x[1], x[2]);
- SWAP(y[1], y[2]);
- SWAP(positions[1], positions[2]);
- SWAP(normals[1], normals[2]);
- }
- if (y[0] > y[1]) {
- SWAP(x[0], x[1]);
- SWAP(y[0], y[1]);
- SWAP(positions[0], positions[1]);
- SWAP(normals[0], normals[1]);
- }
- if (y[1] > y[2]) {
- SWAP(x[1], x[2]);
- SWAP(y[1], y[2]);
- SWAP(positions[1], positions[2]);
- SWAP(normals[1], normals[2]);
- }
-
- double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
- double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
- double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
- double xf = x[0];
- double xt = x[0] + dx_upper; // if y[0] == y[1], special case
- for (int yi = y[0]; yi <= (y[2] > height - 1 ? height - 1 : y[2]); yi++) {
- if (yi >= 0) {
- for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < width ? xt : width - 1); xi++) {
- //pixels[int(x + y * width)] = color;
-
- Vector2 v0 = Vector2(x[1] - x[0], y[1] - y[0]);
- Vector2 v1 = Vector2(x[2] - x[0], y[2] - y[0]);
- //vertices[2] - vertices[0];
- Vector2 v2 = Vector2(xi - x[0], yi - y[0]);
- float d00 = v0.dot(v0);
- float d01 = v0.dot(v1);
- float d11 = v1.dot(v1);
- float d20 = v2.dot(v0);
- float d21 = v2.dot(v1);
- float denom = (d00 * d11 - d01 * d01);
- Vector3 pos;
- Vector3 normal;
- if (denom == 0) {
- pos = positions[0];
- normal = normals[0];
- } else {
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
- pos = positions[0] * u + positions[1] * v + positions[2] * w;
- normal = normals[0] * u + normals[1] * v + normals[2] * w;
- }
-
- int ofs = yi * width + xi;
- pixels[ofs].normal = normal;
- pixels[ofs].pos = pos;
- }
-
- for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) {
- //pixels[int(x + y * width)] = color;
- Vector2 v0 = Vector2(x[1] - x[0], y[1] - y[0]);
- Vector2 v1 = Vector2(x[2] - x[0], y[2] - y[0]);
- //vertices[2] - vertices[0];
- Vector2 v2 = Vector2(xi - x[0], yi - y[0]);
- float d00 = v0.dot(v0);
- float d01 = v0.dot(v1);
- float d11 = v1.dot(v1);
- float d20 = v2.dot(v0);
- float d21 = v2.dot(v1);
- float denom = (d00 * d11 - d01 * d01);
- Vector3 pos;
- Vector3 normal;
- if (denom == 0) {
- pos = positions[0];
- normal = normals[0];
- } else {
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
- pos = positions[0] * u + positions[1] * v + positions[2] * w;
- normal = normals[0] * u + normals[1] * v + normals[2] * w;
- }
-
- int ofs = yi * width + xi;
- pixels[ofs].normal = normal;
- pixels[ofs].pos = pos;
- }
- }
- xf += dx_far;
- if (yi < y[1])
- xt += dx_upper;
- else
- xt += dx_low;
- }
-}
-
-void VoxelLightBaker::_sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha) {
-
- int size = 1 << (cell_subdiv - 1);
-
- int clamp_v = size - 1;
- //first of all, clamp
- Vector3 pos;
- pos.x = CLAMP(p_posf.x, 0, clamp_v);
- pos.y = CLAMP(p_posf.y, 0, clamp_v);
- pos.z = CLAMP(p_posf.z, 0, clamp_v);
-
- float level = (cell_subdiv - 1) - p_level;
-
- int target_level;
- float level_filter;
- if (level <= 0.0) {
- level_filter = 0;
- target_level = 0;
- } else {
- target_level = Math::ceil(level);
- level_filter = target_level - level;
- }
-
- const Cell *cells = bake_cells.ptr();
- const Light *light = bake_light.ptr();
-
- Vector3 color[2][8];
- float alpha[2][8];
- zeromem(alpha, sizeof(float) * 2 * 8);
-
- //find cell at given level first
-
- for (int c = 0; c < 2; c++) {
-
- int current_level = MAX(0, target_level - c);
- int level_cell_size = (1 << (cell_subdiv - 1)) >> current_level;
-
- for (int n = 0; n < 8; n++) {
-
- int x = int(pos.x);
- int y = int(pos.y);
- int z = int(pos.z);
-
- if (n & 1)
- x += level_cell_size;
- if (n & 2)
- y += level_cell_size;
- if (n & 4)
- z += level_cell_size;
-
- int ofs_x = 0;
- int ofs_y = 0;
- int ofs_z = 0;
-
- x = CLAMP(x, 0, clamp_v);
- y = CLAMP(y, 0, clamp_v);
- z = CLAMP(z, 0, clamp_v);
-
- int half = size / 2;
- uint32_t cell = 0;
- for (int i = 0; i < current_level; i++) {
-
- const Cell *bc = &cells[cell];
-
- int child = 0;
- if (x >= ofs_x + half) {
- child |= 1;
- ofs_x += half;
- }
- if (y >= ofs_y + half) {
- child |= 2;
- ofs_y += half;
- }
- if (z >= ofs_z + half) {
- child |= 4;
- ofs_z += half;
- }
-
- cell = bc->children[child];
- if (cell == CHILD_EMPTY)
- break;
-
- half >>= 1;
- }
-
- if (cell == CHILD_EMPTY) {
- alpha[c][n] = 0;
- } else {
- alpha[c][n] = cells[cell].alpha;
-
- for (int i = 0; i < 6; i++) {
- //anisotropic read light
- float amount = p_direction.dot(aniso_normal[i]);
- if (amount < 0)
- amount = 0;
- color[c][n].x += light[cell].accum[i][0] * amount;
- color[c][n].y += light[cell].accum[i][1] * amount;
- color[c][n].z += light[cell].accum[i][2] * amount;
- }
-
- color[c][n].x += cells[cell].emission[0];
- color[c][n].y += cells[cell].emission[1];
- color[c][n].z += cells[cell].emission[2];
- }
- }
- }
-
- float target_level_size = size >> target_level;
- Vector3 pos_fract[2];
-
- pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size;
- pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size;
- pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size;
-
- target_level_size = size >> MAX(0, target_level - 1);
-
- pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size;
- pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size;
- pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size;
-
- float alpha_interp[2];
- Vector3 color_interp[2];
-
- for (int i = 0; i < 2; i++) {
-
- Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x);
- Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x);
- Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y);
-
- Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x);
- Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x);
- Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y);
-
- color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z);
-
- float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x);
- float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x);
- float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y);
-
- float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x);
- float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x);
- float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y);
-
- alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z);
- }
-
- r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter);
- r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter);
-}
-
-Vector3 VoxelLightBaker::_voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture) {
-
- float bias = 2.5;
- float max_distance = (Vector3(1, 1, 1) * (1 << (cell_subdiv - 1))).length();
-
- float dist = bias;
- float alpha = 0.0;
- Vector3 color;
-
- Vector3 scolor;
- float salpha;
-
- while (dist < max_distance && alpha < 0.95) {
- float diameter = MAX(1.0, 2.0 * p_aperture * dist);
- _sample_baked_octree_filtered_and_anisotropic(p_pos + dist * p_normal, p_normal, log2(diameter), scolor, salpha);
- float a = (1.0 - alpha);
- color += scolor * a;
- alpha += a * salpha;
- dist += diameter * 0.5;
- }
-
- /*if (blend_ambient) {
- color.rgb = mix(ambient,color.rgb,min(1.0,alpha/0.95));
- }*/
-
- return color;
-}
-
-Vector3 VoxelLightBaker::_compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal) {
-
- //find arbitrary tangent and bitangent, then build a matrix
- Vector3 v0 = Math::abs(p_normal.z) < 0.999 ? Vector3(0, 0, 1) : Vector3(0, 1, 0);
- Vector3 tangent = v0.cross(p_normal).normalized();
- Vector3 bitangent = tangent.cross(p_normal).normalized();
- Basis normal_xform = Basis(tangent, bitangent, p_normal).transposed();
-
- const Vector3 *cone_dirs = NULL;
- const float *cone_weights = NULL;
- int cone_dir_count = 0;
- float cone_aperture = 0;
-
- switch (bake_quality) {
- case BAKE_QUALITY_LOW: {
- //default quality
- static const Vector3 dirs[4] = {
- Vector3(Math_SQRT12, 0, Math_SQRT12),
- Vector3(0, Math_SQRT12, Math_SQRT12),
- Vector3(-Math_SQRT12, 0, Math_SQRT12),
- Vector3(0, -Math_SQRT12, Math_SQRT12)
- };
-
- static const float weights[4] = { 0.25, 0.25, 0.25, 0.25 };
-
- cone_dirs = dirs;
- cone_dir_count = 4;
- cone_aperture = 1.0; // tan(angle) 90 degrees
- cone_weights = weights;
- } break;
- case BAKE_QUALITY_MEDIUM: {
- //default quality
- static const Vector3 dirs[6] = {
- Vector3(0, 0, 1),
- Vector3(0.866025, 0, 0.5),
- Vector3(0.267617, 0.823639, 0.5),
- Vector3(-0.700629, 0.509037, 0.5),
- Vector3(-0.700629, -0.509037, 0.5),
- Vector3(0.267617, -0.823639, 0.5)
- };
- static const float weights[6] = { 0.25f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f };
- //
- cone_dirs = dirs;
- cone_dir_count = 6;
- cone_aperture = 0.577; // tan(angle) 60 degrees
- cone_weights = weights;
- } break;
- case BAKE_QUALITY_HIGH: {
-
- //high qualily
- static const Vector3 dirs[10] = {
- Vector3(0.8781648411741658, 0.0, 0.478358141694643),
- Vector3(0.5369754325592234, 0.6794204427701518, 0.5000452447267606),
- Vector3(-0.19849436573466497, 0.8429904390140635, 0.49996710542041645),
- Vector3(-0.7856196499811189, 0.3639120321329737, 0.5003696617825604),
- Vector3(-0.7856196499811189, -0.3639120321329737, 0.5003696617825604),
- Vector3(-0.19849436573466497, -0.8429904390140635, 0.49996710542041645),
- Vector3(0.5369754325592234, -0.6794204427701518, 0.5000452447267606),
- Vector3(-0.4451656858129485, 0.0, 0.8954482185892644),
- Vector3(0.19124006749743122, 0.39355745585016605, 0.8991883926788214),
- Vector3(0.19124006749743122, -0.39355745585016605, 0.8991883926788214),
- };
- static const float weights[10] = { 0.08571f, 0.08571f, 0.08571f, 0.08571f, 0.08571f, 0.08571f, 0.08571f, 0.133333f, 0.133333f, 0.13333f };
- cone_dirs = dirs;
- cone_dir_count = 10;
- cone_aperture = 0.404; // tan(angle) 45 degrees
- cone_weights = weights;
- } break;
- }
-
- Vector3 accum;
-
- for (int i = 0; i < cone_dir_count; i++) {
- Vector3 dir = normal_xform.xform(cone_dirs[i]).normalized(); //normal may not completely correct when transformed to cell
- accum += _voxel_cone_trace(p_pos, dir, cone_aperture) * cone_weights[i];
- }
-
- return accum;
-}
-
-_ALWAYS_INLINE_ uint32_t xorshift32(uint32_t *state) {
- /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
- uint32_t x = *state;
- x ^= x << 13;
- x ^= x >> 17;
- x ^= x << 5;
- *state = x;
- return x;
-}
-
-Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal) {
-
- int samples_per_quality[3] = { 48, 128, 512 };
-
- int samples = samples_per_quality[bake_quality];
-
- //create a basis in Z
- Vector3 v0 = Math::abs(p_normal.z) < 0.999 ? Vector3(0, 0, 1) : Vector3(0, 1, 0);
- Vector3 tangent = v0.cross(p_normal).normalized();
- Vector3 bitangent = tangent.cross(p_normal).normalized();
- Basis normal_xform = Basis(tangent, bitangent, p_normal).transposed();
-
- float bias = 1.5;
- int max_level = cell_subdiv - 1;
- int size = 1 << max_level;
-
- Vector3 accum;
- float spread = Math::deg2rad(80.0);
-
- const Light *light = bake_light.ptr();
- const Cell *cells = bake_cells.ptr();
-
- uint32_t local_rng_state = rand(); //needs to be fixed again
-
- for (int i = 0; i < samples; i++) {
-
- float random_angle1 = (((xorshift32(&local_rng_state) % 65535) / 65535.0) * 2.0 - 1.0) * spread;
- Vector3 axis(0, sin(random_angle1), cos(random_angle1));
- float random_angle2 = ((xorshift32(&local_rng_state) % 65535) / 65535.0) * Math_PI * 2.0;
- Basis rot(Vector3(0, 0, 1), random_angle2);
- axis = rot.xform(axis);
-
- Vector3 direction = normal_xform.xform(axis).normalized();
-
- Vector3 advance = direction * _get_normal_advance(direction);
-
- Vector3 pos = p_pos /*+ Vector3(0.5, 0.5, 0.5)*/ + advance * bias;
-
- uint32_t cell = CHILD_EMPTY;
-
- while (cell == CHILD_EMPTY) {
-
- int x = int(pos.x);
- int y = int(pos.y);
- int z = int(pos.z);
-
- int ofs_x = 0;
- int ofs_y = 0;
- int ofs_z = 0;
- int half = size / 2;
-
- if (x < 0 || x >= size)
- break;
- if (y < 0 || y >= size)
- break;
- if (z < 0 || z >= size)
- break;
-
- //int level_limit = max_level;
-
- cell = 0; //start from root
- for (int j = 0; j < max_level; j++) {
-
- const Cell *bc = &cells[cell];
-
- int child = 0;
- if (x >= ofs_x + half) {
- child |= 1;
- ofs_x += half;
- }
- if (y >= ofs_y + half) {
- child |= 2;
- ofs_y += half;
- }
- if (z >= ofs_z + half) {
- child |= 4;
- ofs_z += half;
- }
-
- cell = bc->children[child];
- if (unlikely(cell == CHILD_EMPTY))
- break;
-
- half >>= 1;
- }
-
- pos += advance;
- }
-
- if (unlikely(cell != CHILD_EMPTY)) {
- for (int j = 0; j < 6; j++) {
- //anisotropic read light
- float amount = direction.dot(aniso_normal[j]);
- if (amount <= 0)
- continue;
- accum.x += light[cell].accum[j][0] * amount;
- accum.y += light[cell].accum[j][1] * amount;
- accum.z += light[cell].accum[j][2] * amount;
- }
- accum.x += cells[cell].emission[0];
- accum.y += cells[cell].emission[1];
- accum.z += cells[cell].emission[2];
- }
- }
-
- // Make sure we don't reset this thread's RNG state
-
- return accum / samples;
-}
-
-void VoxelLightBaker::_lightmap_bake_point(uint32_t p_x, LightMap *p_line) {
-
- LightMap *pixel = &p_line[p_x];
- if (pixel->pos == Vector3())
- return;
- switch (bake_mode) {
- case BAKE_MODE_CONE_TRACE: {
- pixel->light = _compute_pixel_light_at_pos(pixel->pos, pixel->normal) * energy;
- } break;
- case BAKE_MODE_RAY_TRACE: {
- pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal) * energy;
- } break;
- }
-}
-
-Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, float default_texels_per_unit, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float), void *p_bake_time_ud) {
-
- //transfer light information to a lightmap
- Ref<Mesh> mesh = p_mesh;
-
- //step 1 - create lightmap
- int width;
- int height;
- Vector<LightMap> lightmap;
- Transform xform = to_cell_space * p_xform;
- if (mesh->get_lightmap_size_hint() == Size2()) {
- double area = 0;
- double uv_area = 0;
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- Array arrays = mesh->surface_get_arrays(i);
- PoolVector<Vector3> vertices = arrays[Mesh::ARRAY_VERTEX];
- PoolVector<Vector2> uv2 = arrays[Mesh::ARRAY_TEX_UV2];
- PoolVector<int> indices = arrays[Mesh::ARRAY_INDEX];
-
- ERR_FAIL_COND_V(vertices.size() == 0, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(uv2.size() == 0, ERR_INVALID_PARAMETER);
-
- int vc = vertices.size();
- PoolVector<Vector3>::Read vr = vertices.read();
- PoolVector<Vector2>::Read u2r = uv2.read();
- PoolVector<int>::Read ir;
- int ic = 0;
-
- if (indices.size()) {
- ic = indices.size();
- ir = indices.read();
- }
-
- int faces = ic ? ic / 3 : vc / 3;
- for (int j = 0; j < faces; j++) {
- Vector3 vertex[3];
- Vector2 uv[3];
-
- for (int k = 0; k < 3; k++) {
- int idx = ic ? ir[j * 3 + k] : j * 3 + k;
- vertex[k] = xform.xform(vr[idx]);
- uv[k] = u2r[idx];
- }
-
- Vector3 p1 = vertex[0];
- Vector3 p2 = vertex[1];
- Vector3 p3 = vertex[2];
- double a = p1.distance_to(p2);
- double b = p2.distance_to(p3);
- double c = p3.distance_to(p1);
- double halfPerimeter = (a + b + c) / 2.0;
- area += sqrt(halfPerimeter * (halfPerimeter - a) * (halfPerimeter - b) * (halfPerimeter - c));
-
- Vector2 uv_p1 = uv[0];
- Vector2 uv_p2 = uv[1];
- Vector2 uv_p3 = uv[2];
- double uv_a = uv_p1.distance_to(uv_p2);
- double uv_b = uv_p2.distance_to(uv_p3);
- double uv_c = uv_p3.distance_to(uv_p1);
- double uv_halfPerimeter = (uv_a + uv_b + uv_c) / 2.0;
- uv_area += sqrt(uv_halfPerimeter * (uv_halfPerimeter - uv_a) * (uv_halfPerimeter - uv_b) * (uv_halfPerimeter - uv_c));
- }
- }
-
- if (uv_area < 0.0001f) {
- uv_area = 1.0;
- }
-
- int pixels = (ceil((1.0 / sqrt(uv_area)) * sqrt(area * default_texels_per_unit)));
- width = height = CLAMP(pixels, 2, 4096);
- } else {
- width = mesh->get_lightmap_size_hint().x;
- height = mesh->get_lightmap_size_hint().y;
- }
-
- lightmap.resize(width * height);
-
- //step 2 plot faces to lightmap
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- Array arrays = mesh->surface_get_arrays(i);
- PoolVector<Vector3> vertices = arrays[Mesh::ARRAY_VERTEX];
- PoolVector<Vector3> normals = arrays[Mesh::ARRAY_NORMAL];
- PoolVector<Vector2> uv2 = arrays[Mesh::ARRAY_TEX_UV2];
- PoolVector<int> indices = arrays[Mesh::ARRAY_INDEX];
-
- ERR_FAIL_COND_V(vertices.size() == 0, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(normals.size() == 0, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(uv2.size() == 0, ERR_INVALID_PARAMETER);
-
- int vc = vertices.size();
- PoolVector<Vector3>::Read vr = vertices.read();
- PoolVector<Vector3>::Read nr = normals.read();
- PoolVector<Vector2>::Read u2r = uv2.read();
- PoolVector<int>::Read ir;
- int ic = 0;
-
- if (indices.size()) {
- ic = indices.size();
- ir = indices.read();
- }
-
- int faces = ic ? ic / 3 : vc / 3;
- for (int j = 0; j < faces; j++) {
- Vector3 vertex[3];
- Vector3 normal[3];
- Vector2 uv[3];
-
- for (int k = 0; k < 3; k++) {
- int idx = ic ? ir[j * 3 + k] : j * 3 + k;
- vertex[k] = xform.xform(vr[idx]);
- normal[k] = xform.basis.xform(nr[idx]).normalized();
- uv[k] = u2r[idx];
- }
-
- _plot_triangle(uv, vertex, normal, lightmap.ptrw(), width, height);
- }
- }
-
- //step 3 perform voxel cone trace on lightmap pixels
- {
- LightMap *lightmap_ptr = lightmap.ptrw();
- uint64_t begin_time = OS::get_singleton()->get_ticks_usec();
- volatile int lines = 0;
-
- // make sure our OS-level rng is seeded
-
- for (int i = 0; i < height; i++) {
-
- thread_process_array(width, this, &VoxelLightBaker::_lightmap_bake_point, &lightmap_ptr[i * width]);
-
- lines = MAX(lines, i); //for multithread
- if (p_bake_time_func) {
- uint64_t elapsed = OS::get_singleton()->get_ticks_usec() - begin_time;
- float elapsed_sec = double(elapsed) / 1000000.0;
- float remaining = lines < 1 ? 0 : (elapsed_sec / lines) * (height - lines - 1);
- if (p_bake_time_func(p_bake_time_ud, remaining, lines / float(height))) {
- return ERR_SKIP;
- }
- }
- }
-
- if (bake_mode == BAKE_MODE_RAY_TRACE) {
- //blur
- //gauss kernel, 7 step sigma 2
- static const float gauss_kernel[4] = { 0.214607f, 0.189879f, 0.131514f, 0.071303f };
- //horizontal pass
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- if (lightmap_ptr[i * width + j].normal == Vector3()) {
- continue; //empty
- }
- float gauss_sum = gauss_kernel[0];
- Vector3 accum = lightmap_ptr[i * width + j].light * gauss_kernel[0];
- for (int k = 1; k < 4; k++) {
- int new_x = j + k;
- if (new_x >= width || lightmap_ptr[i * width + new_x].normal == Vector3())
- break;
- gauss_sum += gauss_kernel[k];
- accum += lightmap_ptr[i * width + new_x].light * gauss_kernel[k];
- }
- for (int k = 1; k < 4; k++) {
- int new_x = j - k;
- if (new_x < 0 || lightmap_ptr[i * width + new_x].normal == Vector3())
- break;
- gauss_sum += gauss_kernel[k];
- accum += lightmap_ptr[i * width + new_x].light * gauss_kernel[k];
- }
-
- lightmap_ptr[i * width + j].pos = accum /= gauss_sum;
- }
- }
- //vertical pass
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- if (lightmap_ptr[i * width + j].normal == Vector3())
- continue; //empty, don't write over it anyway
- float gauss_sum = gauss_kernel[0];
- Vector3 accum = lightmap_ptr[i * width + j].pos * gauss_kernel[0];
- for (int k = 1; k < 4; k++) {
- int new_y = i + k;
- if (new_y >= height || lightmap_ptr[new_y * width + j].normal == Vector3())
- break;
- gauss_sum += gauss_kernel[k];
- accum += lightmap_ptr[new_y * width + j].pos * gauss_kernel[k];
- }
- for (int k = 1; k < 4; k++) {
- int new_y = i - k;
- if (new_y < 0 || lightmap_ptr[new_y * width + j].normal == Vector3())
- break;
- gauss_sum += gauss_kernel[k];
- accum += lightmap_ptr[new_y * width + j].pos * gauss_kernel[k];
- }
-
- lightmap_ptr[i * width + j].light = accum /= gauss_sum;
- }
- }
- }
-
- //add directional light (do this after blur)
- {
- const Cell *cells = bake_cells.ptr();
- const Light *light = bake_light.ptr();
-#ifdef _OPENMP
-#pragma omp parallel
-#endif
- for (int i = 0; i < height; i++) {
-#ifdef _OPENMP
-#pragma omp parallel for schedule(dynamic, 1)
-#endif
- for (int j = 0; j < width; j++) {
-
- //if (i == 125 && j == 280) {
-
- LightMap *pixel = &lightmap_ptr[i * width + j];
- if (pixel->pos == Vector3())
- continue; //unused, skipe
-
- int x = int(pixel->pos.x) - 1;
- int y = int(pixel->pos.y) - 1;
- int z = int(pixel->pos.z) - 1;
- Color accum;
- int size = 1 << (cell_subdiv - 1);
-
- int found = 0;
-
- for (int k = 0; k < 8; k++) {
-
- int ofs_x = x;
- int ofs_y = y;
- int ofs_z = z;
-
- if (k & 1)
- ofs_x++;
- if (k & 2)
- ofs_y++;
- if (k & 4)
- ofs_z++;
-
- if (x < 0 || x >= size)
- continue;
- if (y < 0 || y >= size)
- continue;
- if (z < 0 || z >= size)
- continue;
-
- uint32_t cell = _find_cell_at_pos(cells, ofs_x, ofs_y, ofs_z);
-
- if (cell == CHILD_EMPTY)
- continue;
- for (int l = 0; l < 6; l++) {
- float s = pixel->normal.dot(aniso_normal[l]);
- if (s < 0)
- s = 0;
- accum.r += light[cell].direct_accum[l][0] * s;
- accum.g += light[cell].direct_accum[l][1] * s;
- accum.b += light[cell].direct_accum[l][2] * s;
- }
- found++;
- }
- if (found) {
- accum /= found;
- pixel->light.x += accum.r;
- pixel->light.y += accum.g;
- pixel->light.z += accum.b;
- }
- }
- }
- }
-
- {
- //fill gaps with neighbour vertices to avoid filter fades to black on edges
-
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- if (lightmap_ptr[i * width + j].normal != Vector3()) {
- continue; //filled, skip
- }
-
- //this can't be made separatable..
-
- int closest_i = -1, closest_j = 1;
- float closest_dist = 1e20;
-
- const int margin = 3;
- for (int y = i - margin; y <= i + margin; y++) {
- for (int x = j - margin; x <= j + margin; x++) {
-
- if (x == j && y == i)
- continue;
- if (x < 0 || x >= width)
- continue;
- if (y < 0 || y >= height)
- continue;
- if (lightmap_ptr[y * width + x].normal == Vector3())
- continue; //also ensures that blitted stuff is not reused
-
- float dist = Vector2(i - y, j - x).length();
- if (dist > closest_dist)
- continue;
-
- closest_dist = dist;
- closest_i = y;
- closest_j = x;
- }
- }
-
- if (closest_i != -1) {
- lightmap_ptr[i * width + j].light = lightmap_ptr[closest_i * width + closest_j].light;
- }
- }
- }
- }
-
- {
- //fill the lightmap data
- r_lightmap.width = width;
- r_lightmap.height = height;
- r_lightmap.light.resize(lightmap.size() * 3);
- PoolVector<float>::Write w = r_lightmap.light.write();
- for (int i = 0; i < lightmap.size(); i++) {
- w[i * 3 + 0] = lightmap[i].light.x;
- w[i * 3 + 1] = lightmap[i].light.y;
- w[i * 3 + 2] = lightmap[i].light.z;
- }
- }
-
-#if 0 // Enable for debugging.
- {
- PoolVector<uint8_t> img;
- int ls = lightmap.size();
- img.resize(ls * 3);
- {
- PoolVector<uint8_t>::Write w = img.write();
- for (int i = 0; i < ls; i++) {
- w[i * 3 + 0] = CLAMP(lightmap_ptr[i].light.x * 255, 0, 255);
- w[i * 3 + 1] = CLAMP(lightmap_ptr[i].light.y * 255, 0, 255);
- w[i * 3 + 2] = CLAMP(lightmap_ptr[i].light.z * 255, 0, 255);
- //w[i * 3 + 0] = CLAMP(lightmap_ptr[i].normal.x * 255, 0, 255);
- //w[i * 3 + 1] = CLAMP(lightmap_ptr[i].normal.y * 255, 0, 255);
- //w[i * 3 + 2] = CLAMP(lightmap_ptr[i].normal.z * 255, 0, 255);
- //w[i * 3 + 0] = CLAMP(lightmap_ptr[i].pos.x / (1 << (cell_subdiv - 1)) * 255, 0, 255);
- //w[i * 3 + 1] = CLAMP(lightmap_ptr[i].pos.y / (1 << (cell_subdiv - 1)) * 255, 0, 255);
- //w[i * 3 + 2] = CLAMP(lightmap_ptr[i].pos.z / (1 << (cell_subdiv - 1)) * 255, 0, 255);
- }
- }
-
- Ref<Image> image;
- image.instance();
- image->create(width, height, false, Image::FORMAT_RGB8, img);
-
- String name = p_mesh->get_name();
- if (name == "") {
- name = "Mesh" + itos(p_mesh->get_instance_id());
- }
- image->save_png(name + ".png");
- }
-#endif
- }
-
- return OK;
-}
-
-void VoxelLightBaker::begin_bake(int p_subdiv, const AABB &p_bounds) {
-
- original_bounds = p_bounds;
- cell_subdiv = p_subdiv;
- bake_cells.resize(1);
- material_cache.clear();
-
- //find out the actual real bounds, power of 2, which gets the highest subdivision
- po2_bounds = p_bounds;
- int longest_axis = po2_bounds.get_longest_axis_index();
- axis_cell_size[longest_axis] = (1 << (cell_subdiv - 1));
- leaf_voxel_count = 0;
-
- for (int i = 0; i < 3; i++) {
-
- if (i == longest_axis)
- continue;
-
- axis_cell_size[i] = axis_cell_size[longest_axis];
- float axis_size = po2_bounds.size[longest_axis];
-
- //shrink until fit subdiv
- while (axis_size / 2.0 >= po2_bounds.size[i]) {
- axis_size /= 2.0;
- axis_cell_size[i] >>= 1;
- }
-
- po2_bounds.size[i] = po2_bounds.size[longest_axis];
- }
-
- Transform to_bounds;
- to_bounds.basis.scale(Vector3(po2_bounds.size[longest_axis], po2_bounds.size[longest_axis], po2_bounds.size[longest_axis]));
- to_bounds.origin = po2_bounds.position;
-
- Transform to_grid;
- to_grid.basis.scale(Vector3(axis_cell_size[longest_axis], axis_cell_size[longest_axis], axis_cell_size[longest_axis]));
-
- to_cell_space = to_grid * to_bounds.affine_inverse();
-
- cell_size = po2_bounds.size[longest_axis] / axis_cell_size[longest_axis];
-}
-
-void VoxelLightBaker::end_bake() {
- _fixup_plot(0, 0);
-}
-
-//create the data for visual server
-
-PoolVector<int> VoxelLightBaker::create_gi_probe_data() {
-
- PoolVector<int> data;
-
- data.resize(16 + (8 + 1 + 1 + 1 + 1) * bake_cells.size()); //4 for header, rest for rest.
-
- {
- PoolVector<int>::Write w = data.write();
-
- uint32_t *w32 = (uint32_t *)w.ptr();
-
- w32[0] = 0; //version
- w32[1] = cell_subdiv; //subdiv
- w32[2] = axis_cell_size[0];
- w32[3] = axis_cell_size[1];
- w32[4] = axis_cell_size[2];
- w32[5] = bake_cells.size();
- w32[6] = leaf_voxel_count;
-
- int ofs = 16;
-
- for (int i = 0; i < bake_cells.size(); i++) {
-
- for (int j = 0; j < 8; j++) {
- w32[ofs++] = bake_cells[i].children[j];
- }
-
- { //albedo
- uint32_t rgba = uint32_t(CLAMP(bake_cells[i].albedo[0] * 255.0, 0, 255)) << 16;
- rgba |= uint32_t(CLAMP(bake_cells[i].albedo[1] * 255.0, 0, 255)) << 8;
- rgba |= uint32_t(CLAMP(bake_cells[i].albedo[2] * 255.0, 0, 255)) << 0;
-
- w32[ofs++] = rgba;
- }
- { //emission
-
- Vector3 e(bake_cells[i].emission[0], bake_cells[i].emission[1], bake_cells[i].emission[2]);
- float l = e.length();
- if (l > 0) {
- e.normalize();
- l = CLAMP(l / 8.0, 0, 1.0);
- }
-
- uint32_t em = uint32_t(CLAMP(e[0] * 255, 0, 255)) << 24;
- em |= uint32_t(CLAMP(e[1] * 255, 0, 255)) << 16;
- em |= uint32_t(CLAMP(e[2] * 255, 0, 255)) << 8;
- em |= uint32_t(CLAMP(l * 255, 0, 255));
-
- w32[ofs++] = em;
- }
-
- //w32[ofs++]=bake_cells[i].used_sides;
- { //normal
-
- Vector3 n(bake_cells[i].normal[0], bake_cells[i].normal[1], bake_cells[i].normal[2]);
- n = n * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
- uint32_t norm = 0;
-
- norm |= uint32_t(CLAMP(n.x * 255.0, 0, 255)) << 16;
- norm |= uint32_t(CLAMP(n.y * 255.0, 0, 255)) << 8;
- norm |= uint32_t(CLAMP(n.z * 255.0, 0, 255)) << 0;
-
- w32[ofs++] = norm;
- }
-
- {
- uint16_t alpha = MIN(uint32_t(bake_cells[i].alpha * 65535.0), 65535);
- uint16_t level = bake_cells[i].level;
-
- w32[ofs++] = (uint32_t(level) << 16) | uint32_t(alpha);
- }
- }
- }
-
- return data;
-}
-
-void VoxelLightBaker::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, DebugMode p_mode) {
-
- if (p_level == cell_subdiv - 1) {
-
- Vector3 center = p_aabb.position + p_aabb.size * 0.5;
- Transform xform;
- xform.origin = center;
- xform.basis.scale(p_aabb.size * 0.5);
- p_multimesh->set_instance_transform(idx, xform);
- Color col;
- if (p_mode == DEBUG_ALBEDO) {
- col = Color(bake_cells[p_idx].albedo[0], bake_cells[p_idx].albedo[1], bake_cells[p_idx].albedo[2]);
- } else if (p_mode == DEBUG_LIGHT) {
- for (int i = 0; i < 6; i++) {
- col.r += bake_light[p_idx].accum[i][0];
- col.g += bake_light[p_idx].accum[i][1];
- col.b += bake_light[p_idx].accum[i][2];
- col.r += bake_light[p_idx].direct_accum[i][0];
- col.g += bake_light[p_idx].direct_accum[i][1];
- col.b += bake_light[p_idx].direct_accum[i][2];
- }
- }
- //Color col = Color(bake_cells[p_idx].emission[0], bake_cells[p_idx].emission[1], bake_cells[p_idx].emission[2]);
- p_multimesh->set_instance_color(idx, col);
-
- idx++;
-
- } else {
-
- for (int i = 0; i < 8; i++) {
-
- uint32_t child = bake_cells[p_idx].children[i];
-
- if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells)
- continue;
-
- AABB aabb = p_aabb;
- aabb.size *= 0.5;
-
- if (i & 1)
- aabb.position.x += aabb.size.x;
- if (i & 2)
- aabb.position.y += aabb.size.y;
- if (i & 4)
- aabb.position.z += aabb.size.z;
-
- _debug_mesh(bake_cells[p_idx].children[i], p_level + 1, aabb, p_multimesh, idx, p_mode);
- }
- }
-}
-
-Ref<MultiMesh> VoxelLightBaker::create_debug_multimesh(DebugMode p_mode) {
-
- Ref<MultiMesh> mm;
-
- ERR_FAIL_COND_V(p_mode == DEBUG_LIGHT && bake_light.size() == 0, mm);
- mm.instance();
-
- mm->set_transform_format(MultiMesh::TRANSFORM_3D);
- mm->set_color_format(MultiMesh::COLOR_8BIT);
- mm->set_instance_count(leaf_voxel_count);
-
- Ref<ArrayMesh> mesh;
- mesh.instance();
-
- {
- Array arr;
- arr.resize(Mesh::ARRAY_MAX);
-
- PoolVector<Vector3> vertices;
- PoolVector<Color> colors;
-#define ADD_VTX(m_idx) \
- ; \
- vertices.push_back(face_points[m_idx]); \
- colors.push_back(Color(1, 1, 1, 1));
-
- for (int i = 0; i < 6; i++) {
-
- Vector3 face_points[4];
-
- for (int j = 0; j < 4; j++) {
-
- float v[3];
- v[0] = 1.0;
- v[1] = 1 - 2 * ((j >> 1) & 1);
- v[2] = v[1] * (1 - 2 * (j & 1));
-
- for (int k = 0; k < 3; k++) {
-
- if (i < 3)
- face_points[j][(i + k) % 3] = v[k];
- else
- face_points[3 - j][(i + k) % 3] = -v[k];
- }
- }
-
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
- }
-
- arr[Mesh::ARRAY_VERTEX] = vertices;
- arr[Mesh::ARRAY_COLOR] = colors;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
- }
-
- {
- Ref<SpatialMaterial> fsm;
- fsm.instance();
- fsm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
- fsm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- fsm->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
- fsm->set_albedo(Color(1, 1, 1, 1));
-
- mesh->surface_set_material(0, fsm);
- }
-
- mm->set_mesh(mesh);
-
- int idx = 0;
- _debug_mesh(0, 0, po2_bounds, mm, idx, p_mode);
-
- return mm;
-}
-
-struct VoxelLightBakerOctree {
-
- enum {
- CHILD_EMPTY = 0xFFFFFFFF
- };
-
- uint16_t light[6][3]; //anisotropic light
- float alpha;
- uint32_t children[8];
-};
-
-PoolVector<uint8_t> VoxelLightBaker::create_capture_octree(int p_subdiv) {
-
- p_subdiv = MIN(p_subdiv, cell_subdiv); // use the smaller one
-
- Vector<uint32_t> remap;
- int bc = bake_cells.size();
- remap.resize(bc);
- Vector<uint32_t> demap;
-
- int new_size = 0;
- for (int i = 0; i < bc; i++) {
- uint32_t c = CHILD_EMPTY;
- if (bake_cells[i].level < p_subdiv) {
- c = new_size;
- new_size++;
- demap.push_back(i);
- }
- remap.write[i] = c;
- }
-
- Vector<VoxelLightBakerOctree> octree;
- octree.resize(new_size);
-
- for (int i = 0; i < new_size; i++) {
- octree.write[i].alpha = bake_cells[demap[i]].alpha;
- for (int j = 0; j < 6; j++) {
- for (int k = 0; k < 3; k++) {
- float l = bake_light[demap[i]].accum[j][k]; //add anisotropic light
- l += bake_cells[demap[i]].emission[k]; //add emission
- octree.write[i].light[j][k] = CLAMP(l * 1024, 0, 65535); //give two more bits to octree
- }
- }
-
- for (int j = 0; j < 8; j++) {
- uint32_t child = bake_cells[demap[i]].children[j];
- octree.write[i].children[j] = child == CHILD_EMPTY ? CHILD_EMPTY : remap[child];
- }
- }
-
- PoolVector<uint8_t> ret;
- int ret_bytes = octree.size() * sizeof(VoxelLightBakerOctree);
- ret.resize(ret_bytes);
- {
- PoolVector<uint8_t>::Write w = ret.write();
- copymem(w.ptr(), octree.ptr(), ret_bytes);
- }
-
- return ret;
-}
-
-float VoxelLightBaker::get_cell_size() const {
- return cell_size;
-}
-
-Transform VoxelLightBaker::get_to_cell_space_xform() const {
- return to_cell_space;
-}
-VoxelLightBaker::VoxelLightBaker() {
- color_scan_cell_width = 4;
- bake_texture_size = 128;
- propagation = 0.85;
- energy = 1.0;
-}
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
new file mode 100644
index 0000000000..0257e6e83d
--- /dev/null
+++ b/scene/3d/voxelizer.cpp
@@ -0,0 +1,1224 @@
+/*************************************************************************/
+/* voxelizer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "voxelizer.h"
+#include "core/os/os.h"
+#include "core/os/threaded_array_processor.h"
+
+#include <stdlib.h>
+
+#define FINDMINMAX(x0, x1, x2, min, max) \
+ min = max = x0; \
+ if (x1 < min) min = x1; \
+ if (x1 > max) max = x1; \
+ if (x2 < min) min = x2; \
+ if (x2 > max) max = x2;
+
+static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) {
+ int q;
+ Vector3 vmin, vmax;
+ for (q = 0; q <= 2; q++) {
+ if (normal[q] > 0.0f) {
+ vmin[q] = -maxbox[q];
+ vmax[q] = maxbox[q];
+ } else {
+ vmin[q] = maxbox[q];
+ vmax[q] = -maxbox[q];
+ }
+ }
+ if (normal.dot(vmin) + d > 0.0f) return false;
+ if (normal.dot(vmax) + d >= 0.0f) return true;
+
+ return false;
+}
+
+/*======================== X-tests ========================*/
+#define AXISTEST_X01(a, b, fa, fb) \
+ p0 = a * v0.y - b * v0.z; \
+ p2 = a * v2.y - b * v2.z; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
+ if (min > rad || max < -rad) return false;
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ p0 = a * v0.y - b * v0.z; \
+ p1 = a * v1.y - b * v1.z; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
+ if (min > rad || max < -rad) return false;
+
+/*======================== Y-tests ========================*/
+#define AXISTEST_Y02(a, b, fa, fb) \
+ p0 = -a * v0.x + b * v0.z; \
+ p2 = -a * v2.x + b * v2.z; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
+ if (min > rad || max < -rad) return false;
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ p0 = -a * v0.x + b * v0.z; \
+ p1 = -a * v1.x + b * v1.z; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
+ if (min > rad || max < -rad) return false;
+
+/*======================== Z-tests ========================*/
+
+#define AXISTEST_Z12(a, b, fa, fb) \
+ p1 = a * v1.x - b * v1.y; \
+ p2 = a * v2.x - b * v2.y; \
+ if (p2 < p1) { \
+ min = p2; \
+ max = p1; \
+ } else { \
+ min = p1; \
+ max = p2; \
+ } \
+ rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
+ if (min > rad || max < -rad) return false;
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ p0 = a * v0.x - b * v0.y; \
+ p1 = a * v1.x - b * v1.y; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
+ if (min > rad || max < -rad) return false;
+
+static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) {
+
+ /* use separating axis theorem to test overlap between triangle and box */
+ /* need to test for overlap in these directions: */
+ /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
+ /* we do not even need to test these) */
+ /* 2) normal of the triangle */
+ /* 3) crossproduct(edge from tri, {x,y,z}-directin) */
+ /* this gives 3x3=9 more tests */
+ Vector3 v0, v1, v2;
+ float min, max, d, p0, p1, p2, rad, fex, fey, fez;
+ Vector3 normal, e0, e1, e2;
+
+ /* This is the fastest branch on Sun */
+ /* move everything so that the boxcenter is in (0,0,0) */
+
+ v0 = triverts[0] - boxcenter;
+ v1 = triverts[1] - boxcenter;
+ v2 = triverts[2] - boxcenter;
+
+ /* compute triangle edges */
+ e0 = v1 - v0; /* tri edge 0 */
+ e1 = v2 - v1; /* tri edge 1 */
+ e2 = v0 - v2; /* tri edge 2 */
+
+ /* Bullet 3: */
+ /* test the 9 tests first (this was faster) */
+ fex = Math::abs(e0.x);
+ fey = Math::abs(e0.y);
+ fez = Math::abs(e0.z);
+ AXISTEST_X01(e0.z, e0.y, fez, fey);
+ AXISTEST_Y02(e0.z, e0.x, fez, fex);
+ AXISTEST_Z12(e0.y, e0.x, fey, fex);
+
+ fex = Math::abs(e1.x);
+ fey = Math::abs(e1.y);
+ fez = Math::abs(e1.z);
+ AXISTEST_X01(e1.z, e1.y, fez, fey);
+ AXISTEST_Y02(e1.z, e1.x, fez, fex);
+ AXISTEST_Z0(e1.y, e1.x, fey, fex);
+
+ fex = Math::abs(e2.x);
+ fey = Math::abs(e2.y);
+ fez = Math::abs(e2.z);
+ AXISTEST_X2(e2.z, e2.y, fez, fey);
+ AXISTEST_Y1(e2.z, e2.x, fez, fex);
+ AXISTEST_Z12(e2.y, e2.x, fey, fex);
+
+ /* Bullet 1: */
+ /* first test overlap in the {x,y,z}-directions */
+ /* find min, max of the triangle each direction, and test for overlap in */
+ /* that direction -- this is equivalent to testing a minimal AABB around */
+ /* the triangle against the AABB */
+
+ /* test in X-direction */
+ FINDMINMAX(v0.x, v1.x, v2.x, min, max);
+ if (min > boxhalfsize.x || max < -boxhalfsize.x) return false;
+
+ /* test in Y-direction */
+ FINDMINMAX(v0.y, v1.y, v2.y, min, max);
+ if (min > boxhalfsize.y || max < -boxhalfsize.y) return false;
+
+ /* test in Z-direction */
+ FINDMINMAX(v0.z, v1.z, v2.z, min, max);
+ if (min > boxhalfsize.z || max < -boxhalfsize.z) return false;
+
+ /* Bullet 2: */
+ /* test if the box intersects the plane of the triangle */
+ /* compute plane equation of triangle: normal*x+d=0 */
+ normal = e0.cross(e1);
+ d = -normal.dot(v0); /* plane eq: normal.x+d=0 */
+ return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */
+}
+
+static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
+
+ if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
+ r_uv = p_uv[0];
+ r_normal = p_normal[0];
+ return;
+ }
+ if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) {
+ r_uv = p_uv[1];
+ r_normal = p_normal[1];
+ return;
+ }
+ if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) {
+ r_uv = p_uv[2];
+ r_normal = p_normal[2];
+ return;
+ }
+
+ Vector3 v0 = p_vtx[1] - p_vtx[0];
+ Vector3 v1 = p_vtx[2] - p_vtx[0];
+ Vector3 v2 = p_pos - p_vtx[0];
+
+ float d00 = v0.dot(v0);
+ float d01 = v0.dot(v1);
+ float d11 = v1.dot(v1);
+ float d20 = v2.dot(v0);
+ float d21 = v2.dot(v1);
+ float denom = (d00 * d11 - d01 * d01);
+ if (denom == 0) {
+ r_uv = p_uv[0];
+ r_normal = p_normal[0];
+ return;
+ }
+ float v = (d11 * d20 - d01 * d21) / denom;
+ float w = (d00 * d21 - d01 * d20) / denom;
+ float u = 1.0f - v - w;
+
+ r_uv = p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
+ r_normal = (p_normal[0] * u + p_normal[1] * v + p_normal[2] * w).normalized();
+}
+
+void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) {
+
+ if (p_level == cell_subdiv) {
+ //plot the face by guessing its albedo and emission value
+
+ //find best axis to map to, for scanning values
+ int closest_axis = 0;
+ float closest_dot = 0;
+
+ Plane plane = Plane(p_vtx[0], p_vtx[1], p_vtx[2]);
+ Vector3 normal = plane.normal;
+
+ for (int i = 0; i < 3; i++) {
+
+ Vector3 axis;
+ axis[i] = 1.0;
+ float dot = ABS(normal.dot(axis));
+ if (i == 0 || dot > closest_dot) {
+ closest_axis = i;
+ closest_dot = dot;
+ }
+ }
+
+ Vector3 axis;
+ axis[closest_axis] = 1.0;
+ Vector3 t1;
+ t1[(closest_axis + 1) % 3] = 1.0;
+ Vector3 t2;
+ t2[(closest_axis + 2) % 3] = 1.0;
+
+ t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width);
+ t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width);
+
+ Color albedo_accum;
+ Color emission_accum;
+ Vector3 normal_accum;
+
+ float alpha = 0.0;
+
+ //map to a grid average in the best axis for this face
+ for (int i = 0; i < color_scan_cell_width; i++) {
+
+ Vector3 ofs_i = float(i) * t1;
+
+ for (int j = 0; j < color_scan_cell_width; j++) {
+
+ Vector3 ofs_j = float(j) * t2;
+
+ Vector3 from = p_aabb.position + ofs_i + ofs_j;
+ Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis];
+ Vector3 half = (to - from) * 0.5;
+
+ //is in this cell?
+ if (!fast_tri_box_overlap(from + half, half, p_vtx)) {
+ continue; //face does not span this cell
+ }
+
+ //go from -size to +size*2 to avoid skipping collisions
+ Vector3 ray_from = from + (t1 + t2) * 0.5 - axis * p_aabb.size[closest_axis];
+ Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis] * 2;
+
+ if (normal.dot(ray_from - ray_to) < 0) {
+ SWAP(ray_from, ray_to);
+ }
+
+ Vector3 intersection;
+
+ if (!plane.intersects_segment(ray_from, ray_to, &intersection)) {
+ if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) {
+ intersection = plane.project(ray_from);
+ } else {
+
+ intersection = plane.project(ray_to);
+ }
+ }
+
+ intersection = Face3(p_vtx[0], p_vtx[1], p_vtx[2]).get_closest_point_to(intersection);
+
+ Vector2 uv;
+ Vector3 lnormal;
+ get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal);
+ if (lnormal == Vector3()) //just in case normal as nor provided
+ lnormal = normal;
+
+ int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
+ int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
+
+ int ofs = uv_y * bake_texture_size + uv_x;
+ albedo_accum.r += p_material.albedo[ofs].r;
+ albedo_accum.g += p_material.albedo[ofs].g;
+ albedo_accum.b += p_material.albedo[ofs].b;
+ albedo_accum.a += p_material.albedo[ofs].a;
+
+ emission_accum.r += p_material.emission[ofs].r;
+ emission_accum.g += p_material.emission[ofs].g;
+ emission_accum.b += p_material.emission[ofs].b;
+
+ normal_accum += lnormal;
+
+ alpha += 1.0;
+ }
+ }
+
+ if (alpha == 0) {
+ //could not in any way get texture information.. so use closest point to center
+
+ Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]);
+ Vector3 inters = f.get_closest_point_to(p_aabb.position + p_aabb.size * 0.5);
+
+ Vector3 lnormal;
+ Vector2 uv;
+ get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal);
+ if (lnormal == Vector3()) //just in case normal as nor provided
+ lnormal = normal;
+
+ int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
+ int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
+
+ int ofs = uv_y * bake_texture_size + uv_x;
+
+ alpha = 1.0 / (color_scan_cell_width * color_scan_cell_width);
+
+ albedo_accum.r = p_material.albedo[ofs].r * alpha;
+ albedo_accum.g = p_material.albedo[ofs].g * alpha;
+ albedo_accum.b = p_material.albedo[ofs].b * alpha;
+ albedo_accum.a = p_material.albedo[ofs].a * alpha;
+
+ emission_accum.r = p_material.emission[ofs].r * alpha;
+ emission_accum.g = p_material.emission[ofs].g * alpha;
+ emission_accum.b = p_material.emission[ofs].b * alpha;
+
+ normal_accum = lnormal * alpha;
+
+ } else {
+
+ float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width);
+ alpha *= accdiv;
+
+ albedo_accum.r *= accdiv;
+ albedo_accum.g *= accdiv;
+ albedo_accum.b *= accdiv;
+ albedo_accum.a *= accdiv;
+
+ emission_accum.r *= accdiv;
+ emission_accum.g *= accdiv;
+ emission_accum.b *= accdiv;
+
+ normal_accum *= accdiv;
+ }
+
+ //put this temporarily here, corrected in a later step
+ bake_cells.write[p_idx].albedo[0] += albedo_accum.r;
+ bake_cells.write[p_idx].albedo[1] += albedo_accum.g;
+ bake_cells.write[p_idx].albedo[2] += albedo_accum.b;
+ bake_cells.write[p_idx].emission[0] += emission_accum.r;
+ bake_cells.write[p_idx].emission[1] += emission_accum.g;
+ bake_cells.write[p_idx].emission[2] += emission_accum.b;
+ bake_cells.write[p_idx].normal[0] += normal_accum.x;
+ bake_cells.write[p_idx].normal[1] += normal_accum.y;
+ bake_cells.write[p_idx].normal[2] += normal_accum.z;
+ bake_cells.write[p_idx].alpha += alpha;
+
+ } else {
+ //go down
+
+ int half = (1 << cell_subdiv) >> (p_level + 1);
+ for (int i = 0; i < 8; i++) {
+
+ AABB aabb = p_aabb;
+ aabb.size *= 0.5;
+
+ int nx = p_x;
+ int ny = p_y;
+ int nz = p_z;
+
+ if (i & 1) {
+ aabb.position.x += aabb.size.x;
+ nx += half;
+ }
+ if (i & 2) {
+ aabb.position.y += aabb.size.y;
+ ny += half;
+ }
+ if (i & 4) {
+ aabb.position.z += aabb.size.z;
+ nz += half;
+ }
+ //make sure to not plot beyond limits
+ if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2])
+ continue;
+
+ {
+ AABB test_aabb = aabb;
+ //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
+ Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
+
+ if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
+ //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) {
+ //does not fit in child, go on
+ continue;
+ }
+ }
+
+ if (bake_cells[p_idx].children[i] == CHILD_EMPTY) {
+ //sub cell must be created
+
+ uint32_t child_idx = bake_cells.size();
+ bake_cells.write[p_idx].children[i] = child_idx;
+ bake_cells.resize(bake_cells.size() + 1);
+ bake_cells.write[child_idx].level = p_level + 1;
+ bake_cells.write[child_idx].x = nx / half;
+ bake_cells.write[child_idx].y = ny / half;
+ bake_cells.write[child_idx].z = nz / half;
+ }
+
+ _plot_face(bake_cells[p_idx].children[i], p_level + 1, nx, ny, nz, p_vtx, p_normal, p_uv, p_material, aabb);
+ }
+ }
+}
+
+Vector<Color> Voxelizer::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) {
+
+ Vector<Color> ret;
+
+ if (p_image.is_null() || p_image->empty()) {
+
+ ret.resize(bake_texture_size * bake_texture_size);
+ for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
+ ret.write[i] = p_color_add;
+ }
+
+ return ret;
+ }
+ p_image = p_image->duplicate();
+
+ if (p_image->is_compressed()) {
+ p_image->decompress();
+ }
+ p_image->convert(Image::FORMAT_RGBA8);
+ p_image->resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC);
+
+ const uint8_t *r = p_image->get_data().ptr();
+ ret.resize(bake_texture_size * bake_texture_size);
+
+ for (int i = 0; i < bake_texture_size * bake_texture_size; i++) {
+ Color c;
+ c.r = (r[i * 4 + 0] / 255.0) * p_color_mul.r + p_color_add.r;
+ c.g = (r[i * 4 + 1] / 255.0) * p_color_mul.g + p_color_add.g;
+ c.b = (r[i * 4 + 2] / 255.0) * p_color_mul.b + p_color_add.b;
+
+ c.a = r[i * 4 + 3] / 255.0;
+
+ ret.write[i] = c;
+ }
+
+ return ret;
+}
+
+Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material) {
+
+ //this way of obtaining materials is inaccurate and also does not support some compressed formats very well
+ Ref<StandardMaterial3D> mat = p_material;
+
+ Ref<Material> material = mat; //hack for now
+
+ if (material_cache.has(material)) {
+ return material_cache[material];
+ }
+
+ MaterialCache mc;
+
+ if (mat.is_valid()) {
+
+ Ref<Texture2D> albedo_tex = mat->get_texture(StandardMaterial3D::TEXTURE_ALBEDO);
+
+ Ref<Image> img_albedo;
+ if (albedo_tex.is_valid()) {
+
+ img_albedo = albedo_tex->get_data();
+ mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative
+ } else {
+ mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive
+ }
+
+ Ref<Texture2D> emission_tex = mat->get_texture(StandardMaterial3D::TEXTURE_EMISSION);
+
+ Color emission_col = mat->get_emission();
+ float emission_energy = mat->get_emission_energy();
+
+ Ref<Image> img_emission;
+
+ if (emission_tex.is_valid()) {
+
+ img_emission = emission_tex->get_data();
+ }
+
+ if (mat->get_emission_operator() == StandardMaterial3D::EMISSION_OP_ADD) {
+ mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy);
+ } else {
+ mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0));
+ }
+
+ } else {
+ Ref<Image> empty;
+
+ mc.albedo = _get_bake_texture(empty, Color(0, 0, 0), Color(1, 1, 1));
+ mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0));
+ }
+
+ material_cache[p_material] = mc;
+ return mc;
+}
+
+void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material) {
+
+ for (int i = 0; i < p_mesh->get_surface_count(); i++) {
+
+ if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
+ continue; //only triangles
+
+ Ref<Material> src_material;
+
+ if (p_override_material.is_valid()) {
+ src_material = p_override_material;
+ } else if (i < p_materials.size() && p_materials[i].is_valid()) {
+ src_material = p_materials[i];
+ } else {
+ src_material = p_mesh->surface_get_material(i);
+ }
+ MaterialCache material = _get_material_cache(src_material);
+
+ Array a = p_mesh->surface_get_arrays(i);
+
+ Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV];
+ const Vector2 *uvr;
+ Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
+ const Vector3 *nr;
+ Vector<int> index = a[Mesh::ARRAY_INDEX];
+
+ bool read_uv = false;
+ bool read_normals = false;
+
+ if (uv.size()) {
+
+ uvr = uv.ptr();
+ read_uv = true;
+ }
+
+ if (normals.size()) {
+ read_normals = true;
+ nr = normals.ptr();
+ }
+
+ if (index.size()) {
+
+ int facecount = index.size() / 3;
+ const int *ir = index.ptr();
+
+ for (int j = 0; j < facecount; j++) {
+
+ Vector3 vtxs[3];
+ Vector2 uvs[3];
+ Vector3 normal[3];
+
+ for (int k = 0; k < 3; k++) {
+ vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]);
+ }
+
+ if (read_uv) {
+ for (int k = 0; k < 3; k++) {
+ uvs[k] = uvr[ir[j * 3 + k]];
+ }
+ }
+
+ if (read_normals) {
+ for (int k = 0; k < 3; k++) {
+ normal[k] = nr[ir[j * 3 + k]];
+ }
+ }
+
+ //test against original bounds
+ if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
+ continue;
+ //plot
+ _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
+ }
+
+ } else {
+
+ int facecount = vertices.size() / 3;
+
+ for (int j = 0; j < facecount; j++) {
+
+ Vector3 vtxs[3];
+ Vector2 uvs[3];
+ Vector3 normal[3];
+
+ for (int k = 0; k < 3; k++) {
+ vtxs[k] = p_xform.xform(vr[j * 3 + k]);
+ }
+
+ if (read_uv) {
+ for (int k = 0; k < 3; k++) {
+ uvs[k] = uvr[j * 3 + k];
+ }
+ }
+
+ if (read_normals) {
+ for (int k = 0; k < 3; k++) {
+ normal[k] = nr[j * 3 + k];
+ }
+ }
+
+ //test against original bounds
+ if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
+ continue;
+ //plot face
+ _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
+ }
+ }
+ }
+
+ max_original_cells = bake_cells.size();
+}
+
+void Voxelizer::_sort() {
+
+ // cells need to be sorted by level and coordinates
+ // it is important that level has more priority (for compute), and that Z has the least,
+ // given it may aid older implementations plot using GPU
+
+ Vector<CellSort> sorted_cells;
+ uint32_t cell_count = bake_cells.size();
+ sorted_cells.resize(cell_count);
+ {
+
+ CellSort *sort_cellsp = sorted_cells.ptrw();
+ const Cell *bake_cellsp = bake_cells.ptr();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+ sort_cellsp[i].x = bake_cellsp[i].x;
+ sort_cellsp[i].y = bake_cellsp[i].y;
+ sort_cellsp[i].z = bake_cellsp[i].z;
+ sort_cellsp[i].level = bake_cellsp[i].level;
+ sort_cellsp[i].index = i;
+ }
+ }
+
+ sorted_cells.sort();
+
+ //verify just in case, index 0 must be level 0
+ ERR_FAIL_COND(sorted_cells[0].level != 0);
+
+ Vector<Cell> new_bake_cells;
+ new_bake_cells.resize(cell_count);
+ Vector<uint32_t> reverse_map;
+
+ {
+ reverse_map.resize(cell_count);
+ const CellSort *sort_cellsp = sorted_cells.ptr();
+ uint32_t *reverse_mapp = reverse_map.ptrw();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+ reverse_mapp[sort_cellsp[i].index] = i;
+ }
+ }
+
+ {
+
+ const CellSort *sort_cellsp = sorted_cells.ptr();
+ const Cell *bake_cellsp = bake_cells.ptr();
+ const uint32_t *reverse_mapp = reverse_map.ptr();
+ Cell *new_bake_cellsp = new_bake_cells.ptrw();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+ //copy to new cell
+ new_bake_cellsp[i] = bake_cellsp[sort_cellsp[i].index];
+ //remap children
+ for (uint32_t j = 0; j < 8; j++) {
+ if (new_bake_cellsp[i].children[j] != CHILD_EMPTY) {
+ new_bake_cellsp[i].children[j] = reverse_mapp[new_bake_cellsp[i].children[j]];
+ }
+ }
+ }
+ }
+
+ bake_cells = new_bake_cells;
+ sorted = true;
+}
+
+void Voxelizer::_fixup_plot(int p_idx, int p_level) {
+
+ if (p_level == cell_subdiv) {
+
+ leaf_voxel_count++;
+ float alpha = bake_cells[p_idx].alpha;
+
+ bake_cells.write[p_idx].albedo[0] /= alpha;
+ bake_cells.write[p_idx].albedo[1] /= alpha;
+ bake_cells.write[p_idx].albedo[2] /= alpha;
+
+ //transfer emission to light
+ bake_cells.write[p_idx].emission[0] /= alpha;
+ bake_cells.write[p_idx].emission[1] /= alpha;
+ bake_cells.write[p_idx].emission[2] /= alpha;
+
+ bake_cells.write[p_idx].normal[0] /= alpha;
+ bake_cells.write[p_idx].normal[1] /= alpha;
+ bake_cells.write[p_idx].normal[2] /= alpha;
+
+ Vector3 n(bake_cells[p_idx].normal[0], bake_cells[p_idx].normal[1], bake_cells[p_idx].normal[2]);
+ if (n.length() < 0.01) {
+ //too much fight over normal, zero it
+ bake_cells.write[p_idx].normal[0] = 0;
+ bake_cells.write[p_idx].normal[1] = 0;
+ bake_cells.write[p_idx].normal[2] = 0;
+ } else {
+ n.normalize();
+ bake_cells.write[p_idx].normal[0] = n.x;
+ bake_cells.write[p_idx].normal[1] = n.y;
+ bake_cells.write[p_idx].normal[2] = n.z;
+ }
+
+ bake_cells.write[p_idx].alpha = 1.0;
+
+ /*if (bake_light.size()) {
+ for(int i=0;i<6;i++) {
+
+ }
+ }*/
+
+ } else {
+
+ //go down
+
+ bake_cells.write[p_idx].emission[0] = 0;
+ bake_cells.write[p_idx].emission[1] = 0;
+ bake_cells.write[p_idx].emission[2] = 0;
+ bake_cells.write[p_idx].normal[0] = 0;
+ bake_cells.write[p_idx].normal[1] = 0;
+ bake_cells.write[p_idx].normal[2] = 0;
+ bake_cells.write[p_idx].albedo[0] = 0;
+ bake_cells.write[p_idx].albedo[1] = 0;
+ bake_cells.write[p_idx].albedo[2] = 0;
+
+ float alpha_average = 0;
+ int children_found = 0;
+
+ for (int i = 0; i < 8; i++) {
+
+ uint32_t child = bake_cells[p_idx].children[i];
+
+ if (child == CHILD_EMPTY)
+ continue;
+
+ _fixup_plot(child, p_level + 1);
+ alpha_average += bake_cells[child].alpha;
+
+ children_found++;
+ }
+
+ bake_cells.write[p_idx].alpha = alpha_average / 8.0;
+ }
+}
+
+void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
+
+ sorted = false;
+ original_bounds = p_bounds;
+ cell_subdiv = p_subdiv;
+ bake_cells.resize(1);
+ material_cache.clear();
+
+ print_line("subdiv: " + itos(p_subdiv));
+ //find out the actual real bounds, power of 2, which gets the highest subdivision
+ po2_bounds = p_bounds;
+ int longest_axis = po2_bounds.get_longest_axis_index();
+ axis_cell_size[longest_axis] = 1 << cell_subdiv;
+ leaf_voxel_count = 0;
+
+ for (int i = 0; i < 3; i++) {
+
+ if (i == longest_axis)
+ continue;
+
+ axis_cell_size[i] = axis_cell_size[longest_axis];
+ float axis_size = po2_bounds.size[longest_axis];
+
+ //shrink until fit subdiv
+ while (axis_size / 2.0 >= po2_bounds.size[i]) {
+ axis_size /= 2.0;
+ axis_cell_size[i] >>= 1;
+ }
+
+ po2_bounds.size[i] = po2_bounds.size[longest_axis];
+ }
+
+ Transform to_bounds;
+ to_bounds.basis.scale(Vector3(po2_bounds.size[longest_axis], po2_bounds.size[longest_axis], po2_bounds.size[longest_axis]));
+ to_bounds.origin = po2_bounds.position;
+
+ Transform to_grid;
+ to_grid.basis.scale(Vector3(axis_cell_size[longest_axis], axis_cell_size[longest_axis], axis_cell_size[longest_axis]));
+
+ to_cell_space = to_grid * to_bounds.affine_inverse();
+
+ cell_size = po2_bounds.size[longest_axis] / axis_cell_size[longest_axis];
+}
+
+void Voxelizer::end_bake() {
+ if (!sorted) {
+ _sort();
+ }
+ _fixup_plot(0, 0);
+}
+
+//create the data for visual server
+
+int Voxelizer::get_gi_probe_octree_depth() const {
+ return cell_subdiv;
+}
+Vector3i Voxelizer::get_giprobe_octree_size() const {
+ return Vector3i(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]);
+}
+int Voxelizer::get_giprobe_cell_count() const {
+ return bake_cells.size();
+}
+
+Vector<uint8_t> Voxelizer::get_giprobe_octree_cells() const {
+ Vector<uint8_t> data;
+ data.resize((8 * 4) * bake_cells.size()); //8 uint32t values
+ {
+ uint8_t *w = data.ptrw();
+ uint32_t *children_cells = (uint32_t *)w;
+ const Cell *cells = bake_cells.ptr();
+
+ uint32_t cell_count = bake_cells.size();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+
+ for (uint32_t j = 0; j < 8; j++) {
+ children_cells[i * 8 + j] = cells[i].children[j];
+ }
+ }
+ }
+
+ return data;
+}
+Vector<uint8_t> Voxelizer::get_giprobe_data_cells() const {
+ Vector<uint8_t> data;
+ data.resize((4 * 4) * bake_cells.size()); //8 uint32t values
+ {
+ uint8_t *w = data.ptrw();
+ uint32_t *dataptr = (uint32_t *)w;
+ const Cell *cells = bake_cells.ptr();
+
+ uint32_t cell_count = bake_cells.size();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+
+ { //position
+
+ uint32_t x = cells[i].x;
+ uint32_t y = cells[i].y;
+ uint32_t z = cells[i].z;
+
+ uint32_t position = x;
+ position |= y << 11;
+ position |= z << 21;
+
+ dataptr[i * 4 + 0] = position;
+ }
+
+ { //albedo + alpha
+ uint32_t rgba = uint32_t(CLAMP(cells[i].alpha * 255.0, 0, 255)) << 24; //a
+ rgba |= uint32_t(CLAMP(cells[i].albedo[2] * 255.0, 0, 255)) << 16; //b
+ rgba |= uint32_t(CLAMP(cells[i].albedo[1] * 255.0, 0, 255)) << 8; //g
+ rgba |= uint32_t(CLAMP(cells[i].albedo[0] * 255.0, 0, 255)); //r
+
+ dataptr[i * 4 + 1] = rgba;
+ }
+
+ { //emission, as rgbe9995
+ Color emission = Color(cells[i].emission[0], cells[i].emission[1], cells[i].emission[2]);
+ dataptr[i * 4 + 2] = emission.to_rgbe9995();
+ }
+
+ { //normal
+
+ Vector3 n(bake_cells[i].normal[0], bake_cells[i].normal[1], bake_cells[i].normal[2]);
+ n.normalize();
+
+ uint32_t normal = uint32_t(uint8_t(int8_t(CLAMP(n.x * 127.0, -128, 127))));
+ normal |= uint32_t(uint8_t(int8_t(CLAMP(n.y * 127.0, -128, 127)))) << 8;
+ normal |= uint32_t(uint8_t(int8_t(CLAMP(n.z * 127.0, -128, 127)))) << 16;
+
+ dataptr[i * 4 + 3] = normal;
+ }
+ }
+ }
+
+ return data;
+}
+
+Vector<int> Voxelizer::get_giprobe_level_cell_count() const {
+ uint32_t cell_count = bake_cells.size();
+ const Cell *cells = bake_cells.ptr();
+ Vector<int> level_count;
+ level_count.resize(cell_subdiv + 1); //remember, always x+1 levels for x subdivisions
+ {
+ int *w = level_count.ptrw();
+ for (int i = 0; i < cell_subdiv + 1; i++) {
+ w[i] = 0;
+ }
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+ w[cells[i].level]++;
+ }
+ }
+
+ return level_count;
+}
+
+// euclidean distance computation based on:
+// https://prideout.net/blog/distance_fields/
+
+#define square(m_s) ((m_s) * (m_s))
+#define INF 1e20
+
+/* dt of 1d function using squared distance */
+static void edt(float *f, int stride, int n) {
+
+ float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1));
+ int *v = (int *)&(d[n]);
+ float *z = (float *)&v[n];
+
+ int k = 0;
+ v[0] = 0;
+ z[0] = -INF;
+ z[1] = +INF;
+ for (int q = 1; q <= n - 1; q++) {
+ float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]);
+ while (s <= z[k]) {
+ k--;
+ s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]);
+ }
+ k++;
+ v[k] = q;
+
+ z[k] = s;
+ z[k + 1] = +INF;
+ }
+
+ k = 0;
+ for (int q = 0; q <= n - 1; q++) {
+ while (z[k + 1] < q)
+ k++;
+ d[q] = square(q - v[k]) + f[v[k] * stride];
+ }
+
+ for (int i = 0; i < n; i++) {
+ f[i * stride] = d[i];
+ }
+}
+
+#undef square
+
+Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
+
+ Vector3i octree_size = get_giprobe_octree_size();
+
+ uint32_t float_count = octree_size.x * octree_size.y * octree_size.z;
+ float *work_memory = memnew_arr(float, float_count);
+ for (uint32_t i = 0; i < float_count; i++) {
+ work_memory[i] = INF;
+ }
+
+ uint32_t y_mult = octree_size.x;
+ uint32_t z_mult = y_mult * octree_size.y;
+
+ //plot solid cells
+ {
+ const Cell *cells = bake_cells.ptr();
+ uint32_t cell_count = bake_cells.size();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+
+ if (cells[i].level < (cell_subdiv - 1)) {
+ continue; //do not care about this level
+ }
+
+ work_memory[cells[i].x + cells[i].y * y_mult + cells[i].z * z_mult] = 0;
+ }
+ }
+
+ //process in each direction
+
+ //xy->z
+
+ for (int i = 0; i < octree_size.x; i++) {
+ for (int j = 0; j < octree_size.y; j++) {
+ edt(&work_memory[i + j * y_mult], z_mult, octree_size.z);
+ }
+ }
+
+ //xz->y
+
+ for (int i = 0; i < octree_size.x; i++) {
+ for (int j = 0; j < octree_size.z; j++) {
+ edt(&work_memory[i + j * z_mult], y_mult, octree_size.y);
+ }
+ }
+
+ //yz->x
+ for (int i = 0; i < octree_size.y; i++) {
+ for (int j = 0; j < octree_size.z; j++) {
+ edt(&work_memory[i * y_mult + j * z_mult], 1, octree_size.x);
+ }
+ }
+
+ Vector<uint8_t> image3d;
+ image3d.resize(float_count);
+ {
+ uint8_t *w = image3d.ptrw();
+ for (uint32_t i = 0; i < float_count; i++) {
+ uint32_t d = uint32_t(Math::sqrt(work_memory[i]));
+ if (d == 0) {
+ w[i] = 0;
+ } else {
+ w[i] = MIN(d, 254) + 1;
+ }
+ }
+ }
+
+ return image3d;
+}
+
+#undef INF
+
+void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx) {
+
+ if (p_level == cell_subdiv - 1) {
+
+ Vector3 center = p_aabb.position + p_aabb.size * 0.5;
+ Transform xform;
+ xform.origin = center;
+ xform.basis.scale(p_aabb.size * 0.5);
+ p_multimesh->set_instance_transform(idx, xform);
+ Color col;
+ col = Color(bake_cells[p_idx].albedo[0], bake_cells[p_idx].albedo[1], bake_cells[p_idx].albedo[2]);
+ //Color col = Color(bake_cells[p_idx].emission[0], bake_cells[p_idx].emission[1], bake_cells[p_idx].emission[2]);
+ p_multimesh->set_instance_color(idx, col);
+
+ idx++;
+
+ } else {
+
+ for (int i = 0; i < 8; i++) {
+
+ uint32_t child = bake_cells[p_idx].children[i];
+
+ if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells)
+ continue;
+
+ AABB aabb = p_aabb;
+ aabb.size *= 0.5;
+
+ if (i & 1)
+ aabb.position.x += aabb.size.x;
+ if (i & 2)
+ aabb.position.y += aabb.size.y;
+ if (i & 4)
+ aabb.position.z += aabb.size.z;
+
+ _debug_mesh(bake_cells[p_idx].children[i], p_level + 1, aabb, p_multimesh, idx);
+ }
+ }
+}
+
+Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
+
+ Ref<MultiMesh> mm;
+
+ mm.instance();
+
+ mm->set_transform_format(MultiMesh::TRANSFORM_3D);
+ mm->set_use_colors(true);
+ mm->set_instance_count(leaf_voxel_count);
+
+ Ref<ArrayMesh> mesh;
+ mesh.instance();
+
+ {
+ Array arr;
+ arr.resize(Mesh::ARRAY_MAX);
+
+ Vector<Vector3> vertices;
+ Vector<Color> colors;
+#define ADD_VTX(m_idx) \
+ vertices.push_back(face_points[m_idx]); \
+ colors.push_back(Color(1, 1, 1, 1));
+
+ for (int i = 0; i < 6; i++) {
+
+ Vector3 face_points[4];
+
+ for (int j = 0; j < 4; j++) {
+
+ float v[3];
+ v[0] = 1.0;
+ v[1] = 1 - 2 * ((j >> 1) & 1);
+ v[2] = v[1] * (1 - 2 * (j & 1));
+
+ for (int k = 0; k < 3; k++) {
+
+ if (i < 3)
+ face_points[j][(i + k) % 3] = v[k];
+ else
+ face_points[3 - j][(i + k) % 3] = -v[k];
+ }
+ }
+
+ //tri 1
+ ADD_VTX(0);
+ ADD_VTX(1);
+ ADD_VTX(2);
+ //tri 2
+ ADD_VTX(2);
+ ADD_VTX(3);
+ ADD_VTX(0);
+ }
+
+ arr[Mesh::ARRAY_VERTEX] = vertices;
+ arr[Mesh::ARRAY_COLOR] = colors;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
+ }
+
+ {
+ Ref<StandardMaterial3D> fsm;
+ fsm.instance();
+ fsm->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ fsm->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ fsm->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ fsm->set_albedo(Color(1, 1, 1, 1));
+
+ mesh->surface_set_material(0, fsm);
+ }
+
+ mm->set_mesh(mesh);
+
+ int idx = 0;
+ _debug_mesh(0, 0, po2_bounds, mm, idx);
+
+ return mm;
+}
+
+Transform Voxelizer::get_to_cell_space_xform() const {
+ return to_cell_space;
+}
+Voxelizer::Voxelizer() {
+ sorted = false;
+ color_scan_cell_width = 4;
+ bake_texture_size = 128;
+}
diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxelizer.h
index 7e78a19830..1d50f1cd18 100644
--- a/scene/3d/voxel_light_baker.h
+++ b/scene/3d/voxelizer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* voxel_light_baker.h */
+/* voxelizer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -31,27 +31,11 @@
#ifndef VOXEL_LIGHT_BAKER_H
#define VOXEL_LIGHT_BAKER_H
+#include "core/math/vector3i.h"
#include "scene/3d/mesh_instance.h"
#include "scene/resources/multimesh.h"
-class VoxelLightBaker {
-public:
- enum DebugMode {
- DEBUG_ALBEDO,
- DEBUG_LIGHT
- };
-
- enum BakeQuality {
- BAKE_QUALITY_LOW,
- BAKE_QUALITY_MEDIUM,
- BAKE_QUALITY_HIGH
- };
-
- enum BakeMode {
- BAKE_MODE_CONE_TRACE,
- BAKE_MODE_RAY_TRACE,
- };
-
+class Voxelizer {
private:
enum {
CHILD_EMPTY = 0xFFFFFFFF
@@ -66,7 +50,10 @@ private:
float normal[3];
uint32_t used_sides;
float alpha; //used for upsampling
- int level;
+ uint16_t x;
+ uint16_t y;
+ uint16_t z;
+ uint16_t level;
Cell() {
for (int i = 0; i < 8; i++) {
@@ -80,6 +67,7 @@ private:
}
alpha = 0;
used_sides = 0;
+ x = y = z = 0;
level = 0;
}
};
@@ -87,27 +75,24 @@ private:
Vector<Cell> bake_cells;
int cell_subdiv;
- struct Light {
- int x, y, z;
- float accum[6][3]; //rgb anisotropic
- float direct_accum[6][3]; //for direct bake
- int next_leaf;
- Light() {
- x = y = z = 0;
- for (int i = 0; i < 6; i++) {
- for (int j = 0; j < 3; j++) {
- accum[i][j] = 0;
- direct_accum[i][j] = 0;
- }
- }
- next_leaf = 0;
+ struct CellSort {
+ union {
+ struct {
+ uint64_t z : 16;
+ uint64_t y : 16;
+ uint64_t x : 16;
+ uint64_t level : 16;
+ };
+ uint64_t key;
+ };
+
+ int32_t index;
+
+ _FORCE_INLINE_ bool operator<(const CellSort &p_cell_sort) const {
+ return key < p_cell_sort.key;
}
};
- int first_leaf;
-
- Vector<Light> bake_light;
-
struct MaterialCache {
//128x128 textures
Vector<Color> albedo;
@@ -115,9 +100,6 @@ private:
};
Map<Ref<Material>, MaterialCache> material_cache;
- int leaf_voxel_count;
- bool direct_lights_baked;
-
AABB original_bounds;
AABB po2_bounds;
int axis_cell_size[3];
@@ -127,65 +109,37 @@ private:
int color_scan_cell_width;
int bake_texture_size;
float cell_size;
- float propagation;
- float energy;
-
- BakeQuality bake_quality;
- BakeMode bake_mode;
int max_original_cells;
-
- void _init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent);
+ int leaf_voxel_count;
Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add);
MaterialCache _get_material_cache(Ref<Material> p_material);
void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb);
void _fixup_plot(int p_idx, int p_level);
- void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, DebugMode p_mode);
- void _check_init_light();
-
- uint32_t _find_cell_at_pos(const Cell *cells, int x, int y, int z);
+ void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx);
- struct LightMap {
- Vector3 light;
- Vector3 pos;
- Vector3 normal;
- };
-
- void _plot_triangle(Vector2 *vertices, Vector3 *positions, Vector3 *normals, LightMap *pixels, int width, int height);
-
- _FORCE_INLINE_ void _sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha);
- _FORCE_INLINE_ Vector3 _voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture);
- _FORCE_INLINE_ Vector3 _compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
- _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
-
- void _lightmap_bake_point(uint32_t p_x, LightMap *p_line);
+ bool sorted;
+ void _sort();
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
void plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
- void begin_bake_light(BakeQuality p_quality = BAKE_QUALITY_MEDIUM, BakeMode p_bake_mode = BAKE_MODE_CONE_TRACE, float p_propagation = 0.85, float p_energy = 1);
- void plot_light_directional(const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, bool p_direct);
- void plot_light_omni(const Vector3 &p_pos, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, bool p_direct);
- void plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axis, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, float p_spot_angle, float p_spot_attenuation, bool p_direct);
void end_bake();
- struct LightMapData {
- int width;
- int height;
- PoolVector<float> light;
- };
-
- Error make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, float default_texels_per_unit, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float) = NULL, void *p_bake_time_ud = NULL);
+ int get_gi_probe_octree_depth() const;
+ Vector3i get_giprobe_octree_size() const;
+ int get_giprobe_cell_count() const;
+ Vector<uint8_t> get_giprobe_octree_cells() const;
+ Vector<uint8_t> get_giprobe_data_cells() const;
+ Vector<int> get_giprobe_level_cell_count() const;
+ Vector<uint8_t> get_sdf_3d_image() const;
- PoolVector<int> create_gi_probe_data();
- Ref<MultiMesh> create_debug_multimesh(DebugMode p_mode = DEBUG_ALBEDO);
- PoolVector<uint8_t> create_capture_octree(int p_subdiv);
+ Ref<MultiMesh> create_debug_multimesh();
- float get_cell_size() const;
Transform get_to_cell_space_xform() const;
- VoxelLightBaker();
+ Voxelizer();
};
#endif // VOXEL_LIGHT_BAKER_H
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index c8d7382e81..83a7243906 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -43,12 +43,25 @@ void WorldEnvironment::_notification(int p_what) {
add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
}
+ if (camera_effects.is_valid()) {
+ if (get_viewport()->find_world()->get_camera_effects().is_valid()) {
+ WARN_PRINT("World already has a camera effects (Another WorldEnvironment?), overriding.");
+ }
+ get_viewport()->find_world()->set_camera_effects(camera_effects);
+ add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ }
+
} else if (p_what == Spatial::NOTIFICATION_EXIT_WORLD || p_what == Spatial::NOTIFICATION_EXIT_TREE) {
if (environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) {
get_viewport()->find_world()->set_environment(Ref<Environment>());
remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
}
+
+ if (camera_effects.is_valid() && get_viewport()->find_world()->get_camera_effects() == camera_effects) {
+ get_viewport()->find_world()->set_camera_effects(Ref<CameraEffects>());
+ remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ }
}
}
@@ -77,13 +90,38 @@ Ref<Environment> WorldEnvironment::get_environment() const {
return environment;
}
+void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
+
+ if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world()->get_camera_effects() == camera_effects) {
+ get_viewport()->find_world()->set_camera_effects(Ref<CameraEffects>());
+ remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ //clean up
+ }
+
+ camera_effects = p_camera_effects;
+ if (is_inside_tree() && camera_effects.is_valid()) {
+ if (get_viewport()->find_world()->get_camera_effects().is_valid()) {
+ WARN_PRINT("World already has an camera_effects (Another WorldEnvironment?), overriding.");
+ }
+ get_viewport()->find_world()->set_camera_effects(camera_effects);
+ add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id()));
+ }
+
+ update_configuration_warning();
+}
+
+Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
+
+ return camera_effects;
+}
+
String WorldEnvironment::get_configuration_warning() const {
if (!environment.is_valid()) {
return TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect.");
}
- if (/*!is_visible_in_tree() ||*/ !is_inside_tree())
+ if (!is_inside_tree())
return String();
List<Node *> nodes;
@@ -93,11 +131,6 @@ String WorldEnvironment::get_configuration_warning() const {
return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).");
}
- // Commenting this warning for now, I think it makes no sense. If anyone can figure out what its supposed to do, feedback welcome. Else it should be deprecated.
- //if (environment.is_valid() && get_viewport() && !get_viewport()->get_camera() && environment->get_background() != Environment::BG_CANVAS) {
- // return TTR("This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set this environment's Background Mode to Canvas (for 2D scenes).");
- //}
-
return String();
}
@@ -106,6 +139,10 @@ void WorldEnvironment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_environment", "env"), &WorldEnvironment::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
+
+ ClassDB::bind_method(D_METHOD("set_camera_effects", "env"), &WorldEnvironment::set_camera_effects);
+ ClassDB::bind_method(D_METHOD("get_camera_effects"), &WorldEnvironment::get_camera_effects);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
}
WorldEnvironment::WorldEnvironment() {
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index 6e89fe8517..0c590bfc07 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -38,6 +38,7 @@ class WorldEnvironment : public Node {
GDCLASS(WorldEnvironment, Node);
Ref<Environment> environment;
+ Ref<CameraEffects> camera_effects;
protected:
void _notification(int p_what);
@@ -47,6 +48,9 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
+ void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
+ Ref<CameraEffects> get_camera_effects() const;
+
String get_configuration_warning() const;
WorldEnvironment();