work in progress [might break]

This commit is contained in:
Leon van Kammen 2024-05-13 14:11:02 +02:00
parent dd2434a3ed
commit 00d82cf262
5 changed files with 91 additions and 32 deletions

View file

@ -8,25 +8,38 @@ var player:CharacterBody3D
func _ready(): func _ready():
xrf = preload("res://xrfragment.gd").new() xrf = preload("res://xrfragment.gd").new()
add_child(xrf) add_child(xrf)
xrf.to("https://xrfragment.org/index.glb", _onXRF ) xrf.to("https://xrfragment.org/other.glb", _onXRF )
player = find_child("PlayerBody") player = find_child("PlayerBody")
player.enabled = false # optional: turn off gravity player.enabled = false # optional: turn off gravity
func _onXRF(event:String,data ): func _onXRF(event:String,data ):
if event == "scene_loaded": if event == "scene_loaded":
scene = data scene = data
setPredefinedSceneView() if event == 'href':
print(data)
if event == 'teleport':
print("teleport!")
find_child("XROrigin3D").position = data.origin
#player.teleport( data )
func _input(event): func _input(event):
var cam = find_child("XRCamera3D")
if event is InputEventMouseMotion: if event is InputEventMouseMotion:
var mouse_sens = 0.2 var mouse_sens = 0.2
var cam = find_child("XRCamera3D")
cam.rotate_y(deg_to_rad(-event.relative.x*mouse_sens)) cam.rotate_y(deg_to_rad(-event.relative.x*mouse_sens))
if event is InputEventMouseButton:
var mouse_pos = get_viewport().get_mouse_position()
var from = cam.project_ray_origin(mouse_pos)
var to = from + cam.project_ray_normal(mouse_pos) * 20000 #200
var space_state = get_world_3d().direct_space_state
var handle_query = PhysicsRayQueryParameters3D.create(from, to)
handle_query.collide_with_areas = true
var mesh_query = PhysicsRayQueryParameters3D.create(from, to)
mesh_query.collide_with_areas = true
var intersectMesh = space_state.intersect_ray(mesh_query)
var intersectHandle = space_state.intersect_ray(handle_query)
if intersectMesh.has('collider'):
xrf.traverse( intersectMesh.collider, xrf.href_click )
# info: https://xrfragment.org/#predefined_view
# spec: 6-8 @ https://xrfragment.org/doc/RFC_XR_Fragments.html#navigating-3d
func setPredefinedSceneView():
var XRF = scene.get_meta("XRF")
if XRF && XRF.has("#") && XRF["#"]["fragment"]["pos"]:
player.teleport( xrf.posToTransform3D(XRF["#"]["fragment"]["pos"]) )

View file

@ -43,5 +43,6 @@ input_action = "thumbstick"
input_action = "thumbstick" input_action = "thumbstick"
[node name="PlayerBody" parent="XROrigin3D" instance=ExtResource("6_kfmth")] [node name="PlayerBody" parent="XROrigin3D" instance=ExtResource("6_kfmth")]
visible = false
[node name="StartXR" parent="." instance=ExtResource("8_htpay")] [node name="StartXR" parent="." instance=ExtResource("8_htpay")]

Binary file not shown.

View file

@ -5,7 +5,8 @@ extends Node
class_name XRF class_name XRF
var scene var scene: Node3D
var URI: Dictionary
var isModelLoading = false var isModelLoading = false
var metadata var metadata
var callback: Callable; var callback: Callable;
@ -30,7 +31,7 @@ func _process(delta):
#################################################################################################### ####################################################################################################
func parseURL(url: String) -> Dictionary: func parseURL(url: String) -> Dictionary:
var URI = {} var URI = {"string":url}
# Split URL by '://' to get protocol and the rest of the URL # Split URL by '://' to get protocol and the rest of the URL
var parts = url.split("://") var parts = url.split("://")
@ -70,7 +71,7 @@ func parseURL(url: String) -> Dictionary:
URI["fragment"] = parseArgs(parts[1]) URI["fragment"] = parseArgs(parts[1])
else: else:
URI["fragment"] = {} URI["fragment"] = {}
URI['isLocal'] = url[0] == '#'
return URI return URI
func parseArgs(fragment: String) -> Dictionary: func parseArgs(fragment: String) -> Dictionary:
@ -118,15 +119,24 @@ func guess_type(str: String) -> Dictionary:
# Download model by HTTP and run `downloadModelSuccess` if OK # Download model by HTTP and run `downloadModelSuccess` if OK
func to(url, f:Callable ): func to(url, f:Callable ):
print("loading "+url) print("navigating to "+url)
var URI = self.parseURL(url)
callback = f callback = f
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(downloadModelSuccess)
var error = http_request.request(url) if !URI.isLocal:
if error != OK: var http_request = HTTPRequest.new()
push_error("An error occurred in the HTTP request.") add_child(http_request)
http_request.request_completed.connect(downloadModelSuccess)
var error = http_request.request(url)
if error != OK:
push_error("An error occurred in the HTTP request.")
self.URI = URI
if URI.isLocal && URI.fragment.has('pos'):
print(URI.fragment.pos)
callback.call("teleport", self.posToTransform3D( URI.fragment.pos ) )
func downloadModelSuccess(result, response_code, headers, body): func downloadModelSuccess(result, response_code, headers, body):
# TODO: here different parsing functions should be called # TODO: here different parsing functions should be called
@ -135,8 +145,9 @@ func downloadModelSuccess(result, response_code, headers, body):
_parseXRFMetadata(scene) _parseXRFMetadata(scene)
traverse( scene, _parseXRFMetadata ) traverse( scene, _parseXRFMetadata )
# setup actions & embeds # setup actions & embeds
traverse( scene, init_href ) traverse( scene, href_init )
traverse( scene, init_src ) traverse( scene, src_init )
setPredefinedSceneView()
callback.call("scene_loaded", scene) callback.call("scene_loaded", scene)
func loadModelFromBufferByGLTFDocument(body): func loadModelFromBufferByGLTFDocument(body):
@ -147,6 +158,7 @@ func loadModelFromBufferByGLTFDocument(body):
var error = doc.append_from_buffer(body, "", state) var error = doc.append_from_buffer(body, "", state)
if error == OK: if error == OK:
scene = doc.generate_scene(state) scene = doc.generate_scene(state)
scene.name = "XRFscene"
metadata = _parseMetadata(state,scene) metadata = _parseMetadata(state,scene)
add_child(scene) add_child(scene)
print("model added") print("model added")
@ -205,18 +217,18 @@ func _parseMetadata(state: GLTFState, scene: Node) -> Error:
return OK return OK
func posToTransform3D(v:Dictionary): func posToTransform3D(v:Dictionary):
var pos = Vector3() var transform : Transform3D
if !v.x: if !v.x:
var node:Node3D = scene.find_child(v.string) var node:Node3D = scene.find_child(v.string)
pos.x = node.position.x if node:
pos.y = node.position.y transform = node.global_transform
pos.z = node.position.z
else: else:
var pos = Vector3()
pos.x = v.x pos.x = v.x
pos.y = v.y pos.y = v.y
pos.z = v.z pos.z = v.z
var transform = Transform3D() transform = Transform3D()
transform.origin = pos transform.origin = pos
return transform return transform
@ -225,9 +237,42 @@ func posToTransform3D(v:Dictionary):
# spec: https://xrfragment.org/doc/RFC_XR_Fragments.html # spec: https://xrfragment.org/doc/RFC_XR_Fragments.html
#################################################################################################### ####################################################################################################
func init_href(node:Node): # info: https://xrfragment.org/#predefined_view
null # spec: 6-8 @ https://xrfragment.org/doc/RFC_XR_Fragments.html#navigating-3d
func setPredefinedSceneView():
var XRF = scene.get_meta("XRF")
if XRF && XRF.has("#") && XRF["#"]["fragment"]["pos"]:
callback.call("teleport", posToTransform3D(XRF["#"]["fragment"]["pos"]) )
func init_src(node:Node): func href_init(node:Node):
null if node.has_meta("XRF"):
var XRF = node.get_meta("XRF")
if XRF.has('href'):
var parent = node.get_parent()
var area3D = Area3D.new()
var col3D = CollisionShape3D.new()
var group = MeshInstance3D.new()
parent.remove_child(node)
area3D.add_child(node)
area3D.add_child(col3D)
col3D.make_convex_from_siblings() # generate collision from MeshInstance3D siblings
parent.add_child(area3D)
func href_click(node:Node):
if node.has_meta("XRF"):
var XRF = node.get_meta("XRF")
if XRF.has('href'):
to(XRF.href.string,callback)
callback.call("href", node)
func src_init(node:Node):
if node.has_meta("XRF"):
var XRF = node.get_meta("XRF")
if (XRF.has('src') || (XRF.has('href') && XRF.has('src'))) && node is MeshInstance3D:
var mesh = node as MeshInstance3D
var mat = mesh.get_active_material(0) as BaseMaterial3D
mat = mat.duplicate()
mat.transparency = mat.TRANSPARENCY_ALPHA
mat.albedo = Color(1.0,1.0,1.0, 0.3) # 0.5 sets 50% opacity
mesh.set_surface_override_material(0,mat)