design reflection

This commit is contained in:
spatialfree 2022-10-27 00:35:45 -04:00
parent 510449eebb
commit 3fd6f272d0
5 changed files with 216 additions and 104 deletions

View file

@ -16,8 +16,6 @@ public class Mono {
// ------------------------------------------------- // -------------------------------------------------
public dof[] dofs; public dof[] dofs;
int dofIndex = 0;
dof dof => dofs[dofIndex];
public ColorCube colorCube = new ColorCube(); public ColorCube colorCube = new ColorCube();
@ -43,24 +41,27 @@ public class Mono {
Renderer.SetClip(0.02f, 1000f); Renderer.SetClip(0.02f, 1000f);
dofs = new dof[] { dofs = new dof[] {
// new StretchFinger(), new Chiral() {
dofs = new dof[] {
new WaveCursor() { handed = Handed.Left }, new WaveCursor() { handed = Handed.Left },
new WaveCursor() { handed = Handed.Right }, new WaveCursor() { handed = Handed.Right }
}
},
new Chiral() {
dofs = new dof[] {
new Trackballer() { handed = Handed.Left }, new Trackballer() { handed = Handed.Left },
new Trackballer() { handed = Handed.Right }, new Trackballer() { handed = Handed.Right }
// new StretchCursor() { }, }
// new StretchCursor() { }, },
}; };
} }
public void Init() { public void Init() {
compositor.Init(); compositor.Init();
dofs[0].Init(); for (int i = 0; i < dofs.Length; i++) {
dofs[1].Init(); dofs[i].Init();
dofs[2].Init(); }
dofs[3].Init();
matDev = Material.Default.Copy(); matDev = Material.Default.Copy();
matDev.SetTexture("diffuse", Tex.DevTex); matDev.SetTexture("diffuse", Tex.DevTex);
@ -97,21 +98,29 @@ public class Mono {
// ------------------------------------------------- // -------------------------------------------------
// // dof.Frame(); for (int i = 0; i < dofs.Length; i++) {
dofs[0].Frame(); if (dofs[i].Active) {
dofs[1].Frame(); dofs[i].Frame();
dofs[2].Frame(); }
dofs[3].Frame(); }
WaveCursor lwc = (WaveCursor)dofs[0]; // <Heresy>
WaveCursor rwc = (WaveCursor)dofs[1]; WaveCursor lwc = (WaveCursor)((Chiral)dofs[0]).dofs[0];
Trackballer ltb = (Trackballer)dofs[2]; WaveCursor rwc = (WaveCursor)((Chiral)dofs[0]).dofs[1];
Trackballer rtb = (Trackballer)dofs[3]; Trackballer ltb = (Trackballer)((Chiral)dofs[1]).dofs[0];
Trackballer rtb = (Trackballer)((Chiral)dofs[1]).dofs[1];
if (lwc.Active) {
lwc.Demo(ltb.ori); lwc.Demo(ltb.ori);
}
if (rwc.Active) {
rwc.Demo(rtb.ori); rwc.Demo(rtb.ori);
}
if (rtb.Active) {
rtb.Demo(); rtb.Demo();
}
// </Heresy>
// rBlock.Step(); lBlock.Step(); // rBlock.Step(); lBlock.Step();
@ -127,8 +136,10 @@ public class Mono {
ShowWindowButton(); ShowWindowButton();
} }
int dofIndex = 0;
Pose windowPoseButton = new Pose(-0.5f, 1.3f, 0, Quat.FromAngles(0, -90f, 0)); 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); TextStyle style = Text.MakeStyle(Font.FromFile("add/fonts/DM-Mono.ttf"), 1f * U.cm, Color.White);
TextStyle style2 = Text.MakeStyle(Font.FromFile("add/fonts/DM-Mono.ttf"), 1f * U.cm, new Color(0.5f, 0.5f, 0.5f));
Vec2 fieldSize = new Vec2(6f * U.cm, 3f * U.cm); Vec2 fieldSize = new Vec2(6f * U.cm, 3f * U.cm);
void ShowWindowButton() { void ShowWindowButton() {
UI.WindowBegin("design vars", ref windowPoseButton); UI.WindowBegin("design vars", ref windowPoseButton);
@ -146,60 +157,128 @@ 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("°wavecursor"); if (UI.Button("prev") && dofIndex > 0) {
UI.Input("wavecursor.reach", ref wcReach.str, fieldSize, TextContext.Number); dofIndex--;
UI.SameLine(); UI.Label("reach"); }
UI.Input("wavecursor.length", ref wcLength.str, fieldSize, TextContext.Number); UI.SameLine();
UI.SameLine(); UI.Label("length"); if (UI.Button("next") && dofIndex < dofs.Length - 1) {
UI.Input("wavecursor.scale", ref wcScale.str, fieldSize, TextContext.Number); dofIndex++;
UI.SameLine(); UI.Label("scale"); }
UI.Input("wavecursor.radius", ref wcRadius.str, fieldSize, TextContext.Number);
UI.SameLine(); UI.Label("radius");
UI.Label("°trackballer");
UI.Input("trackballer.compliance", ref tbCompliance.str, fieldSize, TextContext.Number);
UI.SameLine(); UI.Label("compliance");
UI.Input("trackballer.x", ref tbX.str, fieldSize, TextContext.Number);
UI.SameLine(); UI.Label("x");
UI.Input("trackballer.y", ref tbY.str, fieldSize, TextContext.Number);
UI.SameLine(); UI.Label("y");
UI.Input("trackballer.z", ref tbZ.str, fieldSize, TextContext.Number);
UI.SameLine(); UI.Label("z");
// flipIndex dof dof = dofs[dofIndex];
// flipGrip Type type = dof.GetType();
// active toggle
Color tint = dof.Active ? new Color(0, 1, 0) : new Color(1, 0, 0);
UI.PushTint(tint);
if (UI.Button(dof.Active ? "on" : "off")) {
dof.Active = !dof.Active;
}
UI.PopTint();
if (type == typeof(Chiral)) {
Chiral chiral = (Chiral)dof;
System.Reflection.FieldInfo[] fields = typeof(Chiral).GetFields();
foreach (System.Reflection.FieldInfo field in fields) {
if (field.FieldType == typeof(Handed)) {
Handed handed = (Handed)field.GetValue(chiral);
if (UI.Button("<") && (int)handed > 0) {
handed = (Handed)((int)handed - 1);
field.SetValue(chiral, handed);
}
UI.SameLine();
if (UI.Button(">") && (int)handed < 2) {
handed = (Handed)((int)handed + 1);
field.SetValue(chiral, handed);
}
UI.SameLine(); UI.Label(handed.ToString());
}
}
RenderDof(chiral.dofs[0]);
} else {
RenderDof(dof);
}
UI.WindowEnd(); UI.WindowEnd();
} }
public Design wcReach = new Design("1.0", 0); void RenderDof(dof dof) {
public Design wcLength = new Design("0.666", 0f, 1f); Type type = dof.GetType();
public Design wcScale = new Design("0.333", 0.001f); UI.Label("°" + type.Name);
public Design wcRadius = new Design("4", 0); System.Reflection.FieldInfo[] fields = type.GetFields();
for (int j = 0; j < fields.Length; j++) {
System.Reflection.FieldInfo field = fields[j];
if (field.FieldType == typeof(Design)) {
Design design = (Design)field.GetValue(dof);
UI.Input(field.Name, ref design.str, fieldSize, TextContext.Number);
public Design tbCompliance = new Design("0.0", 0f, 1f); UI.SameLine();
public Design tbX = new Design("1.0", -10f, 10f); UI.PushTextStyle(style2);
public Design tbY = new Design("2.0", -10f, 10f); UI.Label(design.term, new Vec2(4f * U.cm, 3f * U.cm));
public Design tbZ = new Design("-4.0", -10f, 10f); UI.PopTextStyle();
// public float playerY = 0;
UI.SameLine(); UI.Label(field.Name);
}
}
}
}
// Chiral : handedness implies symmetry
public class Chiral : dof {
private bool active;
public bool Active {
get { return this.active; }
set {
this.active = value;
for (int i = 0; i < this.dofs.Length; i++) {
dof dof = this.dofs[i];
if ((int)this.handed == 2 || i == (int)this.handed) {
dof.Active = value;
} else {
dof.Active = false;
}
}
}
}
public dof[] dofs = new dof[2];
// public Design handed = new Design { str = "2", min = 0, max = 2};
public Handed handed = Handed.Max;
public void Init() {
dofs[0].Init();
dofs[1].Init();
}
public void Frame() {
// sync the left design variables to the right
System.Reflection.FieldInfo[] fields = dofs[0].GetType().GetFields();
foreach (System.Reflection.FieldInfo field in fields) {
if (field.FieldType == typeof(Design)) {
Design design = (Design)field.GetValue(dofs[0]); // define type?
field.SetValue(dofs[1], design);
}
}
for (int i = 0; i < dofs.Length; i++) {
dof dof = dofs[i];
if ((int)handed == 2 || i == (int)handed) {
dof.Frame();
dof.Active = true;
}
else {
dof.Active = false;
}
}
}
} }
// convert into a class
// which also simplifies injection and persistence
public class Design { public class Design {
public string str; public string str;
public string term;
float min, max; public float min = float.NegativeInfinity;
public Design(string str, public float max = float.PositiveInfinity;
float min = float.NegativeInfinity, public float unit = U.m;
float max = float.PositiveInfinity
) {
this.str = str;
this.min = min;
this.max = max;
}
public float value { public float value {
get { get {
@ -207,21 +286,44 @@ public class Design {
float value = PullRequest.Clamp(float.Parse(str), min, max); float value = PullRequest.Clamp(float.Parse(str), min, max);
// if clamped, update string // if clamped, update string
if (value != float.Parse(str)) { if (value != float.Parse(str)) {
// if (str.Contains(".")) {
// str = "";
// }
str = value.ToString(); str = value.ToString();
} }
return value; return value * unit;
} catch { } catch {
return 0; return 0;
} }
} }
} }
// public int integer; // public int integer {};
} }
/* /*
COMMENTS COMMENTS
ranges
0+1
1-0
1-0+1
-0+
0+&&-
0+||-
units
m
cm
mm
t
demo
virtual shapes -> that can be slotted
physics boxes
debug bool debug bool
rendering the raw output rendering the raw output
particularly for hand tracking dofs (so Moses can better test them!) particularly for hand tracking dofs (so Moses can better test them!)

View file

@ -2,4 +2,5 @@ public interface dof { // <T> ?
void Init(); void Init();
void Frame(); void Frame();
// void Drop(); // void Drop();
bool Active { get; set; }
} }

View file

@ -1,6 +1,8 @@
namespace Oriels; namespace Oriels;
class StretchCursor : dof { class StretchCursor : dof {
public bool Active { get; set; }
// input // input
Vec3 vTo; Vec3 vTo;
Vec3 vFrom; Vec3 vFrom;

View file

@ -1,6 +1,10 @@
namespace Oriels; namespace Oriels;
class WaveCursor : dof { class WaveCursor : dof {
public bool Active { get; set; }
// input
public Handed handed = Handed.Left;
public class Cursor public class Cursor
{ {
@ -25,14 +29,15 @@ class WaveCursor : dof {
float fR = Flexion(hand, FingerId.Ring); float fR = Flexion(hand, FingerId.Ring);
float fL = Flexion(hand, FingerId.Little); float fL = Flexion(hand, FingerId.Little);
float stretch = (fI + fI + fM + fM + fM + fR + fR + fL) / 8f; // based on finger length // Biased by finger length
float stretch = (fI + fI + fM + fM + fM + fR + fR + fL) / 8f;
Vec3 dir = PullRequest.Direction( Vec3 dir = PullRequest.Direction(
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; cursor.raw = hand.Get(FingerId.Index, JointId.Tip).position + dir * stretch * reach.value;
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);
@ -44,11 +49,14 @@ class WaveCursor : dof {
} }
} }
public float deadzone = 0.3f; // design
public float strength { public Design deadzone = new Design { str="0.3", term="0+1t", min=0, max=1 };
get { return Mono.inst.wcReach.value; } // 1f public Design reach = new Design { str="1.0", term="0+m", min=0 };
}
public Handed handed = Handed.Left; // demo
public Design snakeLength = new Design { str="0.5", term="0+1t", min=0, max=1 };
public Design snakeScale = new Design { str="0.333", term="0+", min=0 };
public Design snakeRadius = new Design { str="4", term="0+cm", unit=U.cm, min=0 };
float Flexion(Hand hand, FingerId finger) { float Flexion(Hand hand, FingerId finger) {
@ -63,34 +71,19 @@ class WaveCursor : dof {
) )
) + 1f) / 2; ) + 1f) / 2;
return Math.Max(flexion - deadzone, 0f) / (1 - deadzone); return Math.Max(flexion - deadzone.value, 0f) / (1 - deadzone.value);
} }
Vec3[] mm = new Vec3[81]; Vec3[] mm = new Vec3[128];
Vec3[] xL = new Vec3[81];
Vec3[] xR = new Vec3[81];
Vec3[] yL = new Vec3[81];
Vec3[] yR = new Vec3[81];
Vec3[] zL = new Vec3[81];
Vec3[] zR = new Vec3[81];
public void Demo(Quat ori) { public void Demo(Quat ori) {
Trail( Vec3 tPos = cursor.smooth + ori * Vec3.Forward * snakeRadius.value;
mm, Lines.Add(cursor.smooth, tPos, Color.White, 0.001f);
cursor.smooth + ori * new Vec3(0, 0, Mono.inst.wcRadius.value * U.cm) Trail(mm, tPos);
);
// Trail(xL, smoothPos + cursor.orientation * new Vec3(-1, 0, 0) * 0.1f);
// Trail(xR, smoothPos + cursor.orientation * new Vec3( 1, 0, 0) * 0.1f);
// Trail(yL, smoothPos + cursor.orientation * new Vec3(0, -1, 0) * 0.1f);
// Trail(yR, smoothPos + cursor.orientation * new Vec3(0, 1, 0) * 0.1f);
// Trail(zL, smoothPos + cursor.orientation * new Vec3(0, 0, -1) * 0.1f);
// Trail(zR, smoothPos + cursor.orientation * new Vec3(0, 0, 1) * 0.1f);
} }
void Trail(Vec3[] points, Vec3 nextPos) { void Trail(Vec3[] points, Vec3 nextPos) {
float scale = Mono.inst.wcScale.value; float scale = snakeScale.value;
while (Vec3.Distance(points[0], nextPos) > 0.03f * scale) { 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];
@ -100,7 +93,7 @@ class WaveCursor : dof {
// points[0] = nextPos; // points[0] = nextPos;
int len = (int)(points.Length * Mono.inst.wcLength.value); int len = (int)(points.Length * snakeLength.value);
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;

View file

@ -1,6 +1,10 @@
namespace Oriels; namespace Oriels;
class Trackballer : dof { class Trackballer : dof {
public bool Active { get; set; }
// input
public Handed handed = Handed.Left;
// data // data
public Btn btnIn, btnOut; public Btn btnIn, btnOut;
@ -52,9 +56,9 @@ class Trackballer : dof {
// Ball anchor // Ball anchor
HandJoint ballJoint = hand.Get(FingerId.Index, JointId.KnuckleMajor); HandJoint ballJoint = hand.Get(FingerId.Index, JointId.KnuckleMajor);
Vec3 anchorPos = ballJoint.position + hand.palm.orientation * new Vec3( Vec3 anchorPos = ballJoint.position + hand.palm.orientation * new Vec3(
Mono.inst.tbX.value * U.cm * (handed == Handed.Left ? -1 : 1), aX.value * (handed == Handed.Left ? -1 : 1),
Mono.inst.tbY.value * U.cm, aY.value,
Mono.inst.tbZ.value * U.cm aZ.value
); );
anchorPos += compliance.Update( anchorPos += compliance.Update(
Vec3.Zero, Vec3.Zero,
@ -130,8 +134,13 @@ class Trackballer : dof {
// offset.z = 0; // offset.z = 0;
offset = hand.palm.orientation * offset; offset = hand.palm.orientation * offset;
compliance.value += offset * Mono.inst.tbCompliance.value; compliance.value += offset * compliant.value;
compliance.integral = Vec3.Zero; compliance.integral = Vec3.Zero;
} else {
PullRequest.ToAxisAngle(momentum, out Vec3 axis, out float angle);
if (angle < stop.value) {
momentum = Quat.Slerp(momentum, Quat.Identity, Time.Elapsedf * 10f);
}
} }
} }
@ -144,7 +153,12 @@ class Trackballer : dof {
} }
// design // design
public Handed handed = Handed.Left; public Design stop = new Design { str="0.05", term="0+", min=0 };
public Design compliant = new Design { str="0.2", term="0+1t", min=0, max=1 };
public Design aX = new Design { str=" 1.0", term="-0+cm", unit=U.cm, min=-10f, max=10f };
public Design aY = new Design { str=" 2.0", term="-0+cm", unit=U.cm, min=-10f, max=10f };
public Design aZ = new Design { str="-4.0", term="-0+cm", unit=U.cm, min=-10f, max=10f };
public float[] layer = new float[] { 0.00333f, 0.02f, 0.0666f }; public float[] layer = new float[] { 0.00333f, 0.02f, 0.0666f };