diff --git a/examples/csharp/Demo.csproj b/examples/csharp/Demo.csproj
new file mode 100644
index 0000000..12ebe30
--- /dev/null
+++ b/examples/csharp/Demo.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/examples/csharp/Demo.sln b/examples/csharp/Demo.sln
new file mode 100644
index 0000000..a972a89
--- /dev/null
+++ b/examples/csharp/Demo.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36429.23 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "Demo.csproj", "{EBDDE3D7-AF12-4A1F-B099-0D046C271859}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EBDDE3D7-AF12-4A1F-B099-0D046C271859}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBDDE3D7-AF12-4A1F-B099-0D046C271859}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EBDDE3D7-AF12-4A1F-B099-0D046C271859}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EBDDE3D7-AF12-4A1F-B099-0D046C271859}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1E4249FD-1F82-4EE1-AF0B-68CAB69466C7}
+ EndGlobalSection
+EndGlobal
diff --git a/examples/csharp/LivePlotter.cs b/examples/csharp/LivePlotter.cs
index 8fd1860..d1239a5 100644
--- a/examples/csharp/LivePlotter.cs
+++ b/examples/csharp/LivePlotter.cs
@@ -1,10 +1,10 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
-using Common.Data;
-using pointid = System.UInt64;
-namespace TysonPalletScanner
+using PointID = System.UInt64;
+
+namespace Demo
{
public class LivePlotter
{
@@ -15,22 +15,22 @@ namespace TysonPalletScanner
public static extern bool stop();
[DllImport("LivePlotter.dll")]
- public static extern pointid create_point(float x, float y, float z);
+ public static extern PointID create_point(float x, float y, float z);
[DllImport("LivePlotter.dll")]
- public static extern void set_color(pointid id, float r, float g, float b);
+ public static extern void set_color(PointID id, float r, float g, float b);
[DllImport("LivePlotter.dll")]
- public static extern void set_scale(pointid id, float scale);
+ public static extern void set_scale(PointID id, float scale);
[DllImport("LivePlotter.dll")]
- public static extern void update_point(pointid id, float x, float y, float z);
+ public static extern void update_point(PointID id, float x, float y, float z);
[DllImport("LivePlotter.dll")]
- public static extern void set_lifetime(pointid id, float new_lifetime_s);
+ public static extern void set_lifetime(PointID id, float new_lifetime_s);
[DllImport("LivePlotter.dll")]
- public static extern void clear_point(pointid id);
+ public static extern void clear_point(PointID id);
public static void PlotCameraPoses()
{
@@ -54,7 +54,7 @@ namespace TysonPalletScanner
Vector3 local = new(0);
local[m] = n * 10.0f;
Vector3 global = pose * local;
- pointid id = create_point(global.X, global.Y, global.Z);
+ PointID id = create_point(global.X, global.Y, global.Z);
Vector3 color = new(0);
color[m] = 1.0f;
diff --git a/examples/csharp/Pose.cs b/examples/csharp/Pose.cs
new file mode 100644
index 0000000..ae4be0b
--- /dev/null
+++ b/examples/csharp/Pose.cs
@@ -0,0 +1,40 @@
+using System.Numerics;
+
+namespace Demo
+{
+ ///
+ ///
+ /// Represents a rigid transformation from one coordinate system to another. NOTE: By default, unless otherwise
+ /// stated, the Pose of an object transforms its local space to the ambient world space.
+ ///
+ ///
+ /// Given two Poses p1 and p2 which transform from space A to B and from B to C respectively,
+ /// the pose p2 * p1 transforms from A to C, and p1 * v transforms a vector v from space A to
+ /// B. A Pose has a rotation and a translation. The rotation is always applied first, followed by the
+ /// translation.
+ ///
+ ///
+ /// The rotation of this pose.
+ /// The translation of this pose.
+ public struct Pose(Quaternion rotation, Vector3 translation)
+ {
+ public Vector3 Translation { readonly get; set; } = translation;
+ public Quaternion Rotation { readonly get; set; } = rotation;
+
+ public static Pose Identity => new(Quaternion.Identity, Vector3.Zero);
+
+ public Pose(Vector3 translation) : this(Quaternion.Identity, translation) { }
+ public Pose(Quaternion rotation) : this(rotation, Vector3.Zero) { }
+
+ public static Vector3 operator *(Pose p, Vector3 v) => Vector3.Transform(v, p.Rotation) + p.Translation;
+ public static Pose operator *(Pose a, Pose b) => new(a.Rotation * b.Rotation, a * b.Translation);
+ public readonly Pose Inverse
+ {
+ get
+ {
+ var rotInv = Quaternion.Conjugate(Rotation);
+ return new(rotInv, -Vector3.Transform(Translation, rotInv));
+ }
+ }
+ }
+}
diff --git a/examples/csharp/Program.cs b/examples/csharp/Program.cs
new file mode 100644
index 0000000..24a7832
--- /dev/null
+++ b/examples/csharp/Program.cs
@@ -0,0 +1,6 @@
+using Demo;
+
+LivePlotter.start(800, 800);
+LivePlotter.PlotCameraPoses();
+
+while (true) ;
\ No newline at end of file