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...
Anonymous
3 years agoOh yes and one more thing: all these references to an "avatar anchor" are probably confusing. The "anchor" is basically a point in space that I consider to be the origin for the avatar and I record things relative to this anchor point so that on the remote side, I can render the avatars relative to a movable anchor point. You won't need this and I think the code should be clear enough to modify to your use case.
- Evans_Taylor_Digital3 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_ini3 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
- j7-Hitstream3 years agoProtege
Thanks for the post - this sounds like it should be something part of the AVATAR2 kit -
Were do you use this script?
- I've got a basic XR Rig - and I've added the left/right/head points and added the script to the AvatarSDKManagerHorizon prefab, also disabled the SampleInputManager, but the avatar still stays in the T-pose, with no movements.
Any ideas? - Viconthebeach2 years agoProtege
Great, thank you for your code sample, I was very close to that but I missed the GetTrackingSpacePose and nothing about it found in the guides.
However, the pose is only applied when not using another avatar as 1st person with real hands tracking. Do you know why the OVRCameraRig's tracking seems to override the custom hand pose tracking?
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