summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/camera.cpp10
-rw-r--r--scene/3d/physics_body.cpp40
-rw-r--r--scene/3d/physics_body.h1
-rw-r--r--scene/3d/skeleton.cpp103
-rw-r--r--scene/3d/skeleton.h10
-rw-r--r--scene/3d/soft_body.cpp187
-rw-r--r--scene/3d/soft_body.h11
-rw-r--r--scene/3d/spatial.cpp5
-rw-r--r--scene/3d/spatial.h1
9 files changed, 260 insertions, 108 deletions
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 0fe427d5fc..2176b45faf 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -74,10 +74,7 @@ void Camera::_update_camera() {
if (!is_inside_tree())
return;
- Transform tr = get_camera_transform();
- tr.origin += tr.basis.get_axis(1) * v_offset;
- tr.origin += tr.basis.get_axis(0) * h_offset;
- VisualServer::get_singleton()->camera_set_transform(camera, tr);
+ VisualServer::get_singleton()->camera_set_transform(camera, get_camera_transform());
// here goes listener stuff
/*
@@ -143,7 +140,10 @@ void Camera::_notification(int p_what) {
Transform Camera::get_camera_transform() const {
- return get_global_transform().orthonormalized();
+ Transform tr = get_global_transform().orthonormalized();
+ tr.origin += tr.basis.get_axis(1) * v_offset;
+ tr.origin += tr.basis.get_axis(0) * h_offset;
+ return tr;
}
void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 4b3a4add4a..e53ccb4cf4 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -189,9 +189,10 @@ void StaticBody::set_friction(real_t p_friction) {
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
+
physics_material_override->set_friction(p_friction);
- _reload_physics_characteristics();
}
real_t StaticBody::get_friction() const {
@@ -215,9 +216,9 @@ void StaticBody::set_bounce(real_t p_bounce) {
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_bounce(p_bounce);
- _reload_physics_characteristics();
}
real_t StaticBody::get_bounce() const {
@@ -235,7 +236,8 @@ real_t StaticBody::get_bounce() const {
void StaticBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ 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");
}
physics_material_override = p_physics_material_override;
@@ -313,13 +315,9 @@ void StaticBody::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0);
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT);
} else {
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce());
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
@@ -626,9 +624,9 @@ void RigidBody::set_friction(real_t p_friction) {
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_friction(p_friction);
- _reload_physics_characteristics();
}
real_t RigidBody::get_friction() const {
@@ -648,9 +646,9 @@ void RigidBody::set_bounce(real_t p_bounce) {
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_bounce(p_bounce);
- _reload_physics_characteristics();
}
real_t RigidBody::get_bounce() const {
ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material")
@@ -665,7 +663,8 @@ real_t RigidBody::get_bounce() const {
void RigidBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ 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");
}
physics_material_override = p_physics_material_override;
@@ -1070,13 +1069,9 @@ void RigidBody::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0);
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT);
} else {
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce());
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
@@ -1130,6 +1125,9 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
return colliding;
}
+//so, if you pass 45 as limit, avoid numerical precision erros when angle is 45.
+#define FLOOR_ANGLE_THRESHOLD 0.01
+
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
Vector3 lv = p_linear_velocity;
@@ -1162,7 +1160,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
//all is a wall
on_wall = true;
} else {
- if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
+ if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //floor
on_floor = true;
floor_velocity = collision.collider_vel;
@@ -1176,7 +1174,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
set_global_transform(gt);
return floor_velocity - p_floor_direction * p_floor_direction.dot(floor_velocity);
}
- } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
+ } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
@@ -2044,6 +2042,8 @@ void PhysicalBone::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics);
+ ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id);
+
ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone::set_mass);
ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone::get_mass);
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 4143989671..80bf422c98 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -557,6 +557,7 @@ protected:
private:
static Skeleton *find_skeleton_parent(Node *p_parent);
+
void _fix_joint_offset();
void _reload_joint();
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index 4b6b59b2d3..c796e47f25 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -131,7 +131,7 @@ void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const {
String prep = "bones/" + itos(i) + "/";
p_list->push_back(PropertyInfo(Variant::STRING, prep + "name"));
- p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(i - 1) + ",1"));
+ p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest"));
p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
@@ -139,6 +139,59 @@ void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
+void Skeleton::_update_process_order() {
+
+ if (!process_order_dirty)
+ return;
+
+ Bone *bonesptr = bones.ptrw();
+ int len = bones.size();
+
+ process_order.resize(len);
+ int *order = process_order.ptrw();
+ for (int i = 0; i < len; i++) {
+
+ if (bonesptr[i].parent >= len) {
+ //validate this just in case
+ ERR_PRINTS("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent));
+ bonesptr[i].parent = -1;
+ }
+ order[i] = i;
+ bonesptr[i].sort_index = i;
+ }
+ //now check process order
+ int pass_count = 0;
+ while (pass_count < len * len) {
+ //using bubblesort because of simplicity, it wont run every frame though.
+ //bublesort worst case is O(n^2), and this may be an infinite loop if cyclic
+ bool swapped = false;
+ for (int i = 0; i < len; i++) {
+ int parent_idx = bonesptr[order[i]].parent;
+ if (parent_idx < 0)
+ continue; //do nothing because it has no parent
+ //swap indices
+ int parent_order = bonesptr[parent_idx].sort_index;
+ if (parent_order > i) {
+ bonesptr[order[i]].sort_index = parent_order;
+ bonesptr[parent_idx].sort_index = i;
+ //swap order
+ SWAP(order[i], order[parent_order]);
+ swapped = true;
+ }
+ }
+
+ if (!swapped)
+ break;
+ pass_count++;
+ }
+
+ if (pass_count == len * len) {
+ ERR_PRINT("Skeleton parenthood graph is cyclic");
+ }
+
+ process_order_dirty = false;
+}
+
void Skeleton::_notification(int p_what) {
switch (p_what) {
@@ -181,19 +234,23 @@ void Skeleton::_notification(int p_what) {
vs->skeleton_allocate(skeleton, len); // if same size, nothin really happens
+ _update_process_order();
+
+ const int *order = process_order.ptr();
+
// pose changed, rebuild cache of inverses
if (rest_global_inverse_dirty) {
// calculate global rests and invert them
for (int i = 0; i < len; i++) {
- Bone &b = bonesptr[i];
+ Bone &b = bonesptr[order[i]];
if (b.parent >= 0)
b.rest_global_inverse = bonesptr[b.parent].rest_global_inverse * b.rest;
else
b.rest_global_inverse = b.rest;
}
for (int i = 0; i < len; i++) {
- Bone &b = bonesptr[i];
+ Bone &b = bonesptr[order[i]];
b.rest_global_inverse.affine_invert();
}
@@ -205,7 +262,7 @@ void Skeleton::_notification(int p_what) {
for (int i = 0; i < len; i++) {
- Bone &b = bonesptr[i];
+ Bone &b = bonesptr[order[i]];
if (b.disable_rest) {
if (b.enabled) {
@@ -319,12 +376,13 @@ void Skeleton::add_bone(const String &p_name) {
for (int i = 0; i < bones.size(); i++) {
- ERR_FAIL_COND(bones[i].name == "p_name");
+ ERR_FAIL_COND(bones[i].name == p_name);
}
Bone b;
b.name = p_name;
bones.push_back(b);
+ process_order_dirty = true;
rest_global_inverse_dirty = true;
_make_dirty();
@@ -368,10 +426,11 @@ int Skeleton::get_bone_count() const {
void Skeleton::set_bone_parent(int p_bone, int p_parent) {
ERR_FAIL_INDEX(p_bone, bones.size());
- ERR_FAIL_COND(p_parent != -1 && (p_parent < 0 || p_parent >= p_bone));
+ ERR_FAIL_COND(p_parent != -1 && (p_parent < 0));
bones.write[p_bone].parent = p_parent;
rest_global_inverse_dirty = true;
+ process_order_dirty = true;
_make_dirty();
}
@@ -379,6 +438,8 @@ void Skeleton::unparent_bone_and_rest(int p_bone) {
ERR_FAIL_INDEX(p_bone, bones.size());
+ _update_process_order();
+
int parent = bones[p_bone].parent;
while (parent >= 0) {
bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest;
@@ -387,6 +448,7 @@ void Skeleton::unparent_bone_and_rest(int p_bone) {
bones.write[p_bone].parent = -1;
bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing
+ process_order_dirty = true;
_make_dirty();
}
@@ -489,6 +551,8 @@ void Skeleton::clear_bones() {
bones.clear();
rest_global_inverse_dirty = true;
+ process_order_dirty = true;
+
_make_dirty();
}
@@ -538,12 +602,21 @@ void Skeleton::_make_dirty() {
dirty = true;
}
+int Skeleton::get_process_order(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, bones.size(), -1);
+ _update_process_order();
+ return process_order[p_idx];
+}
+
void Skeleton::localize_rests() {
- for (int i = bones.size() - 1; i >= 0; i--) {
+ _update_process_order();
- if (bones[i].parent >= 0)
- set_bone_rest(i, bones[bones[i].parent].rest.affine_inverse() * bones[i].rest);
+ for (int i = bones.size() - 1; i >= 0; i--) {
+ int idx = process_order[i];
+ if (bones[idx].parent >= 0) {
+ set_bone_rest(idx, bones[bones[idx].parent].rest.affine_inverse() * bones[idx].rest);
+ }
}
}
@@ -600,9 +673,12 @@ PhysicalBone *Skeleton::_get_physical_bone_parent(int p_bone) {
void Skeleton::_rebuild_physical_bones_cache() {
const int b_size = bones.size();
for (int i = 0; i < b_size; ++i) {
- bones.write[i].cache_parent_physical_bone = _get_physical_bone_parent(i);
- if (bones[i].physical_bone)
- bones[i].physical_bone->_on_bone_parent_changed();
+ PhysicalBone *parent_pb = _get_physical_bone_parent(i);
+ if (parent_pb != bones[i].physical_bone) {
+ bones.write[i].cache_parent_physical_bone = parent_pb;
+ if (bones[i].physical_bone)
+ bones[i].physical_bone->_on_bone_parent_changed();
+ }
}
}
@@ -740,6 +816,8 @@ void Skeleton::_bind_methods() {
#endif // _3D_DISABLED
+ ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation);
+
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
}
@@ -747,6 +825,7 @@ Skeleton::Skeleton() {
rest_global_inverse_dirty = true;
dirty = false;
+ process_order_dirty = true;
skeleton = VisualServer::get_singleton()->skeleton_create();
set_notify_transform(true);
}
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index 9672acb57a..e044e08437 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -39,6 +39,8 @@
*/
#ifndef _3D_DISABLED
+typedef int BoneId;
+
class PhysicalBone;
#endif // _3D_DISABLED
@@ -52,6 +54,7 @@ class Skeleton : public Spatial {
bool enabled;
int parent;
+ int sort_index; //used for re-sorting process order
bool ignore_animation;
@@ -90,13 +93,15 @@ class Skeleton : public Spatial {
bool rest_global_inverse_dirty;
Vector<Bone> bones;
+ Vector<int> process_order;
+ bool process_order_dirty;
RID skeleton;
void _make_dirty();
bool dirty;
- //bind helpers
+ // bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
Array bound;
@@ -110,6 +115,8 @@ class Skeleton : public Spatial {
return bound;
}
+ void _update_process_order();
+
protected:
bool _get(const StringName &p_path, Variant &r_ret) const;
bool _set(const StringName &p_path, const Variant &p_value);
@@ -170,6 +177,7 @@ public:
Transform get_bone_custom_pose(int p_bone) const;
void localize_rests(); // used for loaders and tools
+ int get_process_order(int p_idx);
#ifndef _3D_DISABLED
// Physical bone API
diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp
index 8498dc34c0..980c348c9b 100644
--- a/scene/3d/soft_body.cpp
+++ b/scene/3d/soft_body.cpp
@@ -98,7 +98,7 @@ SoftBody::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
point_index = obj_tocopy.point_index;
spatial_attachment_path = obj_tocopy.spatial_attachment_path;
spatial_attachment = obj_tocopy.spatial_attachment;
- vertex_offset_transform = obj_tocopy.vertex_offset_transform;
+ offset = obj_tocopy.offset;
}
void SoftBody::_update_pickable() {
@@ -133,8 +133,8 @@ 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_indices.size();
- PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
+ const int pinned_points_indices_size = pinned_points.size();
+ PoolVector<PinnedPoint>::Read r = pinned_points.read();
arr_ret.resize(pinned_points_indices_size);
for (int i = 0; i < pinned_points_indices_size; ++i) {
@@ -157,13 +157,14 @@ bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const {
void SoftBody::_get_property_list(List<PropertyInfo> *p_list) const {
- const int pinned_points_indices_size = pinned_points_indices.size();
+ const int pinned_points_indices_size = pinned_points.size();
p_list->push_back(PropertyInfo(Variant::POOL_INT_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"));
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "attachments/" + itos(i) + "/spatial_attachment_path"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "attachments/" + itos(i) + "/offset"));
}
}
@@ -172,17 +173,17 @@ 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_indices.read();
- if (p_indices_size < pinned_points_indices.size()) {
- for (int i = pinned_points_indices.size() - 1; i >= p_indices_size; --i) {
+ PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ 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);
}
}
}
- pinned_points_indices.resize(p_indices_size);
+ pinned_points.resize(p_indices_size);
- PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
+ PoolVector<PinnedPoint>::Write w = pinned_points.write();
int point_index;
for (int i = 0; i < p_indices_size; ++i) {
point_index = p_indices.get(i);
@@ -197,13 +198,17 @@ bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) {
}
bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) {
- if (pinned_points_indices.size() <= p_item) {
+ if (pinned_points.size() <= p_item) {
return false;
}
if ("spatial_attachment_path" == p_what) {
- PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
+ PoolVector<PinnedPoint>::Write w = pinned_points.write();
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();
+ w[p_item].offset = p_value;
} else {
return false;
}
@@ -212,15 +217,17 @@ bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &
}
bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const {
- if (pinned_points_indices.size() <= p_item) {
+ if (pinned_points.size() <= p_item) {
return false;
}
- PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
+ PoolVector<PinnedPoint>::Read r = pinned_points.read();
if ("point_index" == p_what) {
r_ret = r[p_item].point_index;
} else if ("spatial_attachment_path" == p_what) {
r_ret = r[p_item].spatial_attachment_path;
+ } else if ("offset" == p_what) {
+ r_ret = r[p_item].offset;
} else {
return false;
}
@@ -229,6 +236,8 @@ 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();
+ _reset_points_offsets();
#ifdef TOOLS_ENABLED
if (p_changed == this) {
update_configuration_warning();
@@ -240,12 +249,13 @@ void SoftBody::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
- if (Engine::get_singleton()->is_editor_hint())
+ if (Engine::get_singleton()->is_editor_hint()) {
+
add_change_receptor(this);
+ }
RID space = get_world()->get_space();
PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space);
- PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
update_physics_server();
} break;
case NOTIFICATION_READY: {
@@ -255,20 +265,32 @@ void SoftBody::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!simulation_started) {
- PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
-
- _update_cache_pin_points_datas();
- // Submit bone attachment
- const int pinned_points_indices_size = pinned_points_indices.size();
- PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
- for (int i = 0; i < pinned_points_indices_size; ++i) {
- if (!r[i].spatial_attachment) {
- // Use soft body position to update the point position
- PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (get_global_transform() * r[i].vertex_offset_transform).origin);
- } else {
- PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (r[i].spatial_attachment->get_global_transform() * r[i].vertex_offset_transform).origin);
- }
+ if (Engine::get_singleton()->is_editor_hint()) {
+ _reset_points_offsets();
+ return;
+ }
+
+ PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
+
+ set_notify_transform(false);
+ // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform
+ set_as_toplevel(true);
+ set_transform(Transform());
+ 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;
@@ -408,8 +430,15 @@ void SoftBody::_draw_soft_mesh() {
void SoftBody::update_physics_server() {
- if (Engine::get_singleton()->is_editor_hint())
+ if (Engine::get_singleton()->is_editor_hint()) {
+
+ if (get_mesh().is_valid())
+ PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
+ else
+ PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL);
+
return;
+ }
if (get_mesh().is_valid()) {
@@ -430,6 +459,9 @@ void SoftBody::become_mesh_owner() {
if (!mesh_owner) {
mesh_owner = true;
+ Vector<Ref<Material> > copy_materials;
+ copy_materials.append_array(materials);
+
ERR_FAIL_COND(!mesh->get_surface_count());
// Get current mesh array and create new mesh array with necessary flag for softbody
@@ -443,11 +475,10 @@ void SoftBody::become_mesh_owner() {
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->surface_set_material(0, mesh->surface_get_material(0));
set_mesh(soft_mesh);
- Vector<Ref<Material> > copy_materials;
- copy_materials.append_array(materials);
for (int i = copy_materials.size() - 1; 0 <= i; --i) {
set_surface_material(i, copy_materials[i]);
}
@@ -506,15 +537,15 @@ const NodePath &SoftBody::get_parent_collision_ignore() const {
}
void SoftBody::set_pinned_points_indices(PoolVector<SoftBody::PinnedPoint> p_pinned_points_indices) {
- pinned_points_indices = p_pinned_points_indices;
- PoolVector<PinnedPoint>::Read w = pinned_points_indices.read();
- for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) {
+ 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() {
- return pinned_points_indices;
+ return pinned_points;
}
void SoftBody::add_collision_exception_with(Node *p_node) {
@@ -651,6 +682,8 @@ SoftBody::SoftBody() :
pinned_points_cache_dirty(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() {
@@ -658,36 +691,30 @@ SoftBody::~SoftBody() {
void SoftBody::reset_softbody_pin() {
PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid);
- PoolVector<PinnedPoint>::Read pps = pinned_points_indices.read();
- for (int i = pinned_points_indices.size() - 1; 0 < i; --i) {
+ PoolVector<PinnedPoint>::Read pps = pinned_points.read();
+ for (int i = pinned_points.size() - 1; 0 < i; --i) {
PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true);
}
}
-void SoftBody::_update_cache_pin_points_datas() {
- if (pinned_points_cache_dirty) {
- pinned_points_cache_dirty = false;
+void SoftBody::_make_cache_dirty() {
+ pinned_points_cache_dirty = true;
+}
- PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
- for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) {
+void SoftBody::_update_cache_pin_points_datas() {
+ if (!pinned_points_cache_dirty)
+ return;
- if (!w[i].spatial_attachment_path.is_empty()) {
- w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(w[i].spatial_attachment_path));
- if (w[i].spatial_attachment) {
+ pinned_points_cache_dirty = false;
- Transform point_global_transform(get_global_transform());
- point_global_transform.translate(PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index));
+ PoolVector<PinnedPoint>::Write w = pinned_points.write();
+ for (int i = pinned_points.size() - 1; 0 <= i; --i) {
- // Local transform relative to spatial attachment node
- w[i].vertex_offset_transform = w[i].spatial_attachment->get_global_transform().affine_inverse() * point_global_transform;
- continue;
- } else {
- ERR_PRINTS("The node with path: " + String(w[i].spatial_attachment_path) + " was not found or is not a spatial node.");
- }
- }
- // Local transform relative to Soft body
- w[i].vertex_offset_transform.origin = PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index);
- w[i].vertex_offset_transform.basis = Basis();
+ if (!w[i].spatial_attachment_path.is_empty()) {
+ w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(w[i].spatial_attachment_path));
+ }
+ if (!w[i].spatial_attachment) {
+ ERR_PRINT("Spatial node not defined in the pinned point, Softbody undefined behaviour!");
}
}
}
@@ -699,22 +726,54 @@ void SoftBody::_pin_point_on_physics_server(int p_point_index, bool pin) {
void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) {
SoftBody::PinnedPoint *pinned_point;
if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
+
// Create new
PinnedPoint pp;
pp.point_index = p_point_index;
pp.spatial_attachment_path = p_spatial_attachment_path;
- pinned_points_indices.push_back(pp);
+
+ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) {
+ pp.spatial_attachment = Object::cast_to<Spatial>(get_node(p_spatial_attachment_path));
+ pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index));
+ }
+
+ pinned_points.push_back(pp);
+
} else {
- // Update
+
pinned_point->point_index = p_point_index;
pinned_point->spatial_attachment_path = p_spatial_attachment_path;
+
+ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) {
+ pinned_point->spatial_attachment = Object::cast_to<Spatial>(get_node(p_spatial_attachment_path));
+ pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index));
+ }
+ }
+}
+
+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();
+ for (int i = pinned_points.size() - 1; 0 <= i; --i) {
+
+ if (!r[i].spatial_attachment)
+ w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(r[i].spatial_attachment_path));
+
+ if (!r[i].spatial_attachment)
+ continue;
+
+ w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index));
}
}
void SoftBody::_remove_pinned_point(int p_point_index) {
const int id(_has_pinned_point(p_point_index));
if (-1 != id) {
- pinned_points_indices.remove(id);
+ pinned_points.remove(id);
}
}
@@ -724,14 +783,14 @@ 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_indices.read()[id]);
+ r_point = const_cast<SoftBody::PinnedPoint *>(&pinned_points.read()[id]);
return id;
}
}
int SoftBody::_has_pinned_point(int p_point_index) const {
- PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
- for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) {
+ PoolVector<PinnedPoint>::Read r = pinned_points.read();
+ 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 f44f337698..cee32b9651 100644
--- a/scene/3d/soft_body.h
+++ b/scene/3d/soft_body.h
@@ -72,9 +72,7 @@ public:
int point_index;
NodePath spatial_attachment_path;
Spatial *spatial_attachment; // Cache
- /// This is the offset from the soft body to point or attachment to point
- /// Depend if the spatial_attachment_node is NULL or not
- Transform vertex_offset_transform; // Cache
+ Vector3 offset;
PinnedPoint();
PinnedPoint(const PinnedPoint &obj_tocopy);
@@ -89,7 +87,7 @@ private:
uint32_t collision_mask;
uint32_t collision_layer;
NodePath parent_collision_ignore;
- PoolVector<PinnedPoint> pinned_points_indices;
+ PoolVector<PinnedPoint> pinned_points;
bool simulation_started;
bool pinned_points_cache_dirty;
@@ -186,9 +184,14 @@ public:
private:
void reset_softbody_pin();
+
+ void _make_cache_dirty();
void _update_cache_pin_points_datas();
+
void _pin_point_on_physics_server(int p_point_index, bool pin);
void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path);
+ void _reset_points_offsets();
+
void _remove_pinned_point(int p_point_index);
int _get_pinned_point(int p_point_index, PinnedPoint *&r_point) const;
int _has_pinned_point(int p_point_index) const;
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 64cb9ec4ca..3f494264e7 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -202,6 +202,7 @@ void Spatial::_notification(int p_what) {
#ifdef TOOLS_ENABLED
if (data.gizmo.is_valid()) {
data.gizmo->free();
+ data.gizmo.unref();
}
#endif
@@ -793,13 +794,13 @@ void Spatial::_bind_methods() {
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
ADD_GROUP("Transform", "");
- ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
-
+ ADD_GROUP("Matrix", "");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_GROUP("Visibility", "");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo");
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 653714dc98..bc054a8763 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -51,6 +51,7 @@ public:
virtual bool can_draw() const = 0;
SpatialGizmo();
+ virtual ~SpatialGizmo() {}
};
class Spatial : public Node {