Skip to content
This repository was archived by the owner on Jan 25, 2025. It is now read-only.

Commit 6b4650d

Browse files
committed
vr site
1 parent 852620d commit 6b4650d

6 files changed

Lines changed: 230 additions & 44 deletions

File tree

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
godot/addons/** linguist-vendored
22
godot/examples_dd3d/** linguist-vendored
3+
xrtest/data.gd linguist-generated

testbed/src/main.rs

Lines changed: 90 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,28 @@ fn desmos_list(name: &str, values: &[f64]) -> String {
6161

6262
#[derive(Serialize)]
6363
struct PhysicsThing {
64-
rails1: Vec<(f64, f64, f64)>,
65-
rails2: Vec<(f64, f64, f64)>,
64+
rails1: Vec<[f64; 3]>,
65+
rails2: Vec<[f64; 3]>,
6666
cross_support: Vec<bool>,
67-
hl_pos: Vec<(f64, f64, f64)>,
68-
hl_up: Vec<(f64, f64, f64)>,
67+
hl_pos: Vec<[f64; 3]>,
68+
hl_up: Vec<[f64; 3]>,
69+
hl_fwd: Vec<[f64; 3]>,
70+
is_extra: Vec<bool>,
71+
}
72+
73+
fn codegen(thing: &PhysicsThing) -> String {
74+
format!(r#"
75+
class_name Data
76+
77+
var rail1 = {:?}
78+
var rail2 = {:?}
79+
var cross = {:?}
80+
var pos = {:?}
81+
var up = {:?}
82+
var fwd = {:?}
83+
var is_extra = {:?}
84+
"#
85+
, thing.rails1, thing.rails2, thing.cross_support, thing.hl_pos, thing.hl_up, thing.hl_fwd, thing.is_extra)
6986
}
7087

7188
fn main() {
@@ -139,29 +156,48 @@ fn main() {
139156
cross_support: Vec::new(),
140157
hl_pos: Vec::new(),
141158
hl_up: Vec::new(),
159+
hl_fwd: Vec::new(),
160+
is_extra: Vec::new(),
142161
};
143162
let mut phys = physics::PhysicsStateV3::new(1.0, -0.01, &curve, 0.5, MU);
144163
let mut i = 0;
164+
const CROSS_DIST: f64 = 2.0;
165+
let mut last_cl_pos: Option<MyVector3<f64>> = None;
166+
let mut distance_since_last_cross = 0.0;
167+
const RAIL_MULT: f64 = 0.75;
145168
while phys.step(&0.05, &curve).is_some() {
146169
i += 1;
147-
if i % 20 != 0 {
170+
if i % 5 != 0 {
148171
continue;
149172
}
150-
let track_centerline = phys.x().inner() - phys.hl_normal().clone() * 1.0 * *phys.o();
173+
let track_centerline = phys.x().inner() - phys.hl_normal().clone() * RAIL_MULT * *phys.o();
174+
if let Some(p) = &last_cl_pos {
175+
distance_since_last_cross += (track_centerline.clone() - p.clone()).magnitude();
176+
if distance_since_last_cross > CROSS_DIST {
177+
distance_since_last_cross = 0.0;
178+
thing.cross_support.push(true);
179+
} else {
180+
thing.cross_support.push(false);
181+
}
182+
} else {
183+
thing.cross_support.push(false);
184+
}
185+
last_cl_pos = Some(track_centerline.clone());
151186
let binormal = phys.v().inner().cross(phys.hl_normal()).normalize();
152-
let rail1 = track_centerline.clone() + binormal.clone() * *phys.o();
153-
let rail2 = track_centerline.clone() - binormal * *phys.o();
187+
let rail1 = track_centerline.clone() + binormal.clone() * *phys.o() * RAIL_MULT;
188+
let rail2 = track_centerline.clone() - binormal * *phys.o() * RAIL_MULT;
154189
println!("{:.4?} {:.4?} {:.4?}", track_centerline, rail1, rail2);
155-
thing.rails1.push((rail1.x, rail1.y, rail1.z));
156-
thing.rails2.push((rail2.x, rail2.y, rail2.z));
157-
thing.cross_support.push(false);
190+
thing.rails1.push([rail1.x, rail1.y, rail1.z]);
191+
thing.rails2.push([rail2.x, rail2.y, rail2.z]);
158192
let hl_pos = curve.curve_at(phys.u()).unwrap();
159-
thing.hl_pos.push((hl_pos.x, hl_pos.y, hl_pos.z));
193+
thing.hl_pos.push([hl_pos.x, hl_pos.y, hl_pos.z]);
160194
let hl_up = phys.hl_normal();
161-
thing.hl_up.push((hl_up.x, hl_up.y, hl_up.z));
195+
thing.hl_up.push([hl_up.x, hl_up.y, hl_up.z]);
196+
let hl_fwd = phys.v().inner();
197+
thing.hl_fwd.push([hl_fwd.x, hl_fwd.y, hl_fwd.z]);
198+
thing.is_extra.push(false);
162199
}
163200

164-
//let mut extras = vec![];
165201
for c in &curve.additional {
166202
let mut u = 0.0;
167203
while u <= 1.0 {
@@ -171,37 +207,67 @@ fn main() {
171207
.make_ortho_to(&tangent)
172208
.normalize();
173209
let com_pos = hl_pos.clone() - up.clone() * *phys.o();
174-
let track_centerline = hl_pos.clone() - up.clone() * *phys.o() * 2.0;
210+
let track_centerline = hl_pos.clone() - up.clone() * *phys.o() * (1.0 + RAIL_MULT);
211+
if let Some(p) = &last_cl_pos {
212+
distance_since_last_cross += (track_centerline.clone() - p.clone()).magnitude();
213+
if distance_since_last_cross > CROSS_DIST {
214+
distance_since_last_cross = 0.0;
215+
thing.cross_support.push(true);
216+
} else {
217+
thing.cross_support.push(false);
218+
}
219+
} else {
220+
thing.cross_support.push(false);
221+
}
222+
last_cl_pos = Some(track_centerline.clone());
175223
let binormal = up.cross(&tangent).normalize();
176-
let rail1 = track_centerline.clone() - binormal.clone() * *phys.o();
177-
let rail2 = track_centerline.clone() + binormal.clone() * *phys.o();
224+
let rail1 = track_centerline.clone() - binormal.clone() * *phys.o() * RAIL_MULT;
225+
let rail2 = track_centerline.clone() + binormal.clone() * *phys.o() * RAIL_MULT;
178226

179-
thing.rails1.push((rail1.x, rail1.y, rail1.z));
180-
thing.rails2.push((rail2.x, rail2.y, rail2.z));
181-
thing.cross_support.push(false);
227+
thing.rails1.push([rail1.x, rail1.y, rail1.z]);
228+
thing.rails2.push([rail2.x, rail2.y, rail2.z]);
229+
thing.is_extra.push(true);
182230

183231
//let hl_pos = curve.curve_at(phys.u()).unwrap();
184-
thing.hl_pos.push((hl_pos.x, hl_pos.y, hl_pos.z));
232+
//thing.hl_pos.push((hl_pos.x, hl_pos.y, hl_pos.z));
185233
//let hl_up = phys.hl_normal();
186-
thing.hl_up.push((up.x, up.y, up.z));
234+
//thing.hl_up.push((up.x, up.y, up.z));
187235

188236
/*extras.push((
189237
Vector3::new(com_pos.x as f32, com_pos.y as f32, com_pos.z as f32),
190238
0.0,
191239
true,
192240
));*/
193-
u += 0.1;
241+
u += 0.001;
194242
}
195243
}
196244

197-
File::create("/tmp/rail1.json")
245+
File::create("/tmp/data.gd").unwrap().write_all(codegen(&thing).as_bytes()).unwrap();
246+
/*File::create("/tmp/rail1.json")
198247
.unwrap()
199248
.write_all(&format!("{:?}", thing.rails1).as_bytes())
200249
.unwrap();
201250
File::create("/tmp/rail2.json")
202251
.unwrap()
203252
.write_all(&format!("{:?}", thing.rails2).as_bytes())
204253
.unwrap();
254+
File::create("/tmp/cross.json")
255+
.unwrap()
256+
.write_all(&format!("{:?}", thing.cross_support).as_bytes())
257+
.unwrap();
258+
File::create("/tmp/pos.json")
259+
.unwrap()
260+
.write_all(&format!("{:?}", thing.hl_pos).as_bytes())
261+
.unwrap();
262+
File::create("/tmp/fwd.json")
263+
.unwrap()
264+
.write_all(&format!("{:?}", thing.hl_fwd).as_bytes())
265+
.unwrap();
266+
File::create("/tmp/up.json")
267+
.unwrap()
268+
.write_all(&format!("{:?}", thing.hl_up).as_bytes())
269+
.unwrap();*/
270+
205271

206272
println!("{}", thing.rails1.len());
207273
println!("{:?}", thing.rails1);

xrtest/data.gd

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

xrtest/main.gd

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,50 @@ extends Node3D
22

33
var webxr_interface
44
var vr_supported = false
5+
var active = false
6+
var t = 0
7+
8+
var pos = []
9+
var up = []
10+
var fwd = []
11+
12+
@onready var mesh = $MeshInstance3D2
13+
14+
func arr_to_vec(x):
15+
return Vector3(x[0], x[1], x[2])
516

617
func _ready():
18+
# coaster setup
19+
#var rail1 = JSON.parse_string(
20+
# FileAccess.open("/tmp/rail1.json", FileAccess.READ).get_as_text()
21+
#)
22+
var data = Data.new()
23+
var rail1 = data.rail1
24+
25+
var rail1pts = rail1.map(arr_to_vec)
26+
var rail2pts = data.rail2.map(arr_to_vec)
27+
pos = data.pos.map(arr_to_vec)
28+
up = data.up.map(arr_to_vec)
29+
fwd = data.fwd.map(arr_to_vec)
30+
31+
var m = mesh.mesh
32+
m.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
33+
cylinder_line(m, rail1pts, 0.1)
34+
cylinder_line(m, rail2pts, 0.1)
35+
36+
# cross
37+
var cross = data.cross
38+
for i in range(cross.size()):
39+
if cross[i]:
40+
cylinder_line(m, [rail1pts[i], rail2pts[i]], 0.1)
41+
42+
m.surface_end()
43+
744
# We assume this node has a button as a child.
845
# This button is for the user to consent to entering immersive VR mode.
946
$Button.pressed.connect(self._on_button_pressed)
47+
$Button2.pressed.connect(self._on_normal_button_pressed)
48+
$Button3.pressed.connect(self._on_reset_button_pressed)
1049

1150
webxr_interface = XRServer.find_interface("WebXR")
1251
if webxr_interface:
@@ -26,10 +65,17 @@ func _webxr_session_supported(session_mode, supported):
2665
if session_mode == 'immersive-vr':
2766
vr_supported = supported
2867

68+
func _on_normal_button_pressed():
69+
active = not active
70+
71+
func _on_reset_button_pressed():
72+
t = 0
73+
2974
func _on_button_pressed():
3075
if not vr_supported:
3176
OS.alert("Your browser doesn't support VR")
3277
return
78+
active = true
3379

3480
# We want an immersive VR session, as opposed to AR ('immersive-ar') or a
3581
# simple 3DoF viewer ('viewer').
@@ -76,20 +122,60 @@ func _webxr_session_ended():
76122
func _webxr_session_failed(message):
77123
OS.alert("Failed to initialize: " + message)
78124

79-
"""extends Node3D
125+
func _process(_delta):
126+
if t < len(pos):
127+
$XROrigin3D.look_at_from_position(pos[t], pos[t] + fwd[t], up[t])
128+
if active:
129+
t += 1
130+
#$XROrigin3D.global_position.z -= _delta
131+
132+
133+
## Adds 3d lines between [points] with the given [radius]
134+
static func cylinder_line(m, points, radius):
135+
if len(points) > 1:
136+
for i in range(1, len(points)):
137+
# create cylinder
138+
const NUM_QUADS = 10
139+
var p = points[i-1]
140+
var q = points[i]
141+
var pq: Vector3 = q - p
142+
var rot = Quaternion(pq.normalized(), Vector3.UP).normalized()
143+
144+
for j in range(NUM_QUADS):
145+
var theta0 = 2*PI * j / NUM_QUADS
146+
var theta1 = 2*PI * (j+1) / NUM_QUADS
147+
var offset0 = (Vector3(1, 0, 0) * Quaternion(Vector3.UP, theta0)) * rot
148+
var offset1 = (Vector3(1, 0, 0) * Quaternion(Vector3.UP, theta1)) * rot
149+
var quad = [
150+
p + radius * (offset1),
151+
q + radius * (offset1),
152+
q + radius * (offset0),
153+
p + radius * (offset0),
154+
155+
offset1,
156+
offset1,
157+
offset0,
158+
offset0,
159+
]
160+
add_quad(
161+
m,
162+
quad[0], quad[1], quad[2], quad[3],
163+
quad[4], quad[5], quad[6], quad[7]
164+
)
80165

81-
var xr_interface: XRInterface
82166

83-
# Called when the node enters the scene tree for the first time.
84-
func _ready() -> void:
85-
xr_interface = XRServer.find_interface("OpenXR")
86-
if xr_interface and xr_interface.is_initialized():
87-
print("OpenXR initialized successfully")
88-
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
89-
get_viewport().use_xr = true
90-
else:
91-
print("OpenXR not initialized, please check if your headset is connected")
167+
## Adds a quad to ImmediateMesh
168+
## CCW winding order
169+
static func add_quad(m, p1, p2, p3, p4, n1, n2, n3, n4):
170+
add_tri(m, p1, p2, p3, n1, n2, n3)
171+
add_tri(m, p3, p4, p1, n3, n4, n1)
92172

93-
# Called every frame. 'delta' is the elapsed time since the previous frame.
94-
func _process(delta: float) -> void:
95-
pass"""
173+
## Adds a triangle to ImmediateMesh
174+
## CCW winding order
175+
static func add_tri(m, p1, p2, p3, n1, n2, n3):
176+
m.surface_set_normal(n1)
177+
m.surface_add_vertex(p1)
178+
m.surface_set_normal(n2)
179+
m.surface_add_vertex(p2)
180+
m.surface_set_normal(n3)
181+
m.surface_add_vertex(p3)

xrtest/node_3d.tscn

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
[gd_scene load_steps=3 format=3 uid="uid://7jpqye8u62tn"]
1+
[gd_scene load_steps=4 format=3 uid="uid://7jpqye8u62tn"]
22

33
[ext_resource type="Script" path="res://main.gd" id="1_qulo4"]
44

5-
[sub_resource type="BoxMesh" id="BoxMesh_p5a7i"]
5+
[sub_resource type="PlaneMesh" id="PlaneMesh_sowto"]
6+
size = Vector2(100, 100)
7+
8+
[sub_resource type="ImmediateMesh" id="ImmediateMesh_772bl"]
69

710
[node name="Node3D" type="Node3D"]
811
script = ExtResource("1_qulo4")
912

1013
[node name="XROrigin3D" type="XROrigin3D" parent="."]
14+
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 40, 30, 10)
1115

1216
[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"]
13-
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 0)
1417

1518
[node name="LeftHand" type="XRController3D" parent="XROrigin3D"]
1619
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1, -0.5)
@@ -22,13 +25,30 @@ tracker = &"right_hand"
2225

2326
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
2427
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.598664, -7.24694)
25-
mesh = SubResource("BoxMesh_p5a7i")
28+
mesh = SubResource("PlaneMesh_sowto")
2629
skeleton = NodePath("../XROrigin3D")
2730

2831
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
29-
transform = Transform3D(1, 0, 0, 0, -0.275084, 0.96142, 0, -0.96142, -0.275084, 0, 2.1761, -5.72324)
32+
transform = Transform3D(1, 0, 0, 0, 0.560104, 0.828423, 0, -0.828423, 0.560104, 0, 2.1761, -5.72324)
3033

3134
[node name="Button" type="Button" parent="."]
3235
offset_right = 8.0
3336
offset_bottom = 8.0
34-
text = "PressMe"
37+
text = "Run in VR"
38+
39+
[node name="Button2" type="Button" parent="."]
40+
offset_left = 1.0
41+
offset_top = 34.0
42+
offset_right = 116.0
43+
offset_bottom = 65.0
44+
text = "Run Normally"
45+
46+
[node name="MeshInstance3D2" type="MeshInstance3D" parent="."]
47+
mesh = SubResource("ImmediateMesh_772bl")
48+
49+
[node name="Button3" type="Button" parent="."]
50+
offset_left = 2.0
51+
offset_top = 69.0
52+
offset_right = 53.0
53+
offset_bottom = 100.0
54+
text = "Reset"

xrtest/utils.gd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extends Node
2+
3+
class_name Util

0 commit comments

Comments
 (0)