feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ANIMATABLE_BODY_3D_H
|
||||
#define ANIMATABLE_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/static_body_3d.h"
|
||||
|
||||
|
|
@ -63,5 +62,3 @@ private:
|
|||
void set_sync_to_physics(bool p_enable);
|
||||
bool is_sync_to_physics_enabled() const;
|
||||
};
|
||||
|
||||
#endif // ANIMATABLE_BODY_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef AREA_3D_H
|
||||
#define AREA_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "core/templates/vset.h"
|
||||
#include "scene/3d/physics/collision_object_3d.h"
|
||||
|
|
@ -231,5 +230,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Area3D::SpaceOverride);
|
||||
|
||||
#endif // AREA_3D_H
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
|
|||
// Avoid to move forward on a wall if floor_block_on_wall is true.
|
||||
// Applies only when the motion angle is under 90 degrees,
|
||||
// in order to avoid blocking lateral motion along a wall.
|
||||
if (motion_angle < .5 * Math_PI) {
|
||||
if (motion_angle < .5 * Math::PI) {
|
||||
apply_default_sliding = false;
|
||||
if (p_was_on_floor && !vel_dir_facing_up) {
|
||||
// Cancel the motion.
|
||||
|
|
@ -569,7 +569,7 @@ void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResu
|
|||
wall_normal = collision.normal;
|
||||
|
||||
// Don't apply wall velocity when the collider is a CharacterBody3D.
|
||||
if (Object::cast_to<CharacterBody3D>(ObjectDB::get_instance(collision.collider_id)) == nullptr) {
|
||||
if (ObjectDB::get_instance<CharacterBody3D>(collision.collider_id) == nullptr) {
|
||||
_set_platform_data(collision);
|
||||
}
|
||||
}
|
||||
|
|
@ -717,7 +717,7 @@ Ref<KinematicCollision3D> CharacterBody3D::_get_slide_collision(int p_bounce) {
|
|||
}
|
||||
|
||||
Ref<KinematicCollision3D> CharacterBody3D::_get_last_slide_collision() {
|
||||
if (motion_results.size() == 0) {
|
||||
if (motion_results.is_empty()) {
|
||||
return Ref<KinematicCollision3D>();
|
||||
}
|
||||
return _get_slide_collision(motion_results.size() - 1);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CHARACTER_BODY_3D_H
|
||||
#define CHARACTER_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/kinematic_collision_3d.h"
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
|
|
@ -185,5 +184,3 @@ protected:
|
|||
|
||||
VARIANT_ENUM_CAST(CharacterBody3D::MotionMode);
|
||||
VARIANT_ENUM_CAST(CharacterBody3D::PlatformOnLeave);
|
||||
|
||||
#endif // CHARACTER_BODY_3D_H
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
|
|||
ShapeData sd;
|
||||
uint32_t id;
|
||||
|
||||
if (shapes.size() == 0) {
|
||||
if (shapes.is_empty()) {
|
||||
id = 0;
|
||||
} else {
|
||||
id = shapes.back()->key() + 1;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef COLLISION_OBJECT_3D_H
|
||||
#define COLLISION_OBJECT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/camera_3d.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
|
|
@ -180,5 +179,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(CollisionObject3D::DisableMode);
|
||||
|
||||
#endif // COLLISION_OBJECT_3D_H
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ void CollisionPolygon3D::_build_polygon() {
|
|||
|
||||
collision_object->shape_owner_clear_shapes(owner_id);
|
||||
|
||||
if (polygon.size() == 0) {
|
||||
if (polygon.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(polygon);
|
||||
if (decomp.size() == 0) {
|
||||
if (decomp.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef COLLISION_POLYGON_3D_H
|
||||
#define COLLISION_POLYGON_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
|
||||
|
|
@ -94,5 +93,3 @@ public:
|
|||
|
||||
CollisionPolygon3D();
|
||||
};
|
||||
|
||||
#endif // COLLISION_POLYGON_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef COLLISION_SHAPE_3D_H
|
||||
#define COLLISION_SHAPE_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/resources/3d/shape_3d.h"
|
||||
|
|
@ -90,5 +89,3 @@ public:
|
|||
CollisionShape3D();
|
||||
~CollisionShape3D();
|
||||
};
|
||||
|
||||
#endif // COLLISION_SHAPE_3D_H
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, Phys
|
|||
}
|
||||
|
||||
ConeTwistJoint3D::ConeTwistJoint3D() {
|
||||
params[PARAM_SWING_SPAN] = Math_PI * 0.25;
|
||||
params[PARAM_TWIST_SPAN] = Math_PI;
|
||||
params[PARAM_SWING_SPAN] = Math::PI * 0.25;
|
||||
params[PARAM_TWIST_SPAN] = Math::PI;
|
||||
params[PARAM_BIAS] = 0.3;
|
||||
params[PARAM_SOFTNESS] = 0.8;
|
||||
params[PARAM_RELAXATION] = 1.0;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CONE_TWIST_JOINT_3D_H
|
||||
#define CONE_TWIST_JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/joints/joint_3d.h"
|
||||
|
||||
|
|
@ -59,5 +58,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(ConeTwistJoint3D::Param);
|
||||
|
||||
#endif // CONE_TWIST_JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GENERIC_6DOF_JOINT_3D_H
|
||||
#define GENERIC_6DOF_JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/joints/joint_3d.h"
|
||||
|
||||
|
|
@ -108,5 +107,3 @@ public:
|
|||
|
||||
VARIANT_ENUM_CAST(Generic6DOFJoint3D::Param);
|
||||
VARIANT_ENUM_CAST(Generic6DOFJoint3D::Flag);
|
||||
|
||||
#endif // GENERIC_6DOF_JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsB
|
|||
|
||||
HingeJoint3D::HingeJoint3D() {
|
||||
params[PARAM_BIAS] = 0.3;
|
||||
params[PARAM_LIMIT_UPPER] = Math_PI * 0.5;
|
||||
params[PARAM_LIMIT_LOWER] = -Math_PI * 0.5;
|
||||
params[PARAM_LIMIT_UPPER] = Math::PI * 0.5;
|
||||
params[PARAM_LIMIT_LOWER] = -Math::PI * 0.5;
|
||||
params[PARAM_LIMIT_BIAS] = 0.3;
|
||||
params[PARAM_LIMIT_SOFTNESS] = 0.9;
|
||||
params[PARAM_LIMIT_RELAXATION] = 1.0;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef HINGE_JOINT_3D_H
|
||||
#define HINGE_JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/joints/joint_3d.h"
|
||||
|
||||
|
|
@ -73,5 +72,3 @@ public:
|
|||
|
||||
VARIANT_ENUM_CAST(HingeJoint3D::Param);
|
||||
VARIANT_ENUM_CAST(HingeJoint3D::Flag);
|
||||
|
||||
#endif // HINGE_JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef JOINT_3D_H
|
||||
#define JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
|
|
@ -81,5 +80,3 @@ public:
|
|||
Joint3D();
|
||||
~Joint3D();
|
||||
};
|
||||
|
||||
#endif // JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef PIN_JOINT_3D_H
|
||||
#define PIN_JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/joints/joint_3d.h"
|
||||
|
||||
|
|
@ -56,5 +55,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(PinJoint3D::Param);
|
||||
|
||||
#endif // PIN_JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SLIDER_JOINT_3D_H
|
||||
#define SLIDER_JOINT_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/joints/joint_3d.h"
|
||||
|
||||
|
|
@ -78,5 +77,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SliderJoint3D::Param);
|
||||
|
||||
#endif // SLIDER_JOINT_3D_H
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ real_t KinematicCollision3D::get_angle(int p_collision_index, const Vector3 &p_u
|
|||
|
||||
Object *KinematicCollision3D::get_local_shape(int p_collision_index) const {
|
||||
ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
|
||||
PhysicsBody3D *owner = Object::cast_to<PhysicsBody3D>(ObjectDB::get_instance(owner_id));
|
||||
PhysicsBody3D *owner = ObjectDB::get_instance<PhysicsBody3D>(owner_id);
|
||||
if (!owner) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef KINEMATIC_COLLISION_3D_H
|
||||
#define KINEMATIC_COLLISION_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "servers/physics_server_3d.h"
|
||||
|
|
@ -61,5 +60,3 @@ public:
|
|||
int get_collider_shape_index(int p_collision_index = 0) const;
|
||||
Vector3 get_collider_velocity(int p_collision_index = 0) const;
|
||||
};
|
||||
|
||||
#endif // KINEMATIC_COLLISION_3D_H
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "physical_bone_3d.h"
|
||||
|
||||
#include "scene/3d/physical_bone_simulator_3d.h"
|
||||
#include "scene/3d/physics/physical_bone_simulator_3d.h"
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#endif //_DISABLE_DEPRECATED
|
||||
|
|
@ -752,8 +752,9 @@ void PhysicalBone3D::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
|
||||
void PhysicalBone3D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
case NOTIFICATION_PARENTED:
|
||||
// We need to wait until the bone has finished being added to the tree
|
||||
// or none of the global transform calls will work correctly.
|
||||
case NOTIFICATION_POST_ENTER_TREE:
|
||||
_update_simulator_path();
|
||||
update_bone_id();
|
||||
reset_to_rest_position();
|
||||
|
|
@ -763,6 +764,9 @@ void PhysicalBone3D::_notification(int p_what) {
|
|||
}
|
||||
break;
|
||||
|
||||
// If we're detached from the skeleton we need to
|
||||
// clear our references to it.
|
||||
case NOTIFICATION_UNPARENTED:
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
PhysicalBoneSimulator3D *simulator = get_simulator();
|
||||
if (simulator) {
|
||||
|
|
@ -1052,7 +1056,7 @@ void PhysicalBone3D::_update_simulator_path() {
|
|||
}
|
||||
|
||||
PhysicalBoneSimulator3D *PhysicalBone3D::get_simulator() const {
|
||||
return Object::cast_to<PhysicalBoneSimulator3D>(ObjectDB::get_instance(simulator_id));
|
||||
return ObjectDB::get_instance<PhysicalBoneSimulator3D>(simulator_id);
|
||||
}
|
||||
|
||||
Skeleton3D *PhysicalBone3D::get_skeleton() const {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef PHYSICAL_BONE_3D_H
|
||||
#define PHYSICAL_BONE_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
|
|
@ -84,8 +83,8 @@ public:
|
|||
virtual bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
real_t swing_span = Math_PI * 0.25;
|
||||
real_t twist_span = Math_PI;
|
||||
real_t swing_span = Math::PI * 0.25;
|
||||
real_t twist_span = Math::PI;
|
||||
real_t bias = 0.3;
|
||||
real_t softness = 0.8;
|
||||
real_t relaxation = 1.;
|
||||
|
|
@ -99,8 +98,8 @@ public:
|
|||
virtual void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
bool angular_limit_enabled = false;
|
||||
real_t angular_limit_upper = Math_PI * 0.5;
|
||||
real_t angular_limit_lower = -Math_PI * 0.5;
|
||||
real_t angular_limit_upper = Math::PI * 0.5;
|
||||
real_t angular_limit_lower = -Math::PI * 0.5;
|
||||
real_t angular_limit_bias = 0.3;
|
||||
real_t angular_limit_softness = 0.9;
|
||||
real_t angular_limit_relaxation = 1.;
|
||||
|
|
@ -307,5 +306,3 @@ private:
|
|||
|
||||
VARIANT_ENUM_CAST(PhysicalBone3D::JointType);
|
||||
VARIANT_ENUM_CAST(PhysicalBone3D::DampMode);
|
||||
|
||||
#endif // PHYSICAL_BONE_3D_H
|
||||
|
|
|
|||
396
engine/scene/3d/physics/physical_bone_simulator_3d.cpp
Normal file
396
engine/scene/3d/physics/physical_bone_simulator_3d.cpp
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/**************************************************************************/
|
||||
/* physical_bone_simulator_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "physical_bone_simulator_3d.h"
|
||||
|
||||
#include "scene/3d/physics/physical_bone_3d.h"
|
||||
|
||||
void PhysicalBoneSimulator3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) {
|
||||
if (p_old) {
|
||||
if (p_old->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
|
||||
p_old->disconnect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
|
||||
}
|
||||
if (p_old->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
|
||||
p_old->disconnect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
|
||||
}
|
||||
}
|
||||
if (p_new) {
|
||||
if (!p_new->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
|
||||
p_new->connect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
|
||||
}
|
||||
if (!p_new->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
|
||||
p_new->connect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
|
||||
}
|
||||
}
|
||||
_bone_list_changed();
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_bone_list_changed() {
|
||||
bones.clear();
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < skeleton->get_bone_count(); i++) {
|
||||
SimulatedBone sb;
|
||||
sb.parent = skeleton->get_bone_parent(i);
|
||||
sb.child_bones = skeleton->get_bone_children(i);
|
||||
bones.push_back(sb);
|
||||
}
|
||||
_rebuild_physical_bones_cache();
|
||||
_pose_updated();
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_pose_updated() {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton || simulating) {
|
||||
return;
|
||||
}
|
||||
// If this triggers that means that we likely haven't rebuilt the bone list yet.
|
||||
if (skeleton->get_bone_count() != bones.size()) {
|
||||
// NOTE: this is re-entrant and will call _pose_updated again.
|
||||
_bone_list_changed();
|
||||
} else {
|
||||
for (int i = 0; i < skeleton->get_bone_count(); i++) {
|
||||
_bone_pose_updated(skeleton, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_bone_pose_updated(Skeleton3D *p_skeleton, int p_bone_id) {
|
||||
ERR_FAIL_INDEX(p_bone_id, bones.size());
|
||||
bones.write[p_bone_id].global_pose = p_skeleton->get_bone_global_pose(p_bone_id);
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_set_active(bool p_active) {
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
_reset_physical_bones_state();
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_reset_physical_bones_state() {
|
||||
for (int i = 0; i < bones.size(); i += 1) {
|
||||
if (bones[i].physical_bone) {
|
||||
bones[i].physical_bone->reset_physics_simulation_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PhysicalBoneSimulator3D::is_simulating_physics() const {
|
||||
return simulating;
|
||||
}
|
||||
|
||||
int PhysicalBoneSimulator3D::find_bone(const String &p_name) const {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return -1;
|
||||
}
|
||||
return skeleton->find_bone(p_name);
|
||||
}
|
||||
|
||||
String PhysicalBoneSimulator3D::get_bone_name(int p_bone) const {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return String();
|
||||
}
|
||||
return skeleton->get_bone_name(p_bone);
|
||||
}
|
||||
|
||||
int PhysicalBoneSimulator3D::get_bone_count() const {
|
||||
return bones.size();
|
||||
}
|
||||
|
||||
bool PhysicalBoneSimulator3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return false;
|
||||
}
|
||||
return skeleton->is_bone_parent_of(p_bone, p_parent_bone_id);
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX(p_bone, bone_size);
|
||||
ERR_FAIL_COND(bones[p_bone].physical_bone);
|
||||
ERR_FAIL_NULL(p_physical_bone);
|
||||
bones.write[p_bone].physical_bone = p_physical_bone;
|
||||
|
||||
_rebuild_physical_bones_cache();
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::unbind_physical_bone_from_bone(int p_bone) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX(p_bone, bone_size);
|
||||
bones.write[p_bone].physical_bone = nullptr;
|
||||
|
||||
_rebuild_physical_bones_cache();
|
||||
}
|
||||
|
||||
PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone(int p_bone) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
|
||||
|
||||
return bones[p_bone].physical_bone;
|
||||
}
|
||||
|
||||
PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone_parent(int p_bone) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
|
||||
|
||||
if (bones[p_bone].cache_parent_physical_bone) {
|
||||
return bones[p_bone].cache_parent_physical_bone;
|
||||
}
|
||||
|
||||
return _get_physical_bone_parent(p_bone);
|
||||
}
|
||||
|
||||
PhysicalBone3D *PhysicalBoneSimulator3D::_get_physical_bone_parent(int p_bone) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
|
||||
|
||||
const int parent_bone = bones[p_bone].parent;
|
||||
if (parent_bone < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PhysicalBone3D *pb = bones[parent_bone].physical_bone;
|
||||
if (pb) {
|
||||
return pb;
|
||||
} else {
|
||||
return get_physical_bone_parent(parent_bone);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_rebuild_physical_bones_cache() {
|
||||
const int b_size = bones.size();
|
||||
for (int i = 0; i < b_size; ++i) {
|
||||
PhysicalBone3D *parent_pb = _get_physical_bone_parent(i);
|
||||
if (parent_pb != bones[i].cache_parent_physical_bone) {
|
||||
bones.write[i].cache_parent_physical_bone = parent_pb;
|
||||
if (bones[i].physical_bone) {
|
||||
bones[i].physical_bone->_on_bone_parent_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _pb_stop_simulation_compat(Node *p_node) {
|
||||
PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
|
||||
if (ps) {
|
||||
return; // Prevent conflict.
|
||||
}
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
|
||||
_pb_stop_simulation_compat(p_node->get_child(i));
|
||||
}
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
|
||||
if (pb) {
|
||||
pb->set_simulate_physics(false);
|
||||
}
|
||||
}
|
||||
#endif // _DISABLE_DEPRECATED
|
||||
|
||||
void _pb_stop_simulation(Node *p_node) {
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
|
||||
if (!pb) {
|
||||
continue;
|
||||
}
|
||||
_pb_stop_simulation(pb);
|
||||
}
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
|
||||
if (pb) {
|
||||
pb->set_simulate_physics(false);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::physical_bones_stop_simulation() {
|
||||
simulating = false;
|
||||
_reset_physical_bones_state();
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (is_compat) {
|
||||
Skeleton3D *sk = get_skeleton();
|
||||
if (sk) {
|
||||
_pb_stop_simulation_compat(sk);
|
||||
}
|
||||
} else {
|
||||
_pb_stop_simulation(this);
|
||||
}
|
||||
#else
|
||||
_pb_stop_simulation(this);
|
||||
#endif // _DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _pb_start_simulation_compat(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
|
||||
PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
|
||||
if (ps) {
|
||||
return; // Prevent conflict.
|
||||
}
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
|
||||
_pb_start_simulation_compat(p_simulator, p_node->get_child(i), p_sim_bones);
|
||||
}
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
|
||||
if (pb) {
|
||||
if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
|
||||
pb->set_simulate_physics(true);
|
||||
} else {
|
||||
for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
|
||||
if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
|
||||
pb->set_simulate_physics(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _DISABLE_DEPRECATED
|
||||
|
||||
void _pb_start_simulation(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
|
||||
if (!pb) {
|
||||
continue;
|
||||
}
|
||||
_pb_start_simulation(p_simulator, pb, p_sim_bones);
|
||||
}
|
||||
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
|
||||
if (pb) {
|
||||
if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
|
||||
pb->set_simulate_physics(true);
|
||||
} else {
|
||||
for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
|
||||
if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
|
||||
pb->set_simulate_physics(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones) {
|
||||
_pose_updated();
|
||||
|
||||
simulating = true;
|
||||
_reset_physical_bones_state();
|
||||
|
||||
Vector<int> sim_bones;
|
||||
if (p_bones.size() > 0) {
|
||||
sim_bones.resize(p_bones.size());
|
||||
int c = 0;
|
||||
for (int i = sim_bones.size() - 1; i >= 0; --i) {
|
||||
int bone_id = find_bone(p_bones[i]);
|
||||
if (bone_id != -1) {
|
||||
sim_bones.write[c++] = bone_id;
|
||||
}
|
||||
}
|
||||
sim_bones.resize(c);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (is_compat) {
|
||||
Skeleton3D *sk = get_skeleton();
|
||||
if (sk) {
|
||||
_pb_start_simulation_compat(this, sk, sim_bones);
|
||||
}
|
||||
} else {
|
||||
_pb_start_simulation(this, this, sim_bones);
|
||||
}
|
||||
#else
|
||||
_pb_start_simulation(this, this, sim_bones);
|
||||
#endif // _DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) {
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
|
||||
_physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception);
|
||||
}
|
||||
|
||||
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_node);
|
||||
if (co) {
|
||||
if (p_add) {
|
||||
PhysicsServer3D::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception);
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::physical_bones_add_collision_exception(RID p_exception) {
|
||||
_physical_bones_add_remove_collision_exception(true, this, p_exception);
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::physical_bones_remove_collision_exception(RID p_exception) {
|
||||
_physical_bones_add_remove_collision_exception(false, this, p_exception);
|
||||
}
|
||||
|
||||
Transform3D PhysicalBoneSimulator3D::get_bone_global_pose(int p_bone) const {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D());
|
||||
return bones[p_bone].global_pose;
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::set_bone_global_pose(int p_bone, const Transform3D &p_pose) {
|
||||
const int bone_size = bones.size();
|
||||
ERR_FAIL_INDEX(p_bone, bone_size);
|
||||
bones.write[p_bone].global_pose = p_pose;
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_process_modification(double p_delta) {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return;
|
||||
}
|
||||
ERR_FAIL_COND(skeleton->get_bone_count() != bones.size());
|
||||
for (int i = 0; i < skeleton->get_bone_count(); i++) {
|
||||
if (!bones[i].physical_bone) {
|
||||
continue;
|
||||
}
|
||||
if (bones[i].physical_bone->is_simulating_physics() == false) {
|
||||
_bone_pose_updated(skeleton, i);
|
||||
bones[i].physical_bone->reset_to_rest_position();
|
||||
} else if (simulating) {
|
||||
skeleton->set_bone_global_pose(i, bones[i].global_pose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBoneSimulator3D::is_simulating_physics);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &PhysicalBoneSimulator3D::physical_bones_stop_simulation);
|
||||
ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &PhysicalBoneSimulator3D::physical_bones_start_simulation_on, DEFVAL(Array()));
|
||||
ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_add_collision_exception);
|
||||
ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_remove_collision_exception);
|
||||
}
|
||||
|
||||
PhysicalBoneSimulator3D::PhysicalBoneSimulator3D() {
|
||||
}
|
||||
105
engine/scene/3d/physics/physical_bone_simulator_3d.h
Normal file
105
engine/scene/3d/physics/physical_bone_simulator_3d.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/**************************************************************************/
|
||||
/* physical_bone_simulator_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/skeleton_modifier_3d.h"
|
||||
|
||||
class PhysicalBone3D;
|
||||
|
||||
class PhysicalBoneSimulator3D : public SkeletonModifier3D {
|
||||
GDCLASS(PhysicalBoneSimulator3D, SkeletonModifier3D);
|
||||
|
||||
bool simulating = false;
|
||||
|
||||
struct SimulatedBone {
|
||||
int parent;
|
||||
Vector<int> child_bones;
|
||||
|
||||
Transform3D global_pose;
|
||||
|
||||
PhysicalBone3D *physical_bone = nullptr;
|
||||
PhysicalBone3D *cache_parent_physical_bone = nullptr;
|
||||
|
||||
SimulatedBone() {
|
||||
parent = -1;
|
||||
global_pose = Transform3D();
|
||||
physical_bone = nullptr;
|
||||
cache_parent_physical_bone = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
Vector<SimulatedBone> bones;
|
||||
|
||||
/// This is a slow API, so it's cached
|
||||
PhysicalBone3D *_get_physical_bone_parent(int p_bone);
|
||||
void _rebuild_physical_bones_cache();
|
||||
void _reset_physical_bones_state();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _set_active(bool p_active) override;
|
||||
|
||||
void _bone_list_changed();
|
||||
void _pose_updated();
|
||||
void _bone_pose_updated(Skeleton3D *skeleton, int p_bone_id);
|
||||
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) override;
|
||||
|
||||
public:
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
bool is_compat = false;
|
||||
#endif // _DISABLE_DEPRECATED
|
||||
bool is_simulating_physics() const;
|
||||
|
||||
int find_bone(const String &p_name) const;
|
||||
String get_bone_name(int p_bone) const;
|
||||
int get_bone_count() const;
|
||||
bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const;
|
||||
|
||||
Transform3D get_bone_global_pose(int p_bone) const;
|
||||
void set_bone_global_pose(int p_bone, const Transform3D &p_pose);
|
||||
|
||||
void bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone);
|
||||
void unbind_physical_bone_from_bone(int p_bone);
|
||||
|
||||
PhysicalBone3D *get_physical_bone(int p_bone);
|
||||
PhysicalBone3D *get_physical_bone_parent(int p_bone);
|
||||
|
||||
void physical_bones_stop_simulation();
|
||||
void physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones);
|
||||
void physical_bones_add_collision_exception(RID p_exception);
|
||||
void physical_bones_remove_collision_exception(RID p_exception);
|
||||
|
||||
PhysicalBoneSimulator3D();
|
||||
};
|
||||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef PHYSICS_BODY_3D_H
|
||||
#define PHYSICS_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/collision_object_3d.h"
|
||||
#include "scene/3d/physics/kinematic_collision_3d.h"
|
||||
|
|
@ -65,5 +64,3 @@ public:
|
|||
void add_collision_exception_with(Node *p_node); //must be physicsbody
|
||||
void remove_collision_exception_with(Node *p_node);
|
||||
};
|
||||
|
||||
#endif // PHYSICS_BODY_3D_H
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ void RayCast3D::_update_debug_shape_vertices() {
|
|||
int vertices_strip_order[14] = { 4, 5, 0, 1, 2, 5, 6, 4, 7, 0, 3, 2, 7, 6 };
|
||||
for (int v = 0; v < 14; v++) {
|
||||
Vector3 vertex = vertices_strip_order[v] < 4 ? normal : normal / 3.0 + target_position;
|
||||
debug_shape_vertices.push_back(vertex.rotated(dir, Math_PI * (0.5 * (vertices_strip_order[v] % 4) + 0.25)));
|
||||
debug_shape_vertices.push_back(vertex.rotated(dir, Math::PI * (0.5 * (vertices_strip_order[v] % 4) + 0.25)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef RAY_CAST_3D_H
|
||||
#define RAY_CAST_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
|
||||
|
|
@ -135,5 +134,3 @@ public:
|
|||
|
||||
RayCast3D();
|
||||
};
|
||||
|
||||
#endif // RAY_CAST_3D_H
|
||||
|
|
|
|||
|
|
@ -521,6 +521,7 @@ bool RigidBody3D::is_sleeping() const {
|
|||
}
|
||||
|
||||
void RigidBody3D::set_max_contacts_reported(int p_amount) {
|
||||
ERR_FAIL_INDEX_MSG(p_amount, MAX_CONTACTS_REPORTED_3D_MAX, "Max contacts reported allocates memory (about 80 bytes each), and therefore must not be set too high.");
|
||||
max_contacts_reported = p_amount;
|
||||
PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
|
||||
}
|
||||
|
|
@ -662,7 +663,7 @@ PackedStringArray RigidBody3D::get_configuration_warnings() const {
|
|||
PackedStringArray warnings = PhysicsBody3D::get_configuration_warnings();
|
||||
|
||||
Vector3 scale = get_transform().get_basis().get_scale();
|
||||
if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) {
|
||||
if (Math::abs(scale.x - 1.0) > 0.05 || Math::abs(scale.y - 1.0) > 0.05 || Math::abs(scale.z - 1.0) > 0.05) {
|
||||
warnings.push_back(RTR("Scale changes to RigidBody3D will be overridden by the physics engine when running.\nPlease change the size in children collision shapes instead."));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef RIGID_BODY_3D_H
|
||||
#define RIGID_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "core/templates/vset.h"
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
|
|
@ -245,5 +244,3 @@ private:
|
|||
VARIANT_ENUM_CAST(RigidBody3D::FreezeMode);
|
||||
VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode);
|
||||
VARIANT_ENUM_CAST(RigidBody3D::DampMode);
|
||||
|
||||
#endif // RIGID_BODY_3D_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SHAPE_CAST_3D_H
|
||||
#define SHAPE_CAST_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/resources/3d/shape_3d.h"
|
||||
|
|
@ -143,5 +142,3 @@ public:
|
|||
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
};
|
||||
|
||||
#endif // SHAPE_CAST_3D_H
|
||||
|
|
|
|||
41
engine/scene/3d/physics/soft_body_3d.compat.inc
Normal file
41
engine/scene/3d/physics/soft_body_3d.compat.inc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/**************************************************************************/
|
||||
/* soft_body_3d.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DISABLE_DEPRECATED
|
||||
|
||||
void SoftBody3D::_pin_point_bind_compat_94684(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) {
|
||||
pin_point(p_point_index, pin, p_spatial_attachment_path, -1);
|
||||
}
|
||||
|
||||
void SoftBody3D::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftBody3D::_pin_point_bind_compat_94684, DEFVAL(NodePath()));
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
||||
823
engine/scene/3d/physics/soft_body_3d.cpp
Normal file
823
engine/scene/3d/physics/soft_body_3d.cpp
Normal file
|
|
@ -0,0 +1,823 @@
|
|||
/**************************************************************************/
|
||||
/* soft_body_3d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "soft_body_3d.h"
|
||||
#include "soft_body_3d.compat.inc"
|
||||
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
|
||||
SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {}
|
||||
|
||||
void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) {
|
||||
clear();
|
||||
|
||||
ERR_FAIL_COND(!p_mesh.is_valid());
|
||||
|
||||
mesh = p_mesh;
|
||||
surface = p_surface;
|
||||
|
||||
RS::SurfaceData surface_data = RS::get_singleton()->mesh_get_surface(mesh, surface);
|
||||
|
||||
uint32_t surface_offsets[RS::ARRAY_MAX];
|
||||
uint32_t vertex_stride;
|
||||
uint32_t normal_tangent_stride;
|
||||
uint32_t attrib_stride;
|
||||
uint32_t skin_stride;
|
||||
RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_data.format, surface_data.vertex_count, surface_data.index_count, surface_offsets, vertex_stride, normal_tangent_stride, attrib_stride, skin_stride);
|
||||
|
||||
buffer = surface_data.vertex_data;
|
||||
stride = vertex_stride;
|
||||
normal_stride = normal_tangent_stride;
|
||||
offset_vertices = surface_offsets[RS::ARRAY_VERTEX];
|
||||
offset_normal = surface_offsets[RS::ARRAY_NORMAL];
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::clear() {
|
||||
buffer.resize(0);
|
||||
stride = 0;
|
||||
normal_stride = 0;
|
||||
offset_vertices = 0;
|
||||
offset_normal = 0;
|
||||
|
||||
surface = 0;
|
||||
mesh = RID();
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::open() {
|
||||
write_buffer = buffer.ptrw();
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::close() {
|
||||
write_buffer = nullptr;
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::commit_changes() {
|
||||
RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer);
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const Vector3 &p_vertex) {
|
||||
float *vertex_buffer = reinterpret_cast<float *>(write_buffer + p_vertex_id * stride + offset_vertices);
|
||||
*vertex_buffer++ = (float)p_vertex.x;
|
||||
*vertex_buffer++ = (float)p_vertex.y;
|
||||
*vertex_buffer++ = (float)p_vertex.z;
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::set_normal(int p_vertex_id, const Vector3 &p_normal) {
|
||||
Vector2 res = p_normal.octahedron_encode();
|
||||
uint32_t value = 0;
|
||||
value |= (uint16_t)CLAMP(res.x * 65535, 0, 65535);
|
||||
value |= (uint16_t)CLAMP(res.y * 65535, 0, 65535) << 16;
|
||||
memcpy(&write_buffer[p_vertex_id * normal_stride + offset_normal], &value, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void SoftBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) {
|
||||
RS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb);
|
||||
}
|
||||
|
||||
SoftBody3D::PinnedPoint::PinnedPoint() {
|
||||
}
|
||||
|
||||
SoftBody3D::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;
|
||||
offset = obj_tocopy.offset;
|
||||
}
|
||||
|
||||
void SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) {
|
||||
point_index = obj.point_index;
|
||||
spatial_attachment_path = obj.spatial_attachment_path;
|
||||
spatial_attachment = obj.spatial_attachment;
|
||||
offset = obj.offset;
|
||||
}
|
||||
|
||||
void SoftBody3D::_update_pickable() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
bool pickable = ray_pickable && is_visible_in_tree();
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable);
|
||||
}
|
||||
|
||||
bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) {
|
||||
String name = p_name;
|
||||
String which = name.get_slicec('/', 0);
|
||||
|
||||
if ("pinned_points" == which) {
|
||||
return _set_property_pinned_points_indices(p_value);
|
||||
|
||||
} else if ("attachments" == which) {
|
||||
int idx = name.get_slicec('/', 1).to_int();
|
||||
String what = name.get_slicec('/', 2);
|
||||
|
||||
return _set_property_pinned_points_attachment(idx, what, p_value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
String name = p_name;
|
||||
String which = name.get_slicec('/', 0);
|
||||
|
||||
if ("pinned_points" == which) {
|
||||
Array arr_ret;
|
||||
const int pinned_points_indices_size = pinned_points.size();
|
||||
const PinnedPoint *r = pinned_points.ptr();
|
||||
arr_ret.resize(pinned_points_indices_size);
|
||||
|
||||
for (int i = 0; i < pinned_points_indices_size; ++i) {
|
||||
arr_ret[i] = r[i].point_index;
|
||||
}
|
||||
|
||||
r_ret = arr_ret;
|
||||
return true;
|
||||
|
||||
} else if ("attachments" == which) {
|
||||
int idx = name.get_slicec('/', 1).to_int();
|
||||
String what = name.get_slicec('/', 2);
|
||||
|
||||
return _get_property_pinned_points(idx, what, r_ret);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftBody3D::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
const int pinned_points_indices_size = pinned_points.size();
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, PNAME("pinned_points")));
|
||||
|
||||
for (int i = 0; i < pinned_points_indices_size; ++i) {
|
||||
const String prefix = vformat("%s/%d/", PNAME("attachments"), i);
|
||||
p_list->push_back(PropertyInfo(Variant::INT, prefix + PNAME("point_index")));
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, prefix + PNAME("spatial_attachment_path")));
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR3, prefix + PNAME("offset")));
|
||||
}
|
||||
}
|
||||
|
||||
bool SoftBody3D::_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
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pinned_points.resize(p_indices_size);
|
||||
|
||||
PinnedPoint *w = pinned_points.ptrw();
|
||||
int point_index;
|
||||
for (int i = 0; i < p_indices_size; ++i) {
|
||||
point_index = p_indices.get(i);
|
||||
if (w[i].point_index != point_index || pinned_points.size() < p_indices_size) {
|
||||
bool insert = false;
|
||||
if (w[i].point_index != -1 && p_indices.find(w[i].point_index) == -1) {
|
||||
pin_point(w[i].point_index, false);
|
||||
insert = true;
|
||||
}
|
||||
w[i].point_index = point_index;
|
||||
if (insert) {
|
||||
pin_point(w[i].point_index, true, NodePath(), i);
|
||||
} else {
|
||||
pin_point(w[i].point_index, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoftBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) {
|
||||
if (pinned_points.size() <= p_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("spatial_attachment_path" == p_what) {
|
||||
PinnedPoint *w = pinned_points.ptrw();
|
||||
|
||||
if (is_inside_tree()) {
|
||||
callable_mp(this, &SoftBody3D::_pin_point_deferred).call_deferred(Variant(w[p_item].point_index), true, p_value);
|
||||
} else {
|
||||
pin_point(w[p_item].point_index, true, p_value);
|
||||
_make_cache_dirty();
|
||||
}
|
||||
} else if ("offset" == p_what) {
|
||||
PinnedPoint *w = pinned_points.ptrw();
|
||||
w[p_item].offset = p_value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoftBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const {
|
||||
if (pinned_points.size() <= p_item) {
|
||||
return false;
|
||||
}
|
||||
const PinnedPoint *r = pinned_points.ptr();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoftBody3D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
// I have no idea what this is supposed to do, it's really weird
|
||||
// leaving for upcoming PK work on physics
|
||||
//add_change_receptor(this);
|
||||
}
|
||||
|
||||
RID space = get_world_3d()->get_space();
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space);
|
||||
_prepare_physics_server();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
if (!parent_collision_ignore.is_empty()) {
|
||||
add_collision_exception_with(get_node(parent_collision_ignore));
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
_reset_points_offsets();
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicsServer3D::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 RenderingServer only to support custom Transform
|
||||
set_as_top_level(true);
|
||||
set_transform(Transform3D());
|
||||
set_notify_transform(true);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_pickable();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID());
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DISABLED: {
|
||||
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
_prepare_physics_server();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENABLED: {
|
||||
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
_prepare_physics_server();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody3D::set_collision_layer);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody3D::get_collision_layer);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &SoftBody3D::set_collision_mask_value);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &SoftBody3D::get_collision_mask_value);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &SoftBody3D::set_collision_layer_value);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &SoftBody3D::get_collision_layer_value);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore);
|
||||
ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions);
|
||||
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with);
|
||||
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody3D::set_simulation_precision);
|
||||
ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody3D::get_simulation_precision);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody3D::set_total_mass);
|
||||
ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody3D::get_total_mass);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness);
|
||||
ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient);
|
||||
ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient);
|
||||
ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody3D::set_drag_coefficient);
|
||||
ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody3D::get_drag_coefficient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftBody3D::get_point_transform);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path", "insert_at"), &SoftBody3D::pin_point, DEFVAL(NodePath()), DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftBody3D::is_point_pinned);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody3D::set_ray_pickable);
|
||||
ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody3D::is_ray_pickable);
|
||||
|
||||
ADD_GROUP("Collision", "collision_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "parent_collision_ignore", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "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::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, "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::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,KeepActive"), "set_disable_mode", "get_disable_mode");
|
||||
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
|
||||
}
|
||||
|
||||
PackedStringArray SoftBody3D::get_configuration_warnings() const {
|
||||
PackedStringArray warnings = MeshInstance3D::get_configuration_warnings();
|
||||
|
||||
if (mesh.is_null()) {
|
||||
warnings.push_back(RTR("This body will be ignored until you set a mesh."));
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void SoftBody3D::_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) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_draw_soft_mesh() {
|
||||
if (mesh.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RID mesh_rid = mesh->get_rid();
|
||||
if (owned_mesh != mesh_rid) {
|
||||
_become_mesh_owner();
|
||||
mesh_rid = mesh->get_rid();
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid);
|
||||
}
|
||||
|
||||
if (!rendering_server_handler->is_ready(mesh_rid)) {
|
||||
rendering_server_handler->prepare(mesh_rid, 0);
|
||||
|
||||
/// Necessary in order to render the mesh correctly (Soft body nodes are in global space)
|
||||
simulation_started = true;
|
||||
callable_mp((Node3D *)this, &Node3D::set_as_top_level).call_deferred(true);
|
||||
callable_mp((Node3D *)this, &Node3D::set_transform).call_deferred(Transform3D());
|
||||
}
|
||||
|
||||
_update_physics_server();
|
||||
|
||||
rendering_server_handler->open();
|
||||
PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, rendering_server_handler);
|
||||
rendering_server_handler->close();
|
||||
|
||||
rendering_server_handler->commit_changes();
|
||||
}
|
||||
|
||||
void SoftBody3D::_prepare_physics_server() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if (mesh.is_valid()) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh->get_rid());
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mesh.is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) {
|
||||
RID mesh_rid = mesh->get_rid();
|
||||
if (owned_mesh != mesh_rid) {
|
||||
_become_mesh_owner();
|
||||
mesh_rid = mesh->get_rid();
|
||||
}
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid);
|
||||
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID());
|
||||
if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) {
|
||||
RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_become_mesh_owner() {
|
||||
Vector<Ref<Material>> copy_materials;
|
||||
copy_materials.append_array(surface_override_materials);
|
||||
|
||||
ERR_FAIL_COND(!mesh->get_surface_count());
|
||||
|
||||
// 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_FLAG_USE_DYNAMIC_UPDATE;
|
||||
surface_format &= ~Mesh::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
|
||||
|
||||
Ref<ArrayMesh> soft_mesh;
|
||||
soft_mesh.instantiate();
|
||||
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);
|
||||
|
||||
for (int i = copy_materials.size() - 1; 0 <= i; --i) {
|
||||
set_surface_override_material(i, copy_materials[i]);
|
||||
}
|
||||
|
||||
owned_mesh = soft_mesh->get_rid();
|
||||
}
|
||||
|
||||
void SoftBody3D::set_collision_mask(uint32_t p_mask) {
|
||||
collision_mask = p_mask;
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask);
|
||||
}
|
||||
|
||||
uint32_t SoftBody3D::get_collision_mask() const {
|
||||
return collision_mask;
|
||||
}
|
||||
|
||||
void SoftBody3D::set_collision_layer(uint32_t p_layer) {
|
||||
collision_layer = p_layer;
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer);
|
||||
}
|
||||
|
||||
uint32_t SoftBody3D::get_collision_layer() const {
|
||||
return collision_layer;
|
||||
}
|
||||
|
||||
void SoftBody3D::set_collision_layer_value(int p_layer_number, bool p_value) {
|
||||
ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
uint32_t collision_layer_new = get_collision_layer();
|
||||
if (p_value) {
|
||||
collision_layer_new |= 1 << (p_layer_number - 1);
|
||||
} else {
|
||||
collision_layer_new &= ~(1 << (p_layer_number - 1));
|
||||
}
|
||||
set_collision_layer(collision_layer_new);
|
||||
}
|
||||
|
||||
bool SoftBody3D::get_collision_layer_value(int p_layer_number) const {
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
return get_collision_layer() & (1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
void SoftBody3D::set_collision_mask_value(int p_layer_number, bool p_value) {
|
||||
ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
uint32_t mask = get_collision_mask();
|
||||
if (p_value) {
|
||||
mask |= 1 << (p_layer_number - 1);
|
||||
} else {
|
||||
mask &= ~(1 << (p_layer_number - 1));
|
||||
}
|
||||
set_collision_mask(mask);
|
||||
}
|
||||
|
||||
bool SoftBody3D::get_collision_mask_value(int p_layer_number) const {
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive.");
|
||||
return get_collision_mask() & (1 << (p_layer_number - 1));
|
||||
}
|
||||
|
||||
void SoftBody3D::set_disable_mode(DisableMode p_mode) {
|
||||
if (disable_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
disable_mode = p_mode;
|
||||
|
||||
if (mesh.is_valid() && is_inside_tree() && !is_enabled()) {
|
||||
_prepare_physics_server();
|
||||
}
|
||||
}
|
||||
|
||||
SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const {
|
||||
return disable_mode;
|
||||
}
|
||||
|
||||
void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) {
|
||||
parent_collision_ignore = p_parent_collision_ignore;
|
||||
}
|
||||
|
||||
const NodePath &SoftBody3D::get_parent_collision_ignore() const {
|
||||
return parent_collision_ignore;
|
||||
}
|
||||
|
||||
void SoftBody3D::set_pinned_points_indices(Vector<SoftBody3D::PinnedPoint> p_pinned_points_indices) {
|
||||
pinned_points = p_pinned_points_indices;
|
||||
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
|
||||
pin_point(p_pinned_points_indices[i].point_index, true);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<SoftBody3D::PinnedPoint> SoftBody3D::get_pinned_points_indices() {
|
||||
return pinned_points;
|
||||
}
|
||||
|
||||
TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() {
|
||||
List<RID> exceptions;
|
||||
PhysicsServer3D::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions);
|
||||
TypedArray<PhysicsBody3D> ret;
|
||||
for (const RID &body : exceptions) {
|
||||
ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body);
|
||||
Object *obj = ObjectDB::get_instance(instance_id);
|
||||
PhysicsBody3D *physics_body = Object::cast_to<PhysicsBody3D>(obj);
|
||||
ret.append(physics_body);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SoftBody3D::add_collision_exception_with(Node *p_node) {
|
||||
ERR_FAIL_NULL(p_node);
|
||||
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
|
||||
ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
|
||||
PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid());
|
||||
}
|
||||
|
||||
void SoftBody3D::remove_collision_exception_with(Node *p_node) {
|
||||
ERR_FAIL_NULL(p_node);
|
||||
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
|
||||
ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
|
||||
PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid());
|
||||
}
|
||||
|
||||
int SoftBody3D::get_simulation_precision() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_simulation_precision(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_simulation_precision(int p_simulation_precision) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision);
|
||||
}
|
||||
|
||||
real_t SoftBody3D::get_total_mass() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_total_mass(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_total_mass(real_t p_total_mass) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_linear_stiffness(real_t p_linear_stiffness) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness);
|
||||
}
|
||||
|
||||
real_t SoftBody3D::get_linear_stiffness() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid);
|
||||
}
|
||||
|
||||
real_t SoftBody3D::get_pressure_coefficient() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient);
|
||||
}
|
||||
|
||||
real_t SoftBody3D::get_damping_coefficient() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_damping_coefficient(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_damping_coefficient(real_t p_damping_coefficient) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient);
|
||||
}
|
||||
|
||||
real_t SoftBody3D::get_drag_coefficient() {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_drag_coefficient(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_drag_coefficient(real_t p_drag_coefficient) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient);
|
||||
}
|
||||
|
||||
Vector3 SoftBody3D::get_point_transform(int p_point_index) {
|
||||
return PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index);
|
||||
}
|
||||
|
||||
void SoftBody3D::pin_point_toggle(int p_point_index) {
|
||||
pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index)));
|
||||
}
|
||||
|
||||
void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path, int p_insert_at) {
|
||||
ERR_FAIL_COND_MSG(p_insert_at < -1 || p_insert_at >= pinned_points.size(), "Invalid index for pin point insertion position.");
|
||||
_pin_point_on_physics_server(p_point_index, pin);
|
||||
if (pin) {
|
||||
_add_pinned_point(p_point_index, p_spatial_attachment_path, p_insert_at);
|
||||
} else {
|
||||
_remove_pinned_point(p_point_index);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_pin_point_deferred(int p_point_index, bool pin, const NodePath p_spatial_attachment_path) {
|
||||
pin_point(p_point_index, pin, p_spatial_attachment_path);
|
||||
_make_cache_dirty();
|
||||
}
|
||||
|
||||
bool SoftBody3D::is_point_pinned(int p_point_index) const {
|
||||
return -1 != _has_pinned_point(p_point_index);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_ray_pickable(bool p_ray_pickable) {
|
||||
ray_pickable = p_ray_pickable;
|
||||
_update_pickable();
|
||||
}
|
||||
|
||||
bool SoftBody3D::is_ray_pickable() const {
|
||||
return ray_pickable;
|
||||
}
|
||||
|
||||
SoftBody3D::SoftBody3D() :
|
||||
physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) {
|
||||
rendering_server_handler = memnew(SoftBodyRenderingServerHandler);
|
||||
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
|
||||
}
|
||||
|
||||
SoftBody3D::~SoftBody3D() {
|
||||
memdelete(rendering_server_handler);
|
||||
ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
|
||||
PhysicsServer3D::get_singleton()->free(physics_rid);
|
||||
}
|
||||
|
||||
void SoftBody3D::_make_cache_dirty() {
|
||||
pinned_points_cache_dirty = true;
|
||||
}
|
||||
|
||||
void SoftBody3D::_update_cache_pin_points_datas() {
|
||||
if (!pinned_points_cache_dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
pinned_points_cache_dirty = false;
|
||||
|
||||
PinnedPoint *w = pinned_points.ptrw();
|
||||
for (int i = pinned_points.size() - 1; 0 <= i; --i) {
|
||||
if (!w[i].spatial_attachment_path.is_empty()) {
|
||||
w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(w[i].spatial_attachment_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin);
|
||||
}
|
||||
|
||||
void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path, int p_insert_at) {
|
||||
SoftBody3D::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;
|
||||
|
||||
if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) {
|
||||
pp.spatial_attachment = Object::cast_to<Node3D>(get_node(p_spatial_attachment_path));
|
||||
pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index));
|
||||
}
|
||||
|
||||
if (p_insert_at != -1) {
|
||||
pinned_points.insert(p_insert_at, pp);
|
||||
} else {
|
||||
pinned_points.push_back(pp);
|
||||
}
|
||||
|
||||
} else {
|
||||
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)) {
|
||||
Node3D *attachment_node = Object::cast_to<Node3D>(get_node(p_spatial_attachment_path));
|
||||
|
||||
ERR_FAIL_NULL_MSG(attachment_node, "Attachment node path is invalid.");
|
||||
|
||||
pinned_point->spatial_attachment = attachment_node;
|
||||
pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_reset_points_offsets() {
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!r[i].spatial_attachment_path.is_empty() && has_node(r[i].spatial_attachment_path)) {
|
||||
w[i].spatial_attachment = Object::cast_to<Node3D>(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(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index));
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_remove_pinned_point(int p_point_index) {
|
||||
const int id(_has_pinned_point(p_point_index));
|
||||
if (-1 != id) {
|
||||
pinned_points.remove_at(id);
|
||||
}
|
||||
}
|
||||
|
||||
int SoftBody3D::_get_pinned_point(int p_point_index, SoftBody3D::PinnedPoint *&r_point) const {
|
||||
const int id = _has_pinned_point(p_point_index);
|
||||
if (-1 == id) {
|
||||
r_point = nullptr;
|
||||
return -1;
|
||||
} else {
|
||||
r_point = const_cast<SoftBody3D::PinnedPoint *>(&pinned_points.ptr()[id]);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
int SoftBody3D::_has_pinned_point(int p_point_index) const {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
207
engine/scene/3d/physics/soft_body_3d.h
Normal file
207
engine/scene/3d/physics/soft_body_3d.h
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/**************************************************************************/
|
||||
/* soft_body_3d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
#include "servers/physics_server_3d.h"
|
||||
|
||||
class PhysicsBody3D;
|
||||
|
||||
class SoftBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler {
|
||||
friend class SoftBody3D;
|
||||
|
||||
RID mesh;
|
||||
int surface = 0;
|
||||
Vector<uint8_t> buffer;
|
||||
uint32_t stride = 0;
|
||||
uint32_t normal_stride = 0;
|
||||
uint32_t offset_vertices = 0;
|
||||
uint32_t offset_normal = 0;
|
||||
|
||||
uint8_t *write_buffer = nullptr;
|
||||
|
||||
private:
|
||||
SoftBodyRenderingServerHandler();
|
||||
bool is_ready(RID p_mesh_rid) const { return mesh.is_valid() && mesh == p_mesh_rid; }
|
||||
void prepare(RID p_mesh_rid, int p_surface);
|
||||
void clear();
|
||||
void open();
|
||||
void close();
|
||||
void commit_changes();
|
||||
|
||||
public:
|
||||
void set_vertex(int p_vertex_id, const Vector3 &p_vertex) override;
|
||||
void set_normal(int p_vertex_id, const Vector3 &p_normal) override;
|
||||
void set_aabb(const AABB &p_aabb) override;
|
||||
};
|
||||
|
||||
class SoftBody3D : public MeshInstance3D {
|
||||
GDCLASS(SoftBody3D, MeshInstance3D);
|
||||
|
||||
public:
|
||||
enum DisableMode {
|
||||
DISABLE_MODE_REMOVE,
|
||||
DISABLE_MODE_KEEP_ACTIVE,
|
||||
};
|
||||
|
||||
struct PinnedPoint {
|
||||
int point_index = -1;
|
||||
NodePath spatial_attachment_path;
|
||||
Node3D *spatial_attachment = nullptr; // Cache
|
||||
Vector3 offset;
|
||||
|
||||
PinnedPoint();
|
||||
PinnedPoint(const PinnedPoint &obj_tocopy);
|
||||
void operator=(const PinnedPoint &obj);
|
||||
};
|
||||
|
||||
private:
|
||||
SoftBodyRenderingServerHandler *rendering_server_handler = nullptr;
|
||||
|
||||
RID physics_rid;
|
||||
|
||||
DisableMode disable_mode = DISABLE_MODE_REMOVE;
|
||||
|
||||
RID owned_mesh;
|
||||
uint32_t collision_mask = 1;
|
||||
uint32_t collision_layer = 1;
|
||||
NodePath parent_collision_ignore;
|
||||
Vector<PinnedPoint> pinned_points;
|
||||
bool simulation_started = false;
|
||||
bool pinned_points_cache_dirty = true;
|
||||
|
||||
Ref<ArrayMesh> debug_mesh_cache;
|
||||
class MeshInstance3D *debug_mesh = nullptr;
|
||||
|
||||
bool capture_input_on_drag = false;
|
||||
bool ray_pickable = true;
|
||||
|
||||
void _update_pickable();
|
||||
|
||||
void _update_physics_server();
|
||||
void _draw_soft_mesh();
|
||||
|
||||
void _prepare_physics_server();
|
||||
void _become_mesh_owner();
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
bool _set_property_pinned_points_indices(const Array &p_indices);
|
||||
bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value);
|
||||
bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _pin_point_bind_compat_94684(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath());
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
public:
|
||||
RID get_physics_rid() const { return physics_rid; }
|
||||
|
||||
void set_collision_mask(uint32_t p_mask);
|
||||
uint32_t get_collision_mask() const;
|
||||
|
||||
void set_collision_layer(uint32_t p_layer);
|
||||
uint32_t get_collision_layer() const;
|
||||
|
||||
void set_collision_layer_value(int p_layer_number, bool p_value);
|
||||
bool get_collision_layer_value(int p_layer_number) const;
|
||||
|
||||
void set_collision_mask_value(int p_layer_number, bool p_value);
|
||||
bool get_collision_mask_value(int p_layer_number) const;
|
||||
|
||||
void set_disable_mode(DisableMode p_mode);
|
||||
DisableMode get_disable_mode() const;
|
||||
|
||||
void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore);
|
||||
const NodePath &get_parent_collision_ignore() const;
|
||||
|
||||
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();
|
||||
|
||||
void set_total_mass(real_t p_total_mass);
|
||||
real_t get_total_mass();
|
||||
|
||||
void set_linear_stiffness(real_t p_linear_stiffness);
|
||||
real_t get_linear_stiffness();
|
||||
|
||||
void set_pressure_coefficient(real_t p_pressure_coefficient);
|
||||
real_t get_pressure_coefficient();
|
||||
|
||||
void set_damping_coefficient(real_t p_damping_coefficient);
|
||||
real_t get_damping_coefficient();
|
||||
|
||||
void set_drag_coefficient(real_t p_drag_coefficient);
|
||||
real_t get_drag_coefficient();
|
||||
|
||||
TypedArray<PhysicsBody3D> get_collision_exceptions();
|
||||
void add_collision_exception_with(Node *p_node);
|
||||
void remove_collision_exception_with(Node *p_node);
|
||||
|
||||
Vector3 get_point_transform(int p_point_index);
|
||||
|
||||
void pin_point_toggle(int p_point_index);
|
||||
void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath(), int p_insert_at = -1);
|
||||
bool is_point_pinned(int p_point_index) const;
|
||||
|
||||
void _pin_point_deferred(int p_point_index, bool pin, const NodePath p_spatial_attachment_path);
|
||||
|
||||
void set_ray_pickable(bool p_ray_pickable);
|
||||
bool is_ray_pickable() const;
|
||||
|
||||
SoftBody3D();
|
||||
~SoftBody3D();
|
||||
|
||||
private:
|
||||
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, int p_insert_at = -1);
|
||||
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;
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SoftBody3D::DisableMode);
|
||||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SPRING_ARM_3D_H
|
||||
#define SPRING_ARM_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/node_3d.h"
|
||||
|
||||
|
|
@ -67,5 +66,3 @@ public:
|
|||
private:
|
||||
void process_spring();
|
||||
};
|
||||
|
||||
#endif // SPRING_ARM_3D_H
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "static_body_3d.h"
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
#include "core/math/convex_hull.h"
|
||||
#include "scene/resources/3d/box_shape_3d.h"
|
||||
#include "scene/resources/3d/capsule_shape_3d.h"
|
||||
|
|
@ -47,6 +48,7 @@
|
|||
|
||||
Callable StaticBody3D::_navmesh_source_geometry_parsing_callback;
|
||||
RID StaticBody3D::_navmesh_source_geometry_parser;
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
|
||||
void StaticBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
|
||||
if (physics_material_override.is_valid()) {
|
||||
|
|
@ -95,6 +97,7 @@ void StaticBody3D::_reload_physics_characteristics() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
void StaticBody3D::navmesh_parse_init() {
|
||||
ERR_FAIL_NULL(NavigationServer3D::get_singleton());
|
||||
if (!_navmesh_source_geometry_parser.is_valid()) {
|
||||
|
|
@ -226,6 +229,7 @@ void StaticBody3D::navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_na
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
|
||||
void StaticBody3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
|
||||
|
|
|
|||
|
|
@ -28,13 +28,14 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef STATIC_BODY_3D_H
|
||||
#define STATIC_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
class NavigationMesh;
|
||||
class NavigationMeshSourceGeometryData3D;
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
|
||||
class StaticBody3D : public PhysicsBody3D {
|
||||
GDCLASS(StaticBody3D, PhysicsBody3D);
|
||||
|
|
@ -63,12 +64,12 @@ public:
|
|||
private:
|
||||
void _reload_physics_characteristics();
|
||||
|
||||
#ifndef NAVIGATION_3D_DISABLED
|
||||
static Callable _navmesh_source_geometry_parsing_callback;
|
||||
static RID _navmesh_source_geometry_parser;
|
||||
|
||||
public:
|
||||
static void navmesh_parse_init();
|
||||
static void navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_node);
|
||||
#endif // NAVIGATION_3D_DISABLED
|
||||
};
|
||||
|
||||
#endif // STATIC_BODY_3D_H
|
||||
|
|
|
|||
|
|
@ -852,18 +852,26 @@ void VehicleBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
|
|||
for (int i = 0; i < wheels.size(); i++) {
|
||||
VehicleWheel3D &wheel = *wheels[i];
|
||||
Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - p_state->get_transform().origin;
|
||||
Vector3 vel = p_state->get_linear_velocity() + (p_state->get_angular_velocity()).cross(relpos); // * mPos);
|
||||
Vector3 vel = p_state->get_linear_velocity() + (p_state->get_angular_velocity()).cross(relpos);
|
||||
|
||||
if (wheel.m_raycastInfo.m_isInContact) {
|
||||
const Transform3D &chassisWorldTransform = p_state->get_transform();
|
||||
|
||||
// Get forward vector.
|
||||
Vector3 fwd(
|
||||
chassisWorldTransform.basis[0][Vector3::AXIS_Z],
|
||||
chassisWorldTransform.basis[1][Vector3::AXIS_Z],
|
||||
chassisWorldTransform.basis[2][Vector3::AXIS_Z]);
|
||||
|
||||
// Apply steering rotation to forward vector for steerable wheels.
|
||||
if (wheel.steers) {
|
||||
Basis steering_mat(Vector3(0, 1, 0), wheel.m_steering);
|
||||
fwd = steering_mat.xform(fwd);
|
||||
}
|
||||
|
||||
real_t proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
|
||||
fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
|
||||
fwd.normalize();
|
||||
|
||||
real_t proj2 = fwd.dot(vel);
|
||||
|
||||
|
|
@ -871,7 +879,7 @@ void VehicleBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
|
|||
}
|
||||
|
||||
wheel.m_rotation += wheel.m_deltaRotation;
|
||||
wheel.m_rpm = ((wheel.m_deltaRotation / step) * 60) / Math_TAU;
|
||||
wheel.m_rpm = ((wheel.m_deltaRotation / step) * 60) / Math::TAU;
|
||||
|
||||
wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef VEHICLE_BODY_3D_H
|
||||
#define VEHICLE_BODY_3D_H
|
||||
#pragma once
|
||||
|
||||
#include "scene/3d/physics/physics_body_3d.h"
|
||||
#include "scene/3d/physics/rigid_body_3d.h"
|
||||
|
|
@ -214,5 +213,3 @@ public:
|
|||
|
||||
VehicleBody3D();
|
||||
};
|
||||
|
||||
#endif // VEHICLE_BODY_3D_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue