Forum Discussion
Anonymous
3 years agoMeta Avatars: how to feed custom input?
Hi, I'm prototyping with the new Meta Avatars system and am using the SampleAvatarEntity script to instantiate fake avatars. I'd like to replay head pose, controller states, and/or hand states (p...
Evans_Taylor_Digital
3 years agoProtege
Thanks, yeah I figured as much. I was able to get this working in the end. For my use case I just wanted to use a custom VR rig (not the OVRCamera Rig) and to be able to use a VR emulator.. so essentially what I wanted was to pass in a transform as a reference for the head, left hand and right hand - and have the body tracking follow these transforms.
Here's what I ended up with:
using Oculus.Avatar2;
using UnityEngine;
using Touch = OVRInput.Touch;
public class CustomAvatarInputManager : OvrAvatarInputManager
{
[SerializeField] private Transform _tackingSpace;
[SerializeField] private Transform _headTarget;
[SerializeField] private Transform _leftHandTarget;
[SerializeField] private Transform _rightHandTarget;
private class CustomInputTrackingDelegate : OvrAvatarInputTrackingDelegate
{
private Transform _headTarget;
private Transform _leftHandTarget;
private Transform _rightHandTarget;
private Transform _trackingSpace;
public CustomInputTrackingDelegate(Transform headTarget, Transform leftHandTarget, Transform rightHandTarget, Transform trackingSpace)
{
_headTarget = headTarget;
_leftHandTarget = leftHandTarget;
_rightHandTarget = rightHandTarget;
_trackingSpace = trackingSpace;
}
public override bool GetRawInputTrackingState(out OvrAvatarInputTrackingState inputTrackingState)
{
inputTrackingState = new OvrAvatarInputTrackingState();
inputTrackingState.headsetActive = true;
inputTrackingState.leftControllerActive = true;
inputTrackingState.rightControllerActive = true;
inputTrackingState.leftControllerVisible = false;
inputTrackingState.rightControllerVisible = false;
Pose headPose = GetTrackingSpacePose(_headTarget.position, _headTarget.rotation);
Pose leftHandPose = GetTrackingSpacePose(_leftHandTarget.position, _leftHandTarget.rotation);
Pose rightHandPose = GetTrackingSpacePose(_rightHandTarget.position, _rightHandTarget.rotation);
inputTrackingState.headset.position = headPose.position;
inputTrackingState.headset.orientation = headPose.rotation;
inputTrackingState.headset.scale = Vector3.one;
inputTrackingState.leftController.position = leftHandPose.position;
inputTrackingState.rightController.position = rightHandPose.position;
inputTrackingState.leftController.orientation = leftHandPose.rotation;
inputTrackingState.rightController.orientation = rightHandPose.rotation;
inputTrackingState.leftController.scale = Vector3.one;
inputTrackingState.rightController.scale = Vector3.one;
return true;
}
private Pose GetTrackingSpacePose(Vector3 worldPosition, Quaternion worldRotation)
{
Vector3 position = _trackingSpace.InverseTransformPoint(worldPosition);
Quaternion rotation = Quaternion.Inverse(_trackingSpace.rotation) * worldRotation;
return new Pose(position, rotation);
}
}
private class CustomInputControlDelegate : OvrAvatarInputControlDelegate
{
public override bool GetInputControlState(out OvrAvatarInputControlState inputControlState)
{
inputControlState = new OvrAvatarInputControlState();
inputControlState.type = GetControllerType();
var input = BNG.InputBridge.Instance;
//Button Press
if (input.AButton)
inputControlState.leftControllerState.buttonMask |= CAPI.ovrAvatar2Button.One;
if (input.BButton)
inputControlState.leftControllerState.buttonMask |= CAPI.ovrAvatar2Button.Two;
if (input.XButton)
inputControlState.rightControllerState.buttonMask |= CAPI.ovrAvatar2Button.One;
if (input.YButton)
inputControlState.rightControllerState.buttonMask |= CAPI.ovrAvatar2Button.Two;
if (input.LeftThumbstick)
inputControlState.leftControllerState.buttonMask |= CAPI.ovrAvatar2Button.Joystick;
if (input.RightThumbstick)
inputControlState.rightControllerState.buttonMask |= CAPI.ovrAvatar2Button.Joystick;
// Left Controller Button Touch
if (OVRInput.Get(Touch.One, OVRInput.Controller.LTouch))
{
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.One;
}
if (OVRInput.Get(Touch.Two, OVRInput.Controller.LTouch))
{
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.Two;
}
if (OVRInput.Get(Touch.PrimaryThumbstick, OVRInput.Controller.LTouch))
{
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.Joystick;
}
if (OVRInput.Get(Touch.PrimaryThumbRest, OVRInput.Controller.LTouch))
{
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.ThumbRest;
}
// Right Controller Button Touch
if (OVRInput.Get(Touch.One, OVRInput.Controller.RTouch))
{
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.One;
}
if (OVRInput.Get(Touch.Two, OVRInput.Controller.RTouch))
{
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.Two;
}
if (OVRInput.Get(Touch.PrimaryThumbstick, OVRInput.Controller.RTouch))
{
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.Joystick;
}
if (OVRInput.Get(Touch.PrimaryThumbRest, OVRInput.Controller.RTouch))
{
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.ThumbRest;
}
// Left Trigger
inputControlState.leftControllerState.indexTrigger = input.LeftTrigger;
if (input.LeftTriggerNear)
{
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.Index;
}
else if (input.LeftTrigger <= 0f)
{
// TODO: Not sure if this is the correct way to do this
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.Pointing;
}
// Right Trigger
inputControlState.rightControllerState.indexTrigger = input.RightTrigger;
if (input.RightTriggerNear)
{
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.Index;
}
else if (input.RightTrigger <= 0f)
{
// TODO: Not sure if this is the correct way to do this
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.Pointing;
}
//Left Grip
inputControlState.leftControllerState.handTrigger = input.LeftGrip;
if(!input.LeftThumbNear)
inputControlState.leftControllerState.touchMask |= CAPI.ovrAvatar2Touch.ThumbUp;
//Right Grip
inputControlState.rightControllerState.handTrigger = input.RightGrip;
if(!input.RightThumbNear)
inputControlState.rightControllerState.touchMask |= CAPI.ovrAvatar2Touch.ThumbUp;
return true;
}
}
private void Start()
{
if (BodyTracking != null)
{
// BodyTracking.InputTrackingDelegate = new CustomInputTrackingDelegate(() => _currentInputTracking);
BodyTracking.InputTrackingDelegate = new CustomInputTrackingDelegate(_headTarget, _leftHandTarget, _rightHandTarget, _tackingSpace);
BodyTracking.InputControlDelegate = new CustomInputControlDelegate();
}
}
protected override void OnDestroyCalled()
{
base.OnDestroyCalled();
}
}
There's some stuff in there specific to the BNG Framework - which is only useful if you're using that asset. But you could just replace the Input Control Delegate with your own version, or with the sample one and everything else will work fine
gem_ini
3 years agoHonored Guest
Hey sorry to necro this -- but I am doing something super simliar to you (BNG and Meta Avatars). I was wondering if you'd have any more pointers/scripts you'd be willing to release to help out on that? The above is a super helpful starting point, but when using the XR Advanced rig, the meta avatars arms still don't follow the emulator
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device
Other Meta Support
Related Content
- 7 months ago
- 2 months ago
- 15 days ago
- 9 months ago