design vars foothold
This commit is contained in:
parent
95b1bd3918
commit
519d3b7813
9 changed files with 264 additions and 145 deletions
66
app/Mono.cs
66
app/Mono.cs
|
@ -67,7 +67,7 @@ public class Mono {
|
||||||
matHolo = Material.Default.Copy();
|
matHolo = Material.Default.Copy();
|
||||||
matHolo.Transparency = Transparency.Add;
|
matHolo.Transparency = Transparency.Add;
|
||||||
matHolo.DepthWrite = false;
|
matHolo.DepthWrite = false;
|
||||||
matHolo.DepthTest = DepthTest.Always;
|
// matHolo.DepthTest = DepthTest.Always;
|
||||||
matHolo.FaceCull = Cull.None;
|
matHolo.FaceCull = Cull.None;
|
||||||
// matHolo.SetTexture("diffuse", Tex.DevTex);
|
// matHolo.SetTexture("diffuse", Tex.DevTex);
|
||||||
matHolo.Wireframe = true;
|
matHolo.Wireframe = true;
|
||||||
|
@ -93,6 +93,8 @@ public class Mono {
|
||||||
|
|
||||||
compositor.Frame();
|
compositor.Frame();
|
||||||
|
|
||||||
|
// Input.Subscribe(InputSource.Hand, BtnState.Any, Action<Hand, BtnState.Any, Pointer>);
|
||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
// // dof.Frame();
|
// // dof.Frame();
|
||||||
|
@ -109,6 +111,8 @@ public class Mono {
|
||||||
lwc.Demo(ltb.ori);
|
lwc.Demo(ltb.ori);
|
||||||
rwc.Demo(rtb.ori);
|
rwc.Demo(rtb.ori);
|
||||||
|
|
||||||
|
rtb.Demo();
|
||||||
|
|
||||||
// rBlock.Step(); lBlock.Step();
|
// rBlock.Step(); lBlock.Step();
|
||||||
|
|
||||||
// cubicCon.Step();
|
// cubicCon.Step();
|
||||||
|
@ -123,9 +127,15 @@ public class Mono {
|
||||||
ShowWindowButton();
|
ShowWindowButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pose windowPoseButton = new Pose(0, 0, 0.75f, Quat.Identity);
|
Pose windowPoseButton = new Pose(-0.5f, 1.3f, 0, Quat.FromAngles(0, -90f, 0));
|
||||||
|
TextStyle style = Text.MakeStyle(Font.FromFile("add/fonts/DM-Mono.ttf"), 1f * U.cm, Color.White);
|
||||||
|
Vec2 fieldSize = new Vec2(6f * U.cm, 3f * U.cm);
|
||||||
void ShowWindowButton() {
|
void ShowWindowButton() {
|
||||||
UI.WindowBegin("Window Button", ref windowPoseButton);
|
UI.WindowBegin("design vars", ref windowPoseButton);
|
||||||
|
UI.SetThemeColor(UIColor.Background, new Color(0f, 0f, 0f));
|
||||||
|
UI.SetThemeColor(UIColor.Primary, new Color(0.5f, 0.5f, 0.5f));
|
||||||
|
UI.PushTextStyle(style);
|
||||||
|
|
||||||
|
|
||||||
// if (UI.Button("Draw Oriel Axis")) { oriel.drawAxis = !oriel.drawAxis; }
|
// if (UI.Button("Draw Oriel Axis")) { oriel.drawAxis = !oriel.drawAxis; }
|
||||||
|
|
||||||
|
@ -139,29 +149,49 @@ public class Mono {
|
||||||
// UI.Label("pos.y");
|
// UI.Label("pos.y");
|
||||||
// UI.HSlider("pos.y", ref playerY, -1f, 1f, 0.1f);
|
// UI.HSlider("pos.y", ref playerY, -1f, 1f, 0.1f);
|
||||||
|
|
||||||
// UI.Label("trail.length");
|
UI.Label("wavecursor.");
|
||||||
// UI.HSlider("trail.length", ref trailLen, 0.1f, 1f, 0.1f);
|
UI.Input("wavecursor.reach", ref wcReach, fieldSize, TextContext.Number);
|
||||||
|
UI.SameLine(); UI.Label("reach");
|
||||||
// UI.Label("trail.scale");
|
UI.Input("wavecursor.length", ref wcLength, fieldSize, TextContext.Number);
|
||||||
// UI.HSlider("trail.str", ref trailScl, 0.1f, 2f, 0.1f);
|
UI.SameLine(); UI.Label("length");
|
||||||
|
UI.Input("wavecursor.scale", ref wcScale, fieldSize, TextContext.Number);
|
||||||
// UI.Label("str");
|
UI.SameLine(); UI.Label("scale");
|
||||||
// UI.HSlider("str", ref stretchStr, 0.1f, 1f, 0.1f);
|
|
||||||
|
|
||||||
|
|
||||||
|
UI.Label("trackballer.");
|
||||||
|
UI.Input("trackballer.compliance", ref tbCompliance, fieldSize, TextContext.Number);
|
||||||
|
UI.SameLine(); UI.Label("compliance");
|
||||||
|
UI.Input("trackballer.x", ref tbX, fieldSize, TextContext.Number);
|
||||||
|
UI.SameLine(); UI.Label("x");
|
||||||
|
UI.Input("trackballer.y", ref tbY, fieldSize, TextContext.Number);
|
||||||
|
UI.SameLine(); UI.Label("y");
|
||||||
|
UI.Input("trackballer.z", ref tbZ, fieldSize, TextContext.Number);
|
||||||
|
UI.SameLine(); UI.Label("z");
|
||||||
|
|
||||||
// flipIndex
|
// flipIndex
|
||||||
// flipGrip
|
// flipGrip
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UI.WindowEnd();
|
UI.WindowEnd();
|
||||||
}
|
}
|
||||||
public float trailLen = 0.666f;
|
|
||||||
public float trailScl = 0.333f;
|
|
||||||
public float stretchStr = 0.5f;
|
|
||||||
public float playerY = 0;
|
|
||||||
|
|
||||||
|
public string wcReach = "1.0";
|
||||||
|
public string wcLength = "0.666";
|
||||||
|
public string wcScale = "0.333";
|
||||||
|
|
||||||
|
public string tbCompliance = "0.0";
|
||||||
|
public string tbX = "1.0";
|
||||||
|
public string tbY = "2.0";
|
||||||
|
public string tbZ = "-4.0";
|
||||||
|
|
||||||
|
|
||||||
|
// public float playerY = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert into a class
|
||||||
|
class Design {
|
||||||
|
public string txt;
|
||||||
|
public int integer;
|
||||||
|
public float floating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,11 @@ public static class PullRequest {
|
||||||
return (to * delta * to.Inverse).Normalized;
|
return (to * delta * to.Inverse).Normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ?
|
||||||
|
public static Vec3 Relative(Quat to, Vec3 delta) {
|
||||||
|
return to * delta * to.Inverse;
|
||||||
|
}
|
||||||
|
|
||||||
// public static void LookDirection(this ref Quat q, Vec3 dir) {
|
// public static void LookDirection(this ref Quat q, Vec3 dir) {
|
||||||
// Vec3 up = Vec3.Up;
|
// Vec3 up = Vec3.Up;
|
||||||
|
|
||||||
|
@ -284,10 +289,27 @@ public static class PullRequest {
|
||||||
return MathF.Max(min, MathF.Min(max, v));
|
return MathF.Max(min, MathF.Min(max, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float ToFloat(
|
||||||
|
ref string s,
|
||||||
|
float min = float.NegativeInfinity,
|
||||||
|
float max = float.PositiveInfinity
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
float value = Clamp(float.Parse(s), min, max);
|
||||||
|
// if clamped, update string
|
||||||
|
if (value != float.Parse(s)) {
|
||||||
|
s = value.ToString();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
} catch {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PID {
|
public class PID {
|
||||||
public float p, i;
|
public float p, i;
|
||||||
float integral = 0f;
|
public float value;
|
||||||
float value = 0f;
|
float integral;
|
||||||
// float scalar = 1f;
|
// float scalar = 1f;
|
||||||
|
|
||||||
public PID(float p = 1, float i = 0.1f) {
|
public PID(float p = 1, float i = 0.1f) {
|
||||||
|
@ -303,6 +325,18 @@ public static class PullRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Vec3PID {
|
||||||
|
public Vec3 value, integral;
|
||||||
|
// float scalar = 1f;
|
||||||
|
|
||||||
|
public Vec3 Update(Vec3 target, float p = 1, float i = 0.1f) {
|
||||||
|
Vec3 error = value - target;
|
||||||
|
integral += error;
|
||||||
|
Vec3 delta = ((p * error) + (i * integral));
|
||||||
|
return value -= delta * Time.Elapsedf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class Lerper {
|
public class Lerper {
|
||||||
public float t = 0;
|
public float t = 0;
|
||||||
public float spring = 1;
|
public float spring = 1;
|
||||||
|
|
|
@ -5,13 +5,7 @@ public class Rig {
|
||||||
public Vec3 pos = new Vec3(0, 0, 0);
|
public Vec3 pos = new Vec3(0, 0, 0);
|
||||||
public Quat ori = Quat.Identity;
|
public Quat ori = Quat.Identity;
|
||||||
|
|
||||||
public Rig() {
|
public Rig() {}
|
||||||
if (World.HasBounds) {
|
|
||||||
// pos.XZ = World.BoundsPose.position.XZ;
|
|
||||||
// pos.y = World.BoundsPose.position.y;
|
|
||||||
// ori = World.BoundsPose.orientation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// public Vec3 center;
|
// public Vec3 center;
|
||||||
// public void Recenter() {
|
// public void Recenter() {
|
||||||
|
@ -44,12 +38,19 @@ public class Rig {
|
||||||
|
|
||||||
|
|
||||||
public Vec3 LocalPos(Vec3 p) {
|
public Vec3 LocalPos(Vec3 p) {
|
||||||
return ori.Inverse * (p - (pos + Vec3.Up * Mono.inst.playerY));
|
return ori.Inverse * (p - (pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gotBounds = false;
|
||||||
|
public void Step() {
|
||||||
|
Matrix bounds = Matrix.T(0, 1.3f, 0);
|
||||||
|
if (!gotBounds && World.HasBounds) {
|
||||||
|
gotBounds = true;
|
||||||
|
bounds = World.BoundsPose.ToMatrix();
|
||||||
|
// Renderer.CameraRoot = World.BoundsPose.ToMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
public void Step() {
|
Renderer.CameraRoot = Matrix.TR(pos, ori) * bounds;
|
||||||
Renderer.CameraRoot = Matrix.TR((pos + Vec3.Up * Mono.inst.playerY), ori);
|
|
||||||
|
|
||||||
// Controllers
|
// Controllers
|
||||||
rCon.Step(true);
|
rCon.Step(true);
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class Space {
|
||||||
// World.BoundsPose.position.y
|
// World.BoundsPose.position.y
|
||||||
|
|
||||||
|
|
||||||
shed.Draw(Matrix.TRS(new Vec3(0, -1.6f, 0), Quat.Identity, Vec3.One));
|
shed.Draw(Matrix.Identity);
|
||||||
|
|
||||||
|
|
||||||
// draw a grid of cube pillars spaced out evenly along the XZ plane
|
// draw a grid of cube pillars spaced out evenly along the XZ plane
|
||||||
|
|
|
@ -20,7 +20,7 @@ Renderer.ClearColor = new Color(0f, 0f, 0f);
|
||||||
|
|
||||||
Oriels.Mono mono = Oriels.Mono.inst;
|
Oriels.Mono mono = Oriels.Mono.inst;
|
||||||
mono.Init();
|
mono.Init();
|
||||||
while (SK.Step(() => {
|
SK.Run(() => {
|
||||||
mono.Frame();
|
mono.Frame();
|
||||||
}));
|
});
|
||||||
SK.Shutdown();
|
// SK.Shutdown();
|
|
@ -31,8 +31,8 @@ class WaveCursor : dof {
|
||||||
hand.Get(FingerId.Index, JointId.Tip).position,
|
hand.Get(FingerId.Index, JointId.Tip).position,
|
||||||
hand.Get(FingerId.Index, JointId.KnuckleMajor).position
|
hand.Get(FingerId.Index, JointId.KnuckleMajor).position
|
||||||
);
|
);
|
||||||
|
|
||||||
cursor.raw = hand.Get(FingerId.Index, JointId.Tip).position + dir * stretch * strength * Mono.inst.stretchStr;
|
cursor.raw = hand.Get(FingerId.Index, JointId.Tip).position + dir * stretch * strength;
|
||||||
cursor.pos.x = (float)xF.Filter(cursor.raw.x, (double)Time.Elapsedf);
|
cursor.pos.x = (float)xF.Filter(cursor.raw.x, (double)Time.Elapsedf);
|
||||||
cursor.pos.y = (float)yF.Filter(cursor.raw.y, (double)Time.Elapsedf);
|
cursor.pos.y = (float)yF.Filter(cursor.raw.y, (double)Time.Elapsedf);
|
||||||
cursor.pos.z = (float)zF.Filter(cursor.raw.z, (double)Time.Elapsedf);
|
cursor.pos.z = (float)zF.Filter(cursor.raw.z, (double)Time.Elapsedf);
|
||||||
|
@ -45,7 +45,9 @@ class WaveCursor : dof {
|
||||||
}
|
}
|
||||||
|
|
||||||
public float deadzone = 0.3f;
|
public float deadzone = 0.3f;
|
||||||
public float strength = 3f;
|
public float strength {
|
||||||
|
get { return PullRequest.ToFloat(ref Mono.inst.wcReach, 0); } // 3f
|
||||||
|
}
|
||||||
public Handed handed = Handed.Left;
|
public Handed handed = Handed.Left;
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,23 +87,24 @@ class WaveCursor : dof {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trail(Vec3[] points, Vec3 nextPos) {
|
void Trail(Vec3[] points, Vec3 nextPos) {
|
||||||
while (Vec3.Distance(points[0], nextPos) > 0.03f * Mono.inst.trailScl) {
|
float scale = PullRequest.ToFloat(ref Mono.inst.wcScale, 0.001f);
|
||||||
|
while (Vec3.Distance(points[0], nextPos) > 0.03f * scale) {
|
||||||
for (int i = points.Length - 1; i > 0; i--) {
|
for (int i = points.Length - 1; i > 0; i--) {
|
||||||
points[i] = points[i - 1];
|
points[i] = points[i - 1];
|
||||||
}
|
}
|
||||||
points[0] += Vec3.Direction(nextPos, points[0]) * 0.02f * Mono.inst.trailScl;
|
points[0] += Vec3.Direction(nextPos, points[0]) * 0.02f * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// points[0] = nextPos;
|
// points[0] = nextPos;
|
||||||
int len = (int)(points.Length * Mono.inst.trailLen);
|
int len = (int)(points.Length * PullRequest.ToFloat(ref Mono.inst.wcLength, 0f, 1f));
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
// if (i > 0) {
|
// if (i > 0) {
|
||||||
// Vec3 dir = Vec3.Forward;
|
// Vec3 dir = Vec3.Forward;
|
||||||
// if (points[i].v != points[i - 1].v) {
|
// if (points[i].v != points[i - 1].v) {
|
||||||
// dir = PullRequest.Direction(points[i], points[i - 1]);
|
// dir = PullRequest.Direction(points[i], points[i - 1]);
|
||||||
// }
|
// }
|
||||||
// // points[i] = points[i - 1] + dir * 0.02f * Mono.inst.trailScl;
|
// // points[i] = points[i - 1] + dir * 0.02f * scale;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Vec3 from = i > 0 ? points[i - 1] : nextPos;
|
Vec3 from = i > 0 ? points[i - 1] : nextPos;
|
||||||
|
@ -109,9 +112,9 @@ class WaveCursor : dof {
|
||||||
Mesh.Cube.Draw(
|
Mesh.Cube.Draw(
|
||||||
Mono.inst.matHolo,
|
Mono.inst.matHolo,
|
||||||
Matrix.TRS(
|
Matrix.TRS(
|
||||||
points[i] + ori * new Vec3(0, 0, 0.01f) * Mono.inst.trailScl,
|
points[i] + ori * new Vec3(0, 0, 0.01f) * scale,
|
||||||
ori,
|
ori,
|
||||||
new Vec3(0.01f, 0.01f, 0.02f) * Mono.inst.trailScl
|
new Vec3(0.01f, 0.01f, 0.02f) * scale
|
||||||
),
|
),
|
||||||
Color.HSV(i / (float)len, 1, 1)
|
Color.HSV(i / (float)len, 1, 1)
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,10 +4,16 @@ class Trackballer : dof {
|
||||||
|
|
||||||
// data
|
// data
|
||||||
public Btn btnIn, btnOut;
|
public Btn btnIn, btnOut;
|
||||||
|
bool onTheBall;
|
||||||
public Quat ori = Quat.Identity;
|
public Quat ori = Quat.Identity;
|
||||||
|
|
||||||
Quat momentum = Quat.Identity;
|
Quat momentum = Quat.Identity;
|
||||||
Quat delta = Quat.Identity;
|
Quat delta = Quat.Identity;
|
||||||
Matrix oldMeshMatrix = Matrix.Identity;
|
Matrix pad = Matrix.Identity;
|
||||||
|
Matrix oldPad = Matrix.Identity;
|
||||||
|
int lastClosestIndex;
|
||||||
|
|
||||||
|
PullRequest.Vec3PID compliance = new PullRequest.Vec3PID();
|
||||||
|
|
||||||
PullRequest.OneEuroFilter xF = new PullRequest.OneEuroFilter(0.0001f, 0.1f);
|
PullRequest.OneEuroFilter xF = new PullRequest.OneEuroFilter(0.0001f, 0.1f);
|
||||||
PullRequest.OneEuroFilter yF = new PullRequest.OneEuroFilter(0.0001f, 0.1f);
|
PullRequest.OneEuroFilter yF = new PullRequest.OneEuroFilter(0.0001f, 0.1f);
|
||||||
|
@ -23,115 +29,161 @@ class Trackballer : dof {
|
||||||
public void Frame() {
|
public void Frame() {
|
||||||
Hand hand = Input.Hand(handed);
|
Hand hand = Input.Hand(handed);
|
||||||
if (hand.tracked.IsActive() && !hand.tracked.IsJustActive()) {
|
if (hand.tracked.IsActive() && !hand.tracked.IsJustActive()) {
|
||||||
Vec3 anchor = hand.Get(FingerId.Index, JointId.KnuckleMajor).position;
|
UpdateMomentum(hand);
|
||||||
anchor = anchor + hand.palm.orientation * new Vec3(handed == Handed.Left ? -0.006f : 0.006f, 0.01f, -0.04f);
|
|
||||||
Matrix mAnchor = Matrix.TR(anchor, hand.palm.orientation);
|
|
||||||
Matrix mAnchorInv = mAnchor.Inverse;
|
|
||||||
|
|
||||||
Vec3 thumbTip = hand.Get(FingerId.Thumb, JointId.Tip).position;
|
|
||||||
// Vec3 tipDelta = mAnchorInv.Transform(thumbTip) - mAnchorInv.Transform(oldTip);
|
|
||||||
// oldTip = thumbTip;
|
|
||||||
Vec3 thumbKnuckle = hand.Get(FingerId.Thumb, JointId.KnuckleMinor).position;
|
|
||||||
|
|
||||||
Quat thumbRot = hand.Get(FingerId.Thumb, JointId.Tip).orientation;
|
|
||||||
Matrix mMesh = Matrix.TRS(
|
|
||||||
thumbTip,
|
|
||||||
thumbRot,
|
|
||||||
new Vec3(handed == Handed.Left ? -1f : 1f, 1f, 1f) * 0.1666f
|
|
||||||
);
|
|
||||||
mesh.Draw(Mono.inst.matHolo, mMesh, new Color(0, 1, 1));
|
|
||||||
|
|
||||||
// closest to anchor
|
|
||||||
float closest = 100000f;
|
|
||||||
int closestIndex = -1;
|
|
||||||
Vertex[] verts = mesh.GetVerts();
|
|
||||||
for (int i = 0; i < verts.Length; i++) {
|
|
||||||
Vec3 v = mMesh.Transform(verts[i].pos);
|
|
||||||
float d = (v - anchor).LengthSq;
|
|
||||||
if (d < closest) {
|
|
||||||
closest = d;
|
|
||||||
closestIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 localPad = mAnchorInv.Transform(mMesh.Transform(verts[closestIndex].pos));
|
|
||||||
Vec3 oldPad = mAnchorInv.Transform(oldMeshMatrix.Transform(verts[closestIndex].pos));
|
|
||||||
|
|
||||||
oldMeshMatrix = mMesh;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Vec3 pad = anchor.SnapToLine(
|
|
||||||
// thumbKnuckle, thumbTip,
|
|
||||||
// true,
|
|
||||||
// out float t, 0f, 1f
|
|
||||||
// );
|
|
||||||
// // t = 1 - t;
|
|
||||||
// // scale to 0.666f - 1f
|
|
||||||
// // t = (t - 0.666f) / 0.334f;
|
|
||||||
// t = t * t;
|
|
||||||
// t = 1 - t;
|
|
||||||
// pad += hand.Get(FingerId.Thumb, JointId.Tip).orientation * -Vec3.Up * 0.00666f * t;
|
|
||||||
|
|
||||||
|
|
||||||
// Vec3 localPad = mAnchorInv.Transform(pad);
|
|
||||||
// Vec3 localPad = mAnchorInv.Transform(thumbTip);
|
|
||||||
|
|
||||||
// ?
|
|
||||||
// localPad.x = (float)xF.Filter(localPad.x, (double)Time.Elapsedf);
|
|
||||||
// localPad.y = (float)yF.Filter(localPad.y, (double)Time.Elapsedf);
|
|
||||||
// localPad.z = (float)zF.Filter(localPad.z, (double)Time.Elapsedf);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Lines.Add(thumbTip, thumbKnuckle, Color.White, 0.002f);
|
|
||||||
Mesh.Sphere.Draw(Mono.inst.matHolo, Matrix.TRS(mAnchor.Transform(localPad), hand.palm.orientation, 0.002f), new Color(0, 1, 1));
|
|
||||||
|
|
||||||
|
|
||||||
// if (btnIn.held) {
|
|
||||||
// btnIn.Step(localPad.Length < layer[1]);
|
|
||||||
// } else {
|
|
||||||
// btnIn.Step(localPad.Length < layer[0]);
|
|
||||||
// }
|
|
||||||
float inT = btnIn.held ? 1 : 0.333f;
|
|
||||||
|
|
||||||
if (btnOut.held) {
|
|
||||||
btnOut.Step(localPad.Length > layer[1]);
|
|
||||||
} else {
|
|
||||||
btnOut.Step(localPad.Length > layer[2]);
|
|
||||||
}
|
|
||||||
float outT = btnOut.held ? 1 : 0.333f;
|
|
||||||
|
|
||||||
if (btnIn.held) {
|
|
||||||
delta = momentum = Quat.Identity;
|
|
||||||
} else {
|
|
||||||
if (localPad.Length < layer[1]) {
|
|
||||||
delta = PullRequest.Relative(
|
|
||||||
hand.palm.orientation,
|
|
||||||
Quat.Delta(
|
|
||||||
oldPad.Normalized,
|
|
||||||
localPad.Normalized
|
|
||||||
)
|
|
||||||
).Normalized;
|
|
||||||
|
|
||||||
momentum = Quat.Slerp(momentum, delta, Time.Elapsedf * 10f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
Mesh.Sphere.Draw(Mono.inst.matHolo, Matrix.TRS(anchor, ori, layer[1] * 2), new Color(inT, 0, 0));
|
|
||||||
// Mesh.Cube.Draw(Mono.inst.matHolo, Matrix.TRS(anchor, ori, 0.04f), new Color(0, outT * 0.2f, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Quat newOri = momentum * ori;
|
Quat newOri = (momentum * ori).Normalized;
|
||||||
if (new Vec3(newOri.x, newOri.y, newOri.z).LengthSq > 0) {
|
if (new Vec3(newOri.x, newOri.y, newOri.z).LengthSq > 0) {
|
||||||
ori = newOri;
|
ori = newOri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateMomentum(Hand hand) {
|
||||||
|
// Thumb pad
|
||||||
|
HandJoint thumbJoint = hand.Get(FingerId.Thumb, JointId.Tip);
|
||||||
|
oldPad = pad;
|
||||||
|
pad = Matrix.TRS(
|
||||||
|
thumbJoint.position,
|
||||||
|
thumbJoint.orientation,
|
||||||
|
new Vec3(handed == Handed.Left ? -1f : 1f, 1f, 1f) * 0.1666f
|
||||||
|
);
|
||||||
|
mesh.Draw(Mono.inst.matHolo, pad, new Color(0, 1, 1));
|
||||||
|
|
||||||
|
// Ball anchor
|
||||||
|
HandJoint ballJoint = hand.Get(FingerId.Index, JointId.KnuckleMajor);
|
||||||
|
Vec3 anchorPos = ballJoint.position + hand.palm.orientation * new Vec3(
|
||||||
|
PullRequest.ToFloat(ref Mono.inst.tbX, -10f, 10f) * U.cm * (handed == Handed.Left ? -1 : 1),
|
||||||
|
PullRequest.ToFloat(ref Mono.inst.tbY, -10f, 10f) * U.cm,
|
||||||
|
PullRequest.ToFloat(ref Mono.inst.tbZ, -10f, 10f) * U.cm
|
||||||
|
);
|
||||||
|
anchorPos += compliance.Update(
|
||||||
|
Vec3.Zero,
|
||||||
|
onTheBall ? 1f : 10f,
|
||||||
|
onTheBall ? 0.1f : 1f // 10x less integral when on the ball?
|
||||||
|
);
|
||||||
|
// compliance;
|
||||||
|
// compliance = Vec3.Lerp(compliance, Vec3.Zero, Time.Elapsedf * 10f);
|
||||||
|
Matrix anchor = Matrix.TR(anchorPos, hand.palm.orientation);
|
||||||
|
Matrix anchorInv = anchor.Inverse;
|
||||||
|
|
||||||
|
// Traction delta mesh matrix
|
||||||
|
Vertex[] verts = mesh.GetVerts();
|
||||||
|
float oldClosest = (
|
||||||
|
pad.Transform(verts[lastClosestIndex].pos) - anchorPos
|
||||||
|
).LengthSq;
|
||||||
|
float closest = 100000f;
|
||||||
|
int closestIndex = lastClosestIndex;
|
||||||
|
for (int i = 0; i < verts.Length; i++) {
|
||||||
|
Vec3 v = pad.Transform(verts[i].pos);
|
||||||
|
float d = (v - anchorPos).LengthSq;
|
||||||
|
if (d < closest && d < oldClosest - 0.00002f) {
|
||||||
|
closest = d;
|
||||||
|
closestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastClosestIndex = closestIndex;
|
||||||
|
|
||||||
|
Vec3 point = anchorInv.Transform(
|
||||||
|
pad.Transform(verts[closestIndex].pos)
|
||||||
|
);
|
||||||
|
Vec3 oldPoint = anchorInv.Transform(
|
||||||
|
oldPad.Transform(verts[closestIndex].pos)
|
||||||
|
);
|
||||||
|
|
||||||
|
// ?
|
||||||
|
// localPad.x = (float)xF.Filter(localPad.x, (double)Time.Elapsedf);
|
||||||
|
// localPad.y = (float)yF.Filter(localPad.y, (double)Time.Elapsedf);
|
||||||
|
// localPad.z = (float)zF.Filter(localPad.z, (double)Time.Elapsedf);
|
||||||
|
|
||||||
|
// Lines.Add(thumbTip, thumbKnuckle, Color.White, 0.002f);
|
||||||
|
Mesh.Sphere.Draw(
|
||||||
|
Mono.inst.matHolo,
|
||||||
|
Matrix.TRS(anchor.Transform(point), hand.palm.orientation, 0.002f),
|
||||||
|
new Color(0, 1, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
float dist = point.Length;
|
||||||
|
// if (btnIn.held) { btnIn.Step(dist < layer[1]); }
|
||||||
|
// else { btnIn.Step(dist < layer[0]); }
|
||||||
|
float inT = btnIn.held ? 1 : 0.333f;
|
||||||
|
|
||||||
|
if (btnOut.held) { btnOut.Step(dist > layer[1]); }
|
||||||
|
else { btnOut.Step(dist > layer[2]); }
|
||||||
|
float outT = btnOut.held ? 1 : 0.333f;
|
||||||
|
|
||||||
|
if (btnIn.held) {
|
||||||
|
delta = momentum = Quat.Identity;
|
||||||
|
} else {
|
||||||
|
onTheBall = dist < layer[1];
|
||||||
|
if (onTheBall) {
|
||||||
|
delta = Quat.Delta(
|
||||||
|
oldPoint.Normalized,
|
||||||
|
point.Normalized
|
||||||
|
).Relative(hand.palm.orientation);
|
||||||
|
|
||||||
|
momentum = Quat.Slerp(momentum, delta, Time.Elapsedf * 10f);
|
||||||
|
|
||||||
|
Vec3 contact = point.Normalized * layer[1];
|
||||||
|
Vec3 offset = point - contact;
|
||||||
|
|
||||||
|
// no z axis
|
||||||
|
// offset.z = 0;
|
||||||
|
|
||||||
|
offset = hand.palm.orientation * offset;
|
||||||
|
compliance.value += offset * PullRequest.ToFloat(ref Mono.inst.tbCompliance, 0f, 1f);
|
||||||
|
compliance.integral = Vec3.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
Mesh.Sphere.Draw(
|
||||||
|
Mono.inst.matHolo,
|
||||||
|
Matrix.TRS(anchorPos, ori, layer[1] * 2),
|
||||||
|
new Color(inT, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// design
|
// design
|
||||||
public Handed handed = Handed.Left;
|
public Handed handed = Handed.Left;
|
||||||
public float[] layer = new float[] { 0.00333f, 0.02f, 0.0666f };
|
public float[] layer = new float[] { 0.00333f, 0.02f, 0.0666f };
|
||||||
|
|
||||||
|
|
||||||
|
Vec3 cursorPos = new Vec3(0f, 0f, 0f);
|
||||||
|
public void Demo() {
|
||||||
|
Matrix panel = Matrix.TR(
|
||||||
|
new Vec3(
|
||||||
|
1.47f,
|
||||||
|
1.145f, // - World.BoundsPose.position.y,
|
||||||
|
1.08f),
|
||||||
|
Quat.FromAngles(-3.2f, 90f, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
float width = 52 * U.cm;
|
||||||
|
float height = 29f * U.cm;
|
||||||
|
Mesh.Quad.Draw(
|
||||||
|
Mono.inst.matHolo,
|
||||||
|
Matrix.S(new Vec3(width, height, 1)) * panel,
|
||||||
|
new Color(1, 1, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
cursorPos.x = PullRequest.Clamp(
|
||||||
|
cursorPos.x + (delta * Vec3.Right).z * 0.1f,
|
||||||
|
width / -2f,
|
||||||
|
width / 2f
|
||||||
|
);
|
||||||
|
cursorPos.y = PullRequest.Clamp(
|
||||||
|
cursorPos.y + (delta * Vec3.Right).y * -0.1f,
|
||||||
|
height / -2f,
|
||||||
|
height / 2f
|
||||||
|
);
|
||||||
|
|
||||||
|
Mesh.Quad.Draw(
|
||||||
|
Material.Unlit,
|
||||||
|
Matrix.TS(cursorPos, 1 * U.cm) * panel,
|
||||||
|
new Color(1, 1, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="add/**">
|
<None Include="add/**">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<!-- <Link>add/%(RecursiveDir)%(Filename)%(Extension)</Link> -->
|
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue