Skip to content

Commit

Permalink
feat(proxyHandModule):Hand scaling support
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgejgnz committed Dec 19, 2020
1 parent caa2d90 commit 329b679
Show file tree
Hide file tree
Showing 22 changed files with 737 additions and 200 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# HPTK [![](https://img.shields.io/badge/unity-2019.4%20or%20later-green.svg)](https://unity3d.com/es/get-unity/download/archive) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jorgejgnz/HPTK/blob/master/LICENSE.md) [![version](https://img.shields.io/badge/version-0.2.0-blue)](https://github.com/jorgejgnz/HPTK/releases) [![](https://img.shields.io/twitter/follow/jorgejgnz.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=jorgejgnz)
# HPTK [![](https://img.shields.io/badge/unity-2019.4%20or%20later-green.svg)](https://unity3d.com/es/get-unity/download/archive) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jorgejgnz/HPTK/blob/master/LICENSE.md) [![version](https://img.shields.io/badge/version-0.4.0-blue)](https://github.com/jorgejgnz/HPTK/releases) [![](https://img.shields.io/twitter/follow/jorgejgnz.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=jorgejgnz)

Hand Physics Toolkit (HPTK) is a toolkit to build physical hand-driven interactions in a modular and scalable way. Hand physics and hover/touch/grab detection are modules included. This toolkit can be combined with [MRTK-Quest](https://github.com/provencher/MRTK-Quest) for UI interactions. Only Oculus Quest is supported at the moment.

Expand All @@ -16,7 +16,6 @@ Hand Physics Toolkit (HPTK) is a toolkit to build physical hand-driven interacti

# Supported versions
- Unity 2019.4.4f1 LTS, 2019.3.15f1
- [Oculus Integration 20.0](https://developer.oculus.com/downloads/package/unity-integration/)

# Supported target devices
- Oculus Quest - Android
Expand Down
65 changes: 63 additions & 2 deletions Runtime/Helpers/PhysHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,67 @@

namespace HPTK.Helpers
{
[Serializable]
public class CustomJointDrive
{
public static CustomJointDrive zero = new CustomJointDrive();

public float spring;
public float damper;
public float maxForce;

public static CustomJointDrive ScaledCopy(CustomJointDrive normalizedDrive, float scale)
{
CustomJointDrive drive = new CustomJointDrive();
drive.spring = normalizedDrive.spring; // * scale;
drive.damper = normalizedDrive.damper; // * scale;
drive.maxForce = normalizedDrive.maxForce * scale;

return drive;
}

public JointDrive toJointDrive()
{
JointDrive jDrive = new JointDrive();
jDrive.positionSpring = spring;
jDrive.positionDamper = damper;
jDrive.maximumForce = maxForce;

return jDrive;
}

public SoftJointLimitSpring toSoftJointLimitSpring()
{
SoftJointLimitSpring lSpring = new SoftJointLimitSpring();
lSpring.spring = spring;
lSpring.damper = damper;

return lSpring;
}

public CustomJointDrive()
{
spring = 0.0f;
damper = 0.0f;
maxForce = 0.0f;
}

public CustomJointDrive(float spring, float damper, float maxForce)
{
this.spring = spring;
this.damper = damper;
this.maxForce = maxForce;
}

public CustomJointDrive(CustomJointDrive drive)
{
this.spring = drive.spring;
this.damper = drive.damper;
this.maxForce = drive.maxForce;
}

}

public static class PhysHelpers
{
public static Vector3 GetDesiredWorldPos(Transform slave, Transform master, Space space)
Expand Down Expand Up @@ -129,7 +190,7 @@ public static bool ToggleLockJoints(SlaveBoneModel[] bones, bool toggleValue)
return toggleValue;
}

public static ConfigurableJoint CreateSnapJoint(Rigidbody body, Rigidbody connectedBody, Vector3 pointPosition, Quaternion pointRotation, Vector3 destinationPosition, Quaternion destinationRotation, bool matchRotation, bool enableCollisions)
public static ConfigurableJoint CreateSnapJoint(Rigidbody body, Rigidbody connectedBody, Vector3 pointPosition, Quaternion pointRotation, Vector3 destinationPosition, Quaternion destinationRotation, bool matchRotation, bool enableCollisions, float massScale)
{
// Initial configuration
ConfigurableJoint joint = body.gameObject.AddComponent<ConfigurableJoint>();
Expand All @@ -140,7 +201,7 @@ public static ConfigurableJoint CreateSnapJoint(Rigidbody body, Rigidbody connec
joint.anchor = joint.transform.InverseTransformPoint(pointPosition);
joint.connectedAnchor = joint.connectedBody.transform.InverseTransformPoint(destinationPosition);

joint.massScale = 1.6f;
joint.massScale = massScale;

joint.enableCollision = enableCollisions;

Expand Down
3 changes: 3 additions & 0 deletions Runtime/Input/InputDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ public class InputDataProvider : MonoBehaviour
[Range(0.0f, 1.0f)]
public float confidence = 0.0f;

[Range(0.5f, 2.0f)]
public float scale = 1.0f;

// Replaceable by inherited classes
public virtual void InitData()
{
Expand Down
2 changes: 2 additions & 0 deletions Runtime/Input/RelativeSkeletonTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public override void UpdateData()

confidence = 1.0f;

scale = referenceHand.extraScale;

UpdateFingers();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using HPTK.Helpers;
using UnityEngine;
using System;
using UnityEditor;

namespace HPTK.Settings
{
[Serializable]
public class CustomJointDrive
{
public static CustomJointDrive zero = new CustomJointDrive();

public float spring;
public float damper;
public float maxForce;

public JointDrive toJointDrive()
{
JointDrive jDrive = new JointDrive();
jDrive.positionSpring = spring;
jDrive.positionDamper = damper;
jDrive.maximumForce = maxForce;

return jDrive;
}

public SoftJointLimitSpring toSoftJointLimitSpring()
{
SoftJointLimitSpring lSpring = new SoftJointLimitSpring();
lSpring.spring = spring;
lSpring.damper = damper;

return lSpring;
}

public CustomJointDrive()
{
spring = 0.0f;
damper = 0.0f;
maxForce = 0.0f;
}

public CustomJointDrive(float spring, float damper, float maxForce)
{
this.spring = spring;
this.damper = damper;
this.maxForce = maxForce;
}

}

[Serializable]
public class SlaveBoneConfiguration
{
Expand Down Expand Up @@ -107,14 +65,29 @@ public SlaveBoneConfiguration(SlaveBoneConfiguration conf)
}
}

[CreateAssetMenu(menuName = "HPTK/HandPhysicsConfiguration Asset", order = 2)]
public class HandPhysicsConfiguration : ScriptableObject
[Serializable]
public class HandPhysicsConfiguration
{
public string alias;

public SlaveBoneConfiguration fingers;
public SlaveBoneConfiguration wrist;
public SlaveBoneConfiguration specials;

public HandPhysicsConfiguration(HandPhysicsConfiguration conf)
{
this.alias = conf.alias;
this.fingers = new SlaveBoneConfiguration(conf.fingers);
this.wrist = new SlaveBoneConfiguration(conf.wrist);
this.specials = new SlaveBoneConfiguration(conf.specials);
}
}

[CreateAssetMenu(menuName = "HPTK/HandPhysicsConfiguration Asset", order = 2)]
public class HandPhysicsConfigurationAsset : ScriptableObject
{
[Header("For normalized scale")]
public HandPhysicsConfiguration configuration;
}

}
56 changes: 52 additions & 4 deletions Runtime/Modules/HandPhysics/HandPhysicsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ private void Start()
slaveBones = AvatarHelpers.GetSlaveHandBones(model.proxyHand.slave);

// Set default configuration if needed
if (model.configuration == null)
model.configuration = BasicHelpers.FindScriptableObject<HandPhysicsConfiguration>(core.model.defaultConfAssets);
if (model.asset == null)
model.asset = BasicHelpers.FindScriptableObject<HandPhysicsConfigurationAsset>(core.model.defaultConfAssets);

// Make configuration editable
model.configuration = new HandPhysicsConfiguration(model.asset.configuration);

for (int i = 0; i < slaveBones.Length; i++)
{
Expand All @@ -48,8 +51,13 @@ private void Start()

if (slaveBones[i].jointRef)
{
// Get initial connected body local rotations
if (slaveBones[i].jointRef.connectedBody != null) slaveBones[i].initialConnectedBodyLocalRotation = slaveBones[i].jointRef.connectedBody.transform.localRotation;
// Get initial connected body local rotations and conn anchors
if (slaveBones[i].jointRef.connectedBody != null)
{
slaveBones[i].initialConnectedBodyLocalRotation = slaveBones[i].jointRef.connectedBody.transform.localRotation;
slaveBones[i].initialConnectedAnchor = slaveBones[i].jointRef.connectedAnchor;
slaveBones[i].jointRef.autoConfigureConnectedAnchor = false;
}
else slaveBones[i].initialConnectedBodyLocalRotation = slaveBones[i].jointRef.transform.rotation;

// Set initial joint configurations
Expand All @@ -60,6 +68,7 @@ private void Start()
else
PhysHelpers.SetSlaveBoneConfiguration(slaveBones[i].jointRef, model.configuration.fingers);

// Initial built-in velocity clamps
slaveBones[i].rigidbodyRef.maxDepenetrationVelocity = model.configuration.fingers.maxLinearVelocity;
slaveBones[i].rigidbodyRef.maxAngularVelocity = model.configuration.fingers.maxAngularVelocity;
}
Expand All @@ -72,6 +81,45 @@ private void Update()

if (model.proxyHand.error > core.model.configuration.maxErrorAllowed && !decoupled)
StartCoroutine(RecoverFromError());

for (int i = 0; i < slaveBones.Length; i++)
{
if (model.updateConfFromScale)
{
model.configuration.fingers.positionDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.fingers.positionDrive, model.proxyHand.slave.extraScale);
model.configuration.fingers.rotationDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.fingers.rotationDrive, model.proxyHand.slave.extraScale);
model.configuration.fingers.rigidbodyMass = model.asset.configuration.fingers.rigidbodyMass * model.proxyHand.slave.extraScale;

model.configuration.wrist.positionDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.wrist.positionDrive, model.proxyHand.slave.extraScale);
model.configuration.wrist.rotationDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.wrist.rotationDrive, model.proxyHand.slave.extraScale);
model.configuration.wrist.rigidbodyMass = model.asset.configuration.wrist.rigidbodyMass * model.proxyHand.slave.extraScale;

model.configuration.specials.positionDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.specials.positionDrive, model.proxyHand.slave.extraScale);
model.configuration.specials.rotationDrive = CustomJointDrive.ScaledCopy(model.asset.configuration.specials.rotationDrive, model.proxyHand.slave.extraScale);
model.configuration.specials.rigidbodyMass = model.asset.configuration.specials.rigidbodyMass * model.proxyHand.slave.extraScale;
}

if (model.applyConfOnUpdate && slaveBones[i].jointRef)
{
// Update joint configurations
if (slaveBones[i] == model.proxyHand.slave.wrist)
PhysHelpers.SetSlaveBoneConfiguration(slaveBones[i].jointRef, model.configuration.wrist);
else if (slaveBones[i].isSpecial)
PhysHelpers.SetSlaveBoneConfiguration(slaveBones[i].jointRef, model.configuration.specials);
else
PhysHelpers.SetSlaveBoneConfiguration(slaveBones[i].jointRef, model.configuration.fingers);

// Update built-in velocity clamps
slaveBones[i].rigidbodyRef.maxDepenetrationVelocity = model.configuration.fingers.maxLinearVelocity;
slaveBones[i].rigidbodyRef.maxAngularVelocity = model.configuration.fingers.maxAngularVelocity;

// NO-PROD
if (slaveBones[i].jointRef.connectedBody)
{
slaveBones[i].jointRef.connectedAnchor = slaveBones[i].initialConnectedAnchor;
}
}
}
}

private void FixedUpdate()
Expand Down
6 changes: 6 additions & 0 deletions Runtime/Modules/HandPhysics/HandPhysicsModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ namespace HPTK.Models.Avatar
public class HandPhysicsModel : HPTKModel
{
public ProxyHandModel proxyHand;

public HandPhysicsConfigurationAsset asset;
[HideInInspector]
public HandPhysicsConfiguration configuration;

public bool isActive = true;
public bool applyConfOnUpdate = false;
public bool updateConfFromScale = true;
}
}
9 changes: 8 additions & 1 deletion Runtime/Modules/Input/InputController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static HPTK.Views.Handlers.ProxyHandHandler;

namespace HPTK.Controllers.Input
{
Expand Down Expand Up @@ -314,6 +315,7 @@ void Update()
}
}

// If we need to record and confidence is good enough to record
if (conf.usePredictiveTrackingWhenLost && model.inputDataProvider.confidence > conf.saveHandHistoricOverConfidence)
{
// Before updating wristVelocityDirection and wristPosition
Expand All @@ -332,7 +334,12 @@ void Update()
// Update timeOfLastRecord
timeOfLastRecord = Time.timeSinceLevelLoad;
}


// Hand scaling
if (model.updateRealScale)
{
model.proxyHand.realScale = model.inputDataProvider.scale;
}
}

void UpdateMasterBonePos(MasterBoneModel masterBone, AbstractTsf inputData, float maxSpeed)
Expand Down
3 changes: 3 additions & 0 deletions Runtime/Modules/Input/InputModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ public class InputModel : HPTKModel
public MasterBoneModel pinky2;
public MasterBoneModel pinky3;

[Header("Scaling")]
public bool updateRealScale = true;

[Header("Updated by Controller")]
public bool handIsTracked = false;
public bool fingersAreTracked = false;
Expand Down
4 changes: 4 additions & 0 deletions Runtime/Modules/ProxyHand/Hand/HandModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public class HandModel : HPTKModel

public Transform ray;

[Header("Scaling")]
public float extraScale = 1.0f;
public float totalScale;

[Header("Components")]
public SkinnedMeshRenderer skinnedMR;

Expand Down
3 changes: 3 additions & 0 deletions Runtime/Modules/ProxyHand/Hand/Slave/SlaveBoneModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ public class SlaveBoneModel : BoneModel

[HideInInspector]
public Quaternion minLocalRot = Quaternion.identity;

[HideInInspector]
public Vector3 initialConnectedAnchor;
}
}
Loading

0 comments on commit 329b679

Please sign in to comment.