LoginSignup
2
4

More than 3 years have passed since last update.

C#で様々なライブラリのVector構造体を相互運用 (LayoutKind, Spanを使う方法)

Last updated at Posted at 2019-07-22

はじめに

(心の声) System.Numerics.Vector3 からOpenTK.Vector3に変換できない!
周辺の小さなライブラリでVectorを使いたいときはSystem.Numerics.Vector3で作成し、いざ3D系(OpenTK)アプリで使用しようとするとOpenTK.Vector3に変換しないといけない。実態は両方ともfloat * 3 のメモリなのに....

世の中には様々なVector系構造体があります。System.Numerics.Vector3をはじめとして、OpenTKや3dの各種ラップライブラリでVector構造体が宣言されています。
ほぼすべての構造体がfloat * 3 (x,y,z)のフィールドを持ちますが、相互に変換となるとnewしなおすしかありません。float * 3だと、Marshalやポインタを使ったアプローチはコストに見合わなさそう。

ということで、構造体のメモリレイアウトを重ねることで複数種類のVectorを取り出そうというのが今回のアプローチです。

早速ですが、答えは以下になります。FieldOffsetでメモリの位置を重ねています。

[StructLayout(LayoutKind.Explicit)]
public struct Tvec
{
  [FieldOffset(0)]
  public System.Numerics.Vector3 nvec;
  [FieldOffset(0)]
  public OpenTK.Vector3 tkvec;
  [FieldOffset(0)]
  public float X;
  [FieldOffset(4)]
  public float Y;
  [FieldOffset(8)]
  public float Z;
}

使ってみます。

Mainと実行結果
void Main()
{
  System.Numerics.Vector3 vecn = new System.Numerics.Vector3(1, 2, 3);
  Tvec vec = new Tvec();
  vec.nvec = vecn;
  Console.WriteLine("OpenTK->" + vec.tkvec.ToString());
  Console.WriteLine("System.Numerics->" + vec.nvec.ToString());
  Console.WriteLine("float X->" +vec.X);
  Console.WriteLine("float Y->" +vec.Y);
  Console.WriteLine("float Z->" +vec.Z);
}
---------------------------
OpenTK->(1, 2, 3)
System.Numerics-><1, 2, 3>
float X->1
float Y->2
float Z->3

めでたしめでたし...
と言いたいところですけど結局vec.nvec = vecn;で構造体コピーしてるわけだから普通にnewすれば良かったというオチです。相互に何度も行き来するときはこちらの方がよいのかな?


(追記 19.08.15)
ちょっとふがいないのでnewせずにメモリを共用する方法も記載します。
最近使用できるようになったSpanを使用します。
.Net Core2.1以上でない場合、nugetからSystem.Memoryをインストールします。

System.Numerics.Vector3[] n_vec = new System.Numerics.Vector3[]
{
  new System.Numerics.Vector3(1,0,0),
  new System.Numerics.Vector3(0,1,0),
  new System.Numerics.Vector3(0,0,1),
};
var n_vec_span = n_vec.AsSpan();
var tk_vec_span = MemoryMarshal.Cast<System.Numerics.Vector3, OpenTK.Vector3>(n_vec_span).ToArray();

たぶんこの方法が最近の現実解な気がします。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4