work in progress [might break]
This commit is contained in:
parent
dd2434a3ed
commit
00d82cf262
5 changed files with 91 additions and 32 deletions
|
|
@ -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"]) )
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")]
|
||||||
|
|
|
||||||
BIN
example/godot/webxr_template/godot.javascript.opt.debug.zip
Normal file
BIN
example/godot/webxr_template/godot.javascript.opt.debug.zip
Normal file
Binary file not shown.
BIN
example/godot/webxr_template/godot.javascript.opt.zip
Normal file
BIN
example/godot/webxr_template/godot.javascript.opt.zip
Normal file
Binary file not shown.
|
|
@ -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,8 +119,11 @@ 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
|
||||||
|
|
||||||
|
if !URI.isLocal:
|
||||||
var http_request = HTTPRequest.new()
|
var http_request = HTTPRequest.new()
|
||||||
add_child(http_request)
|
add_child(http_request)
|
||||||
http_request.request_completed.connect(downloadModelSuccess)
|
http_request.request_completed.connect(downloadModelSuccess)
|
||||||
|
|
@ -128,6 +132,12 @@ func to(url, f:Callable ):
|
||||||
if error != OK:
|
if error != OK:
|
||||||
push_error("An error occurred in the HTTP request.")
|
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
|
||||||
# based on the filetype (glb,gltf,ade,obj e.g.)
|
# based on the filetype (glb,gltf,ade,obj e.g.)
|
||||||
|
|
@ -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,17 +217,17 @@ 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)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue