You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
4.8 KiB
C#

using UnityEngine;
using System.Collections;
namespace RootMotion.Dynamics {
public static class PuppetMasterTools {
public static void PositionRagdoll(PuppetMaster puppetMaster) {
Rigidbody[] rigidbodies = puppetMaster.transform.GetComponentsInChildren<Rigidbody>();
if (rigidbodies.Length == 0) return;
foreach (Muscle m in puppetMaster.muscles) if (m.joint == null || m.target == null) return;
Vector3[] swingAxes = new Vector3[rigidbodies.Length];
for (int i = 0; i < rigidbodies.Length; i++) {
if (rigidbodies[i].transform.childCount == 1) {
swingAxes[i] = rigidbodies[i].transform.InverseTransformDirection(rigidbodies[i].transform.GetChild(0).position - rigidbodies[i].transform.position);
}
}
foreach (Rigidbody r in rigidbodies) {
foreach (Muscle m in puppetMaster.muscles) {
if (m.joint.GetComponent<Rigidbody>() == r) {
r.transform.position = m.target.position;
}
}
}
for (int i = 0; i < rigidbodies.Length; i++) {
if (rigidbodies[i].transform.childCount == 1) {
Vector3 childPosition = rigidbodies[i].transform.GetChild(0).position;
rigidbodies[i].transform.rotation = Quaternion.FromToRotation(rigidbodies[i].transform.rotation * swingAxes[i], childPosition - rigidbodies[i].transform.position) * rigidbodies[i].transform.rotation;
rigidbodies[i].transform.GetChild(0).position = childPosition;
}
}
}
public static void RealignRagdoll(PuppetMaster puppetMaster) {
foreach (Muscle m in puppetMaster.muscles) {
if (m.joint == null || m.joint.transform == null || m.target == null) {
Debug.LogWarning("Muscles incomplete, can not realign ragdoll.");
return;
}
}
foreach (Muscle m in puppetMaster.muscles) {
if (m.target != null) {
Transform[] children = new Transform[m.joint.transform.childCount];
for (int c = 0 ; c < children.Length; c++) {
children[c] = m.joint.transform.GetChild(c);
}
foreach (Transform c in children) c.parent = null;
BoxCollider box = m.joint.GetComponent<BoxCollider>();
Vector3 boxSizeWorldSpace = Vector3.zero;
Vector3 boxCenterWorldSpace = Vector3.zero;
if (box != null) {
boxSizeWorldSpace = box.transform.TransformVector(box.size);
boxCenterWorldSpace = box.transform.TransformVector(box.center);
}
CapsuleCollider capsule = m.joint.GetComponent<CapsuleCollider>();
Vector3 capsuleCenterWorldSpace = Vector3.zero;
Vector3 capsuleDirectionWorldSpace = Vector3.zero;
if (capsule != null) {
capsuleCenterWorldSpace = capsule.transform.TransformVector(capsule.center);
capsuleDirectionWorldSpace = capsule.transform.TransformVector(DirectionIntToVector3(capsule.direction));
}
SphereCollider sphere = m.joint.GetComponent<SphereCollider>();
Vector3 sphereCenterWorldSpace = Vector3.zero;
if (sphere != null) {
sphereCenterWorldSpace = sphere.transform.TransformVector(sphere.center);
}
Vector3 jointAxisWorldSpace = m.joint.transform.TransformVector(m.joint.axis);
Vector3 jointSecondaryAxisWorldSpace = m.joint.transform.TransformVector(m.joint.secondaryAxis);
// Rotate the bone
m.joint.transform.rotation = m.target.rotation;
if (box != null) {
box.size = box.transform.InverseTransformVector(boxSizeWorldSpace);
box.center = box.transform.InverseTransformVector(boxCenterWorldSpace);
}
if (capsule != null) {
capsule.center = capsule.transform.InverseTransformVector(capsuleCenterWorldSpace);
Vector3 directionLocalSpace = capsule.transform.InverseTransformDirection(capsuleDirectionWorldSpace);
capsule.direction = DirectionVector3ToInt(directionLocalSpace);
}
if (sphere != null) {
sphere.center = sphere.transform.InverseTransformVector(sphereCenterWorldSpace);
}
m.joint.axis = m.joint.transform.InverseTransformVector(jointAxisWorldSpace);
m.joint.secondaryAxis = m.joint.transform.InverseTransformVector(jointSecondaryAxisWorldSpace);
foreach (Transform c in children) c.parent = m.joint.transform;
}
}
}
private static Vector3 DirectionIntToVector3(int dir) {
if (dir == 0) return Vector3.right;
if (dir == 1) return Vector3.up;
return Vector3.forward;
}
private static int DirectionVector3ToInt(Vector3 dir) {
float dotX = Vector3.Dot(dir, Vector3.right);
float dotY = Vector3.Dot(dir, Vector3.up);
float dotZ = Vector3.Dot(dir, Vector3.forward);
float absDotX = Mathf.Abs(dotX);
float absDotY = Mathf.Abs(dotY);
float absDotZ = Mathf.Abs(dotZ);
int rotatedDirection = 0;
if (absDotY > absDotX && absDotY > absDotZ) rotatedDirection = 1;
if (absDotZ > absDotX && absDotZ > absDotY) rotatedDirection = 2;
return rotatedDirection;
}
}
}