From 8beb8ef061220eaac195de61a2bac99bf752d28f Mon Sep 17 00:00:00 2001 From: QuantumCoderQC Date: Tue, 29 Oct 2019 23:12:40 +0100 Subject: [PATCH] Implemented Physics constraints: Generic, Generic-Spring, Slider, Piston and Hinge. Point constraint now uses Bullet Physics btPoint2Point constraint. Hinge constraint now obeys orientation inputs. Generic constraint can now be fully configured within Blender. Constraint behaviour matches that of Blender physics constraints. --- .../trait/physics/bullet/PhysicsConstraint.hx | 217 ++++++++++++++++-- blender/arm/exporter.py | 74 +++++- 2 files changed, 262 insertions(+), 29 deletions(-) diff --git a/Sources/armory/trait/physics/bullet/PhysicsConstraint.hx b/Sources/armory/trait/physics/bullet/PhysicsConstraint.hx index 9c176b60..58d65c4c 100644 --- a/Sources/armory/trait/physics/bullet/PhysicsConstraint.hx +++ b/Sources/armory/trait/physics/bullet/PhysicsConstraint.hx @@ -1,10 +1,10 @@ package armory.trait.physics.bullet; #if arm_bullet - +import Math; +import iron.math.Quat; import armory.trait.physics.RigidBody; import armory.trait.physics.PhysicsWorld; - class PhysicsConstraint extends iron.Trait { var body1:String; @@ -21,6 +21,7 @@ class PhysicsConstraint extends iron.Trait { static var vec3:bullet.Bt.Vector3; static var trans1:bullet.Bt.Transform; static var trans2:bullet.Bt.Transform; + static var transt:bullet.Bt.Transform; public function new(body1:String, body2:String, type:String, disableCollisions:Bool, breakingThreshold:Float, limits:Array = null) { super(); @@ -32,6 +33,7 @@ class PhysicsConstraint extends iron.Trait { vec3 = new bullet.Bt.Vector3(0, 0, 0); trans1 = new bullet.Bt.Transform(); trans2 = new bullet.Bt.Transform(); + } this.body1 = body1; @@ -62,22 +64,19 @@ class PhysicsConstraint extends iron.Trait { vec1.setY(t.worldy() - t1.worldy()); vec1.setZ(t.worldz() - t1.worldz()); trans1.setOrigin(vec1); + //trans1.setRotation(new bullet.Bt.Quaternion(t1.rot.x, t1.rot.y, t1.rot.z, t1.rot.w)); trans2.setIdentity(); vec2.setX(t.worldx() - t2.worldx()); vec2.setY(t.worldy() - t2.worldy()); vec2.setZ(t.worldz() - t2.worldz()); trans2.setOrigin(vec2); + //trans2.setRotation(new bullet.Bt.Quaternion(t2.rot.x, t2.rot.y, t2.rot.z, t2.rot.w)); + trans1.setRotation(new bullet.Bt.Quaternion(t.rot.x, t.rot.y, t.rot.z, t.rot.w)); + trans2.setRotation(new bullet.Bt.Quaternion(t.rot.x, t.rot.y, t.rot.z, t.rot.w)); - if (type == "GENERIC" || type == "FIXED" || type == "POINT") { + if (type == "GENERIC" || type == "FIXED") { var c = bullet.Bt.Generic6DofConstraint.new2(rb1.body, rb2.body, trans1, trans2, false); - if (type == "POINT") { - vec1.setX(0); - vec1.setY(0); - vec1.setZ(0); - c.setLinearLowerLimit(vec1); - c.setLinearUpperLimit(vec1); - } - else if (type == "FIXED") { + if (type == "FIXED") { vec1.setX(0); vec1.setY(0); vec1.setZ(0); @@ -86,8 +85,38 @@ class PhysicsConstraint extends iron.Trait { c.setAngularLowerLimit(vec1); c.setAngularUpperLimit(vec1); } - else { // GENERIC - // limit_x:Bool = limits[0] > 0.0; + + else if(type == "GENERIC") { + if(limits[0] == 0){ + limits[1] = 1.0; + limits[2] = -1.0; + + } + if(limits[3] == 0){ + limits[4] = 1.0; + limits[5] = -1.0; + + } + if(limits[6] == 0){ + limits[7] = 1.0; + limits[8] = -1.0; + + } + if(limits[9] == 0){ + limits[10] = 1.0; + limits[11] = -1.0; + + } + if(limits[12] == 0){ + limits[13] = 1.0; + limits[14] = -1.0; + + } + if(limits[15] == 0){ + limits[16] = 1.0; + limits[17] = -1.0; + + } vec1.setX(limits[1]); vec1.setY(limits[4]); vec1.setZ(limits[7]); @@ -107,16 +136,162 @@ class PhysicsConstraint extends iron.Trait { } con = cast c; } - else if (type == "HINGE") { - var axis = vec3; - axis.setX(0); - axis.setY(0); - axis.setZ(1); - var c = new bullet.Bt.HingeConstraint(rb1.body, rb2.body, vec2, vec1, axis, axis); + + else if( type == "GENERIC_SPRING"){ + var c = new bullet.Bt.Generic6DofSpringConstraint(rb1.body, rb2.body, trans1, trans2, false); + + if(limits[0] == 0){ + limits[1] = 1.0; + limits[2] = -1.0; + + } + if(limits[3] == 0){ + limits[4] = 1.0; + limits[5] = -1.0; + + } + if(limits[6] == 0){ + limits[7] = 1.0; + limits[8] = -1.0; + + } + if(limits[9] == 0){ + limits[10] = 1.0; + limits[11] = -1.0; + + } + if(limits[12] == 0){ + limits[13] = 1.0; + limits[14] = -1.0; + + } + if(limits[15] == 0){ + limits[16] = 1.0; + limits[17] = -1.0; + + } + vec1.setX(limits[1]); + vec1.setY(limits[4]); + vec1.setZ(limits[7]); + c.setLinearLowerLimit(vec1); + vec1.setX(limits[2]); + vec1.setY(limits[5]); + vec1.setZ(limits[8]); + c.setLinearUpperLimit(vec1); + vec1.setX(limits[10]); + vec1.setY(limits[13]); + vec1.setZ(limits[16]); + c.setAngularLowerLimit(vec1); + vec1.setX(limits[11]); + vec1.setY(limits[14]); + vec1.setZ(limits[17]); + c.setAngularUpperLimit(vec1); + if(limits[18] != 0) + { + c.enableSpring(0,true); + c.setStiffness(0,limits[19]); + c.setDamping(0,limits[20]); + + } + else{c.enableSpring(0,false);} + if(limits[21] != 0) + { + c.enableSpring(1,true); + c.setStiffness(1,limits[22]); + c.setDamping(1,limits[23]); + + } + else{c.enableSpring(1,false);} + if(limits[24] != 0) + { + c.enableSpring(2,true); + c.setStiffness(2,limits[25]); + c.setDamping(2,limits[26]); + + } + else{c.enableSpring(2,false);} + if(limits[27] != 0) + { + c.enableSpring(3,true); + c.setStiffness(3,limits[28]); + c.setDamping(3,limits[29]); + } + else{c.enableSpring(3,false);} + if(limits[30] != 0) + { + c.enableSpring(4,true); + c.setStiffness(4,limits[31]); + c.setDamping(4,limits[32]); + } + else{c.enableSpring(4,false);} + if(limits[33] != 0) + { + c.enableSpring(5,true); + c.setStiffness(5,limits[34]); + c.setDamping(5,limits[35]); + } + else{c.enableSpring(5,false);} + con = cast c; + + } + else if (type == "POINT"){ + var c = new bullet.Bt.Point2PointConstraint(rb1.body, rb2.body, vec1, vec2); con = cast c; } - // else if (type == "SLIDER") {} - // else if (type == "PISTON") {} + + else if (type == "HINGE") { + var axis = vec3; + var _softness:Float = 0.9; + var _biasFactor:Float = 0.3; + var _relaxationFactor:Float = 1.0; + + axis.setX(t.up().x); + axis.setY(t.up().y); + axis.setZ(t.up().z); + + var c = new bullet.Bt.HingeConstraint(rb1.body, rb2.body, vec1, vec2, axis, axis); + + if(limits[0] != 0){ + c.setLimit(limits[1],limits[2],_softness ,_biasFactor ,_relaxationFactor ); + } + + con = cast c; + } + else if (type == "SLIDER") { + var c = new bullet.Bt.SliderConstraint(rb1.body, rb2.body, trans1, trans2, true); + + + + if(limits[0] != 0){ + c.setLowerLinLimit(limits[1]); + c.setUpperLinLimit(limits[2]); + } + + con = cast c; + + + } + else if (type == "PISTON") { + + var c = new bullet.Bt.SliderConstraint(rb1.body, rb2.body, trans1, trans2, true); + + if(limits[0] != 0){ + c.setLowerLinLimit(limits[1]); + c.setUpperLinLimit(limits[2]); + } + if(limits[3] != 0){ + c.setLowerAngLimit(limits[4]); + c.setUpperAngLimit(limits[5]); + } + else{ + c.setLowerAngLimit(1); + c.setUpperAngLimit(-1); + + } + con = cast c; + + + } if (breakingThreshold > 0) con.setBreakingImpulseThreshold(breakingThreshold); diff --git a/blender/arm/exporter.py b/blender/arm/exporter.py index 6a8cd99e..dbe181cc 100755 --- a/blender/arm/exporter.py +++ b/blender/arm/exporter.py @@ -1062,7 +1062,7 @@ class ArmoryExporter: cdata[i3 ] = col[0] cdata[i3 + 1] = col[1] cdata[i3 + 2] = col[2] - + mats = exportMesh.materials poly_map = [] for i in range(max(len(mats), 1)): @@ -1071,14 +1071,14 @@ class ArmoryExporter: poly_map[poly.material_index].append(poly) o['index_arrays'] = [] - + # map polygon indices to triangle loops tri_loops = {} for loop in exportMesh.loop_triangles: if loop.polygon_index not in tri_loops: tri_loops[loop.polygon_index] = [] tri_loops[loop.polygon_index].append(loop) - + for index, polys in enumerate(poly_map): tris = 0 for poly in polys: @@ -1489,9 +1489,7 @@ class ArmoryExporter: mat.arm_particle_flag = True # Empty material roughness mat.use_nodes = True - for node in mat.node_tree.nodes: - if node.type == 'BSDF_PRINCIPLED': - node.inputs[7].default_value = 0.25 + mat.node_tree.nodes['Principled BSDF'].inputs[7].default_value = 0.25 o = {} o['name'] = mat.name o['contexts'] = [] @@ -2248,7 +2246,7 @@ class ArmoryExporter: col_mask = '' for b in bobject.arm_rb_collision_filter_mask: col_mask = ('1' if b else '0') + col_mask - + x['parameters'] = [str(shape), str(body_mass), str(rb.friction), str(rb.restitution), str(int(col_group, 2)), str(int(col_mask, 2)) ] lx = bobject.arm_rb_linear_factor[0] ly = bobject.arm_rb_linear_factor[1] @@ -2425,7 +2423,7 @@ class ArmoryExporter: bobject_eval = bobject.evaluated_get(self.depsgraph) if apply_modifiers else bobject exportMesh = bobject_eval.to_mesh() - + with open(nav_filepath, 'w') as f: for v in exportMesh.vertices: f.write("v %.4f " % (v.co[0] * bobject_eval.scale.x)) @@ -2531,6 +2529,66 @@ class ArmoryExporter: limits.append(rbc.limit_ang_z_lower) limits.append(rbc.limit_ang_z_upper) trait['parameters'].append(str(limits)) + if rbc.type == "GENERIC_SPRING": + limits = [] + limits.append(1 if rbc.use_limit_lin_x else 0) + limits.append(rbc.limit_lin_x_lower) + limits.append(rbc.limit_lin_x_upper) + limits.append(1 if rbc.use_limit_lin_y else 0) + limits.append(rbc.limit_lin_y_lower) + limits.append(rbc.limit_lin_y_upper) + limits.append(1 if rbc.use_limit_lin_z else 0) + limits.append(rbc.limit_lin_z_lower) + limits.append(rbc.limit_lin_z_upper) + limits.append(1 if rbc.use_limit_ang_x else 0) + limits.append(rbc.limit_ang_x_lower) + limits.append(rbc.limit_ang_x_upper) + limits.append(1 if rbc.use_limit_ang_y else 0) + limits.append(rbc.limit_ang_y_lower) + limits.append(rbc.limit_ang_y_upper) + limits.append(1 if rbc.use_limit_ang_z else 0) + limits.append(rbc.limit_ang_z_lower) + limits.append(rbc.limit_ang_z_upper) + limits.append(1 if rbc.use_spring_x else 0) + limits.append(rbc.spring_stiffness_x) + limits.append(rbc.spring_damping_x) + limits.append(1 if rbc.use_spring_y else 0) + limits.append(rbc.spring_stiffness_y) + limits.append(rbc.spring_damping_y) + limits.append(1 if rbc.use_spring_z else 0) + limits.append(rbc.spring_stiffness_z) + limits.append(rbc.spring_damping_z) + limits.append(1 if rbc.use_spring_ang_x else 0) + limits.append(rbc.spring_stiffness_ang_x) + limits.append(rbc.spring_damping_ang_x) + limits.append(1 if rbc.use_spring_ang_y else 0) + limits.append(rbc.spring_stiffness_ang_y) + limits.append(rbc.spring_damping_ang_y) + limits.append(1 if rbc.use_spring_ang_z else 0) + limits.append(rbc.spring_stiffness_ang_z) + limits.append(rbc.spring_damping_ang_z) + trait['parameters'].append(str(limits)) + if rbc.type == "HINGE": + limits = [] + limits.append(1 if rbc.use_limit_ang_z else 0) + limits.append(rbc.limit_ang_z_lower) + limits.append(rbc.limit_ang_z_upper) + trait['parameters'].append(str(limits)) + if rbc.type == "SLIDER": + limits = [] + limits.append(1 if rbc.use_limit_lin_x else 0) + limits.append(rbc.limit_lin_x_lower) + limits.append(rbc.limit_lin_x_upper) + trait['parameters'].append(str(limits)) + if rbc.type == "PISTON": + limits = [] + limits.append(1 if rbc.use_limit_lin_x else 0) + limits.append(rbc.limit_lin_x_lower) + limits.append(rbc.limit_lin_x_upper) + limits.append(1 if rbc.use_limit_ang_x else 0) + limits.append(rbc.limit_ang_x_lower) + limits.append(rbc.limit_ang_x_upper) + trait['parameters'].append(str(limits)) o['traits'].append(trait) def post_export_world(self, world, o):