Last active
May 2, 2023 18:06
-
-
Save austinbhale/15037f67e446402531a309452b183b99 to your computer and use it in GitHub Desktop.
A workaround to get model scaling into StereoKit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Program | |
{ | |
private static void Main(string[] _) | |
{ | |
// Initialize StereoKit | |
SKSettings settings = new() | |
{ | |
appName = "ModelScaleSK", | |
assetsFolder = "Assets", | |
}; | |
if (!SK.Initialize(settings)) | |
{ | |
Environment.Exit(1); | |
} | |
Material volumeMat = Default.MaterialUIBox.Copy(); | |
volumeMat["border_size"] = 0.0f; | |
volumeMat["border_affect_radius"] = 0.3f; | |
var model = Model.FromMesh(Mesh.GenerateSphere(15 * U.cm), Material.Default); | |
float modelScale = 1; | |
Pose modelPose = new(Input.Head.ToMatrix().Transform(Vec3.Forward * 0.3f), Quat.Identity); | |
SK.Run(() => | |
{ | |
Bounds modelBoundsScaled = model.Bounds * modelScale; | |
if (UIExtension.HandleBegin($"Test", ref modelPose, modelBoundsScaled, ref modelScale)) | |
{ | |
Default.MeshCube.Draw(volumeMat, Matrix.TS(modelBoundsScaled.center, modelBoundsScaled.dimensions)); | |
} | |
UI.HandleEnd(); | |
Hierarchy.Push(modelPose.ToMatrix(modelScale)); | |
model.Draw(Matrix.Identity); | |
Hierarchy.Pop(); | |
}); | |
} | |
/// <summary> | |
/// Extends StereoKit UI capabilities. | |
/// </summary> | |
public static class UIExtension | |
{ | |
/// <summary> | |
/// Temporary dictionary to store scale information of the model being scaled by the user. | |
/// </summary> | |
private static readonly Dictionary<string, float> s_IdScalePairs = new(); | |
/// <summary> | |
/// A modification of UI.HandleBegin, that allows for scaling 3D models through | |
/// hand interaction. | |
/// </summary> | |
/// <param name="id">Name of the 3d model being manipulated.</param> | |
/// <param name="pose">Pose of the object being manipulated.</param> | |
/// <param name="handle">Bounds of the object being manipulated.</param> | |
/// <param name="scale">Current scale of the object.</param> | |
/// <param name="drawHandle">Flag to indicate whether to draw the bounds.</param> | |
/// <param name="moveType">Defines how the handle follows the user's hands.</param> | |
/// <returns>The original result from StereoKit's HandleBegin.</returns> | |
public static bool HandleBegin(string id, ref Pose pose, Bounds handle, ref float scale, | |
bool drawHandle = false, UIMove moveType = UIMove.Exact) | |
{ | |
if (UI.HandleBegin(id, ref pose, handle, drawHandle, moveType)) | |
{ | |
if (moveType != UIMove.Exact) | |
{ | |
return true; | |
} | |
Hand leftHand = Input.Hand(Handed.Left); | |
Hand rightHand = Input.Hand(Handed.Right); | |
if (leftHand.IsTracked && rightHand.IsTracked | |
&& leftHand.IsPinched && rightHand.IsPinched) | |
{ | |
if (leftHand.IsJustPinched || rightHand.IsJustPinched) | |
{ | |
handle.center = pose.ToMatrix().Transform(handle.center); | |
if (handle.Contains(leftHand.pinchPt) && handle.Contains(rightHand.pinchPt)) | |
{ | |
s_IdScalePairs[id] = Vec3.Distance(leftHand.pinchPt, rightHand.pinchPt) / scale; | |
} | |
} | |
else if (s_IdScalePairs.ContainsKey(id)) | |
{ | |
float currentDist = Vec3.Distance(leftHand.pinchPt, rightHand.pinchPt); | |
scale = currentDist / s_IdScalePairs[id]; | |
} | |
} | |
else if (s_IdScalePairs.ContainsKey(id)) | |
{ | |
s_IdScalePairs.Remove(id); | |
} | |
return true; | |
} | |
if (s_IdScalePairs.ContainsKey(id)) | |
{ | |
s_IdScalePairs.Remove(id); | |
} | |
return false; | |
} | |
public static bool Handle(string id, ref Pose pose, Bounds handle, ref float scale, | |
bool drawHandle = false, UIMove moveType = UIMove.Exact) | |
{ | |
bool result = HandleBegin(id, ref pose, handle, ref scale, drawHandle, moveType); | |
UI.HandleEnd(); | |
return result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment