Merge pull request #2028 from QuantumCoderQC/rb_nodes

New Add rigid body node
This commit is contained in:
Lubos Lenco 2020-11-30 10:38:20 +01:00 committed by GitHub
commit 5ff3ec9055
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 273 additions and 7 deletions

View file

@ -0,0 +1,109 @@
package armory.logicnode;
#if arm_physics
import armory.trait.physics.bullet.RigidBody.Shape;
#end
import iron.object.Object;
import armory.trait.physics.RigidBody;
class AddRigidBodyNode extends LogicNode {
public var property0: String;//Shape
public var property1: String;//Advanced
public var object: Object;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
object = inputs[1].get();
var mass: Float = inputs[2].get();
var active: Bool = inputs[3].get();
var animated: Bool = inputs[4].get();
var trigger: Bool = inputs[5].get();
var friction: Float = inputs[6].get();
var bounciness: Float = inputs[7].get();
var ccd: Bool = inputs[8].get();
var margin: Bool = false;
var marginLen: Float = 0.0;
var linDamp: Float = 0.0;
var angDamp: Float = 0.0;
var useDeactiv: Bool = false;
var linearVelThreshold: Float = 0.0;
var angVelThreshold: Float = 0.0;
var group: Int = 1;
var mask: Int = 1;
var shape: Shape = 1;
if(property1 == 'true')
{
margin = inputs[9].get();
marginLen = inputs[10].get();
linDamp = inputs[11].get();
angDamp = inputs[12].get();
useDeactiv = inputs[13].get();
linearVelThreshold = inputs[14].get();
angVelThreshold = inputs[15].get();
group = inputs[16].get();
mask = inputs[17].get();
}
if (object == null) return;
#if arm_physics
var rb: RigidBody = object.getTrait(RigidBody);
if((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
if((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
if(rb == null)
{
switch (property0){
case 'Box':
shape = Box;
case 'Sphere':
shape = Sphere;
case 'Capsule':
shape = Capsule;
case 'Cone':
shape = Cone;
case 'Cylinder':
shape = Cylinder;
case 'Convex Hull':
shape = ConvexHull;
case 'Mesh':
shape = Mesh;
}
rb = new RigidBody(shape, mass, friction, bounciness, group, mask);
rb.animated = animated;
rb.staticObj = ! active;
rb.isTriggerObject(trigger);
if(property1 == 'true')
{
rb.linearDamping = linDamp;
rb.angularDamping = angDamp;
if(margin) rb.collisionMargin = marginLen;
if(useDeactiv) {
rb.setDeactivation(true);
rb.setDeactivationParams(linearVelThreshold, angVelThreshold, 0.0);
}
}
object.addTrait(rb);
}
#end
runOutput(0);
}
override function get(from: Int): Object {
return object;
}
}

View file

@ -30,6 +30,7 @@ class RigidBody extends iron.Trait {
public var destroyed = false;
var linearFactors: Array<Float>;
var angularFactors: Array<Float>;
var useDeactivation: Bool;
var deactivationParams: Array<Float>;
var ccd = false; // Continuous collision detection
public var group = 1;
@ -96,7 +97,29 @@ class RigidBody extends iron.Trait {
this.mask = mask;
if (params == null) params = [0.04, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0];
if (flags == null) flags = [false, false, false, false];
/**
* params:[ linear damping
* angular damping
* linear factor X
* linear factor Y
* linear factor Z
* angular factor X
* angular factor Y
* angular factor Z
* collision margin
* linear deactivation threshold
* angular deactivation thrshold
* deactivation time(Not used)]
*/
if (flags == null) flags = [false, false, false, false, true];
/**
* flags:[ is animated
* is trigger
* continuous collision detection
* is static
* use deactivation]
*/
this.linearDamping = params[0];
this.angularDamping = params[1];
@ -108,6 +131,7 @@ class RigidBody extends iron.Trait {
this.trigger = flags[1];
this.ccd = flags[2];
this.staticObj = flags[3];
this.useDeactivation = flags[4];
notifyOnAdd(init);
}
@ -241,7 +265,7 @@ class RigidBody extends iron.Trait {
}
bodyColl.setRestitution(restitution);
if (deactivationParams != null) {
if ( useDeactivation) {
setDeactivationParams(deactivationParams[0], deactivationParams[1], deactivationParams[2]);
}
else {
@ -358,6 +382,14 @@ class RigidBody extends iron.Trait {
// body.setDeactivationTime(time); // not available in ammo
}
public function setDeactivation(useDeactivation: Bool) {
this.useDeactivation = useDeactivation;
}
public function isTriggerObject(isTrigger: Bool) {
this.trigger = isTrigger;
}
public function applyForce(force: Vec4, loc: Vec4 = null) {
activate();
vec1.setValue(force.x, force.y, force.z);

View file

@ -2360,7 +2360,7 @@ class ArmoryExporter:
if bobject.lock_rotation[2]:
az = 0
col_margin = str(rb.collision_margin) if rb.use_margin else '0.0'
if rb.use_deactivation or bobject.arm_rb_force_deactivation:
if rb.use_deactivation:
deact_lv = str(rb.deactivate_linear_velocity)
deact_av = str(rb.deactivate_angular_velocity)
deact_time = str(bobject.arm_rb_deactivation_time)
@ -2376,11 +2376,12 @@ class ArmoryExporter:
col_margin,
deact_lv, deact_av, deact_time
)
body_flags = '[{0}, {1}, {2}, {3}]'.format(
body_flags = '[{0}, {1}, {2}, {3}, {4}]'.format(
str(rb.kinematic).lower(),
str(bobject.arm_rb_trigger).lower(),
str(bobject.arm_rb_ccd).lower(),
str(is_static).lower()
str(is_static).lower(),
str(rb.use_deactivation).lower()
)
x['parameters'].append(body_params)
x['parameters'].append(body_flags)

View file

@ -0,0 +1,126 @@
from arm.logicnode.arm_nodes import *
class AddRigidBodyNode(ArmLogicTreeNode):
"""Adds a rigid body to an object if not already present.
@option Advanced: Shows optional advanced options for rigid body.
@option Shape: Shape of the rigid body including Box, Sphere, Capsule, Cone, Cylinder, Convex Hull and Mesh
@input Object: Object to which rigid body is added.
@input Mass: Mass of the rigid body. Must be > 0.
@input Active: Rigid body actively participates in the physics world and will be affected by collisions
@input Animated: Rigid body follows animation and will affect other active non-animated rigid bodies.
@input Trigger: Rigid body behaves as a trigger and detects collision. However, rigd body does not contribute to or receive collissions.
@input Friction: Surface friction of the rigid body. Minimum value = 0, Preferred max value = 1.
@input Bounciness: How elastic is the surface of the rigid body. Minimum value = 0, Preferred max value = 1.
@input Continuous Collision Detection (CCD): Detects for collisions in between frames. Use only for very fast moving objects.
@input Collision Margin: Enable an external margin for collision detection
@input Margin: Length of the collision margin. Must be > 0.
@input Linear Damping: Damping for linear translation. Recommended range 0 to 1.
@input Angular Damping: Damping for angular translation. Recommended range 0 to 1.
@input Use Deactivation: Deactive this rigid body when below the Linear and Angular velocity threshold. Enable to improve performance.
@input Linear Velocity Threshold: Velocity below which decativation occurs if enabled.
@input Angular Velocity Threshold: Velocity below which decativation occurs if enabled.
@input Collision Group: A set of rigid bodies that can interact with each other
@input Collision Mask: Bitmask to filter collisions. Collision can occur between two rigid bodies if they have atleast one bit in common.
@output Rigid body: Object to which rigid body was added.
@output Out: activated after rigid body is added.
"""
bl_idname = 'LNAddRigidBodyNode'
bl_label = 'Add Rigid Body'
arm_version = 1
NUM_STATIC_INS = 9
def update_advanced(self, context):
"""This is a helper method to allow declaring the `advanced`
property before the update_sockets() method. It's not required
but then you would need to move the declaration of `advanced`
further down."""
self.update_sockets(context)
@property
def property1(self):
return 'true' if self.property1_ else 'false'
property1_: BoolProperty(
name="Advanced",
description="Show advanced options",
default=False,
update=update_advanced
)
property0: EnumProperty(
items = [('Box', 'Box', 'Box'),
('Sphere', 'Sphere', 'Sphere'),
('Capsule', 'Capsule', 'Capsule'),
('Cone', 'Cone', 'Cone'),
('Cylinder', 'Cylinder', 'Cylinder'),
('Convex Hull', 'Convex Hull', 'Convex Hull'),
('Mesh', 'Mesh', 'Mesh')],
name='Shape', default='Box')
def init(self, context):
super(AddRigidBodyNode, self).init(context)
self.add_input('ArmNodeSocketAction', 'In')
self.add_input('ArmNodeSocketObject', 'Object')
self.add_input('NodeSocketFloat', 'Mass', 1.0)
self.add_input('NodeSocketBool', 'Active', True)
self.add_input('NodeSocketBool', 'Animated', False)
self.add_input('NodeSocketBool', 'Trigger', False)
self.add_input('NodeSocketFloat', 'Friction', 0.5)
self.add_input('NodeSocketFloat', 'Bounciness', 0.0)
self.add_input('NodeSocketBool', 'Continuous Collision Detection', False)
self.add_output('ArmNodeSocketAction', 'Out')
self.add_output('ArmNodeSocketObject', 'Rigid body')
self.update_sockets(context)
def update_sockets(self, context):
# It's bad to remove from a list during iteration so we use
# this helper list here
remove_list = []
# Remove dynamically placed input sockets
for i in range(AddRigidBodyNode.NUM_STATIC_INS, len(self.inputs)):
remove_list.append(self.inputs[i])
for i in remove_list:
self.inputs.remove(i)
# Add dynamic input sockets
if self.property1_:
self.add_input('NodeSocketBool', 'Collision Margin', False)
self.add_input('NodeSocketFloat', 'Margin', 0.04)
self.add_input('NodeSocketFloat', 'Linear Damping', 0.04)
self.add_input('NodeSocketFloat', 'Angular Damping', 0.1)
self.add_input('NodeSocketBool', 'Use Deacivation')
self.add_input('NodeSocketFloat', 'Linear Velocity Threshold', 0.4)
self.add_input('NodeSocketFloat', 'Angular Velocity Threshold', 0.5)
self.add_input('NodeSocketInt', 'Collision Group', 1)
self.add_input('NodeSocketInt', 'Collision Mask', 1)
def draw_buttons(self, context, layout):
layout.prop(self, "property1_")
layout.prop(self, 'property0')

View file

@ -276,7 +276,6 @@ def init_properties():
bpy.types.Object.arm_rb_linear_factor = FloatVectorProperty(name="Linear Factor", size=3, description="Set to 0 to lock axis", default=[1,1,1])
bpy.types.Object.arm_rb_angular_factor = FloatVectorProperty(name="Angular Factor", size=3, description="Set to 0 to lock axis", default=[1,1,1])
bpy.types.Object.arm_rb_trigger = BoolProperty(name="Trigger", description="Disable contact response", default=False)
bpy.types.Object.arm_rb_force_deactivation = BoolProperty(name="Force Deactivation", description="Force deactivation on all rigid bodies for performance", default=True)
bpy.types.Object.arm_rb_deactivation_time = FloatProperty(name="Deactivation Time", description="Delay putting rigid body into sleep", default=0.0)
bpy.types.Object.arm_rb_ccd = BoolProperty(name="Continuous Collision Detection", description="Improve collision for fast moving objects", default=False)
bpy.types.Object.arm_animation_enabled = BoolProperty(name="Animation", description="Enable skinning & timeline animation", default=True)

View file

@ -152,7 +152,6 @@ class ARM_PT_PhysicsPropsPanel(bpy.types.Panel):
layout.prop(obj, 'arm_rb_linear_factor')
layout.prop(obj, 'arm_rb_angular_factor')
layout.prop(obj, 'arm_rb_trigger')
layout.prop(obj, 'arm_rb_force_deactivation')
layout.prop(obj, 'arm_rb_ccd')
if obj.soft_body != None: