namespace Oriels; public class Oriel { Model model = Model.FromFile("oriel.glb"); Mesh meshCube, meshSphere; Material matClear = new Material(Shader.Default); public Material matOriel = new Material(Shader.FromFile("shaders/oriel.hlsl")); Material matFrame = new Material(Shader.FromFile("shaders/frame.hlsl")); Material matPanes = new Material(Shader.FromFile("shaders/panes.hlsl")); public Matrix matrix, matrixInv; public Bounds bounds; public Quat ori = Quat.Identity; // inner matrix public bool scaleHeight = true; public float scale = 0.1f; public float multiplier = 1f; public Oriel() { // meshCube = model.GetMesh("oriel"); meshCube = Mesh.Cube; meshSphere = Mesh.Sphere; matClear.Transparency = Transparency.Add; matFrame.SetMat(102, Cull.Back, true); matFrame.Transparency = Transparency.Blend; matFrame.SetTexture("dither", Tex.FromFile("dither.png")); matPanes.SetMat(100, Cull.Front, false); matOriel.SetMat(101, Cull.None, true); bounds = new Bounds( new Vec3(-1.0f, -0.5f, 0.5f), new Vec3(0.8f, 0.5f, 0.5f) ); matrix = Matrix.TR(bounds.center, ori); matrixInv = matrix.Inverse; cursor = bounds.center; cornerRadius = cursorRadius / 2; } public Vec3 cursor = Vec3.Zero; public float cursorRadius = 0.1f; public float cornerRadius; Vec3 detect = Vec3.Zero; int detectCount = 0; public Vec3 LocalAnchor { get { return detect * bounds.dimensions / 2; } } public Vec3 Anchor { get { return matrix.Transform(LocalAnchor); } } Quat qOffset = Quat.Identity; Vec3 vOffset = Vec3.Zero; Vec3 lOffset = Vec3.Zero; Matrix mOffset = Matrix.Identity; public void Frame() { // input Rig rig = Mono.inst.rig; Glove rGlove = Mono.inst.rGlove; // cursor = rGlove.virtualGlove.position; Quat rGloveRot = rGlove.virtualGlove.orientation; // Vec3 lGlovePos = rig.lGlove.virtualGlove.position; bool grab = !Input.Key(Key.Space).IsActive(); // !rig.rCon.triggerBtn.held if (!Input.Key(Key.Shift).IsActive()) { Vec3 input = new Vec3( (Input.Key(Key.S).IsActive() ? 1 : 0) - (Input.Key(Key.A).IsActive() ? 1 : 0), (Input.Key(Key.F).IsActive() ? 1 : 0) - (Input.Key(Key.Q).IsActive() ? 1 : 0), (Input.Key(Key.R).IsActive() ? 1 : 0) - (Input.Key(Key.W).IsActive() ? 1 : 0) ); if (input.Length > 0) { cursor += input.Normalized * Time.Elapsedf * 0.4f; } } Vec3 localCursor = matrixInv.Transform(cursor); // ori = Quat.FromAngles(0, MathF.Sin(Time.Totalf) * 90f, 0); if (grab) { // generate all the potential anchors // pick the closest one Vec3 v = Vec3.Zero; float minDist = float.MaxValue; for (int i = 0; i < anchors.Length; i++) { Vec3 a = matrix.Transform(anchors[i] * bounds.dimensions / 2); float dist = (a - cursor).Length; if (dist < minDist) { minDist = dist; v = anchors[i]; } } detect = v; // rename this detectCount = (int)(MathF.Abs(v.x) + MathF.Abs(v.y) + MathF.Abs(v.z)); vOffset = cursor - bounds.center; lOffset = ori.Inverse * vOffset; qOffset = (ori.Inverse * rGloveRot).Normalized; mOffset = matrix; } else { if (detectCount == 1) { // Move (face -> crown *face) ori = (rGloveRot * qOffset.Inverse).Normalized; bounds.center = cursor - ori * lOffset; } else if (detectCount == 2) { // Rotate (edge -> edge) // localPos = mOffset.Inverse.Transform(cursor); // Vec3 dir = new Vec3( // detect.x == 0 ? 0 : localPos.x, // detect.y == 0 ? 0 : localPos.y, // detect.z == 0 ? 0 : localPos.z // ); // Vec3 up = new Vec3( // detect.x == 0 ? 1 : 0, // detect.y == 0 ? 1 : 0, // detect.z == 0 ? 1 : 0 // ); // Quat q = Quat.LookAt(Vec3.Zero, dir, up); // if (!adjusting) { // qOffset = (q.Inverse * ori).Normalized; // adjusting = true; // } else { // ori = (q * qOffset).Normalized; // } } else if (detectCount == 3) { // Scale (corner -> corner) Vec3 zAnchor = Anchor - ori * detect.JustZ() * cornerRadius; float stab = MathF.Max(cursorRadius - Vec3.Distance(zAnchor, cursor), 0); if (stab > 0) { float distZ = Math.Abs(-LocalAnchor.z - localCursor.z); bounds.center.z = PullRequest.Lerp(matrix.Transform(-LocalAnchor).z, cursor.z, 0.5f); bounds.dimensions.z = distZ; } } } matrix = Matrix.TR(bounds.center, ori); matrixInv = matrix.Inverse; } // design vars public float crown = 0.16f; public void Render() { // // matFrame.Wireframe = true; // matFrame.DepthTest = DepthTest.Always; // matFrame.SetVector("_cursor", cursor); // matFrame.SetFloat("_time", Time.Totalf); // meshCube.Draw(matFrame, // Matrix.TRS(bounds.center, ori, bounds.dimensions), // new Color(0.1f, 0.1f, 0.1f) // ); // matPanes.DepthTest = DepthTest.Greater; matPanes["_matrix"] = (Matrix)System.Numerics.Matrix4x4.Transpose(matrixInv); meshCube.Draw(matPanes, Matrix.TRS(bounds.center, ori, bounds.dimensions), new Color(0f, 0f, 0f) // new Color(78 / 256f, 142 / 256f, 191 / 256f) ); matOriel.SetVector("_center", bounds.center); matOriel.SetVector("_dimensions", bounds.dimensions); matOriel.SetVector("_light", ori * new Vec3(0.6f, -0.9f, 0.3f)); matOriel.SetFloat("_lit", 1); matOriel["_matrix"] = (Matrix)System.Numerics.Matrix4x4.Transpose(matrixInv); // cursor if (detectCount > 0) { meshCube.Draw(Material.Default, Matrix.TS(LocalAnchor, Vec3.One * 0.01f) * matrix ); // draw the corner with 0.1f length lines if (detectCount == 3) { Color col = new Color(1f, 1f, 1f); float thk = 0.005f; Lines.Add(Anchor, Anchor - ori * detect.JustX() * cornerRadius, col, thk); Lines.Add(Anchor, Anchor - ori * detect.JustY() * cornerRadius, col, thk); Lines.Add(Anchor, Anchor - ori * detect.JustZ() * cornerRadius, col, thk); // draw cube(s) on intersecting corner ends // Lines.Add( // zAnchor, zAnchor + ori * detect.JustZ() * stab * 1.5f, // new Color(0, 0, 1), 0.01f // ); } } meshCube.Draw(Material.Default, Matrix.TRS(cursor, Quat.Identity, new Vec3(0.01f, 0.01f, 0.01f)), new Color(1f, 1f, 1f) ); meshSphere.Draw(matClear, Matrix.TRS(cursor, Quat.Identity, new Vec3(1f, 1f, 1f) * cursorRadius * 2), new Color(0.5f, 0.5f, 0.5f) ); } // faces, edges, corners Vec3[] anchors = new Vec3[] { // faces new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, -1, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1), // edges new Vec3(1, 1, 0), new Vec3(-1, 1, 0), new Vec3(1, -1, 0), new Vec3(-1, -1, 0), new Vec3(1, 0, 1), new Vec3(-1, 0, 1), new Vec3(1, 0, -1), new Vec3(-1, 0, -1), new Vec3(0, 1, 1), new Vec3(0, -1, 1), new Vec3(0, 1, -1), new Vec3(0, -1, -1), // corners new Vec3(1, 1, 1), new Vec3(-1, 1, 1), new Vec3(1, -1, 1), new Vec3(-1, -1, 1), new Vec3(1, 1, -1), new Vec3(-1, 1, -1), new Vec3(1, -1, -1), new Vec3(-1, -1, -1) }; }