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
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();
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|