diff --git a/Tetrahedrons/MVec4D.cs b/Tetrahedrons/MVec4D.cs index eb9bdd5..bfb056b 100644 --- a/Tetrahedrons/MVec4D.cs +++ b/Tetrahedrons/MVec4D.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data.SqlClient; using System.Dynamic; +using System.Runtime.CompilerServices; using System.Runtime.Remoting.Messaging; using System.Text; using OpenTK; @@ -42,6 +43,8 @@ namespace Tetrahedrons public double Norm => Math.Sqrt(Norm2); + public MVec4D Normalized => this * (1 / Norm); + public MVec4D Grade(int k) { switch (k) @@ -929,12 +932,8 @@ namespace Tetrahedrons ); } - public static MVec4D? Div(MVec4D m, MVec4D n) => Mul(m, n.Inv); - public static MVec4D Div(MVec4D m, double c) => Mul(m, 1 / c); - public static MVec4D? Div(double c, MVec4D n) => Mul(c, n.Inv); - public static MVec4D Inner(MVec4D m, MVec4D n) { var m0 = m.Grade(0); @@ -1030,10 +1029,6 @@ namespace Tetrahedrons public static MVec4D operator *(double c, MVec4D n) => Mul(c, n); public static MVec4D operator *(MVec4D m, double c) => Mul(m, c); - public static MVec4D? operator /(MVec4D m, MVec4D n) => Div(m, n); - public static MVec4D? operator /(double c, MVec4D n) => Div(c, n); - public static MVec4D operator /(MVec4D m, double c) => Div(m, c); - public static MVec4D operator &(MVec4D m, MVec4D n) => Inner(m, n); public static MVec4D operator &(MVec4D m, double c) => Inner(m, c); public static MVec4D operator &(double c, MVec4D n) => Inner(c, n); @@ -1054,10 +1049,6 @@ namespace Tetrahedrons public static MVec4D? operator *(double? c, MVec4D? n) => Mul(c, n); public static MVec4D? operator *(MVec4D? m, double? c) => Mul(m, c); - public static MVec4D? operator /(MVec4D? m, MVec4D? n) => Div(m, n); - public static MVec4D? operator /(double? c, MVec4D? n) => Div(c, n); - public static MVec4D? operator /(MVec4D? m, double? c) => Div(m, c); - public static MVec4D? operator &(MVec4D? m, MVec4D? n) => Inner(m, n); public static MVec4D? operator &(MVec4D? m, double? c) => Inner(m, c); public static MVec4D? operator &(double? c, MVec4D? n) => Inner(c, n); diff --git a/Tetrahedrons/Simplex.cs b/Tetrahedrons/Simplex.cs new file mode 100644 index 0000000..1fc6e42 --- /dev/null +++ b/Tetrahedrons/Simplex.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Tetrahedrons +{ + public class Simplex + { + public MVec4D[] Verts; + + public Simplex(IEnumerable verts) + { + Verts = verts.ToArray(); + } + + public Simplex(params MVec4D[] verts) + { + Verts = verts; + } + + public bool[] Sides(MVec4D blade, MVec4D pivot) + { + var sides = new bool[Verts.Length]; + + var perp = blade.Dual; + + for (var i = 0; i < Verts.Length; i++) + { + var m = Verts[i]; + var p = m - pivot; + var rej = (p ^ blade) * ~blade; + if (!rej.HasValue) continue; + var dot = rej & perp; + + sides[i] = dot.Value.S > 0; + } + + return sides; + } + + public Simplex Intersect(MVec4D blade, MVec4D pivot) + { + var sides = Sides(blade, pivot); + var verts = new List(); + + for (var i = 0; i < Verts.Length; i++) + for (var j = i + 1; j < Verts.Length; j++) + { + if (sides[i] == sides[j]) continue; + var m = Verts[i] - pivot; + var n = Verts[j] - pivot; + + var v = m - n; + var alph = (blade ^ m) * ~(blade ^ v); + if (!alph.HasValue) continue; + var p = m - v * alph.Value; + verts.Add(p); + } + + return new Simplex(verts); + } + + public int[] Faces() + { + switch (Verts.Length) + { + case 3: + return new[] {0, 1, 2}; + case 4: + return new[] + { + 0, 1, 2, + 0, 1, 3, + 0, 2, 3, + 1, 2, 3 + }; + case 6: + return new[] + { + 0, 2, 4 + // todo: vertices of a face must be on lines which share a vertex in the simplex + // that's the pattern, and why it "just works" for the 3-simplex. + // think of it as truncating the embedded simplex + }; + + default: + return new int[0]; + } + } + } +} \ No newline at end of file diff --git a/Tetrahedrons/TetrahedronWindow.cs b/Tetrahedrons/TetrahedronWindow.cs index b95f896..124e9da 100644 --- a/Tetrahedrons/TetrahedronWindow.cs +++ b/Tetrahedrons/TetrahedronWindow.cs @@ -1,13 +1,17 @@ using System; -using System.Collections.Generic; +using System.Diagnostics.PerformanceData; using System.Drawing; using System.Drawing.Printing; +using System.Net; using System.Net.Mail; +using System.Runtime.InteropServices.ComTypes; using System.Security; +using System.Xml.XPath; using OpenTK; using OpenTK.Audio.OpenAL; using OpenTK.Graphics.OpenGL; using OpenTK.Input; +using OpenTK.Platform.Windows; namespace Tetrahedrons { @@ -16,10 +20,13 @@ namespace Tetrahedrons private Matrix4 _proj3d; private Matrix4 _view; - MVec4D a = MVec4D.UnitX; - MVec4D b = MVec4D.UnitY; - MVec4D v = MVec4D.Vec1(1, 1, 0, -1); - MVec4D t = MVec4D.Vec1(0, 0, 0, 1); + private MVec4D _a = MVec4D.UnitX; + private MVec4D _b = MVec4D.UnitY; + + private Simplex _pent; + private Simplex _intr; + + private double _t; protected override void OnLoad(EventArgs e) { @@ -28,8 +35,14 @@ namespace Tetrahedrons X = (DisplayDevice.Default.Width - Width) / 2; Y = (DisplayDevice.Default.Height - Height) / 2; - _view = Matrix4.LookAt(Vector3.Zero, -new Vector3(1, 1, 1), Vector3.UnitZ); + _view = Matrix4.LookAt(Vector3.Zero, -new Vector3(.86f, .5f, 1), Vector3.UnitZ); + _pent = new Simplex( // not-quite-regular pentatope + new Vector4d(1, -1, -1, -1), + new Vector4d(-1, 1, -1, -1), + new Vector4d(-1, -1, 1, -1), + new Vector4d(-1, -1, -1, 1), + new Vector4d(1, 1, 1, 1)); } protected override void OnRenderFrame(FrameEventArgs e) @@ -39,7 +52,6 @@ namespace Tetrahedrons GL.Viewport(ClientRectangle); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - GL.Enable(EnableCap.DepthTest); GL.PointSize(10f); GL.LineWidth(3f); @@ -50,41 +62,42 @@ namespace Tetrahedrons GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref _view); - GL.Disable(EnableCap.DepthTest); GL.Begin(PrimitiveType.TriangleStrip); GL.Color3(1d, 1, 1); - GL.Vertex3((-a - b).V3); - GL.Vertex3((-a + b).V3); - GL.Vertex3((a - b).V3); - GL.Vertex3((a + b).V3); + Util.Vertex3(-_a - _b); + Util.Vertex3(-_a + _b); + Util.Vertex3(_a - _b); + Util.Vertex3(_a + _b); GL.End(); + GL.Enable(EnableCap.DepthTest); - - GL.Begin(PrimitiveType.Lines); - GL.Color3(1d,0,0); GL.Vertex3(0,0,0); GL.Vertex3(1,0,0); - GL.Color3(0,1d,0); GL.Vertex3(0,0,0); GL.Vertex3(0,1,0); - GL.Color3(0,0,1d); GL.Vertex3(0,0,0); GL.Vertex3(0,0,1); + GL.Begin(PrimitiveType.Triangles); + foreach (var f in _intr.Faces()) + { + Util.Color3(_intr.Verts[f]); + Util.Vertex3(_intr.Verts[f]); + } + GL.End(); + GL.Disable(EnableCap.DepthTest); + + GL.Begin(PrimitiveType.Points); + foreach (var m in _pent.Verts) + Util.Vertex4(m); GL.End(); - var B = MVec4D.UnitXyz; - var bt = B ^ t; - var bv = B ^ v; - var alph = bt / bv ?? MVec4D.Zero; - var dt = alph * v; - var p = t - dt; - - Console.Out.WriteLine("p = {0}", p); - GL.Begin(PrimitiveType.Lines); - GL.Color3(.5 + t.W/4, 0, .5 - t.W/4); - GL.Vertex3(t.V3); - GL.Color3(.5 + (t + v).W/4, 0, .5 - (t + v).W/4); - GL.Vertex3((t + v).V3); + for (var i = 0; i < _pent.Verts.Length; i++) + for (var j = i + 1; j < _pent.Verts.Length; j++) + { + Util.Vertex4(_pent.Verts[i]); + Util.Vertex4(_pent.Verts[j]); + } + GL.End(); GL.Begin(PrimitiveType.Points); - GL.Color3(0d, 0, 1); - GL.Vertex3(p.V3); + foreach (var m in _intr.Verts) + Util.Vertex4(m); GL.End(); SwapBuffers(); @@ -94,13 +107,24 @@ namespace Tetrahedrons { base.OnUpdateFrame(e); - _proj3d = Matrix4.CreateOrthographic(6, 6f * Height / Width, -2, 2); + _proj3d = Matrix4.CreateOrthographic(6, 6f * Height / Width, -4, 4); - var rv = MVec4D.Rotor(e.Time, MVec4D.UnitXy); - v = rv * v * !rv; + _t += e.Time; - var rt = MVec4D.Rotor(e.Time / 4, MVec4D.UnitZw); - t = rt * t * !rt; + var pln = MVec4D.UnitXy + MVec4D.UnitZw; + + var r = MVec4D.Rotor(e.Time / 10, pln.Normalized); + for (var i = 0; i < _pent.Verts.Length; i++) + { + var m = _pent.Verts[i]; + m = r * m * !r; + _pent.Verts[i] = m; + } + + var blade = MVec4D.UnitXyz; +// var pivot = .5 * MVec4D.UnitW; + var pivot = 1.1 * Math.Sin(_t) * MVec4D.UnitW; + _intr = _pent.Intersect(blade, pivot); } } } \ No newline at end of file diff --git a/Tetrahedrons/Tetrahedrons.csproj b/Tetrahedrons/Tetrahedrons.csproj index ad503ef..546af1a 100644 --- a/Tetrahedrons/Tetrahedrons.csproj +++ b/Tetrahedrons/Tetrahedrons.csproj @@ -45,7 +45,9 @@ + + diff --git a/Tetrahedrons/Util.cs b/Tetrahedrons/Util.cs new file mode 100644 index 0000000..6f3aa54 --- /dev/null +++ b/Tetrahedrons/Util.cs @@ -0,0 +1,25 @@ +using OpenTK.Graphics.OpenGL; + +namespace Tetrahedrons +{ + public static class Util + { + public static void Color3(MVec4D m) + { + m *= .5; + GL.Color3(.5 + m.X, .5 + m.Y, .5 * m.Z); + } + + public static void Vertex4(MVec4D m) + { + var i = m.W / 2; + GL.Color3(.5 + i, 0, .5 - i); + GL.Vertex3(m.X, m.Y, m.Z); + } + + public static void Vertex3(MVec4D m) + { + GL.Vertex3(m.X, m.Y, m.Z); + } + } +} \ No newline at end of file