implementation of drecon in unity 2022 lts forked from: https://github.com/joanllobera/marathon-envs
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.

351 lines
8.1 KiB

9 months ago
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RagdollControllerArtanim : MonoBehaviour
//this class does exactly the symetrical of MocapControllerArtanim: it maps animations from a ragdoll to a rigged character
{
[SerializeField]
ArticulationBody _articulationBodyRoot;
//to generate an environment automatically from a rigged character and an animation (see folder ROM-extraction)
public ArticulationBody ArticulationBodyRoot { set => _articulationBodyRoot = value;
get => _articulationBodyRoot; }
private List<ArticulationBody> _articulationbodies = null;
private List<Transform> _targetPoseTransforms = null;
private List<MappingOffset> _offsetsRB2targetPoseTransforms = null;
private List<MappingOffset> _offsetsSource2RB = null;
[Space(20)]
//not used in
[SerializeField]
float _debugDistance= 0.0f;
[SerializeField]
bool _isGeneratedProcedurally = false;
public bool IsGeneratedProcedurally { set => _isGeneratedProcedurally = value; }
[SerializeField]
bool _debugWithRigidBody = false;
[SerializeField]
Rigidbody _rigidbodyRoot;
private List<Rigidbody> _rigidbodies = null;
// Start is called before the first frame update
public void Start()
{
}
//this one is for the case where everything is generated procedurally
void SetOffsetRB2targetPoseInProceduralWorld() {
if(_targetPoseTransforms == null)
_targetPoseTransforms = GetComponentsInChildren<Transform>().ToList();
if(_offsetsRB2targetPoseTransforms == null)
_offsetsRB2targetPoseTransforms = new List<MappingOffset>();
if(_articulationbodies == null)
_articulationbodies = _articulationBodyRoot.GetComponentsInChildren<ArticulationBody>().ToList();
foreach (ArticulationBody ab in _articulationbodies) {
//ArticulationBody ab = _articulationbodies.First(x => x.name == abname);
string[] temp = ab.name.Split(':');
//if it has another ":" in the name, it crashes miserably
//string tname = temp[1];
//instead, we do:
string tname = ab.name.TrimStart(temp[0].ToArray<char>());
tname = tname.TrimStart(':');
//Debug.Log("the full name is: " + ab.name + " and the trimmed name is: " + tname);
//if structure is "articulation:" + t.name, it comes from a joint:
if (temp[0].Equals("articulation")) {
Transform t = _targetPoseTransforms.First(x => x.name == tname);
//TODO: check these days if those values are different from 0, sometimes
Quaternion qoffset = ab.transform.rotation * Quaternion.Inverse(t.rotation);
MappingOffset r = new MappingOffset(t, ab, Quaternion.Inverse(qoffset));
if (ab.isRoot)
{
r.SetAsRoot(true, _debugDistance);
}
_offsetsRB2targetPoseTransforms.Add(r);
}
}
}
MappingOffset SetOffsetRB2targetPose(string rbname, string tname)
{
//here we set up:
// a. the transform of the rigged character output
// b. the rigidbody of the physical character
// c. the offset calculated between the rigged character INPUT, and the rigidbody
if (_targetPoseTransforms == null)
{
_targetPoseTransforms = GetComponentsInChildren<Transform>().ToList();
// Debug.Log("the number of transforms intarget pose is: " + _targetPoseTransforms.Count);
}
if (_offsetsRB2targetPoseTransforms == null)
{
_offsetsRB2targetPoseTransforms = new List<MappingOffset>();
}
if (_articulationbodies == null)
{
if (_debugWithRigidBody) {
_rigidbodies = _rigidbodyRoot.GetComponentsInChildren<Rigidbody>().ToList();
}
else {
_articulationbodies = _articulationBodyRoot.GetComponentsInChildren<ArticulationBody>().ToList();
}
}
Transform rb;
if (_debugWithRigidBody)
{
rb = _rigidbodies.First(x => x.name == rbname).transform;
}else
{
rb = null;
try
{
rb = _articulationbodies.First(x => x.name == rbname).transform;
if (rb == null)
{
Debug.LogError("no rigidbody with name " + rbname);
}
}
catch {
Debug.LogError("problem with finding rigidbody with a name like: " + rbname);
}
}
Transform t = null;
try
{
t = _targetPoseTransforms.First(x => x.name == tname);
}
catch
{
Debug.LogError("no bone transform with name in target pose" + tname);
}
Transform tref = null;
try
{
tref = _targetPoseTransforms.First(x => x.name == tname);
}
catch
{
Debug.LogError("no bone transform with name in input pose " + tname);
}
//from refPose to Physical body:
//q_{physical_body} = q_{offset} * q_{refPose}
//q_{offset} = q_{physical_body} * Quaternion.Inverse(q_{refPose})
//Quaternion qoffset = rb.transform.localRotation * Quaternion.Inverse(tref.localRotation);
Quaternion qoffset = rb.transform.rotation * Quaternion.Inverse(tref.rotation);
//from physical body to targetPose:
//q_{target_pose} = q_{offset2} * q_{physical_body}
//q_{offset2} = Quaternion.Inverse(q_{offset})
MappingOffset r;
if (_debugWithRigidBody)
{
Rigidbody myrb = rb.GetComponent<Rigidbody>();
r = new MappingOffset(t, myrb, Quaternion.Inverse(qoffset));
r.SetAsRagdollcontrollerDebug(_debugWithRigidBody);
}
else
{
ArticulationBody myrb = rb.GetComponent<ArticulationBody>();
r = new MappingOffset(t, myrb, Quaternion.Inverse(qoffset));
}
_offsetsRB2targetPoseTransforms.Add(r);
return r;
}
void MimicPhysicalChar()
{
try
{
foreach (MappingOffset o in _offsetsRB2targetPoseTransforms)
{
o.UpdateRotation();
}
}
catch
{
Debug.Log("not calibrated yet...");
}
}
private void FixedUpdate()
{
MimicAnimationArtanim();
}
void MimicAnimationArtanim()
{
if (_offsetsRB2targetPoseTransforms == null)
{
if (_isGeneratedProcedurally)
{
SetOffsetRB2targetPoseInProceduralWorld();
}
else {
MappingOffset o = SetOffsetRB2targetPose("articulation:Hips", "mixamorig:Hips");
o.SetAsRoot(true, _debugDistance);
SetOffsetRB2targetPose("articulation:Spine", "mixamorig:Spine");
SetOffsetRB2targetPose("articulation:Spine1", "mixamorig:Spine1");
SetOffsetRB2targetPose("articulation:Spine2", "mixamorig:Spine2");
SetOffsetRB2targetPose("articulation:Neck", "mixamorig:Neck");
SetOffsetRB2targetPose("head", "mixamorig:Head");
SetOffsetRB2targetPose("articulation:LeftShoulder", "mixamorig:LeftShoulder");
SetOffsetRB2targetPose("articulation:LeftArm", "mixamorig:LeftArm");
SetOffsetRB2targetPose("articulation:LeftForeArm", "mixamorig:LeftForeArm");
// SetOffsetRB2targetPose("left_hand", "mixamorig:LeftHand");
// hands do not have rigidbodies
SetOffsetRB2targetPose("articulation:RightShoulder", "mixamorig:RightShoulder");
SetOffsetRB2targetPose("articulation:RightArm", "mixamorig:RightArm");
SetOffsetRB2targetPose("articulation:RightForeArm", "mixamorig:RightForeArm");
// SetOffsetRB2targetPose("right_hand", "mixamorig:RightHand");
SetOffsetRB2targetPose("articulation:LeftUpLeg", "mixamorig:LeftUpLeg");
// SetOffsetRB2targetPose("left_shin", "mixamorig:LeftLeg");
SetOffsetRB2targetPose("articulation:LeftLeg", "mixamorig:LeftLeg");
SetOffsetRB2targetPose("articulation:LeftFoot", "mixamorig:LeftFoot");
SetOffsetRB2targetPose("articulation:LeftToeBase", "mixamorig:LeftToeBase");
// SetOffsetRB2targetPose("right_left_foot", "mixamorig:LeftToeBase");
SetOffsetRB2targetPose("articulation:RightUpLeg", "mixamorig:RightUpLeg");
//SetOffsetRB2targetPose("right_shin", "mixamorig:RightLeg");
SetOffsetRB2targetPose("articulation:RightLeg", "mixamorig:RightLeg");
SetOffsetRB2targetPose("articulation:RightFoot", "mixamorig:RightFoot");
SetOffsetRB2targetPose("articulation:RightToeBase", "mixamorig:RightToeBase");
// SetOffsetRB2targetPose("left_right_foot", "mixamorig:RightToeBase");
}
}
else
{
MimicPhysicalChar();
}
}
}