mieki256's diary



2025/01/15(水) [n年前の日記]

#1 [godot] ボールの軌跡の形状について試行錯誤中

_昨日の作業 の続き。Windows10 x64 22H2 + Godot Engine 4.3 64bit でゴルフゲームっぽいものが作れないものかなと試してる。

ボールの軌跡を、ImmediateMesh を使って、動的にポリゴンモデルを生成することで表現したい。別プロジェクトで実験していたけれど、それらしく描画できそうな気がしてきた。以下のような見た目になった。




ソースは以下。白いソレ、青いソレ、赤いソレの順番で並べてある。

_im3_mesh_instance_3d.gd
_im2_mesh_instance_3d.gd
_im1_mesh_instance_3d.gd

それぞれを、MeshInstance3Dノードにアタッチしている。

node_list_ss02.png


一応、ソースの中身も貼っておく。毎フレーム、配列 poslist: PackedVector3Array に座標値群を入れておいて、その座標値群を元にして、ImmediateMesh によるポリゴンモデルを作成している。

_im3_mesh_instance_3d.gd
extends MeshInstance3D

var mat: StandardMaterial3D
var ang: float = 0.0
var poslist: PackedVector3Array = PackedVector3Array()

func _ready():
    mat = StandardMaterial3D.new()
    mat.albedo_color = Color(1, 1, 1, 0.25)
    mat.cull_mode = BaseMaterial3D.CULL_DISABLED
    mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
    mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
    
    mesh = ImmediateMesh.new()
    
    var n = 30
    for i in range(0, n, 1):
        poslist.append(Vector3.ZERO)


func _process(delta):
    # store positon to PackedVector3Array
    for i in range(0, poslist.size(), 1):
        var x1 = -12.0 + 4.0 * sin(deg_to_rad((ang + 10 * i) * 0.75))
        var y1 = 4.0 + 4.0 * sin(deg_to_rad(ang + 10 * i))
        var z1 = 10 - 1.0 * i
        poslist[i] = Vector3(x1, y1, z1)

    # set ImmediateMesh
    mesh.clear_surfaces()
    mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES, mat)
    # mesh.surface_set_color(Color.WHITE)

    var r = 0.5
    for i in range(0, poslist.size() - 2, 1):
        var p0 = get_rect_pos(poslist[i], poslist[i+1], r)
        var p1 = get_rect_pos(poslist[i+1], poslist[i+2], r)
        mesh.surface_add_vertex(p0[3])
        mesh.surface_add_vertex(p0[0])
        mesh.surface_add_vertex(p1[3])
        mesh.surface_add_vertex(p1[3])
        mesh.surface_add_vertex(p0[0])
        mesh.surface_add_vertex(p1[0])
    
        mesh.surface_add_vertex(p0[0])
        mesh.surface_add_vertex(p0[2])
        mesh.surface_add_vertex(p1[0])
        mesh.surface_add_vertex(p1[0])
        mesh.surface_add_vertex(p0[2])
        mesh.surface_add_vertex(p1[2])
    
        mesh.surface_add_vertex(p0[2])
        mesh.surface_add_vertex(p0[1])
        mesh.surface_add_vertex(p1[2])
        mesh.surface_add_vertex(p1[2])
        mesh.surface_add_vertex(p0[1])
        mesh.surface_add_vertex(p1[1])
    
        mesh.surface_add_vertex(p0[1])
        mesh.surface_add_vertex(p0[3])
        mesh.surface_add_vertex(p1[1])
        mesh.surface_add_vertex(p1[1])
        mesh.surface_add_vertex(p0[3])
        mesh.surface_add_vertex(p1[3])
    
    mesh.surface_end()
    
    ang += 120.0 * delta

func get_rect_pos(v0: Vector3, v1: Vector3, r: float):
    var v = v1 - v0
    var va = v.cross(Vector3.UP).normalized()
    var vb = v.cross(va).normalized()
    var pv0 = v0 + r * vb
    var pv1 = v0 - r * vb
    var pv2 = v0 + r * va
    var pv3 = v0 - r * va
    return [pv0, pv1, pv2, pv3]

ベクトルに垂直な矩形を求めるあたりは、以下の図が参考になる…のかな…どうなんだろ…。

about_get_vector_ss01.png

元ベクトルとY軸の外積で横方向に垂直なベクトルを求めてから、元ベクトルと横方向のベクトルの外積で縦方向のベクトルを求めて、その縦方向と横方向のベクトルから矩形の頂点座標を求める。上のソースで言えば、get_rect_pos() がその処理をしている。


ゴルフゲームにも組み込んでみた。




イイ感じになってきた気がする。

ちなみに、以前の版の見た目は以下。

課題 :

Godot Engine の ImmediateMesh で描画できるプリミティブは以下がある。点、線、三角ポリゴンが指定できる模様。
  • PrimitiveType PRIMITIVE_POINTS = 0
  • PrimitiveType PRIMITIVE_LINES = 1
  • PrimitiveType PRIMITIVE_LINE_STRIP = 2
  • PrimitiveType PRIMITIVE_TRIANGLES = 3
  • PrimitiveType PRIMITIVE_TRIANGLE_STRIP = 4

今回は三角ポリゴン、PRIMITIVE_TRIANGLES を使ったけれど、おそらく PRIMITIVE_TRIANGLE_STRIP を使ったほうが描画の効率は良さそうな気もする。

ただ、どういう順番、どういう形で頂点を指定していけばいいのか、そこが分からない…。輪を描くように描画したほうがいいのか、帯を描くように描画したほうがいいのか…。

以上、1 日分です。

過去ログ表示

Prev - 2025/01 - Next
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project