|
@@ -33,6 +33,7 @@ void Start()
|
|
|
SubscribeToEvent("MouseButtonUp", "HandleMouseButtonUp");
|
|
SubscribeToEvent("MouseButtonUp", "HandleMouseButtonUp");
|
|
|
SubscribeToEvent("PostRenderUpdate", "HandlePostRenderUpdate");
|
|
SubscribeToEvent("PostRenderUpdate", "HandlePostRenderUpdate");
|
|
|
SubscribeToEvent("SpawnBox", "HandleSpawnBox");
|
|
SubscribeToEvent("SpawnBox", "HandleSpawnBox");
|
|
|
|
|
+ SubscribeToEvent("PhysicsCollision", "HandlePhysicsCollision");
|
|
|
|
|
|
|
|
network.RegisterRemoteEvent("SpawnBox");
|
|
network.RegisterRemoteEvent("SpawnBox");
|
|
|
|
|
|
|
@@ -219,6 +220,12 @@ void InitScene()
|
|
|
object.material = cache.GetResource("Material", "Materials/Jack.xml");
|
|
object.material = cache.GetResource("Material", "Materials/Jack.xml");
|
|
|
object.castShadows = true;
|
|
object.castShadows = true;
|
|
|
|
|
|
|
|
|
|
+ // Create a capsule shape for detecting collisions
|
|
|
|
|
+ RigidBody@ body = objectNode.CreateComponent("RigidBody");
|
|
|
|
|
+ body.phantom = true;
|
|
|
|
|
+ CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
|
|
|
|
|
+ shape.SetCapsule(0.7, 1.8, Vector3(0.0, 0.9, 0.0));
|
|
|
|
|
+
|
|
|
AnimationController@ ctrl = objectNode.CreateComponent("AnimationController");
|
|
AnimationController@ ctrl = objectNode.CreateComponent("AnimationController");
|
|
|
ctrl.Play("Models/Jack_Walk.ani", 0, true, 0.0f);
|
|
ctrl.Play("Models/Jack_Walk.ani", 0, true, 0.0f);
|
|
|
}
|
|
}
|
|
@@ -450,10 +457,6 @@ void HandlePostRenderUpdate()
|
|
|
Vector3 rayHitPos = cameraRay.origin + cameraRay.direction * result.distance;
|
|
Vector3 rayHitPos = cameraRay.origin + cameraRay.direction * result.distance;
|
|
|
testScene.debugRenderer.AddBoundingBox(BoundingBox(rayHitPos + Vector3(-0.01, -0.01, -0.01), rayHitPos +
|
|
testScene.debugRenderer.AddBoundingBox(BoundingBox(rayHitPos + Vector3(-0.01, -0.01, -0.01), rayHitPos +
|
|
|
Vector3(0.01, 0.01, 0.01)), Color(1.0, 1.0, 1.0), true);
|
|
Vector3(0.01, 0.01, 0.01)), Color(1.0, 1.0, 1.0), true);
|
|
|
-
|
|
|
|
|
- // Test creating a ragdoll
|
|
|
|
|
- if (input.keyPress['R'] && result.drawable.typeName == "AnimatedModel")
|
|
|
|
|
- CreateRagdoll(result.drawable);
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -465,28 +468,49 @@ void HandleClientConnected(StringHash eventType, VariantMap& eventData)
|
|
|
connection.logStatistics = true;
|
|
connection.logStatistics = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void HandlePhysicsCollision(StringHash eventType, VariantMap& eventData)
|
|
|
|
|
+{
|
|
|
|
|
+ // Check if either of the nodes has an AnimatedModel component
|
|
|
|
|
+ Node@ nodeA = eventData["NodeA"].GetNode();
|
|
|
|
|
+ Node@ nodeB = eventData["NodeB"].GetNode();
|
|
|
|
|
+ if (nodeA.HasComponent("AnimatedModel"))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Remove the trigger physics shape, and create the ragdoll
|
|
|
|
|
+ nodeA.RemoveComponent("RigidBody");
|
|
|
|
|
+ nodeA.RemoveComponent("CollisionShape");
|
|
|
|
|
+ CreateRagdoll(nodeA.GetComponent("AnimatedModel"));
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (nodeB.HasComponent("AnimatedModel"))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Remove the trigger physics shape, and create the ragdoll
|
|
|
|
|
+ nodeB.RemoveComponent("RigidBody");
|
|
|
|
|
+ nodeB.RemoveComponent("CollisionShape");
|
|
|
|
|
+ CreateRagdoll(nodeB.GetComponent("AnimatedModel"));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void CreateRagdoll(AnimatedModel@ model)
|
|
void CreateRagdoll(AnimatedModel@ model)
|
|
|
{
|
|
{
|
|
|
Node@ root = model.node;
|
|
Node@ root = model.node;
|
|
|
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_Pelvis", 1.0, SHAPE_BOX, Vector3(0.2, 0.2, 0.2), Vector3(0.1, 0, 0), Quaternion(0, 0, 0));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_Spine1", 1.0, SHAPE_BOX, Vector3(0.25, 0.2, 0.2), Vector3(0.15, 0, 0), Quaternion(0, 0, 0));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_L_Thigh", 0.75, SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_R_Thigh", 0.75, SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_L_Calf", 0.75, SHAPE_CAPSULE, Vector3(0.15, 0.45, 0.15), Vector3(0.2, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_R_Calf", 0.75, SHAPE_CAPSULE, Vector3(0.15, 0.45, 0.15), Vector3(0.2, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_Head", 0.75, SHAPE_SPHERE, Vector3(0.25, 0.25, 0.25), Vector3(0.1, 0, 0), Quaternion(0, 0, 0));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_L_UpperArm", 0.5, SHAPE_CAPSULE, Vector3(0.125, 0.3, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_R_UpperArm", 0.5, SHAPE_CAPSULE, Vector3(0.125, 0.3, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_L_Forearm", 0.5, SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
- CreateRagdollBone(root, "Bip01_R_Forearm", 0.5, SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
-
|
|
|
|
|
- CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 15), Vector2(0, 0));
|
|
|
|
|
- CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 15), Vector2(0, 0));
|
|
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_CAPSULE, Vector3(0.3, 0.3, 0.3), Vector3(0.0, 0, 0), Quaternion(0, 0, 0));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_Spine1", SHAPE_CAPSULE, Vector3(0.3, 0.4, 0.3), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_L_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_R_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_L_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_R_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_Head", SHAPE_SPHERE, Vector3(0.25, 0.25, 0.25), Vector3(0.1, 0, 0), Quaternion(0, 0, 0));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_L_UpperArm", SHAPE_CAPSULE, Vector3(0.125, 0.35, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_R_UpperArm", SHAPE_CAPSULE, Vector3(0.125, 0.35, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_L_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+ CreateRagdollBone(root, "Bip01_R_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
|
|
|
|
|
+
|
|
|
|
|
+ CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
|
|
|
|
|
+ CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
|
|
|
CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
|
CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
|
- CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(30, 15), Vector2(0, 0));
|
|
|
|
|
- CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(45, 15), Vector2(0, 0));
|
|
|
|
|
|
|
+ CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(90, 0), Vector2(-25, 0));
|
|
|
|
|
+ CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
|
|
|
CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
|
|
CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
|
|
|
CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
|
|
CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
|
|
|
CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
|
|
@@ -498,16 +522,21 @@ void CreateRagdoll(AnimatedModel@ model)
|
|
|
skel.bones[i].animated = false;
|
|
skel.bones[i].animated = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void CreateRagdollBone(Node@ root, String boneName, float mass, ShapeType type, Vector3 size, Vector3 position, Quaternion rotation)
|
|
|
|
|
|
|
+void CreateRagdollBone(Node@ root, String boneName, ShapeType type, Vector3 size, Vector3 position, Quaternion rotation)
|
|
|
{
|
|
{
|
|
|
Node@ boneNode = root.GetChild(boneName, true);
|
|
Node@ boneNode = root.GetChild(boneName, true);
|
|
|
if (boneNode is null || boneNode.HasComponent("RigidBody"))
|
|
if (boneNode is null || boneNode.HasComponent("RigidBody"))
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
|
|
+ // In networked operation both client and server detect collisions separately, and create ragdolls on their own
|
|
|
|
|
+ // (bones are not synced over network.) To prevent replicated component ID range clashes when the client creates
|
|
|
|
|
+ // any components, it is important that the LOCAL creation mode is specified.
|
|
|
RigidBody@ body = boneNode.CreateComponent("RigidBody", LOCAL);
|
|
RigidBody@ body = boneNode.CreateComponent("RigidBody", LOCAL);
|
|
|
- body.mass = mass;
|
|
|
|
|
- body.linearDamping = 0.75;
|
|
|
|
|
- body.angularDamping = 0.75;
|
|
|
|
|
|
|
+ body.mass = 1.0;
|
|
|
|
|
+ body.linearDamping = 0.05;
|
|
|
|
|
+ body.angularDamping = 0.85;
|
|
|
|
|
+ body.linearRestThreshold = 1.5;
|
|
|
|
|
+ body.angularRestThreshold = 2.5;
|
|
|
|
|
|
|
|
CollisionShape@ shape = boneNode.CreateComponent("CollisionShape", LOCAL);
|
|
CollisionShape@ shape = boneNode.CreateComponent("CollisionShape", LOCAL);
|
|
|
shape.shapeType = type;
|
|
shape.shapeType = type;
|
|
@@ -523,7 +552,7 @@ void CreateRagdollConstraint(Node@ root, String boneName, String parentName, Con
|
|
|
if (boneNode is null || parentNode is null || boneNode.HasComponent("Constraint"))
|
|
if (boneNode is null || parentNode is null || boneNode.HasComponent("Constraint"))
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
- Constraint@ constraint = boneNode.CreateComponent("Constraint");
|
|
|
|
|
|
|
+ Constraint@ constraint = boneNode.CreateComponent("Constraint", LOCAL);
|
|
|
constraint.constraintType = type;
|
|
constraint.constraintType = type;
|
|
|
constraint.disableCollision = true;
|
|
constraint.disableCollision = true;
|
|
|
// The connected body must be specified before setting the world position
|
|
// The connected body must be specified before setting the world position
|