[Godot Engine] 3D空間にラインを引く方法
Godot Engineについては以前の記事をご覧ください。
今回は3D空間の好きな座標にラインを引く方法を共有します。
CanvasItem
を継承するNode2D
とControl
には_draw()
メソッドが用意されているので、割と容易にビューポート上にラインを引くことはできるのですが、Spatial
には_draw()
メソッドはないので、自前でどうにかする必要があります。
どうにかする方法も色々あるのですが、パッと考えつくのは以下でしょうか。
- 3D座標を2D座標に変換して
CanvasItem
で描画してViewportに表示する -
CanvasItem
に描画したものを3D空間のポリゴンに貼り付ける - 3D空間に頂点を追加してポリゴンを作る
この記事で紹介するのは3
です。
ImmediateGeometryクラスを使用
ImmediateGeometry
は単純なポリゴン描画を提供するクラスです。
フレームごとに変化する少量の頂点を扱うのに適したクラスですが、より複雑で最適化が必要となる頂点データを動的に扱う場合は、ArrayMesh
やMeshTool
、SurfaceTool
を使用する方が良いです。
単純な描画方法
extends ImmediateGeometry
func _ready():
begin(Mesh.PRIMITIVE_LINES)
set_color(Color.red)
add_vertex(0, 0, 0)
add_vertex(0, 1, 0)
end()
使い方は非常にシンプルで、begin()
とend()
の間でadd_vertex()
で頂点を追加していくだけです。
begin()
の引数でMesh.PRIMITIVE_LINES
を設定しています。
これで、begin()
からend()
の間で追加された頂点をラインで描画する という設定になります。
他にもenum
で定義されたPrimitiveType
がありますが、今回はラインを描画するだけなので、PRIMITIVE_LINES
を使用します。
頂点を追加する間にset_color(Color)
を指定すると、頂点の色を設定できます。
しかしこのままでは色は描画されず、デフォルトのシェーディングになっているので、環境光の影響を受けたポリラインが表示されます。
マテリアルオーバーライド
通常の3Dモデルだとメッシュに対してマテリアルを設定しますが、今回は動的にメッシュを作っているので、ポリラインの生成が終わったジオメトリに対してマテリアルをオーバーライドして描画します。
VisualServer
を介してスクリプトで動的にマテリアルを作る事もできますが、処理負荷の割に意味があまりないので、インスペクタ上でSpatial
マテリアルを設定します。
設定したらスクリプトに戻ります。
extends ImmediateGeometry
func _ready():
# 以下はインスペクタ上で設定してもOK
var _mat = get_override?material()
_mat.flags_unshaded = true
_mat.flags_no_depth_test = true
_mat.vertex_color_use_as_albedo = true
begin(Mesh.PRIMITIVE_LINES)
set_color(Color.red)
add_vertex(0, 0, 0)
add_vertex(0, 1, 0)
end()
flags_unshaded
で環境光などをすべて切って、ジオメトリの色をそのまま表示させます。
vertex_color_use_as_albedo
は頂点カラーをアルベドカラーとして表示します。
flags_no_depth_test
で最前面に描画させます(別のメッシュで隠れても見えるように)
さいごに
やることはシンプルなんですが、意外と情報が少なかったので備忘録として記事にしました。
ImmediateGeometry
は非常にシンプルなポリゴン描画クラスなので、結構使いそうです。
多少描画負荷は上がりますが、デバッグモードで使うことはかなり多いと思います。
これを機にArrayMesh
やMeshTool
に触れながら、プロシージャルにアセットを作るアドオンを作りたいなぁ(野望)
そしてZennではこのくらいショートな記事を今後も作れたらいいなーと思ってます。
Discussion