teleportxr 1.0.92 → 1.0.93

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/client/client.js CHANGED
@@ -228,6 +228,9 @@ class Client {
228
228
  this.setupCommand.int64_startTimestamp_utc_unix_us = BigInt(core.getStartTimeUnixUs());
229
229
  if(this.scene)
230
230
  {
231
+ // Tell the client which axes standard the server authored the scene in. Node transforms
232
+ // are converted to the client's own standard at encode time (see SendNode).
233
+ this.setupCommand.AxesStandard_axesStandard=this.scene.serverAxesStandard;
231
234
  if(this.scene.backgroundTexturePath&&this.scene.backgroundTexturePath!="")
232
235
  {
233
236
  this.setupCommand.BackgroundMode_backgroundMode=BackgroundMode.TEXTURE;
@@ -550,7 +553,9 @@ class Client {
550
553
  var node=this.scene.GetNode(uid);
551
554
  const MAX_NODE_SIZE=500;
552
555
  const buffer = new ArrayBuffer(MAX_NODE_SIZE);
553
- const nodeSize=node_encoder.encodeNode(node,buffer);
556
+ // Convert the node's transform from the server's axes standard to this client's, exactly as
557
+ // the C++ server does in GeometryEncoder::encodeNodes (ConvertTransform server->client).
558
+ const nodeSize=node_encoder.encodeNode(node,buffer,this.scene.serverAxesStandard,this.clientAxesStandard);
554
559
  const view2 = new DataView(buffer, 0, nodeSize);
555
560
  if(!this.webRtcConnection)
556
561
  {
package/core/core.js CHANGED
@@ -200,6 +200,111 @@ function AxesStandardToCubemapSuffix(axesStandard)
200
200
  }
201
201
  }
202
202
 
203
+ // ---- Axes-standard conversions for object transforms ----
204
+ // Ported from the C++ server (libavstream common_maths.h ConvertPosition/Rotation/Scale), which
205
+ // converts each node's transform from the server's axes standard to the client's during encoding.
206
+ // The C++ table only covers Unreal/Unity <-> Gl/Engineering (its server is engine-driven), so the
207
+ // Engineering <-> GlStyle cases below are added here (both right-handed: position/quat vector part
208
+ // maps as (x, z, -y); its inverse as (x, -z, y); scale permutes y/z).
209
+ function ConvertPosition(from, to, p)
210
+ {
211
+ const A = AxesStandard;
212
+ if (from === to) return { x: p.x, y: p.y, z: p.z };
213
+ if (from === A.UnrealStyle)
214
+ {
215
+ if (to === A.GlStyle) return { x: +p.y, y: +p.z, z: -p.x };
216
+ if (to === A.EngineeringStyle) return { x: p.y, y: p.x, z: p.z };
217
+ }
218
+ else if (from === A.UnityStyle)
219
+ {
220
+ if (to === A.GlStyle) return { x: p.x, y: p.y, z: -p.z };
221
+ if (to === A.EngineeringStyle) return { x: p.x, y: p.z, z: p.y };
222
+ }
223
+ else if (from === A.EngineeringStyle)
224
+ {
225
+ if (to === A.UnrealStyle) return { x: p.y, y: p.x, z: p.z };
226
+ if (to === A.UnityStyle) return { x: p.x, y: p.z, z: p.y };
227
+ if (to === A.GlStyle) return { x: p.x, y: p.z, z: -p.y }; // added
228
+ }
229
+ else if (from === A.GlStyle)
230
+ {
231
+ if (to === A.UnrealStyle) return { x: -p.z, y: +p.x, z: +p.y };
232
+ if (to === A.UnityStyle) return { x: p.x, y: p.y, z: -p.z };
233
+ if (to === A.EngineeringStyle) return { x: p.x, y: -p.z, z: p.y }; // added
234
+ }
235
+ console.warn("ConvertPosition: unsupported axes "+from+"->"+to+"; leaving unchanged");
236
+ return { x: p.x, y: p.y, z: p.z };
237
+ }
238
+
239
+ function ConvertRotation(from, to, q)
240
+ {
241
+ const A = AxesStandard;
242
+ if (from === to) return { x: q.x, y: q.y, z: q.z, w: q.w };
243
+ if (from === A.UnrealStyle)
244
+ {
245
+ if (to === A.GlStyle) return { x: -q.y, y: -q.z, z: +q.x, w: q.w };
246
+ if (to === A.EngineeringStyle) return { x: -q.y, y: -q.x, z: -q.z, w: q.w };
247
+ }
248
+ else if (from === A.EngineeringStyle)
249
+ {
250
+ if (to === A.UnrealStyle) return { x: -q.y, y: -q.x, z: -q.z, w: q.w };
251
+ if (to === A.UnityStyle) return { x: -q.x, y: -q.z, z: -q.y, w: q.w };
252
+ if (to === A.GlStyle) return { x: q.x, y: q.z, z: -q.y, w: q.w }; // added
253
+ }
254
+ else if (from === A.GlStyle)
255
+ {
256
+ if (to === A.UnrealStyle) return { x: +q.z, y: -q.x, z: -q.y, w: q.w };
257
+ if (to === A.UnityStyle) return { x: -q.x, y: -q.y, z: q.z, w: q.w };
258
+ if (to === A.EngineeringStyle) return { x: q.x, y: -q.z, z: q.y, w: q.w }; // added
259
+ }
260
+ else if (from === A.UnityStyle)
261
+ {
262
+ if (to === A.GlStyle) return { x: -q.x, y: -q.y, z: q.z, w: q.w };
263
+ if (to === A.EngineeringStyle) return { x: -q.x, y: -q.z, z: -q.y, w: q.w };
264
+ }
265
+ console.warn("ConvertRotation: unsupported axes "+from+"->"+to+"; leaving unchanged");
266
+ return { x: q.x, y: q.y, z: q.z, w: q.w };
267
+ }
268
+
269
+ function ConvertScale(from, to, s)
270
+ {
271
+ const A = AxesStandard;
272
+ if (from === to) return { x: s.x, y: s.y, z: s.z };
273
+ if (from === A.UnrealStyle)
274
+ {
275
+ if (to === A.GlStyle) return { x: +s.y, y: +s.z, z: s.x };
276
+ if (to === A.EngineeringStyle) return { x: s.y, y: s.x, z: s.z };
277
+ }
278
+ else if (from === A.UnityStyle)
279
+ {
280
+ if (to === A.GlStyle) return { x: s.x, y: s.y, z: s.z };
281
+ if (to === A.EngineeringStyle) return { x: s.x, y: s.z, z: s.y };
282
+ }
283
+ else if (from === A.EngineeringStyle)
284
+ {
285
+ if (to === A.UnrealStyle) return { x: s.y, y: s.x, z: s.z };
286
+ if (to === A.UnityStyle) return { x: s.x, y: s.z, z: s.y };
287
+ if (to === A.GlStyle) return { x: s.x, y: s.z, z: s.y }; // added (abs of position map)
288
+ }
289
+ else if (from === A.GlStyle)
290
+ {
291
+ if (to === A.UnrealStyle) return { x: s.z, y: +s.x, z: +s.y };
292
+ if (to === A.UnityStyle) return { x: s.x, y: s.y, z: s.z };
293
+ if (to === A.EngineeringStyle) return { x: s.x, y: s.z, z: s.y }; // added
294
+ }
295
+ return { x: s.x, y: s.y, z: s.z };
296
+ }
297
+
298
+ //! Convert a {position, orientation, scale} pose from one axes standard to another.
299
+ function ConvertPose(from, to, pose)
300
+ {
301
+ return {
302
+ position: ConvertPosition(from, to, pose.position),
303
+ orientation: ConvertRotation(from, to, pose.orientation),
304
+ scale: ConvertScale(from, to, pose.scale || { x: 1, y: 1, z: 1 }),
305
+ };
306
+ }
307
+
203
308
  const GeometryPayloadType =
204
309
  {
205
310
  Invalid: 0,
@@ -460,7 +565,9 @@ function put_string(dataView, byteOffset, name) {
460
565
 
461
566
  module.exports = {
462
567
  UID_SIZE, endian, SizeOfType, encodeIntoDataView, decodeFromDataView
463
- , vec4, BackgroundMode, AxesStandard, AxesStandardToCubemapSuffix, GeometryPayloadType, DisplayInfo, RenderingFeatures, LightingMode, VideoCodec
568
+ , vec4, BackgroundMode, AxesStandard, AxesStandardToCubemapSuffix
569
+ , ConvertPosition, ConvertRotation, ConvertScale, ConvertPose
570
+ , GeometryPayloadType, DisplayInfo, RenderingFeatures, LightingMode, VideoCodec
464
571
  , VideoConfig, ClientDynamicLighting, encodeToUint8Array, decodeFromUint8Array
465
572
  , generateUid, getStartTimeUnixUs, getTimestampUs,
466
573
  unixTimeToUTCString, put_float32, put_uint16, put_int32, put_uint32
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "name": "teleportxr",
18
18
  "description": "Teleport Spatial Server on node.js",
19
- "version": "1.0.92",
19
+ "version": "1.0.93",
20
20
  "repository": {
21
21
  "type": "git",
22
22
  "url": "git+https://github.com/simul/teleport-nodejs.git"
@@ -13,13 +13,15 @@ function putPlaceholderSize(dataView)
13
13
  }
14
14
 
15
15
  // return the size of the encoded node.
16
- function encodeNode(node,buffer)
16
+ // fromAxes/toAxes, when supplied, convert the node's transform from the server's axes standard to
17
+ // the client's during encoding (matches the C++ server). Omit them to encode the pose unchanged.
18
+ function encodeNode(node,buffer,fromAxes,toAxes)
17
19
  {
18
20
  var byteOffset=0;
19
- const dataView = new DataView(buffer);
21
+ const dataView = new DataView(buffer);
20
22
  byteOffset=putPlaceholderSize(dataView);
21
23
 
22
- var t=node.encodeIntoDataView(dataView,byteOffset);
24
+ var t=node.encodeIntoDataView(dataView,byteOffset,fromAxes,toAxes);
23
25
  byteOffset=t;
24
26
  // Actual size is now known: write the count of bytes that follow the
25
27
  // size field, in little-endian (the protocol convention). Without the
package/scene/node.js CHANGED
@@ -308,7 +308,7 @@ class Node {
308
308
  );
309
309
  this.components.push(tc);
310
310
  }
311
- encodeIntoDataView(dataView, byteOffset) {
311
+ encodeIntoDataView(dataView, byteOffset, fromAxes, toAxes) {
312
312
  byteOffset = core.put_uint8(
313
313
  dataView,
314
314
  byteOffset,
@@ -317,8 +317,19 @@ class Node {
317
317
 
318
318
  byteOffset = core.put_uint64(dataView, byteOffset, this.uid);
319
319
  byteOffset = core.put_string(dataView, byteOffset, this.name);
320
+ // Convert the node's transform into the client's axes standard (server -> client). When no
321
+ // conversion is requested, or the standards match, the pose is encoded unchanged.
320
322
  var clientsidePose = this.pose;
321
-
323
+ if (fromAxes !== undefined && toAxes !== undefined && fromAxes !== toAxes &&
324
+ toAxes !== core.AxesStandard.NotInitialized)
325
+ {
326
+ const c = core.ConvertPose(fromAxes, toAxes, this.pose);
327
+ clientsidePose = new Pose();
328
+ clientsidePose.position = c.position;
329
+ clientsidePose.orientation = c.orientation;
330
+ clientsidePose.scale = c.scale;
331
+ }
332
+
322
333
  byteOffset = clientsidePose.encodeIntoDataView(dataView, byteOffset);
323
334
 
324
335
  byteOffset = core.put_uint8(dataView, byteOffset, this.stationary);
package/scene/scene.js CHANGED
@@ -15,6 +15,10 @@ class Scene {
15
15
  this.specularCubemapPath="";
16
16
  this.assetsPath="assets";
17
17
  this.publicPath="http_resources";
18
+ // The axes standard the scene (node poses, cubemaps) is authored in. Node transforms are
19
+ // converted from this to each client's axes standard when streamed. Z-up Engineering by
20
+ // default, matching the C++ client's native frame and the *_eng cubemap source.
21
+ this.serverAxesStandard=core.AxesStandard.EngineeringStyle;
18
22
  }
19
23
  GetOrCreateNode(uid) {
20
24
  if (!this.nodes.has(uid)) {