design reflection
This commit is contained in:
parent
510449eebb
commit
3fd6f272d0
5 changed files with 216 additions and 104 deletions
242
app/Mono.cs
242
app/Mono.cs
|
@ -16,8 +16,6 @@ public class Mono {
|
|||
// -------------------------------------------------
|
||||
|
||||
public dof[] dofs;
|
||||
int dofIndex = 0;
|
||||
dof dof => dofs[dofIndex];
|
||||
|
||||
public ColorCube colorCube = new ColorCube();
|
||||
|
||||
|
@ -43,24 +41,27 @@ public class Mono {
|
|||
Renderer.SetClip(0.02f, 1000f);
|
||||
|
||||
dofs = new dof[] {
|
||||
// new StretchFinger(),
|
||||
new WaveCursor() { handed = Handed.Left },
|
||||
new WaveCursor() { handed = Handed.Right },
|
||||
new Trackballer() { handed = Handed.Left },
|
||||
new Trackballer() { handed = Handed.Right },
|
||||
// new StretchCursor() { },
|
||||
// new StretchCursor() { },
|
||||
new Chiral() {
|
||||
dofs = new dof[] {
|
||||
new WaveCursor() { handed = Handed.Left },
|
||||
new WaveCursor() { handed = Handed.Right }
|
||||
}
|
||||
},
|
||||
new Chiral() {
|
||||
dofs = new dof[] {
|
||||
new Trackballer() { handed = Handed.Left },
|
||||
new Trackballer() { handed = Handed.Right }
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public void Init() {
|
||||
compositor.Init();
|
||||
|
||||
dofs[0].Init();
|
||||
dofs[1].Init();
|
||||
dofs[2].Init();
|
||||
dofs[3].Init();
|
||||
|
||||
for (int i = 0; i < dofs.Length; i++) {
|
||||
dofs[i].Init();
|
||||
}
|
||||
|
||||
matDev = Material.Default.Copy();
|
||||
matDev.SetTexture("diffuse", Tex.DevTex);
|
||||
|
@ -97,21 +98,29 @@ public class Mono {
|
|||
|
||||
// -------------------------------------------------
|
||||
|
||||
// // dof.Frame();
|
||||
dofs[0].Frame();
|
||||
dofs[1].Frame();
|
||||
dofs[2].Frame();
|
||||
dofs[3].Frame();
|
||||
for (int i = 0; i < dofs.Length; i++) {
|
||||
if (dofs[i].Active) {
|
||||
dofs[i].Frame();
|
||||
}
|
||||
}
|
||||
|
||||
WaveCursor lwc = (WaveCursor)dofs[0];
|
||||
WaveCursor rwc = (WaveCursor)dofs[1];
|
||||
Trackballer ltb = (Trackballer)dofs[2];
|
||||
Trackballer rtb = (Trackballer)dofs[3];
|
||||
// <Heresy>
|
||||
WaveCursor lwc = (WaveCursor)((Chiral)dofs[0]).dofs[0];
|
||||
WaveCursor rwc = (WaveCursor)((Chiral)dofs[0]).dofs[1];
|
||||
Trackballer ltb = (Trackballer)((Chiral)dofs[1]).dofs[0];
|
||||
Trackballer rtb = (Trackballer)((Chiral)dofs[1]).dofs[1];
|
||||
|
||||
lwc.Demo(ltb.ori);
|
||||
rwc.Demo(rtb.ori);
|
||||
if (lwc.Active) {
|
||||
lwc.Demo(ltb.ori);
|
||||
}
|
||||
if (rwc.Active) {
|
||||
rwc.Demo(rtb.ori);
|
||||
}
|
||||
|
||||
rtb.Demo();
|
||||
if (rtb.Active) {
|
||||
rtb.Demo();
|
||||
}
|
||||
// </Heresy>
|
||||
|
||||
// rBlock.Step(); lBlock.Step();
|
||||
|
||||
|
@ -127,8 +136,10 @@ public class Mono {
|
|||
ShowWindowButton();
|
||||
}
|
||||
|
||||
int dofIndex = 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 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);
|
||||
void ShowWindowButton() {
|
||||
UI.WindowBegin("design vars", ref windowPoseButton);
|
||||
|
@ -146,60 +157,128 @@ public class Mono {
|
|||
// UI.Label("pos.y");
|
||||
// UI.HSlider("pos.y", ref playerY, -1f, 1f, 0.1f);
|
||||
|
||||
UI.Label("°wavecursor");
|
||||
UI.Input("wavecursor.reach", ref wcReach.str, fieldSize, TextContext.Number);
|
||||
UI.SameLine(); UI.Label("reach");
|
||||
UI.Input("wavecursor.length", ref wcLength.str, fieldSize, TextContext.Number);
|
||||
UI.SameLine(); UI.Label("length");
|
||||
UI.Input("wavecursor.scale", ref wcScale.str, fieldSize, TextContext.Number);
|
||||
UI.SameLine(); UI.Label("scale");
|
||||
UI.Input("wavecursor.radius", ref wcRadius.str, fieldSize, TextContext.Number);
|
||||
UI.SameLine(); UI.Label("radius");
|
||||
if (UI.Button("prev") && dofIndex > 0) {
|
||||
dofIndex--;
|
||||
}
|
||||
UI.SameLine();
|
||||
if (UI.Button("next") && dofIndex < dofs.Length - 1) {
|
||||
dofIndex++;
|
||||
}
|
||||
|
||||
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
|
||||
// flipGrip
|
||||
dof dof = dofs[dofIndex];
|
||||
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();
|
||||
}
|
||||
|
||||
public Design wcReach = new Design("1.0", 0);
|
||||
public Design wcLength = new Design("0.666", 0f, 1f);
|
||||
public Design wcScale = new Design("0.333", 0.001f);
|
||||
public Design wcRadius = new Design("4", 0);
|
||||
void RenderDof(dof dof) {
|
||||
Type type = dof.GetType();
|
||||
UI.Label("°" + type.Name);
|
||||
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);
|
||||
public Design tbX = new Design("1.0", -10f, 10f);
|
||||
public Design tbY = new Design("2.0", -10f, 10f);
|
||||
public Design tbZ = new Design("-4.0", -10f, 10f);
|
||||
|
||||
// public float playerY = 0;
|
||||
UI.SameLine();
|
||||
UI.PushTextStyle(style2);
|
||||
UI.Label(design.term, new Vec2(4f * U.cm, 3f * U.cm));
|
||||
UI.PopTextStyle();
|
||||
|
||||
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 string str;
|
||||
|
||||
float min, max;
|
||||
public Design(string str,
|
||||
float min = float.NegativeInfinity,
|
||||
float max = float.PositiveInfinity
|
||||
) {
|
||||
this.str = str;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
public string term;
|
||||
public float min = float.NegativeInfinity;
|
||||
public float max = float.PositiveInfinity;
|
||||
public float unit = U.m;
|
||||
|
||||
public float value {
|
||||
get {
|
||||
|
@ -207,21 +286,44 @@ public class Design {
|
|||
float value = PullRequest.Clamp(float.Parse(str), min, max);
|
||||
// if clamped, update string
|
||||
if (value != float.Parse(str)) {
|
||||
// if (str.Contains(".")) {
|
||||
// str = "";
|
||||
// }
|
||||
str = value.ToString();
|
||||
}
|
||||
return value;
|
||||
return value * unit;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// public int integer;
|
||||
// public int integer {};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
rendering the raw output
|
||||
particularly for hand tracking dofs (so Moses can better test them!)
|
||||
|
|
|
@ -2,4 +2,5 @@ public interface dof { // <T> ?
|
|||
void Init();
|
||||
void Frame();
|
||||
// void Drop();
|
||||
bool Active { get; set; }
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
namespace Oriels;
|
||||
|
||||
class StretchCursor : dof {
|
||||
public bool Active { get; set; }
|
||||
|
||||
// input
|
||||
Vec3 vTo;
|
||||
Vec3 vFrom;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
namespace Oriels;
|
||||
|
||||
class WaveCursor : dof {
|
||||
public bool Active { get; set; }
|
||||
|
||||
// input
|
||||
public Handed handed = Handed.Left;
|
||||
|
||||
public class Cursor
|
||||
{
|
||||
|
@ -25,14 +29,15 @@ class WaveCursor : dof {
|
|||
float fR = Flexion(hand, FingerId.Ring);
|
||||
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(
|
||||
hand.Get(FingerId.Index, JointId.Tip).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.y = (float)yF.Filter(cursor.raw.y, (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;
|
||||
public float strength {
|
||||
get { return Mono.inst.wcReach.value; } // 1f
|
||||
}
|
||||
public Handed handed = Handed.Left;
|
||||
// design
|
||||
public Design deadzone = new Design { str="0.3", term="0+1t", min=0, max=1 };
|
||||
public Design reach = new Design { str="1.0", term="0+m", min=0 };
|
||||
|
||||
// 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) {
|
||||
|
@ -63,34 +71,19 @@ class WaveCursor : dof {
|
|||
)
|
||||
) + 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[] 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];
|
||||
Vec3[] mm = new Vec3[128];
|
||||
public void Demo(Quat ori) {
|
||||
Trail(
|
||||
mm,
|
||||
cursor.smooth + ori * new Vec3(0, 0, Mono.inst.wcRadius.value * U.cm)
|
||||
);
|
||||
|
||||
// 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);
|
||||
Vec3 tPos = cursor.smooth + ori * Vec3.Forward * snakeRadius.value;
|
||||
Lines.Add(cursor.smooth, tPos, Color.White, 0.001f);
|
||||
Trail(mm, tPos);
|
||||
}
|
||||
|
||||
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) {
|
||||
for (int i = points.Length - 1; i > 0; i--) {
|
||||
points[i] = points[i - 1];
|
||||
|
@ -100,7 +93,7 @@ class WaveCursor : dof {
|
|||
|
||||
|
||||
// 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++) {
|
||||
// if (i > 0) {
|
||||
// Vec3 dir = Vec3.Forward;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
namespace Oriels;
|
||||
|
||||
class Trackballer : dof {
|
||||
public bool Active { get; set; }
|
||||
|
||||
// input
|
||||
public Handed handed = Handed.Left;
|
||||
|
||||
// data
|
||||
public Btn btnIn, btnOut;
|
||||
|
@ -52,9 +56,9 @@ class Trackballer : dof {
|
|||
// Ball anchor
|
||||
HandJoint ballJoint = hand.Get(FingerId.Index, JointId.KnuckleMajor);
|
||||
Vec3 anchorPos = ballJoint.position + hand.palm.orientation * new Vec3(
|
||||
Mono.inst.tbX.value * U.cm * (handed == Handed.Left ? -1 : 1),
|
||||
Mono.inst.tbY.value * U.cm,
|
||||
Mono.inst.tbZ.value * U.cm
|
||||
aX.value * (handed == Handed.Left ? -1 : 1),
|
||||
aY.value,
|
||||
aZ.value
|
||||
);
|
||||
anchorPos += compliance.Update(
|
||||
Vec3.Zero,
|
||||
|
@ -130,8 +134,13 @@ class Trackballer : dof {
|
|||
// offset.z = 0;
|
||||
|
||||
offset = hand.palm.orientation * offset;
|
||||
compliance.value += offset * Mono.inst.tbCompliance.value;
|
||||
compliance.value += offset * compliant.value;
|
||||
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
|
||||
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 };
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue