teleportxr 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +18 -0
- package/.vscode/settings.json +12 -0
- package/LICENSE +21 -0
- package/LICENSES/Apache-2.0.txt +73 -0
- package/LICENSES/BSD-3-Clause.txt +11 -0
- package/LICENSES/BSL-1.0.txt +7 -0
- package/LICENSES/CC-BY-4.0.txt +156 -0
- package/LICENSES/CC0-1.0.txt +121 -0
- package/LICENSES/MIT.txt +9 -0
- package/README.md +6 -0
- package/assets/scene.json +8 -0
- package/client/client.js +305 -0
- package/client/client_manager.js +114 -0
- package/client/geometry_service.js +422 -0
- package/connections/connection.js +0 -0
- package/connections/connectionmanager.js +0 -0
- package/connections/webrtcconnection.js +384 -0
- package/connections/webrtcconnectionmanager.js +86 -0
- package/core/core.js +447 -0
- package/index.js +13 -0
- package/package.json +36 -0
- package/protocol/command.js +127 -0
- package/protocol/encoders/node_encoder.js +28 -0
- package/protocol/encoders/resource_encoder.js +28 -0
- package/protocol/message.js +145 -0
- package/scene/material.js +105 -0
- package/scene/node.js +255 -0
- package/scene/resources.js +62 -0
- package/scene/scene.js +83 -0
- package/server.js +35 -0
- package/signaling.js +255 -0
- package/temp.js +1 -0
- package/test.json +2 -0
package/core/core.js
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var microtime = require('microtime') // timings in microseconds.
|
|
3
|
+
const UID_SIZE = 8;
|
|
4
|
+
const endian = true;
|
|
5
|
+
// Get type information by "typename". Everything not listed is assumed to be a struct
|
|
6
|
+
// (i.e. a js class with its own encodeIntoDataView function.)
|
|
7
|
+
function SizeOfType(member) {
|
|
8
|
+
switch (member) {
|
|
9
|
+
case "float":
|
|
10
|
+
case "float32":
|
|
11
|
+
return [4, "float32"];
|
|
12
|
+
case "double":
|
|
13
|
+
case "float64":
|
|
14
|
+
return [8, "float64"];
|
|
15
|
+
case "float16":
|
|
16
|
+
return [2, "float16"];
|
|
17
|
+
case "CommandPayloadType":
|
|
18
|
+
case "MessagePayloadType":
|
|
19
|
+
case "BackgroundMode":
|
|
20
|
+
case "AxesStandard":
|
|
21
|
+
case "GeometryPayloadType":
|
|
22
|
+
return [1, "uint8"];
|
|
23
|
+
case "CommandPayloadType":
|
|
24
|
+
return [1, "uint8"];
|
|
25
|
+
case "bool":
|
|
26
|
+
return [1, "uint8"];
|
|
27
|
+
case "int8":
|
|
28
|
+
return [1, "uint8"];
|
|
29
|
+
case "uint8":
|
|
30
|
+
return [1, "uint8"];
|
|
31
|
+
case "vec4":
|
|
32
|
+
return [16, "struct"];
|
|
33
|
+
case "uid":
|
|
34
|
+
return [8, "uint64"];
|
|
35
|
+
case "int32":
|
|
36
|
+
return [4, "int32"];
|
|
37
|
+
case "uint32":
|
|
38
|
+
return [4, "uint32"];
|
|
39
|
+
case "uint64":
|
|
40
|
+
return [8, "uint64"];
|
|
41
|
+
case "int64":
|
|
42
|
+
return [8, "int64"];
|
|
43
|
+
case "VideoConfig":
|
|
44
|
+
return [89, "struct"];
|
|
45
|
+
case "VideoCodec":
|
|
46
|
+
case "AxesStandard":
|
|
47
|
+
case "GeometryPayloadType":
|
|
48
|
+
case "BackgroundMode":
|
|
49
|
+
case "LightingMode":
|
|
50
|
+
return [1, "uint8"];
|
|
51
|
+
default:
|
|
52
|
+
// must have defined size() for the object:
|
|
53
|
+
return [0, "struct"];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function encodeIntoDataView(obj, dataView, byteOffset) {
|
|
58
|
+
for (let [key, value] of Object.entries(obj)) {
|
|
59
|
+
let first_underscore = key.search('_');
|
|
60
|
+
var name = key.substring(first_underscore + 1, key.end);
|
|
61
|
+
var type = key.substring(0, first_underscore);
|
|
62
|
+
var [sz, tp] = SizeOfType(type);
|
|
63
|
+
if (tp == "uint8") {
|
|
64
|
+
dataView.setUint8(byteOffset, value, endian);
|
|
65
|
+
}
|
|
66
|
+
else if (tp == "int8") {
|
|
67
|
+
dataView.setInt8(byteOffset, value, endian);
|
|
68
|
+
}
|
|
69
|
+
else if (tp == "uint32") {
|
|
70
|
+
dataView.setUint32(byteOffset, value, endian);
|
|
71
|
+
}
|
|
72
|
+
else if (tp == "int32") {
|
|
73
|
+
dataView.setInt32(byteOffset, value, endian);
|
|
74
|
+
}
|
|
75
|
+
else if (tp == "float32") {
|
|
76
|
+
dataView.setFloat32(byteOffset, value, endian);
|
|
77
|
+
}
|
|
78
|
+
else if (tp == "int64") {
|
|
79
|
+
dataView.setBigInt64(byteOffset, value, endian);
|
|
80
|
+
}
|
|
81
|
+
else if (tp == "uint64") {
|
|
82
|
+
dataView.setBigUint64(byteOffset, value, endian);
|
|
83
|
+
}
|
|
84
|
+
else if (tp == "struct") {
|
|
85
|
+
sz = encodeIntoDataView(value, dataView, byteOffset) - byteOffset;
|
|
86
|
+
}
|
|
87
|
+
if (sz == 0 || sz == NaN) {
|
|
88
|
+
throw new Error("Can't find size of " + key + " in " + obj.toString());
|
|
89
|
+
}
|
|
90
|
+
byteOffset += sz;
|
|
91
|
+
console.log(byteOffset + ": " + sz + " bytes\t\t" + tp + " " + name + " " + value.toString());
|
|
92
|
+
}
|
|
93
|
+
console.log("Total size: " + byteOffset + "\n");
|
|
94
|
+
return byteOffset;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function decodeFromDataView(obj, dataView, byteOffset) {
|
|
98
|
+
for (let [key, sub_obj] of Object.entries(obj)) {
|
|
99
|
+
let first_underscore = key.search('_');
|
|
100
|
+
var name = key.substring(first_underscore + 1, key.end);
|
|
101
|
+
var type = key.substring(0, first_underscore);
|
|
102
|
+
var [sz, tp] = SizeOfType(type);
|
|
103
|
+
if (tp == "uint8") {
|
|
104
|
+
var value = dataView.getUint8(byteOffset);
|
|
105
|
+
obj[key] = value;
|
|
106
|
+
}
|
|
107
|
+
else if (tp == "int8") {
|
|
108
|
+
var value = dataView.getInt8(byteOffset);
|
|
109
|
+
obj[key] = value;
|
|
110
|
+
}
|
|
111
|
+
else if (tp == "uint32") {
|
|
112
|
+
var value = dataView.getUint32(byteOffset, endian);
|
|
113
|
+
obj[key] = value;
|
|
114
|
+
}
|
|
115
|
+
else if (tp == "int32") {
|
|
116
|
+
var value = dataView.getInt32(byteOffset, endian);
|
|
117
|
+
obj[key] = value;
|
|
118
|
+
}
|
|
119
|
+
else if (tp == "float32") {
|
|
120
|
+
var value = dataView.getFloat32(byteOffset, endian);
|
|
121
|
+
obj[key] = value;
|
|
122
|
+
}
|
|
123
|
+
else if (tp == "int64") {
|
|
124
|
+
var value = dataView.getBigInt64(byteOffset, endian);
|
|
125
|
+
obj[key] = value;
|
|
126
|
+
}
|
|
127
|
+
else if (tp == "uint64") {
|
|
128
|
+
var value = dataView.getBigUint64(byteOffset, endian);
|
|
129
|
+
obj[key] = value;
|
|
130
|
+
}
|
|
131
|
+
else if (tp == "struct") {
|
|
132
|
+
try {
|
|
133
|
+
sz = decodeFromDataView(sub_obj, dataView, byteOffset) - byteOffset;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error(error);
|
|
136
|
+
throw new Error("decodeFromDataView failed for " + key);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (sz == 0 || sz == NaN) {
|
|
140
|
+
throw new Error("Can't find size of " + key);
|
|
141
|
+
}
|
|
142
|
+
byteOffset += sz;
|
|
143
|
+
console.log(byteOffset + ": " + sz + " bytes\t\t" + tp + " " + name + " " + sub_obj.toString());
|
|
144
|
+
}
|
|
145
|
+
console.log("Total size: " + byteOffset + "\n");
|
|
146
|
+
return byteOffset;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
class vec4 {
|
|
150
|
+
constructor() {
|
|
151
|
+
this.float_x = 0.0;
|
|
152
|
+
this.float_y = 0.0;
|
|
153
|
+
this.float_z = 0.0;
|
|
154
|
+
this.float_w = 0.0;
|
|
155
|
+
}
|
|
156
|
+
static sizeof() {
|
|
157
|
+
return 16;
|
|
158
|
+
}
|
|
159
|
+
size() {
|
|
160
|
+
return vec4.sizeof();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const BackgroundMode =
|
|
165
|
+
{
|
|
166
|
+
NONE: 0, COLOUR: 1, TEXTURE: 2, VIDEO: 3
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const AxesStandard =
|
|
170
|
+
{
|
|
171
|
+
NotInitialized: 0,
|
|
172
|
+
RightHanded: 1,
|
|
173
|
+
LeftHanded: 2,
|
|
174
|
+
YVertical: 4,
|
|
175
|
+
ZVertical: 8,
|
|
176
|
+
EngineeringStyle: this.ZVertical | this.RightHanded,
|
|
177
|
+
GlStyle: 16 | this.YVertical | this.RightHanded,
|
|
178
|
+
UnrealStyle: 32 | this.ZVertical | this.LeftHanded,
|
|
179
|
+
UnityStyle: 64 | this.YVertical | this.LeftHanded,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const GeometryPayloadType =
|
|
183
|
+
{
|
|
184
|
+
Invalid: 0,
|
|
185
|
+
Mesh: 1,
|
|
186
|
+
Material: 2,
|
|
187
|
+
MaterialInstance: 3,
|
|
188
|
+
Texture: 4,
|
|
189
|
+
Animation: 5,
|
|
190
|
+
Node: 6,
|
|
191
|
+
Skeleton: 7,
|
|
192
|
+
FontAtlas: 8,
|
|
193
|
+
TextCanvas: 9,
|
|
194
|
+
TexturePointer: 10,
|
|
195
|
+
MeshPointer: 11,
|
|
196
|
+
MaterialPointer: 12,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
class DisplayInfo {
|
|
200
|
+
constructor() {
|
|
201
|
+
this.uint32_width = 0; //!< Width of the display.
|
|
202
|
+
this.uint32_height = 0; //!< Height of the display.
|
|
203
|
+
this.float_framerate = 0.0; //!< Expected framerate.
|
|
204
|
+
}
|
|
205
|
+
static sizeof() {
|
|
206
|
+
return 12;
|
|
207
|
+
}
|
|
208
|
+
size() {
|
|
209
|
+
return DisplayInfo.sizeof();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
//! Features supported by a client.
|
|
213
|
+
class RenderingFeatures {
|
|
214
|
+
constructor() {
|
|
215
|
+
this.bool_normals = false; //!< Whether normal maps are supported.
|
|
216
|
+
this.bool_ambientOcclusion = false; //!< Whether ambient occlusion maps are supported.
|
|
217
|
+
}
|
|
218
|
+
static sizeof() {
|
|
219
|
+
return 2;
|
|
220
|
+
}
|
|
221
|
+
size() {
|
|
222
|
+
return RenderingFeatures.sizeof();
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const LightingMode =
|
|
227
|
+
{
|
|
228
|
+
NONE: 0,
|
|
229
|
+
TEXTURE: 1,
|
|
230
|
+
VIDEO: 2
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const VideoCodec =
|
|
234
|
+
{
|
|
235
|
+
Invalid: 0,
|
|
236
|
+
H264: 1, /*!< H264 */
|
|
237
|
+
HEVC: 2 /*!< HEVC (H265) */
|
|
238
|
+
};
|
|
239
|
+
//! Information on the configuration of a video stream.
|
|
240
|
+
|
|
241
|
+
class VideoConfig {
|
|
242
|
+
constructor() {
|
|
243
|
+
this.uint32_video_width = 0;
|
|
244
|
+
this.uint32_video_height = 0;
|
|
245
|
+
this.uint32_depth_width = 0;
|
|
246
|
+
this.uint32_depth_height = 0;
|
|
247
|
+
this.uint32_perspective_width = 0;
|
|
248
|
+
this.uint32_perspective_height = 0;
|
|
249
|
+
this.float_perspective_fov = 110;
|
|
250
|
+
this.float_nearClipPlane = 0.5;
|
|
251
|
+
this.uint32_webcam_width = 0;
|
|
252
|
+
this.uint32_webcam_height = 0;
|
|
253
|
+
this.int32_webcam_offset_x = 0;
|
|
254
|
+
this.int32_webcam_offset_y = 0;
|
|
255
|
+
this.uint32_use_10_bit_decoding = 0;
|
|
256
|
+
this.uint32_use_yuv_444_decoding = 0;
|
|
257
|
+
this.uint32_use_alpha_layer_decoding = 1;
|
|
258
|
+
this.uint32_colour_cubemap_size = 0;
|
|
259
|
+
this.int32_compose_cube = 0;
|
|
260
|
+
this.int32_use_cubemap = 1;
|
|
261
|
+
this.int32_stream_webcam = 0;
|
|
262
|
+
this.VideoCodec_videoCodec = VideoCodec.Invalid;
|
|
263
|
+
this.int32_shadowmap_x = 0;
|
|
264
|
+
this.int32_shadowmap_y = 0;
|
|
265
|
+
this.int32_shadowmap_size = 0;
|
|
266
|
+
}
|
|
267
|
+
static sizeof() {
|
|
268
|
+
return 89;
|
|
269
|
+
}
|
|
270
|
+
}; // 89 bytes
|
|
271
|
+
|
|
272
|
+
//! Setup for dynamically-lit objects on the client.
|
|
273
|
+
class ClientDynamicLighting {
|
|
274
|
+
constructor() {
|
|
275
|
+
this.int2_specularPos = { int32_x: 0, int32_y: 0 };
|
|
276
|
+
this.int32_specularCubemapSize = 0;
|
|
277
|
+
this.int32_specularMips = 0;
|
|
278
|
+
this.int2_diffusePos = { int32_x: 0, int32_y: 0 };
|
|
279
|
+
this.int32_diffuseCubemapSize = 0;
|
|
280
|
+
this.int2_lightPos = { int32_x: 0, int32_y: 0 };
|
|
281
|
+
this.int32_lightCubemapSize = 0;
|
|
282
|
+
this.uid_specular_cubemap_texture_uid = BigInt.asUintN(64, BigInt(0));
|
|
283
|
+
this.uid_diffuse_cubemap_texture_uid = BigInt.asUintN(64, BigInt(0)); //14*4=56
|
|
284
|
+
this.LightingMode_lightingMode = LightingMode.TEXTURE;// 57
|
|
285
|
+
}
|
|
286
|
+
static sizeof() {
|
|
287
|
+
return 57;
|
|
288
|
+
}
|
|
289
|
+
}; // 57 bytes
|
|
290
|
+
|
|
291
|
+
function encodeToUint8Array(object) {
|
|
292
|
+
var array = new Uint8Array(object.size());
|
|
293
|
+
var dataView = new DataView(array.buffer);
|
|
294
|
+
var byteOffset = 0;
|
|
295
|
+
byteOffset = encodeIntoDataView(object, dataView, byteOffset);
|
|
296
|
+
console.log("\n");
|
|
297
|
+
return array;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function decodeFromUint8Array(object, array) {
|
|
301
|
+
if (array.length < object.size()) {
|
|
302
|
+
console.log("Array is wrong size for " + object.toString() + ". have " + array.length.toString() + ", need " + object.size().toString() + ".");
|
|
303
|
+
}
|
|
304
|
+
var dataView = new DataView(array.buffer, array.offset, array.length);
|
|
305
|
+
var byteOffset = 0;
|
|
306
|
+
byteOffset = decodeFromDataView(object, dataView, byteOffset);
|
|
307
|
+
if (byteOffset != object.size()) {
|
|
308
|
+
console.error("Failed to read all of object. Read " + byteOffset + " but expected " + object.size());
|
|
309
|
+
}
|
|
310
|
+
console.log("\n");
|
|
311
|
+
return byteOffset;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
var generateUid = (function () {
|
|
315
|
+
var i = 1;
|
|
316
|
+
return function () {
|
|
317
|
+
return BigInt(i++);
|
|
318
|
+
};
|
|
319
|
+
})();
|
|
320
|
+
|
|
321
|
+
function unixTimeToUTCString(unix_time_us) {
|
|
322
|
+
let unix_timestamp_ms = unix_time_us / 1000.0;
|
|
323
|
+
|
|
324
|
+
// Create a new JavaScript Date object based on the timestamp
|
|
325
|
+
// multiplied by 1000 so that the argument is in milliseconds, not seconds
|
|
326
|
+
var date = new Date(unix_timestamp_ms);
|
|
327
|
+
|
|
328
|
+
var hours = date.getHours();
|
|
329
|
+
return Intl.DateTimeFormat('en-GB', {
|
|
330
|
+
dateStyle: 'full',
|
|
331
|
+
timeStyle: 'long',
|
|
332
|
+
timeZone: 'UTC',
|
|
333
|
+
}).format(date)
|
|
334
|
+
// Hours part from the timestamp
|
|
335
|
+
/* var hours = date.getHours();
|
|
336
|
+
|
|
337
|
+
// Minutes part from the timestamp
|
|
338
|
+
var minutes = "0" + date.getMinutes();
|
|
339
|
+
|
|
340
|
+
// Seconds part from the timestamp
|
|
341
|
+
var seconds = "0" + date.getSeconds();
|
|
342
|
+
|
|
343
|
+
// Will display time in 10:30:23 format
|
|
344
|
+
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
|
|
345
|
+
|
|
346
|
+
return formattedTime;*/
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
var startTimeUnixUs = 0;
|
|
350
|
+
|
|
351
|
+
function getStartTimeUnixUs() {
|
|
352
|
+
if (startTimeUnixUs == 0)
|
|
353
|
+
startTimeUnixUs = microtime.now();
|
|
354
|
+
return startTimeUnixUs;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function getTimestampUs() {
|
|
358
|
+
//var t_unix_ms=Date.now();
|
|
359
|
+
//var t_perf_us=performance.now();
|
|
360
|
+
const t_unix_us = microtime.now();
|
|
361
|
+
const t_us = t_unix_us - getStartTimeUnixUs();
|
|
362
|
+
return t_us;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function put_float32(dataView, byteOffset, value) {
|
|
366
|
+
dataView.setFloat32(byteOffset, value, endian);
|
|
367
|
+
byteOffset += 4;
|
|
368
|
+
return byteOffset;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function put_uint16(dataView, byteOffset, value) {
|
|
372
|
+
dataView.setUint16(byteOffset, value, endian);
|
|
373
|
+
byteOffset += 2;
|
|
374
|
+
return byteOffset;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function put_int32(dataView, byteOffset, value) {
|
|
378
|
+
dataView.setInt32(byteOffset, value, endian);
|
|
379
|
+
byteOffset += 4;
|
|
380
|
+
return byteOffset;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function put_uint32(dataView, byteOffset, value) {
|
|
384
|
+
dataView.setUint32(byteOffset, value, endian);
|
|
385
|
+
byteOffset += 4;
|
|
386
|
+
return byteOffset;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function put_uint64(dataView, byteOffset, value) {
|
|
390
|
+
dataView.setBigUint64(byteOffset, BigInt(value), endian);
|
|
391
|
+
byteOffset += 8;
|
|
392
|
+
return byteOffset;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function put_uint8(dataView, byteOffset, value) {
|
|
396
|
+
dataView.setUint8(byteOffset, value, endian);
|
|
397
|
+
byteOffset++;
|
|
398
|
+
return byteOffset;
|
|
399
|
+
}
|
|
400
|
+
function put_vec2(dataView, byteOffset, value) {
|
|
401
|
+
dataView.setFloat32(byteOffset, value.x, endian);
|
|
402
|
+
byteOffset+=4;
|
|
403
|
+
dataView.setFloat32(byteOffset, value.y, endian);
|
|
404
|
+
byteOffset+=4;
|
|
405
|
+
return byteOffset;
|
|
406
|
+
}
|
|
407
|
+
function put_vec3(dataView, byteOffset, value) {
|
|
408
|
+
dataView.setFloat32(byteOffset, value.x, endian);
|
|
409
|
+
byteOffset+=4;
|
|
410
|
+
dataView.setFloat32(byteOffset, value.y, endian);
|
|
411
|
+
byteOffset+=4;
|
|
412
|
+
dataView.setFloat32(byteOffset, value.z, endian);
|
|
413
|
+
byteOffset+=4;
|
|
414
|
+
return byteOffset;
|
|
415
|
+
}
|
|
416
|
+
function put_vec4(dataView, byteOffset, value) {
|
|
417
|
+
dataView.setFloat32(byteOffset, value.x, endian);
|
|
418
|
+
byteOffset+=4;
|
|
419
|
+
dataView.setFloat32(byteOffset, value.y, endian);
|
|
420
|
+
byteOffset+=4;
|
|
421
|
+
dataView.setFloat32(byteOffset, value.z, endian);
|
|
422
|
+
byteOffset+=4;
|
|
423
|
+
dataView.setFloat32(byteOffset, value.w, endian);
|
|
424
|
+
byteOffset+=4;
|
|
425
|
+
return byteOffset;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
//! Insert a string to the dataView.
|
|
429
|
+
function put_string(dataView, byteOffset, name) {
|
|
430
|
+
byteOffset = put_uint16(dataView, byteOffset, name.length);
|
|
431
|
+
//Push name.
|
|
432
|
+
for (var i = 0; i < name.length; i++) {
|
|
433
|
+
var char = name[i];
|
|
434
|
+
var code = char.charCodeAt(0);
|
|
435
|
+
byteOffset = put_uint8(dataView, byteOffset, code);
|
|
436
|
+
}
|
|
437
|
+
return byteOffset;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
module.exports = {
|
|
441
|
+
UID_SIZE, endian, SizeOfType, encodeIntoDataView, decodeFromDataView
|
|
442
|
+
, vec4, BackgroundMode, AxesStandard, GeometryPayloadType, DisplayInfo, RenderingFeatures, LightingMode, VideoCodec
|
|
443
|
+
, VideoConfig, ClientDynamicLighting, encodeToUint8Array, decodeFromUint8Array
|
|
444
|
+
, generateUid, getStartTimeUnixUs, getTimestampUs,
|
|
445
|
+
unixTimeToUTCString, put_float32, put_uint16, put_int32, put_uint32
|
|
446
|
+
, put_uint64, put_uint8, put_vec2, put_vec3, put_vec4, put_string
|
|
447
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
const WebRtcConnectionManager = require('./connections/webrtcconnectionmanager.js');
|
|
3
|
+
const signaling =require("./signaling.js");
|
|
4
|
+
const client_manager = require('./client/client_manager.js');
|
|
5
|
+
|
|
6
|
+
function initServer() {
|
|
7
|
+
var cm=client_manager.getInstance();
|
|
8
|
+
const webRtcConnectionManager = WebRtcConnectionManager.getInstance();
|
|
9
|
+
webRtcConnectionManager.SetSendConfigMessage(signaling.sendConfigMessage);
|
|
10
|
+
signaling.init(webRtcConnectionManager,cm.newClient.bind(cm));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = {initServer}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"bitset": "^5.2.3",
|
|
4
|
+
"get-current-line": "^7.4.0",
|
|
5
|
+
"microtime": "^3.1.1",
|
|
6
|
+
"underscore": "^1.13.7",
|
|
7
|
+
"uuid": "^9.0.1",
|
|
8
|
+
"wrtc": "^0.4.7",
|
|
9
|
+
"ws": "^8.13.0"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node server.js"
|
|
13
|
+
},
|
|
14
|
+
"name": "teleportxr",
|
|
15
|
+
"description": "A minimal Teleport server on node.js",
|
|
16
|
+
"version": "1.0.0",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/simul/teleport-nodejs.git"
|
|
20
|
+
},
|
|
21
|
+
"author": "rvkennedy",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/simul/teleport-nodejs/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/simul/teleport-nodejs#readme",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./index.js",
|
|
29
|
+
"./signaling": "./signaling.js",
|
|
30
|
+
"./client/client_manager": "./client/client_manager.js",
|
|
31
|
+
"./connections/webrtcconnectionmanager": "./connections/webrtcconnectionmanager.js",
|
|
32
|
+
"./scene/scene":"./scene/scene.js"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const core= require("../core/core.js");
|
|
3
|
+
|
|
4
|
+
//! The payload type, or how to interpret the server's message.
|
|
5
|
+
const CommandPayloadType =
|
|
6
|
+
{
|
|
7
|
+
Invalid:0,
|
|
8
|
+
Shutdown:1,
|
|
9
|
+
Setup:2,
|
|
10
|
+
AcknowledgeHandshake:3,
|
|
11
|
+
ReconfigureVideo:4,
|
|
12
|
+
NodeVisibility:5,
|
|
13
|
+
UpdateNodeMovement:6,
|
|
14
|
+
UpdateNodeEnabledState:7,
|
|
15
|
+
SetNodeHighlighted:8,
|
|
16
|
+
ApplyNodeAnimation:9,
|
|
17
|
+
UpdateNodeAnimationControlX:10,
|
|
18
|
+
SetNodeAnimationSpeed:11,
|
|
19
|
+
SetupLighting:12,
|
|
20
|
+
UpdateNodeStructure:13,
|
|
21
|
+
AssignNodePosePath:14,
|
|
22
|
+
SetupInputs:15,
|
|
23
|
+
PingForLatency:16,
|
|
24
|
+
SetOriginNode:128
|
|
25
|
+
};
|
|
26
|
+
class Command{
|
|
27
|
+
constructor(){
|
|
28
|
+
this.CommandPayloadType_commandPayloadType=CommandPayloadType.Invalid;
|
|
29
|
+
}
|
|
30
|
+
size(){
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SetupCommand extends Command
|
|
37
|
+
{
|
|
38
|
+
constructor(){
|
|
39
|
+
super();
|
|
40
|
+
// Command=1 byte
|
|
41
|
+
this.CommandPayloadType_commandPayloadType=CommandPayloadType.Setup;
|
|
42
|
+
this.uint32_debug_stream = 0; //!< 1+4=5
|
|
43
|
+
this.uint32_debug_network_packets = 0; //!< 5+4=9
|
|
44
|
+
this.int32_requiredLatencyMs = 0; //!< 9+4=13
|
|
45
|
+
this.uint32_idle_connection_timeout = 5000.0; //!< 13+4=17
|
|
46
|
+
this.uint64_session_id = BigInt.asUintN(64, BigInt(0)); //!< 17+8=25 The server's session id changes when the server session changes. 37 bytes
|
|
47
|
+
this.VideoConfig_video_config=new core.VideoConfig(); //!< 25+89=114 Video setup structure. 41+89=130 bytes
|
|
48
|
+
this.float32_draw_distance = 0.0; //!< 114+4=118 Maximum distance in metres to render locally. 134
|
|
49
|
+
this.AxesStandard_axesStandard = core.AxesStandard.NotInitialized; //!< 118+1=119 The axis standard that the server uses, may be different from the client's. 147
|
|
50
|
+
this.uint8_audio_input_enabled = 0; //!< 119+1=120 Server accepts audio stream from client.
|
|
51
|
+
this.bool_using_ssl = true; //!< 120+1=121 Not in use, for later.
|
|
52
|
+
this.int64_startTimestamp_utc_unix_us = BigInt.asUintN(64, BigInt(0)); //!< 121+8=129 UTC Unix Timestamp in microseconds when the server session began.
|
|
53
|
+
// TODO: replace this with a background Material, which MAY contain video, te xture and/or plain colours.
|
|
54
|
+
this.BackgroundMode_backgroundMode=core.BackgroundMode.COLOUR; //!< 129+1=130 Whether the server supplies a background, and of which type.
|
|
55
|
+
this.vec4_backgroundColour=new core.vec4(); //!< 130+16=146 If the background is of the COLOUR type, which colour to use.
|
|
56
|
+
this.ClientDynamicLighting_clientDynamicLighting=new core.ClientDynamicLighting(); //!< Setup for dynamic object lighting. 174+57=231 bytes
|
|
57
|
+
this.uid_backgroundTexture=BigInt(0);
|
|
58
|
+
}
|
|
59
|
+
static sizeof(){
|
|
60
|
+
return 211;
|
|
61
|
+
}
|
|
62
|
+
size(){
|
|
63
|
+
return SetupCommand.sizeof();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
class AcknowledgeHandshakeCommand extends Command{
|
|
68
|
+
|
|
69
|
+
constructor(){
|
|
70
|
+
super();
|
|
71
|
+
// Command=1 byte
|
|
72
|
+
this.CommandPayloadType_commandPayloadType=CommandPayloadType.AcknowledgeHandshake;
|
|
73
|
+
this.uint64_visibleNodeCount=BigInt(0);
|
|
74
|
+
}
|
|
75
|
+
static sizeof(){
|
|
76
|
+
return 9;
|
|
77
|
+
}
|
|
78
|
+
size(){
|
|
79
|
+
return AcknowledgeHandshakeCommand.sizeof();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
//! A command that expects an acknowledgement of receipt from the client using an AcknowledgementMessage.
|
|
85
|
+
class AckedCommand extends Command
|
|
86
|
+
{
|
|
87
|
+
constructor(){
|
|
88
|
+
super();
|
|
89
|
+
// Command=1 byte
|
|
90
|
+
// ackId 8 bytes
|
|
91
|
+
this.uint64_ackId=BigInt(0);
|
|
92
|
+
//! The id that is used to acknowledge receipt via AcknowledgementMessage.
|
|
93
|
+
// Should increase monotonically per-full-client-session: clients can ignore any id less than or equal to a previously received id.
|
|
94
|
+
}
|
|
95
|
+
static sizeof(){
|
|
96
|
+
return 9;
|
|
97
|
+
}
|
|
98
|
+
size(){
|
|
99
|
+
return AckedCommand.sizeof();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
//! Sent from server to client to set the origin of the client's space.
|
|
104
|
+
class SetOriginNodeCommand extends AckedCommand
|
|
105
|
+
{
|
|
106
|
+
constructor(){
|
|
107
|
+
super();
|
|
108
|
+
// Command=1 byte
|
|
109
|
+
this.CommandPayloadType_commandPayloadType=CommandPayloadType.SetOriginNode;
|
|
110
|
+
// AckedCommand=9 bytes
|
|
111
|
+
// uint64_originNodeUid 8 bytes
|
|
112
|
+
this.uint64_originNodeUid=BigInt(0); //!< The session uid of the node to use as the origin.
|
|
113
|
+
|
|
114
|
+
// uint64_validCounter 8 bytes
|
|
115
|
+
//! A validity value. Larger values indicate newer data, so the client ignores messages with smaller validity than the last one received.
|
|
116
|
+
this.uint64_validCounter =BigInt(0);
|
|
117
|
+
}
|
|
118
|
+
static sizeof()
|
|
119
|
+
{
|
|
120
|
+
return AckedCommand.sizeof()+16;
|
|
121
|
+
}
|
|
122
|
+
size(){
|
|
123
|
+
return SetOriginNodeCommand.sizeof();
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
module.exports= {Command,CommandPayloadType,SetupCommand,AcknowledgeHandshakeCommand,SetOriginNodeCommand};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const nd = require('../../scene/node.js');
|
|
4
|
+
const core= require('../../core/core.js');
|
|
5
|
+
const { error } = require('console');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
function putPlaceholderSize(dataView)
|
|
9
|
+
{
|
|
10
|
+
// Add placeholder for the payload size
|
|
11
|
+
dataView.setBigUint64(0,BigInt(0),core.endian);
|
|
12
|
+
return 8;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// return the size of the encoded node.
|
|
16
|
+
function encodeNode(node,buffer)
|
|
17
|
+
{
|
|
18
|
+
var byteOffset=0;
|
|
19
|
+
const dataView = new DataView(buffer);
|
|
20
|
+
byteOffset=putPlaceholderSize(dataView);
|
|
21
|
+
|
|
22
|
+
var t=node.encodeIntoDataView(dataView,byteOffset);
|
|
23
|
+
byteOffset=t;
|
|
24
|
+
// Actual size is now known so update payload size
|
|
25
|
+
dataView.setBigUint64(0,BigInt(byteOffset));
|
|
26
|
+
return byteOffset;
|
|
27
|
+
}
|
|
28
|
+
module.exports= {encodeNode};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const resources = require('../../scene/resources.js');
|
|
4
|
+
const core= require('../../core/core.js');
|
|
5
|
+
const { error } = require('console');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
function putPlaceholderSize(dataView)
|
|
9
|
+
{
|
|
10
|
+
// Add placeholder for the payload size
|
|
11
|
+
dataView.setBigUint64(0,BigInt(0),core.endian);
|
|
12
|
+
return 8;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// return the size of the encoded resource.
|
|
16
|
+
function EncodeResource(res,buffer)
|
|
17
|
+
{
|
|
18
|
+
var byteOffset=0;
|
|
19
|
+
const dataView = new DataView(buffer);
|
|
20
|
+
byteOffset=putPlaceholderSize(dataView);
|
|
21
|
+
|
|
22
|
+
var t=res.encodeIntoDataView(dataView,byteOffset);
|
|
23
|
+
byteOffset=t;
|
|
24
|
+
// Actual size is now known so update payload size
|
|
25
|
+
dataView.setBigUint64(0,BigInt(byteOffset));
|
|
26
|
+
return byteOffset;
|
|
27
|
+
}
|
|
28
|
+
module.exports= {EncodeResource};
|