2025/01/17(金) [n年前の日記]
#1 [godot] ピンの位置を2Dで表示したい。その2
_昨日の作業
の続き。Windows10 x64 22H2 + Godot Engine 4.3 64bit でゴルフゲームっぽいものが作れないものかなと試してる。
ベクトルの外積を使って、ピンが右にあるか左にあるかを判別することはできた。以下のような感じになった。上のほうに旗アイコンがあるけれど、球の位置に連動して動いてる。
ノード構成は以下。

ソースは以下。
_main.gd
上記のソース内では、x-z平面でだけ考えて、外積を使って任意の座標がカメラから見て右にあるか左にあるかを調べてる。外積は、2つのベクトルに対して垂直なベクトルを求めることができるので…。x-z平面上でその垂直ベクトルが上を向いているか下を向いているか、つまりは符号を見るだけで、右にあるか左にあるかを判別できる。
ベクトルの外積を使って、ピンが右にあるか左にあるかを判別することはできた。以下のような感じになった。上のほうに旗アイコンがあるけれど、球の位置に連動して動いてる。
ノード構成は以下。

ソースは以下。
_main.gd
extends Node3D
@export var target: MeshInstance3D
@export var markdown: TextureRect
@export var markleft: TextureRect
@export var markright: TextureRect
@export var message: Label
func _ready():
pass
func _process(delta):
var cam = get_viewport().get_camera_3d()
if cam == null:
printerr("Not found Camera3D")
return
var cam_ang = Input.get_axis("ui_left", "ui_right") * (120.0 * delta)
cam.rotate_y(deg_to_rad(cam_ang))
var is_behind = cam.is_position_behind(target.global_position)
var in_frustum = cam.is_position_in_frustum(target.global_position)
var msg = ""
msg += "behind: %s" % ("true" if is_behind else "false")
msg += "\nin frustum: %s" % ("true" if in_frustum else "false")
message.text = msg
var viewport_size = get_viewport().get_visible_rect().size
var screen_pos = cam.unproject_position(target.global_position)
var tw = markdown.texture.get_width() / 2
if not is_behind and (screen_pos.x > tw and screen_pos.x < (viewport_size.x - tw)):
markleft.hide()
markright.hide()
markdown.show()
markdown.global_position.x = screen_pos.x - tw
#markicon.global_position.y = screen_pos.y - (markicon.texture.get_height())
else:
var camvec: Vector3 = -cam.global_transform.basis.z
var tgtvec: Vector3 = (target.global_position - cam.global_position)
var d = Vector2(camvec.x, camvec.z).cross(Vector2(tgtvec.x, tgtvec.z))
if d > 0:
markleft.hide()
markright.show()
elif d < 0:
markleft.show()
markright.hide()
else:
markleft.hide()
markright.hide()
markdown.hide()
- 3D空間の座標をスクリーン座標に変換するのは、Camera3D の unproject_position(Vector3) を使う。
- Camera3D の .global_transform.basis.z のマイナス値が、カメラが向いてる方向を示すベクトルとして使えるらしい。
- Vector3.cross(Vector3) や Vector2.cross(Vector2) でベクトルの外積を求められる。
- .hide() で、そのノードを非表示にできる。
- .show() で、そのノードを表示するように指定できる。
上記のソース内では、x-z平面でだけ考えて、外積を使って任意の座標がカメラから見て右にあるか左にあるかを調べてる。外積は、2つのベクトルに対して垂直なベクトルを求めることができるので…。x-z平面上でその垂直ベクトルが上を向いているか下を向いているか、つまりは符号を見るだけで、右にあるか左にあるかを判別できる。
[ ツッコむ ]
以上です。
