dwelling act 4 (live motion cap w/ kinect azure)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
17 KiB

1 year ago
using System.Collections.Generic;
using UnityEngine;
public class Avatar : MonoBehaviour
{
public bool showSkeleton = true;
public Material skeletonMaterial;
public float skeletonX;
public float skeletonY;
public float skeletonZ;
public float skeletonScale = 1;
private GameObject skeleton;
private List<Skeleton> skeletons = new List<Skeleton>();
public GameObject nose;
public JointPoint[] jointPoints;
private Animator animator;
private Vector3 initPosition;
private float centerTall = 224 * 0.75f;
private float tall = 224 * 0.75f;
private float prevTall = 224 * 0.75f;
private float zScale = 1;
private void Awake()
{
skeleton = new GameObject("Skeleton");
animator = this.GetComponent<Animator>();
Initialize();
}
private void Update()
{
PoseUpdate();
}
public void Initialize()
{
jointPoints = new JointPoint[PositionIndex.Count.Int()];
for( int i = 0; i < PositionIndex.Count.Int(); i++ )
{
jointPoints[i] = new JointPoint();
}
// Right arm.
jointPoints[PositionIndex.RightShoulderBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
jointPoints[PositionIndex.RightForearmBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
jointPoints[PositionIndex.RightHand.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightHand);
jointPoints[PositionIndex.RightThumb2.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightThumbIntermediate);
jointPoints[PositionIndex.RightMid1.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightMiddleProximal);
// Left arm.
jointPoints[PositionIndex.LeftShoulderBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
jointPoints[PositionIndex.LeftForearmBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
jointPoints[PositionIndex.LeftHand.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftHand);
jointPoints[PositionIndex.LeftThumb2.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftThumbIntermediate);
jointPoints[PositionIndex.LeftMid1.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftMiddleProximal);
// Face.
jointPoints[PositionIndex.LeftEar.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Head);
jointPoints[PositionIndex.LeftEye.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftEye);
jointPoints[PositionIndex.RightEar.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Head);
jointPoints[PositionIndex.RightEye.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightEye);
jointPoints[PositionIndex.Nose.Int()].transform = nose.transform;
// Right leg.
jointPoints[PositionIndex.RightThighBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightUpperLeg);
jointPoints[PositionIndex.RightShin.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg);
jointPoints[PositionIndex.RightFoot.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightFoot);
jointPoints[PositionIndex.RightToe.Int()].transform = animator.GetBoneTransform(HumanBodyBones.RightToes);
// Left leg.
jointPoints[PositionIndex.LeftThighBend.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
jointPoints[PositionIndex.LeftShin.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
jointPoints[PositionIndex.LeftFoot.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
jointPoints[PositionIndex.LeftToe.Int()].transform = animator.GetBoneTransform(HumanBodyBones.LeftToes);
// Etc.
jointPoints[PositionIndex.AbdomenUpper.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Spine);
jointPoints[PositionIndex.Hip.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Hips);
jointPoints[PositionIndex.Head.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Head);
jointPoints[PositionIndex.Neck.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Neck);
jointPoints[PositionIndex.Spine.Int()].transform = animator.GetBoneTransform(HumanBodyBones.Spine);
// Child settings.
// Right arm.
jointPoints[PositionIndex.RightShoulderBend.Int()].child = jointPoints[PositionIndex.RightForearmBend.Int()];
jointPoints[PositionIndex.RightForearmBend.Int()].child = jointPoints[PositionIndex.RightHand.Int()];
jointPoints[PositionIndex.RightForearmBend.Int()].parent = jointPoints[PositionIndex.RightShoulderBend.Int()];
// Left arm.
jointPoints[PositionIndex.LeftShoulderBend.Int()].child = jointPoints[PositionIndex.LeftForearmBend.Int()];
jointPoints[PositionIndex.LeftForearmBend.Int()].child = jointPoints[PositionIndex.LeftHand.Int()];
jointPoints[PositionIndex.LeftForearmBend.Int()].parent = jointPoints[PositionIndex.LeftShoulderBend.Int()];
// Fase.
// Right leg.
jointPoints[PositionIndex.RightThighBend.Int()].child = jointPoints[PositionIndex.RightShin.Int()];
jointPoints[PositionIndex.RightShin.Int()].child = jointPoints[PositionIndex.RightFoot.Int()];
jointPoints[PositionIndex.RightFoot.Int()].child = jointPoints[PositionIndex.RightToe.Int()];
jointPoints[PositionIndex.RightFoot.Int()].parent = jointPoints[PositionIndex.RightShin.Int()];
// Left leg.
jointPoints[PositionIndex.LeftThighBend.Int()].child = jointPoints[PositionIndex.LeftShin.Int()];
jointPoints[PositionIndex.LeftShin.Int()].child = jointPoints[PositionIndex.LeftFoot.Int()];
jointPoints[PositionIndex.LeftFoot.Int()].child = jointPoints[PositionIndex.LeftToe.Int()];
jointPoints[PositionIndex.LeftFoot.Int()].parent = jointPoints[PositionIndex.LeftShin.Int()];
// Etc.
jointPoints[PositionIndex.Spine.Int()].child = jointPoints[PositionIndex.Neck.Int()];
jointPoints[PositionIndex.Neck.Int()].child = jointPoints[PositionIndex.Head.Int()];
//jointPoints[PositionIndex.Head.Int()].child = jointPoints[PositionIndex.Nose.Int()];
if( showSkeleton )
{
// Line child settings.
// Right arm.
AddSkeleton(PositionIndex.RightShoulderBend, PositionIndex.RightForearmBend);
AddSkeleton(PositionIndex.RightForearmBend, PositionIndex.RightHand);
AddSkeleton(PositionIndex.RightHand, PositionIndex.RightThumb2);
AddSkeleton(PositionIndex.RightHand, PositionIndex.RightMid1);
// Left arm.
AddSkeleton(PositionIndex.LeftShoulderBend, PositionIndex.LeftForearmBend);
AddSkeleton(PositionIndex.LeftForearmBend, PositionIndex.LeftHand);
AddSkeleton(PositionIndex.LeftHand, PositionIndex.LeftThumb2);
AddSkeleton(PositionIndex.LeftHand, PositionIndex.LeftMid1);
// Fase.
AddSkeleton(PositionIndex.LeftEar, PositionIndex.Nose);
AddSkeleton(PositionIndex.RightEar, PositionIndex.Nose);
// Right leg.
AddSkeleton(PositionIndex.RightThighBend, PositionIndex.RightShin);
AddSkeleton(PositionIndex.RightShin, PositionIndex.RightFoot);
AddSkeleton(PositionIndex.RightFoot, PositionIndex.RightToe);
// Left leg.
AddSkeleton(PositionIndex.LeftThighBend, PositionIndex.LeftShin);
AddSkeleton(PositionIndex.LeftShin, PositionIndex.LeftFoot);
AddSkeleton(PositionIndex.LeftFoot, PositionIndex.LeftToe);
// Etc.
AddSkeleton(PositionIndex.Spine, PositionIndex.Neck);
AddSkeleton(PositionIndex.Neck, PositionIndex.Head);
AddSkeleton(PositionIndex.Head, PositionIndex.Nose);
AddSkeleton(PositionIndex.Neck, PositionIndex.RightShoulderBend);
AddSkeleton(PositionIndex.Neck, PositionIndex.LeftShoulderBend);
AddSkeleton(PositionIndex.RightThighBend, PositionIndex.RightShoulderBend);
AddSkeleton(PositionIndex.LeftThighBend, PositionIndex.LeftShoulderBend);
AddSkeleton(PositionIndex.RightShoulderBend, PositionIndex.AbdomenUpper);
AddSkeleton(PositionIndex.LeftShoulderBend, PositionIndex.AbdomenUpper);
AddSkeleton(PositionIndex.RightThighBend, PositionIndex.AbdomenUpper);
AddSkeleton(PositionIndex.LeftThighBend, PositionIndex.AbdomenUpper);
AddSkeleton(PositionIndex.LeftThighBend, PositionIndex.RightThighBend);
}
// Set inverse.
Vector3 forward = TriangleNormal(jointPoints[PositionIndex.Hip.Int()].transform.position, jointPoints[PositionIndex.LeftThighBend.Int()].transform.position, jointPoints[PositionIndex.RightThighBend.Int()].transform.position);
foreach( JointPoint jointPoint in jointPoints )
{
if( jointPoint.transform != null )
{
jointPoint.initRotation = jointPoint.transform.rotation;
}
if( jointPoint.child != null )
{
jointPoint.inverse = GetInverse(jointPoint, jointPoint.child, forward);
jointPoint.inverseRotation = jointPoint.inverse * jointPoint.initRotation;
}
}
JointPoint hip = jointPoints[PositionIndex.Hip.Int()];
initPosition = jointPoints[PositionIndex.Hip.Int()].transform.position;
hip.inverse = Quaternion.Inverse(Quaternion.LookRotation(forward));
hip.inverseRotation = hip.inverse * hip.initRotation;
// Head rotation.
JointPoint head = jointPoints[PositionIndex.Head.Int()];
head.initRotation = jointPoints[PositionIndex.Head.Int()].transform.rotation;
Vector3 gaze = jointPoints[PositionIndex.Nose.Int()].transform.position - jointPoints[PositionIndex.Head.Int()].transform.position;
head.inverse = Quaternion.Inverse(Quaternion.LookRotation(gaze));
head.inverseRotation = head.inverse * head.initRotation;
JointPoint lHand = jointPoints[PositionIndex.LeftHand.Int()];
Vector3 lf = TriangleNormal(lHand.pos3D, jointPoints[PositionIndex.LeftMid1.Int()].pos3D, jointPoints[PositionIndex.LeftThumb2.Int()].pos3D);
lHand.initRotation = lHand.transform.rotation;
lHand.inverse = Quaternion.Inverse(Quaternion.LookRotation(jointPoints[PositionIndex.LeftThumb2.Int()].transform.position - jointPoints[PositionIndex.LeftMid1.Int()].transform.position, lf));
lHand.inverseRotation = lHand.inverse * lHand.initRotation;
JointPoint rHand = jointPoints[PositionIndex.RightHand.Int()];
Vector3 rf = TriangleNormal(rHand.pos3D, jointPoints[PositionIndex.RightThumb2.Int()].pos3D, jointPoints[PositionIndex.RightMid1.Int()].pos3D);
rHand.initRotation = jointPoints[PositionIndex.RightHand.Int()].transform.rotation;
rHand.inverse = Quaternion.Inverse(Quaternion.LookRotation(jointPoints[PositionIndex.RightThumb2.Int()].transform.position - jointPoints[PositionIndex.RightMid1.Int()].transform.position, rf));
rHand.inverseRotation = rHand.inverse * rHand.initRotation;
jointPoints[PositionIndex.Hip.Int()].score3D = 1f;
jointPoints[PositionIndex.Neck.Int()].score3D = 1f;
jointPoints[PositionIndex.Nose.Int()].score3D = 1f;
jointPoints[PositionIndex.Head.Int()].score3D = 1f;
jointPoints[PositionIndex.Spine.Int()].score3D = 1f;
}
public void PoseUpdate()
{
// Calculate movement range of z-coordinate from height.
float t1 = Vector3.Distance(jointPoints[PositionIndex.Head.Int()].pos3D, jointPoints[PositionIndex.Neck.Int()].pos3D);
float t2 = Vector3.Distance(jointPoints[PositionIndex.Neck.Int()].pos3D, jointPoints[PositionIndex.Spine.Int()].pos3D);
Vector3 pm = (jointPoints[PositionIndex.RightThighBend.Int()].pos3D + jointPoints[PositionIndex.LeftThighBend.Int()].pos3D) / 2f;
float t3 = Vector3.Distance(jointPoints[PositionIndex.Spine.Int()].pos3D, pm);
float t4r = Vector3.Distance(jointPoints[PositionIndex.RightThighBend.Int()].pos3D, jointPoints[PositionIndex.RightShin.Int()].pos3D);
float t4l = Vector3.Distance(jointPoints[PositionIndex.LeftThighBend.Int()].pos3D, jointPoints[PositionIndex.LeftShin.Int()].pos3D);
float t4 = (t4r + t4l) / 2f;
float t5r = Vector3.Distance(jointPoints[PositionIndex.RightShin.Int()].pos3D, jointPoints[PositionIndex.RightFoot.Int()].pos3D);
float t5l = Vector3.Distance(jointPoints[PositionIndex.LeftShin.Int()].pos3D, jointPoints[PositionIndex.LeftFoot.Int()].pos3D);
float t5 = (t5r + t5l) / 2f;
float t = t1 + t2 + t3 + t4 + t5;
// Low pass filter in z direction.
tall = t * 0.7f + prevTall * 0.3f;
prevTall = tall;
if( tall == 0 )
{
tall = centerTall;
}
float dz = (centerTall - tall) / centerTall * zScale;
// Movement and rotatation of center.
Vector3 forward = TriangleNormal(jointPoints[PositionIndex.Hip.Int()].pos3D, jointPoints[PositionIndex.LeftThighBend.Int()].pos3D, jointPoints[PositionIndex.RightThighBend.Int()].pos3D);
jointPoints[PositionIndex.Hip.Int()].transform.position = jointPoints[PositionIndex.Hip.Int()].pos3D * 0.005f + new Vector3(initPosition.x, initPosition.y, initPosition.z + dz);
jointPoints[PositionIndex.Hip.Int()].transform.rotation = Quaternion.LookRotation(forward) * jointPoints[PositionIndex.Hip.Int()].inverseRotation;
// Rotate each of the bones.
foreach( JointPoint jointPoint in jointPoints )
{
if( jointPoint.parent != null )
{
Vector3 fv = jointPoint.parent.pos3D - jointPoint.pos3D;
jointPoint.transform.rotation = Quaternion.LookRotation(jointPoint.pos3D - jointPoint.child.pos3D, fv) * jointPoint.inverseRotation;
}
else if( jointPoint.child != null )
{
jointPoint.transform.rotation = Quaternion.LookRotation(jointPoint.pos3D - jointPoint.child.pos3D, forward) * jointPoint.inverseRotation;
}
}
// Head rotation.
Vector3 gaze = jointPoints[PositionIndex.Nose.Int()].pos3D - jointPoints[PositionIndex.Head.Int()].pos3D;
Vector3 f = TriangleNormal(jointPoints[PositionIndex.Nose.Int()].pos3D, jointPoints[PositionIndex.RightEar.Int()].pos3D, jointPoints[PositionIndex.LeftEar.Int()].pos3D);
JointPoint head = jointPoints[PositionIndex.Head.Int()];
head.transform.rotation = Quaternion.LookRotation(gaze, f) * head.inverseRotation;
// Wrist rotation (test).
JointPoint lHand = jointPoints[PositionIndex.LeftHand.Int()];
Vector3 lf = TriangleNormal(lHand.pos3D, jointPoints[PositionIndex.LeftMid1.Int()].pos3D, jointPoints[PositionIndex.LeftThumb2.Int()].pos3D);
lHand.transform.rotation = Quaternion.LookRotation(jointPoints[PositionIndex.LeftThumb2.Int()].pos3D - jointPoints[PositionIndex.LeftMid1.Int()].pos3D, lf) * lHand.inverseRotation;
JointPoint rHand = jointPoints[PositionIndex.RightHand.Int()];
Vector3 rf = TriangleNormal(rHand.pos3D, jointPoints[PositionIndex.RightThumb2.Int()].pos3D, jointPoints[PositionIndex.RightMid1.Int()].pos3D);
//rHand.transform.rotation = Quaternion.LookRotation(jointPoints[PositionIndex.RightThumb2.Int()].pos3D - jointPoints[PositionIndex.RightMid1.Int()].pos3D, rf) * rHand.inverseRotation;
rHand.transform.rotation = Quaternion.LookRotation(jointPoints[PositionIndex.RightThumb2.Int()].pos3D - jointPoints[PositionIndex.RightMid1.Int()].pos3D, rf) * rHand.inverseRotation;
foreach( Skeleton sk in skeletons )
{
JointPoint s = sk.start;
JointPoint e = sk.end;
sk.lineRenderer.SetPosition(0, new Vector3(s.pos3D.x * skeletonScale + skeletonX, s.pos3D.y * skeletonScale + skeletonY, s.pos3D.z * skeletonScale + skeletonZ));
sk.lineRenderer.SetPosition(1, new Vector3(e.pos3D.x * skeletonScale + skeletonX, e.pos3D.y * skeletonScale + skeletonY, e.pos3D.z * skeletonScale + skeletonZ));
}
}
private Vector3 TriangleNormal( Vector3 a, Vector3 b, Vector3 c )
{
Vector3 d1 = a - b;
Vector3 d2 = a - c;
Vector3 dd = Vector3.Cross(d1, d2);
dd.Normalize();
return dd;
}
private Quaternion GetInverse( JointPoint p1, JointPoint p2, Vector3 forward )
{
return Quaternion.Inverse(Quaternion.LookRotation(p1.transform.position - p2.transform.position, forward));
}
private void AddSkeleton( PositionIndex s, PositionIndex e )
{
Skeleton sk = new Skeleton()
{
gameObject = new GameObject("Line"),
start = jointPoints[s.Int()],
end = jointPoints[e.Int()],
};
sk.gameObject.transform.SetParent(skeleton.transform);
sk.lineRenderer = sk.gameObject.AddComponent<LineRenderer>();
sk.lineRenderer.startWidth = 0.04f;
sk.lineRenderer.endWidth = 0.01f;
// Define the number of vertices.
sk.lineRenderer.positionCount = 2;
sk.lineRenderer.material = skeletonMaterial;
skeletons.Add(sk);
}
}