3Dでのカメラ設定

デバイスのプロパティ Device.Transform.View に、Matrix インスタンスを指定することで設定可能。

// 左手座標の視点マトリクスを構築する
public static Matrix Matrix.LookAtLH(
    Vector3 cameraPosition, // カメラの位置。
    Vector3 cameraTarget, // カメラの見ている位置。
    Vector3 cameraUpVector // カメラの頭の方向(例: 正立は new Vector3(0f,1f,0f), 倒立は new Vector3(0f,-1f,0f)). 方向を指定する目的なので、ベクトルの大きさは問わない
)

例:

Device device;
 
// ..中略..
 
// 座標 (0,0,-10) から正立状態で 座標 (0,0,0) を見る
device.Transform.View = Matrix.LookAtLH(
    new Vector3(0f, 0f, -10.0f),
    new Vector3(0f,0f,0f),
    new Vector3(0f,1f,0f) );
    
);

実際に表示するには、さらに 3D から 2D への投影の設定を行う必要があります。
この設定を行うには Device.Transform.Projection プロパティに Matrix インスタンスを指定します。

// 左手座標のパースペクティブマトリクスを構築する
public Matrix Matrix.PerspectiveFovLH(
    float fieldOfViewY, // (カメラから見て) Y軸方向の視野。ラジアンで指定する。(1/4 π == 45度 くらいが適切)
    float aspectRatio, // 2Dに変換後の画面のアスペクト比(横幅 ÷ 縦幅) (例: 高さも幅も同じなら 1.0f, 汎用:(float)device.Viewport.Width / (float)device.Viewport.Height )
    float znearPlane, // (カメラから見た)可視範囲のうち、最も近い距離(1.0f)
    float zfarPlane // (カメラから見た)可視範囲のうち、最も遠い距離 (100.0f)
);

例:

Device device;
// …中略…
 
device.Transform.View = … // 略
 
// 上下角度45度で奥行き 1.0f 前方から 100.0f 前方までの範囲を表示する
device.Transform.Projection = Matrix.PerspectiveFovLH(
    (float) Math.PI / 4,
    (float) device.Viewport.Width / device.Viewport.Height,
    1.0f, 100.0f );

ちなみに、Matrix.PerspectiveForLH ではなくて Matrix.PerspectiveFovLH なので注意してください。for でなく fov です。
 
参考:
チュートリアル3 行列の使い方(MSDN Direct3D)
Matrix.LookAtLH メソッド(MSDN)
ビュー行列を設定する(MSDN)
Matrix.PerspectiveFovLH メソッド

C#.NET で UDP 通信を簡単に行うには

この記事はC#での実装例です。
もしPCからの接続、コマンドラインからの接続方法を知りたい方は、こちらの記事をどうぞ。

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SendTo(…);
socket.ReceiveFrom(…);

のように System.Net.Sockets.Socket を使う方法もありますが、System.Net.Sockets.UdpClient を使うと簡単に UDP 通信を行うことができます。

// 必要な宣言
using System.Net;
using System.Net.Sockets;

private void DoSend(){
// 送信元とするポート
int localPort = 1234;
 
UdpClient client = new UdpClient(localPort);
 
// UDP パケットの送信先
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(“192.168.2.1”), 5678);
// 送信する内容(バイト配列で指定)
byte[] msg = Encoding.ASCII.GetBytes(“Hello, world\n”);
 
// 送信する
client.Send(msg, msg.Length, remoteEP);
// // 同じ場所に送信し続ける場合は次のように接続と送信をわけてもよい
// client.Connect(remoteEP);
// client.Send(msg, msg.Length);
}

以下のようにすれば、受信ができます。

private void DoReceive(){
int localPort = 5678;
UdpClient client = new UdpClient(localPort);
 
// 送信元。任意のIPアドレス、任意のポートから許可
IPEndPoint remoteEP = IPEndPoint(IPAddress.Any, 0);
 
// 受信するまで待ち続ける
byte[] res = client.Receive(ref remoteEP);
 
// バイト配列から ASCII 文字列に変換して表示
System.Console.Write(
   “送信元:” + remoteEP + “\n” + // 実際に送信が行われた IPアドレス, ポートが格納されているので一緒に表示
   “受信内容:”+Encoding.ASCII.GetString(res)
  );
}

TCP 版の TcpClient もあります。
 
参考:
UdpClient クラス (System.Net.Sockets)
TcpClient クラス
Socket クラス(System.Net.Sockets)

enum 型の一覧を得る

列挙型のすべての要素を得るには、Enum.GetValues() や Enum.GetNames() を使います。

private enum UserType {
    Guest = 1,
    Member,
    VIP,
    Refused = 99
}
 
private void SomeMethod(){
    foreach(UserType type in Enum.GetValues(typeof(UserType))){
        System.Console.Write(type + ” = ” + ((int) type)+ “\n”);
    }
}

結果:

Guest = 1
Member = 2
VIP = 3
Refused = 99

C# で DirectX

.NET Framework で DirectX を利用するには、Microsoft DirectX SDK を利用するのが一般的です。
 
マネージコードの使用に関するヒント(MSDN)
Direct3D のチュートリアル(MSDN)
参考になりますが、とくにチュートリアル3以降、部分解説になっているので完全に動作させるにはSDK 付属のチュートリアルのソースの参照が必須です。
サンプルソースは

(SDK ルート)\Samples\Managed\Direct3D\Tutorials

にあります。

UDP Hole Punching の実験

以前から気になっていた、NAT ごしに UDP 通信を行う, UDP Hole Punching の実験を NetCat(ports: net/netcat) を使って行ってみました。
 
1. (A)ホスト側端末(Firewall なし), WAN IP アドレス: 10.0.1.2

nc -lup 1234 -v # UDP の 1234 番で LISTEN

 
2. (B)クライアント側端末(ルータあり), 端末の IP アドレス: 192.168.1.100, ルータの WAN IP アドレス: 10.0.5.6

nc -u -p 5678 10.0.1.2 1234 # 10.0.1.2 の UDP 1234 に接続

 
3. (B) で Hello を入力
 
4. (A) に以下のようなログが出る

connect to [10.0.1.2] from ********* [10.0.5.6] 50000
Hello

(この例では 10.0.5.6 の UDP50000ポートからの送信があった。クライアント側 NAT で送信元ポートが書きかわっている事に注意)
 
5. (A), (B) 両方で netcat を一度終了させる
 
6. (B) で, 先程送信元にしたポートに対して UDP 受信を開始する(src port, dst port の入れ換え)

nc -lup 5678 -v

 
7. (A) で, 先程 LISTEN していたポートから、(4) で送信元になっていた IP アドレス、ポートに対して接続を開始する

nc -u -p 1234 10.0.5.6 50000

 
8. (A) から Hello over NAT を送信
 
9. (B) で以下のようなログが表示される

connect to [192.168.1.100] from ********* [10.0.1.2] 1234
Hello over NAT

 
両方が NAT 内にいる場合、双方について source port が書きかわるため、(A),(B) が通信することが不可能になります。
この場合、双方の source port を記録するための非 NAT 内ホスト端末 (C) が必要です。
ただし、双方が Symmetric NAT 内にいる場合は、宛先のポート番号に対して送信元の IP アドレス、ポート番号が固定されるためこの方法を用いることができません。
 
参考:
P2Pとファイアウォール
ごろ猫ブログ
みかログ
IT media エンタープライズ:PART2 Skype, その通信の仕組み

別オブジェクトからフォームインスタンスの参照を得るには?

.NET Framework 2.0 以降のみですが、System.Windows.Forms.Application クラスの静的プロパティ、 OpenForms により、開いているフォームインスタンスを参照することができます。
 

Form form = Application.OpenForms[0]; // 開いているフォームのうち一番古いものを得る

 

Form form = Application.OpenForms[“form1”]; // form1 という名前のフォームインスタンスを得る

 
参考:
Windowsフォームでフォームのコレクションを使用するには?
Application.OpenForms プロパティ(MSDN)
FormCollection クラス

別スレッドからフォームコントロールを操作するには?

VB.NET にも該当することですが、C#.NET では、

using System;
using System.Windows.Forms;
using System.Threading;
 
namespace Foo{
public class Form1 : Form{
    public Form1(){
        InitializeComponent();
    }
 
    private void button1_Click(object sender, EventArgs e){
        new Thread(new ThreadStart(delegate{
textBox1.Text = “Hello, world”;
})).Start();
    }

    // その他については略
}
}

としても InvalidOperationException が発生し、

有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール ‘textBox1’ がアクセスされました。

のように表示されてしまい、クロススレッドなフォームコントロールの操作ができません。
 
これを回避するには、System.Windows.Forms.Control の Invoke() メソッドを使い、コントロールの操作時のみ、そのコントロールが属するウィンドウハンドルを持つスレッドで実行するようにします。

            // Invoke() 用デリゲート
            private delegate void Del();
 
            private void button1_Click(object sender, EventArgs e){
 
                new Thread(new ThreadStart( delegate {
Invoke( (Del) delegate { // 匿名メソッドを Del 型にキャストし, それを呼び出す。
textBox1.Text = “Hello, world”; // コントロールの操作
});
                    })).Start();
            }

あるいは、MSDN の「Windows フォーム コントロールのスレッド セーフな呼び出しを行う」にあるように、

            private void button1_Click(object sender, EventArgs e){

new Thread(new ThreadStart( delegate {
SetText(“Hello, world”);
})).Start();
}

private delegate void SetTextCallback(string msg);

private void SetText(string msg){
if(textBox1.InvokeRequired){ // 指定したコントロールの操作に Invoke()が必要かどうか(この場合、this.InvokeRequired としてもよい)。

Invoke(new SetTextCallback(SetText), new object[] {msg}); // 必要であれば自身を Invoke する。
return;

}

// 以下本来の処理

textBox1.Text = msg;
}

のように、Control クラスの InvokeRequred プロパティで Invoke が必要かどうかを判別し、必要なら Invoke によりメソッドを呼び直すという方法もあります。
 
どちらを利用する場合も、Invoke() 中はメインスレッドでの実行になるため、マルチスレッド処理の恩恵を受けられません。このため、Invoke() 中のコードでは、コントロールの操作をするために最低限の実装であることが望ましいでしょう。
 
なお、本記事のコードで使用している匿名メソッド( delegate (){ /* */ } というコード)は、.NET Framework 2.0 以降でしか利用できないため、2.0 未満で利用する場合は該当箇所をメソッド定義に置き換えてください。
 

追記: C# 3.0(Visual Studio 2008)以降はラムダ式が使えるようになってさらに書きやすくなりました。

Invoke( (MethodInvoker)(()=> // ラムダ式をUIスレッドで実行する。
    textBox1.Text = "Hello, world";        // コントロールの操作
});
}

参考:
System.Windows.Forms.Control.Invoke()
Windows フォーム コントロールのスレッド セーフな呼び出しを行う(MSDN)
  MSDN ライブラリ -> 開発ツールと言語 -> Visual Studio ドキュメント -> Windows ベースのアプリケーション、コンポーネント、サービス -> Windows ベースのアプリケーションの作成 -> Windows フォーム -> Windows フォームについて -> Windows フォームコントロール -> .NET Framework を使用したカスタム Windows フォームコントロールの開発 -> Windows フォームコントロールのマルチスレッド処理

servname not supported for ai_socktype エラー

chroot 環境で作業をしていたら whois でこんなエラーが。

$ whois google.co.jp
whois: jp.whois-servers.net: servname not supported for ai_socktype

調べてみると、原因は /etc/service の不備でした。
whois の場合、/etc/service に

nicname 43/tcp whois
nicname 43/udp whois

がないのが原因です。
 
参考:
Error: Servname not supported for ai_socktype