Skip to content
This repository has been archived by the owner on Jan 11, 2025. It is now read-only.
jorgejgnz edited this page Sep 9, 2020 · 13 revisions

How to set up a simple scene using HPTK?

You can build a scene with an avatar and a dummy following these steps:

  1. Follow Getting Started section. Check that Project Settings are configured according to the following guide. [https://developer.oculus.com/documentation/unity/unity-conf-settings/]

a. Check that ProjectSettings/Physics are configured as specified in Getting Started section. a. It is recommended to use ILCCP as scripting backend, ARM64 as target architecture and ASTC for texture compression (Build Settings).

  1. Add OVRCameraRig prefab to the scene. In its OVRManager component, set Hand Tracking Support to ‘Controllers and Hands’.
  2. Add OVRHandPrefabs. Disable all their components excepting OVRHand and OVRSkeleton. Set Hand Type and Skeleton Type to ‘Hand Left’ and ‘Hand Right’ for left and right OVRHandPrefabs respectively.
  3. Add HPTKCore prefab to Scene.
  4. Set each OVRHand into the variables HandData and BoneData in both InputDataProvider included in SpAvatar (SpAvatar>InputDataProviders>OVRSkeletonTracker.*).
  5. Set OVRCameraRig>TrackingSpace>CenterEyeAnchor into the variable TrackedCamera in HPTKCore>HPTKCoreModel.

Bult-in HPTK modules

HPTK Class Diagram

Core

The model of this module is accessible from any HPTKElement and contains both the models for every avatars in the scene and the references to the objects that should only be instantiated once in the scene (singletons). It includes references to configuration assets.

Avatar

This module contains and updates the information related to the body (e.g. position of the head, feet or shoulders) including the list of ProxyHands of the avatar (for humanoids, two).

ProxyHand

This module contains and updates the information related to each hand, both in its master and slave representation (or any other extra representation that may be required). Each one of these "representations" is an instance of the HandModel class, from which we can access not only the information and references of each finger and each bone but also the updated values of finger-level and hand-level gestures (e.g. pinch for each finger, flex lerp for each finger, fist lerp or grasp lerp). ProxyHandModel includes the list of HPTKHandlers of other modules associated with this ProxyHand (registered by themselves on Start).

Input

This module takes the values provided by an InputDataProvider and updates the transformations of each bone of the master representation of a ProxyHand. An InputDataProvider is responsible for providing the list of AbstractTransforms for each bone in the correct format regardless of the platform (input abstraction). At the moment, only 2 are included:

  • OVRSkeletonTracker: It takes the transforms from OVRSkeleton.Bones (Oculus Quest).
  • RelativeskeletonTracker: Mimics the transforms of another ProxyHand according to a reference point. Used in the mirrored character.

HandPhysics

This module updates the ConfigurableJoints of the slave representation of a ProxyHand and allows the slave to reach its master. You can change the physical configuration of the hand by changing the reference to the HandPhysicsConfiguration asset in HandPhysicsModel. If you leave it empty, HPTK will use the HandPhysicsConfiguration asset referenced in CoreModel. HandPhysicsConfiguration allows you to fine tune many parameters to make hands stronger, weaker or even make the hand to follow fingers but not wrist.

Interactor

This module contains and updates the list and state of interactions (hover, touch or grab) that the slave representation of a ProxyHand is having with other Interactable objects. InteractorHandler (instantiated as InteractorController) invokes useful UnityEvents that you can use (e.g. OnHover, OnFirstGrab or OnLastUntouch).

Interactable

This module contains the number of interactions that are happening on it as well as the list of other modules that are associated to the object instead of a ProxyHand. The interactable doesn’t know what interactors it is interacting with. Its model is updated thanks to the events invoked by the different Interactors that act on it. InteractableHandler (instantiated as InteractableController) also has useful UnityEvents that you can use (e.g. OnHover, OnFirstGrab, or OnLastUntouch).

How to build new HTPK modules

The file Scripts/ModuleSkeleton.cs contains a skeleton code that you can use as a guide. Each module involves 4 main classes: Model, Handler, ViewModel (nested class in Handler) and Controller.

The following image depicts the code architecture of a HPTK module:

HPTK Module Architecture

Model

Include those variables that are relevant to Your module. Make sure that these variables do not already exist in any HPTKModel. If the information domain for Your module involves an Avatar, ProxyHand or Interactable object, include a reference to AvatarModel, ProxyHandModel or InteractableModel respectively. Let’s assume that we want to build a Your module. Then we will need to create YourModel, YourHandler, YourHandler.YourViewModel and YourController. If you need to extend a HPTKModel and you can't include the new information in YourModel, create a class that extends the HPTKModel that YourModel is referring to and include the variables you need there, this way it will be easier to maintain and combine with other projects.

Controller

If YourModel includes a reference to an HPTKModel with a relatedHandler field and you want other modules to be able to access YourHandler, you must register YourHandler in the list of relatedHandlers of the HPTKModel that is referred in YourModel. The Awake function in YourController initializes the ViewModel by passing YourModel to the ViewModel builder. Only the Controllers can access their Models directly. Thus, by sharing Handlers instead of Controllers, the ViewModel can only be accessed from outside the module.

Handler

Handler has no functions, only events and ViewModel. The information that can be accessed from a Handler should be, whenever possible, read-only.

Example

If you want to generate sound feedback according to the friction of a slave hand, you can calculate and store a friction value for the whole hand to be read by the sound engine. To calculate the friction value, you will need to access the Rigidbodies of one or more bones in the slave hand so YourModel should contain a reference to a ProxyHandModel which contains the references to the Rigidbodies of that slave hand. In the Start function of YourController you must register YourHandler in the ProxyHandModel.relatedHandlers list so that YourHandler is accessible to other modules from ProxyHandModel. Once YourController has calculated the friction value, it stores the value in YourModel. If you want other modules to be able to read this value, make it accessible via YourViewModel.

Clone this wiki locally