様々な 2D ラインの描画
スクリーン座標(2D)でラインを表示させるようにしています。
座標変換済み頂点を使用してもラインは描画できるのですが、SDK の「Line」クラスを使用することにより、いくつかのパターンでラインを描画することが出来ます。

下のリンクから今回のプロジェクトをダウンロードできます。
今回のメインコードファイルを載せます。重要なコードを赤色で表示させています。
MainSample.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace MDXSample
{
/// <summary>
///
/// </summary>
public partial class MainSample : IDisposable
{
/// <summary>
/// ラインクラス
/// </summary>
private Line _line = null;
/// <summary>
///
/// </summary>
/// <param name="topLevelForm"></param>
/// <returns></returns>
/// <remarks>
///
/// </remarks>
public bool InitializeApplication(MainForm topLevelForm)
{
this._form = topLevelForm;
this.CreateInputEvent(topLevelForm);
try
{
this.CreateDevice(topLevelForm);
this.CreateFont();
}
catch (DirectXException ex)
{
MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
this.CreateXYZLine();
// ラインクラスの作成
this._line = new Line(this._device);
return true;
}
/// <summary>
///
/// </summary>
public void MainLoop()
{
if (this._keys[(int)Keys.Escape])
{
this._form.Close();
return;
}
this.SettingCamera();
this._device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, Color.DarkBlue, 1.0f, 0);
this._device.BeginScene();
this._device.RenderState.Lighting = false;
this._device.SetTexture(0, null);
this._device.SetTransform(TransformType.World, Matrix.Identity);
this.RenderXYZLine();
// ラインの描画
// 本来は「Line.Begin」メソッドと「LineEnd」メソッドの間に
// ��イン����画���ード��入��るが
// ラインクラスのパラメータを常に変更しているので使わない
//this._line.Begin();
// ラインの位置を保持するためのベクトル配列
Vector2[] positions = new Vector2[3];
// 初期化
this._line.Width = 1.0f;
this._line.Antialias = false;
this._line.Pattern = -1;
this._line.PatternScale = 1.0f;
// 通常のライン
this._font.DrawText(null, "通常のライン", 20, 120, Color.White);
positions[0] = new Vector2(50.0f, 150.0f);
positions[1] = new Vector2(250.0f, 150.0f);
positions[2] = new Vector2(450.0f, 100.0f);
this._line.Draw(positions, Color.White);
// 太いライン
this._font.DrawText(null, "太いライン", 20, 170, Color.White);
positions[0] = new Vector2(50.0f, 200.0f);
positions[1] = new Vector2(250.0f, 200.0f);
positions[2] = new Vector2(450.0f, 150.0f);
this._line.Width = 10.0f;
this._line.Draw(positions, Color.Yellow);
// アンチエイリアス
this._font.DrawText(null, "アンチエイリアス", 20, 220, Color.White);
positions[0] = new Vector2(50.0f, 250.0f);
positions[1] = new Vector2(250.0f, 250.0f);
positions[2] = new Vector2(450.0f, 200.0f);
this._line.Antialias = true;
this._line.Draw(positions, Color.Yellow);
// パターン通常
this._font.DrawText(null, "パターン通常", 20, 270, Color.White);
positions[0] = new Vector2(50.0f, 300.0f);
positions[1] = new Vector2(250.0f, 300.0f);
positions[2] = new Vector2(450.0f, 250.0f);
this._line.Pattern = 1;
this._line.PatternScale = 1.0f;
this._line.Draw(positions, Color.LightBlue);
// パターン間隔0.5倍
this._font.DrawText(null, "パターン間隔 0.5 倍", 20, 320, Color.White);
positions[0] = new Vector2(50.0f, 350.0f);
positions[1] = new Vector2(250.0f, 350.0f);
positions[2] = new Vector2(450.0f, 300.0f);
this._line.PatternScale = 0.5f;
this._line.Draw(positions, Color.LightPink);
// 「Line.Begin」を使用していないのでコメントアウト
//this._line.End();
this._font.DrawText(null, "[Escape]終了", 0, 0, Color.White);
this._font.DrawText(null, "θ:" + this._lensPosTheta, 0, 12, Color.White);
this._font.DrawText(null, "φ:" + this._lensPosPhi, 0, 24, Color.White);
this._device.EndScene();
this._device.Present();
}
/// <summary>
///
/// </summary>
public void Dispose()
{
// ラインクラスの解放
this.SafeDispose(this._line);
this.DisposeResource();
}
}
}
|
では、赤文字の部分を説明していきます。MainSamplePartial.cs ファイルのコードはこちらです。
/// <summary>
///
/// </summary>
private Line _line = null;
|
今回2Dラインを描画するのに「Line」クラスを使用します。座標変換済み頂点をライン描画に置き換えてしまうことも出来るのですが、描画パターンが限られています。Line クラスを使用することにより、線を太くしたり、アンチエイリアスを掛けたりするのが非常に簡単なので、こちらを使ってみたいと思います。
this._line = new Line(this._device);
|
Direct3D デバイスを渡せば Line クラスを作成することが出来ます。今回メインループでパラメータを変更させているので、初期化メソッドで設定するものは特にありません。
ラインを描画する場合は「Line.Begin」メソッドと「Line.End」メソッドの間に記述しないといけないのですが、その2つのメソッドの間で Line クラスのプロパティを変更するとエラーが発生するようなので今回は使用しないことにします。
「LineBegin」と「Line.End」を使用しなくでもライン描画時に内部で呼んでいるので実際には問題ありません。ただ、複数のライン描画を行う場合は「LineBegin」と「Line.End」を使用しないと処理速度が低下する場合があります。(今回はサンプルなので処理速度にはこだわっていません)
Vector2[] positions = new Vector2[3];
|
ライン描画時には各頂点の位置の配列を渡す必要があるので、「Vector2」の配列を作成します。別なラインを描画するたびに配列を作成するのも面倒なので、一律下のようなラインを描画することにします。

this._line.Width = 1.0f;
this._line.Antialias = false;
this._line.Pattern = -1;
this._line.PatternScale = 1.0f;
|
描画毎に違う設定をしているので最初に初期化するようにしています。各パラメータに関しては後のセクションで説明します。
this._font.DrawText(null, "通常のライン", 20, 120, Color.White);
positions[0] = new Vector2(50.0f, 150.0f);
positions[1] = new Vector2(250.0f, 150.0f);
positions[2] = new Vector2(450.0f, 100.0f);
this._line.Draw(positions, Color.White);
|
設定を何も変更していない状態のラインを描画しています。描画するには「Line.Draw」メソッドにスクリーン座標での頂点位置の配列と線の色を渡します。
頂点の配列の数に応じて繋がった(折れ曲がった)線を描画することが出来ます。

this._font.DrawText(null, "太いライン", 20, 170, Color.White);
positions[0] = new Vector2(50.0f, 200.0f);
positions[1] = new Vector2(250.0f, 200.0f);
positions[2] = new Vector2(450.0f, 150.0f);
this._line.Width = 10.0f;
this._line.Draw(positions, Color.Yellow);
|
「Line.Width」プロパティを変更することにより、線の太さを変更することが出来ます。float で設定しますが、スクリーン座標での設定なので 1.0f が太さ1ドットになります。
よく見ると線が曲がっているところで微妙に切れていることが分かります。実はこの Line クラスは線を描画しているのではなく、四角形ポリゴンを変換させて描画しているのです。そのため、下の図のように描画しているのでこのようになってしまうのです。
太いラインを曲げるときは、繋げて描画するのではなく、個別に描画したほうがいいかもしれません。
this._font.DrawText(null, "アンチエイリアス", 20, 220, Color.White);
positions[0] = new Vector2(50.0f, 250.0f);
positions[1] = new Vector2(250.0f, 250.0f);
positions[2] = new Vector2(450.0f, 200.0f);
this._line.Antialias = true;
this._line.Draw(positions, Color.Yellow);
|
「Line.Antialias」プロパティを true にすることにより、アンチエイリアスが掛かり、線のギザギザが滑らかに見えるようになります。
下の図では直線はギザギザが無いのであまり分からないですが、斜めの線が滑らかになっていることが分かります。
this._font.DrawText(null, "パターン通常", 20, 270, Color.White);
positions[0] = new Vector2(50.0f, 300.0f);
positions[1] = new Vector2(250.0f, 300.0f);
positions[2] = new Vector2(450.0f, 250.0f);
this._line.Pattern = 1;
this._line.PatternScale = 1.0f;
this._line.Draw(positions, Color.LightBlue);
|
「Line.Pattern」プロパティを 1 に設定するとラインが点描みたいに描画されます。1 以上も設定できるようですが、どのような法則で描画されているかは不明です。(ヘルプにも 0 と 1 のことしか書かれていません)
わかりやすいように線を太くしています。
this._font.DrawText(null, "パターン間隔 0.5 倍", 20, 320, Color.White);
positions[0] = new Vector2(50.0f, 350.0f);
positions[1] = new Vector2(250.0f, 350.0f);
positions[2] = new Vector2(450.0f, 300.0f);
this._line.PatternScale = 0.5f;
this._line.Draw(positions, Color.LightPink);
|
「Line.PatternScale」プロパティを変更すると点描の間隔を変更することが出来ます。1.0 を標準として、1.0 以下を指定すると間隔が短くなり、1.0 以上の場合は間隔が広くなります。
「Line.Begin」を使用している場合はライン描画後に「Line.End」を使用する必要がありますが、今回は使用していません。
this.SafeDispose(this._line);
|
Line クラスを使用し終わったら解放します。
|