oriels/app/Glove.cs
2022-01-11 12:35:00 -05:00

125 lines
3.9 KiB
C#

using System;
using StereoKit;
public enum Pull {
Stretch, Backhanded
}
public class Glove {
Monolith mono;
bool chirality;
public Glove(Monolith mono, bool chirality) {
this.mono = mono;
this.chirality = chirality;
}
public Pose virtualGlove;
Vec3 direction;
public Pull? pulling = null;
float stretch;
float stretchDeadzone = 0;
Vec3 pullPoint;
Vec3 twistPoint;
bool twistOut;
public void Step() {
Pose shoulder = mono.Shoulder(chirality);
Pose wrist = mono.Wrist(chirality);
Con con = mono.Con(chirality), otherCon = mono.Con(!chirality);
bool reach = con.device.IsX2Pressed;
bool pull = otherCon.gripBtn.frameDown;
bool lift = con.device.IsX1Pressed;
lift = false;
bool twist = con.device.IsX1Pressed;
// exclusive states?
if (reach) {
// shoulder stuff
// pullPoint = (shoulder.orientation * origin) + shoulder.position;
// shoulder.orientation.Inverse * (con.pose.position - shoulder.position)
if (lift) {
pullPoint = con.pos + -direction * stretch;
} else {
direction = PullRequest.Direction(con.pos, pullPoint);
}
} else {
pullPoint = con.pos;
}
switch (pulling) {
default:
if (pull) {
// need the rotation of the wrist rather than the hand for this to be reliable
Vec3 localPos = con.ori.Inverse * (otherCon.pos - con.pos);
pulling = (chirality ? localPos.x < 0 : localPos.x > 0) ? Pull.Stretch : Pull.Backhanded;
}
stretchDeadzone = pull ? Vec3.Distance(con.pos, otherCon.pos) : 0;
virtualGlove.orientation = con.ori;
break;
case Pull.Stretch:
pullPoint = otherCon.pos;
direction = con.ori * Vec3.Forward;
virtualGlove.orientation = otherCon.ori;
break;
case Pull.Backhanded:
pullPoint = otherCon.pos;
direction = PullRequest.Direction(con.pos, otherCon.pos);
virtualGlove.orientation = con.ori;
break;
}
if (!otherCon.gripBtn.held) {
pulling = null;
}
stretch = Math.Max(Vec3.Distance(pullPoint, con.pos) - stretchDeadzone, 0);
if (!twist) { twistPoint = con.ori * Vec3.Up; }
Quat twistFrom = Quat.LookAt(Vec3.Zero, con.ori * Vec3.Forward, twistPoint);
if (twist) {
stretch = (float)(Math.Acos(Vec3.Dot(twistFrom * Vec3.Up, con.ori * Vec3.Up)) / Math.PI);
twistOut = Vec3.Dot(twistFrom * Vec3.Up, con.ori * Vec3.Right * (chirality ? 1 : -1)) > 0;
direction = con.ori * Vec3.Forward;
virtualGlove.orientation = twistFrom;
}
virtualGlove.position = con.pos + direction * stretch * 3;
Render(con.Pose(), virtualGlove, wrist, twist, stretch, twistOut, twistFrom);
}
// decouple the rendering
// the render-relevent DATA that gets streamed over the network
// that way we can render the same way for all peers
static Mesh mesh = Default.MeshCube;
static Material mat = Default.Material;
public void Render(Pose glove, Pose virtualGlove, Pose wrist, bool twist, float stretch, bool twistOut, Quat twistFrom) {
Lines.Add(pullPoint, glove.position, new Color(1, 0, 1), 0.005f);
Lines.Add(glove.position, virtualGlove.position, new Color(0, 1, 1), 0.005f);
// Twist
float twistValue = twist ? stretch : 0;
Lines.Add(
wrist.position + glove.orientation * Vec3.Up * 0.04f,
wrist.position + glove.orientation * Vec3.Up * 0.05f,
new Color(1, 1, 0), 0.005f
);
Vec3 lastPos = wrist.position;
for (int i = 0; i < 32; i++) {
float tw = twistValue * (i / 31f);
tw *= twistOut ? -1 : 1;
Vec3 nextPos = wrist.position + twistFrom * new Vec3(SKMath.Sin(tw * SKMath.Pi), SKMath.Cos(tw * SKMath.Pi), 0) * 0.05f;
Lines.Add(lastPos, nextPos, new Color(1, 1, 0), 0.005f); // convert to LinePoints ?
lastPos = nextPos;
}
mesh.Draw(mat, glove.ToMatrix(new Vec3(0.025f, 0.1f, 0.1f) / 3));
mesh.Draw(mat, virtualGlove.ToMatrix(new Vec3(0.025f, 0.1f, 0.1f)));
}
}