%%%
Title = "XR Fragments"
area = "Internet"
workgroup = "Jens & Leon Internet Engineering Task Force"
[seriesInfo]
name = "XR-Fragments"
value = "draft-XRFRAGMENTS-leonvankammen-00"
stream = "IETF"
status = "informational"
date = 2023-04-12T00:00:00Z
[[author]]
initials="L.R."
surname="van Kammen"
fullname="L.R. van Kammen"
%%%
.# Abstract
> Version: 0.5
An open specification for hyperlinking & deeplinking 3D fileformats.
This draft is a specification for interactive URI-controllable 3D files, enabling [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.
XR Fragments allows us to better use implicit metadata inside 3D scene(files), by mapping it to proven technologies like [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment).
> Almost every idea in this document is demonstrated at [https://xrfragment.org](https://xrfragment.org)
{mainmatter}
# Quick reference
1. [Abstract](#abstract)
1. [Index](#index)
1. [Introduction](#introduction)
1. [How does it work](#how-does-it-work)
1. [What does it solve](#what-does-it-solve)
1. [HFL (Hypermediatic Feedback Loop) for XR Browsers](#hfl-hypermediatic-feedback-loop-for-xr-browsers)
1. [Conventions and Definitions](#conventions-and-definitions)
1. [XR Fragment URL Grammar](#xr-fragment-url-grammar)
1. [Spatial Referencing 3D](#spatial-referencing-3d)
1. [Level0: Files](#level0-files)
1. [timelines](#timelines)
1. [via href metadata](#via-href-metadata)
1. [via chained extension](#via-chained-extension)
1. [via subdocuments/xattr](#via-subdocuments-xattr)
1. [JSON sidecar-file](#json-sidecar-file)
1. [Level1: URI](#level1-uri)
1. [List of URI Fragments](#list-of-uri-fragments)
1. [List of explicit metadata](#list-of-explicit-metadata)
1. [Level2: href links](#level2-href-links)
1. [Interaction behaviour](#interaction-behaviour)
1. [XR Viewer implementation](#xr-viewer-implementation)
1. [Level3: Media Fragments](#level3-media-fragments)
1. [Animation(s) timeline](#animation-s-timeline)
1. [Specify playback loopmode](#specify-playback-loopmode)
1. [Controlling embedded content](#controlling-embedded-content)
1. [Level4: prefix operators](#level4-prefix-operators)
1. [Object teleports](#object-teleports)
1. [Object multipliers](#object-multipliers)
1. [De/selectors (+ and -)](#de-selectors-and)
1. [Sharing object or file (#|)](#sharing-object-or-file)
1. [xrf:// URI scheme](#xrf-uri-scheme)
1. [Level5: URI Templates (RFC6570)](#level5-uri-templates-rfc6570)
1. [Top-level URL processing](#top-level-url-processing)
1. [UX](#ux)
1. [Example: Navigating content href portals](#example-navigating-content-href-portals)
1. [Walking surfaces](#walking-surfaces)
1. [Example: Virtual world rings](#example-virtual-world-rings)
1. [Additional scene metadata](#additional-scene-metadata)
1. [Accessibility interface](#accessibility-interface)
1. [Two-button navigation](#two-button-navigation)
1. [Overlap with fileformat-specific extensions](#overlap-with-fileformat-specific-extensions)
1. [Vendor Prefixes](#vendor-prefixes)
1. [Security Considerations](#security-considerations)
1. [FAQ](#faq)
1. [Authors](#authors)
1. [IANA Considerations](#iana-considerations)
1. [Acknowledgments](#acknowledgments)
1. [Appendix: Definitions](#appendix-definitions)
# Introduction
(!Introduction)
How can we add more control to existing text and 3D scenes, without introducing new dataformats?
Historically, there's many attempts to create the ultimate 3D fileformat.
The lowest common denominator is: designers describing/tagging/naming things using **plain text**.
XR Fragments exploits the fact that all 3D models already contain such metadata:
**XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments**
# How does it work
(!What is XR Fragments )
XR Fragments utilizes URLs:
1. for 3D viewers/browser to manipulate the camera or objects (via URI fragments)
2. implicitly: by mapping 3D objectnames (of a 3D scene/file) to URI fragments (3D deeplinking)
3. explicitly: by scanning `href` metadata **inside** 3D scene-files to enable interactions
4. externally: progressively enhance a 3D (file) into an experience via [sidecarfiles](https://en.wikipedia.org/wiki/Sidecar_file)
# What does it solve
It solves:
1. addressibility and [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation of 3D scenes/objects: [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment) using src/href spatial metadata
1. Interlinking text & spatial objects by collapsing space into a Word Graph (XRWG) to show [visible links](#visible-links)
1. unlocking spatial potential of the (originally 2D) hashtag (which jumps to a chapter) for navigating XR documents
1. refraining from introducing scripting-engines for mundane tasks (and preventing its inevitable security-headaches)
1. the gap between text an 3d objects: object-names directly map to hashtags (=fragments), which allows 3D to text transcription.
> NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
XR Fragments views XR experiences through the lens of 3D deeplinked URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
To aid adoption, the standard comprises of various (optional) support-levels, which incorporate existing standards like [W3C Media Fragments](https://www.w3.org/TR/media-frags/) and [URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
> XR Fragments is in a sense, a heuristical 3D format or meta-format, which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
These heuristics, enable features that are both meaningful and consistent across different scene representations, allowing higher interop between fileformats, 3D editors, viewers and game-engines.
# HFL (Hypermediatic Feedback Loop) for XR Browsers
(!HFL (Hypermediatic Feedback Loop) for XR Browsers)
`href` metadata traditionally implies **click** AND **navigate**, however XR Fragments adds stateless **click** (`xrf://....`) via the `xrf://` scheme, which does not change the top-level URL-adress (of the browser).
This allows for many extra interactions via URLs, which otherwise needs a scripting language.
These are called **hashbus**-only events/
> Being able to use the same URI Fragment DSL for navigation (`href: #foo`) as well as interactions (`href: xrf://#foo`) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
This opens up the following benefits for traditional & future webbrowsers:
* [hypermediatic](https://github.com/coderofsalvation/hypermediatic) loading/clicking 3D assets (gltf/fbx e.g.) natively (with or without using HTML).
* potentially allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the `xrf://` hashbus (`xrf://#person=walk` to trigger `walk`-animation for object `person`)
* potentially collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
* completely bypassing the security-trap of loading external scripts (by loading 3D model-files, not HTML-javascriptable resources)
XR Fragments itself are [hypermediatic](https://github.com/coderofsalvation/hypermediatic) and HTML-agnostic, though pseudo-XR Fragment browsers **can** be implemented on top of HTML/Javascript.
| principle | 3D URL | HTML 2D URL |
|-----------------------------|-------------------------------------------------|---------------------------------------|
| the XRWG | wordgraph (collapses 3D scene to tags) | Ctrl-F (find) |
| the hashbus | hashtags alter camera/scene/object-projections | hashtags alter document positions |
| src metadata | renders content and offers sourceportation | renders content |
| href metadata | teleports to other XR document | jumps to other HTML document |
| href metadata | triggers predefined view | Media fragments |
| href metadata | triggers camera/scene/object/projections | n/a |
| href metadata | draws visible connection(s) for XRWG 'tag' | n/a |
| href metadata | filters certain (in)visible objects | n/a |
| href metadata | href="xrf://#-foo&bar" | href="javascript:hideFooAndShowBar()` |
| | (this does not update topLevel URI) | (this is non-standard, non-hypermediatic) |
> An important aspect of HFL is that URI Fragments can be triggered without updating the top-level URI (default href-behaviour) thru their own 'bus' (`xrf://#.....`). This decoupling between navigation and interaction prevents non-standard things like (`href`:`javascript:dosomething()`).
# Conventions and Definitions
(!Conventions and Definitions)
See appendix below in case certain terms are not clear.
## XR Fragment URL Grammar
(! XR Fragment URL Grammar )
For typical HTTP-like browsers/applications:
```
reserved = gen-delims / sub-delims
gen-delims = "#" / "&"
sub-delims = "," / "="
```
> Example: `://foo.com/my3d.gltf#room1&prio=-5&t=0,100`
| Demo | Explanation |
|-------------------------------|---------------------------------|
| `room1` | vector/coordinate argument e.g. |
| `room1&cam1` | combinators |
> this is already implemented in all browsers
Pseudo (non-native) browser-implementations (supporting XR Fragments using HTML+JS e.g.) can use the `?` search-operator to address outbound content.
In other words, the URL updates to: `https://me.com?https://me.com/other.glb` when navigating to `https://me.com/other.glb` from inside a `https://me.com` WebXR experience e.g.
That way, if the link gets shared, the XR Fragments implementation at `https://me.com` can load the latter (and still indicates which XR Fragments entrypoint-experience/client was used).
# Spatial Referencing 3D
(!Spatial Referencing 3D )
3D files contain an hierarchy of objects.
XR Fragments assumes the following objectname-to-URI-Fragment mapping, in order to deeplink 3D objects:
```
my.io/scene.fbx
+─────────────────────────────+
│ sky │ src: http://my.io/scene.fbx#sky (includes building,mainobject,floor)
│ +─────────────────────────+ │
│ │ building │ │ src: http://my.io/scene.fbx#building (includes mainobject,floor)
│ │ +─────────────────────+ │ │
│ │ │ mainobject │ │ │ src: http://my.io/scene.fbx#mainobject (includes floor)
│ │ │ +─────────────────+ │ │ │
│ │ │ │ floor │ │ │ │ src: http://my.io/scene.fbx#floor (just floor object)
│ │ │ │ │ │ │ │
│ │ │ +─────────────────+ │ │ │
│ │ +─────────────────────+ │ │
│ +─────────────────────────+ │
+─────────────────────────────+
```
> Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).
Clever nested design of 3D scenes allow great ways for re-using content, and/or previewing scenes.
For example, to render a portal with a preview-version of the scene, create an 3D object with:
* href: `https://scene.fbx`
> It also allows **sourceportation**, which basically means the enduser can teleport to the original XR Document of an `src` embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.
# Level0: Files
(!Level0: Files )
(!Level0: Files)
Compatible 3D fileformats: [glTF](https://www.khronos.org/gltf/), [usdz](https://openusd.org/release/spec_usdz.html), [obj](https://en.wikipedia.org/wiki/Wavefront_.obj_file), [collada](https://www.khronos.org/collada), [THREE.json](https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4), [X3D](https://en.wikipedia.org/wiki/X3D) e.g.
A 3D scene-file can be considered XR Fragment-compatible when it contains metadata:
1. implicit: there's at least one object with a name (*)
2. explicit: (optional) object(s) have (level2) href extras.
> \* = last wins in case of non-unique names
There are **optional** auto-loaded [side-car files]() to enable hasslefree [XR Movies](#XR%20Movies).
they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a `.glb` e.g.).
## Timelines
when a loaded file contains a timeline (animations/subtitles e.g.), then:
> All timelines must play (looped) by default (to enable [[XR Movies]])
Unless an object has multiple animations (actions e.g.), then just play the first or with name `default`.
## via href metadata
```
scene.glb <--- 'href' extra [heuristic] detected inside!
scene.png (preview thumbnail)
scene.ogg (soundtrack to plays when global 3D animation starts)
scene.vtt (subtitles for accessibility or screenreaders)
scene.json (sidecar JSON-file with explicit metadata)
```
**heuristics**:
* if at least one `href` custom property/extra is found in a 3D scene
* The viewer should poll for the above mentioned sidecar-file extensions (and present accordingly)
## via chained extension
```
scene.xrf.glb <--- '.xrf.' sidecar file heuristic detected!
scene.xrf.png (preview thumbnail)
scene.xrf.ogg (soundtrack to plays when global 3D animation starts)
scene.xrf.vtt (subtitles for accessibility or screenreaders)
scene.xrf.json (sidecar JSON-file with explicit metadata)
```
> A fallback-mechanism to turn 3D files into [XR Movies](#XR%20Movies) without editing them.
**heuristics**:
* the chained-extension heuristic `.xrf.` should be present in the filename (`scene.xrf.glb` e.g.)
## via subdocuments/xattr
More secure protocols (Nextgraph e.g.) don't allow for simply polling files.
In such case, subdocuments or extended attributes should be polled:
> NOTE: in the examples below we use the href-heuristic, but also the `.xrf.` chained-extension applies here.
```
myspreadsheet.ods
└── explainer.glb <--- 'href' extra [heuristic] detected inside!
├── explainer.ogg (soundtrack to play when global 3D animation starts)
├── explainer.png (preview thumnbnail)
├── explainer.json (sidecar JSON-file with explicit metadata)
└── explainer.vtt (subtitles for accessibility or screenreaders)
```
If only extended attributes (xattr) are available, the respective referenced file can be embedded:
```
$ setfattr -n explainer.ogg -v "soundtrack.ogg" explainer.glb
$ setfattr -n explainer.png -v "thumbnail.png" explainer.glb
$ setfattr -n explainer.vtt -v "subtitles.vtt" explainer.glb
```
> NOTE: Linux's `setfattr/getfattr` is `xattr` on mac, and `Set-Content/Get-content` on Windows. See [pxattr](https://www.lesbonscomptes.com/pxattr/index.html) for lowlevel access.
## JSON sidecar-file
For developers, sidecar-file can allow for defining **explicit** XR Fragments links (>level1), outside of the 3D file.
This can be done via (objectname/metadata) key/value-pairs in a JSON [sidecar-file](https://en.wikipedia.org/wiki/Sidecar_file):
* experience.glb
* experience.json `<----`
```json
{
"aria-description": "description of scene",
"button": {
"href": "#roomB",
"aria-description": "description of room"
}
}
```
> This will make object `button` clickable, and teleport the user to object `roomB`.
So after loading `experience.glb` the existence of `experience.json` is detected, to apply the explicit metadata.
The sidecar will define (or **override** already existing) extras, which can be handy for multi-user platforms (offer 3D scene customization/personalization to users).
> In THREE.js-code this would boil down to:
```javascript
scene.userData['aria-description'] = "description of scene"
scene.getObjectByName("button").userData.href = "#roomB"
// now the XR Fragments parser can process the XR Fragments userData 'extras' in the scene
```
# Level1: URI
(!Level1: URI)
> **XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments**
XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments **integrates all** which allows a universal viewing experience.
```
+───────────────────────────────────────────────────────────────────────────────────────────────+
│ │
│ U R N │
│ U R L | │
│ | |-----------------+--------| │
│ +--------------------------------------------------| │
│ | │
│ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │
│ | │
│ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │
│ │
│ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │
│ │
│ │
│ |------------------------+-------------------------| │
│ | │
│ U R I │
│ │
+───────────────────────────────────────────────────────────────────────────────────────────────+
```
Fact: our typical browser URL's are just **a possible implementation** of URI's (for untapped humancentric potential of URI's [see interpeer.io](https://interpeer.io) or [NextGraph](https://nextgraph.org) )
> XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
But approaches things from a higherlevel local-first 3D hypermedia browser-perspective.
Below you can see how this translates back into good-old URLs:
```
+───────────────────────────────────────────────────────────────────────────────────────────────+
│ │
│ the soul of any URL: ://macro /meso ?micro #nano │
│ │
│ 2D URL: ://library.com /document ?search #chapter │
│ xrf:// │
│ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #object ─> hashbus │
│ │ #filter │ │
│ │ #tag │ │
│ │ (hypermediatic) #material │ │
│ │ ( feedback ) #animation │ │
│ │ ( loop ) #texture │ │
│ │ #variable │ │
│ │ │ │
│ XRWG <─────────────────────<─────────────+ │
│ │ │ │
│ └─ objects ──────────────>─────────────+ │
│ │
│ │
+───────────────────────────────────────────────────────────────────────────────────────────────+
```
> ?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
## List of URI Fragments
| fragment | type | example | info |
|-------------------|------------|--------------------|----------------------------------------------------------------------|
| `#......` | vector3 | `#room1` `#room2` `#cam2` | positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector |
| [Media Fragments](https://www.w3.org/TR/media-frags/) | [media fragment](#media%20fragments%20and%20datatypes) | `#t=0,2&loop` | play (and loop) 3D animation from 0 seconds till 2 seconds|
## List of **explicit* metadata
These are the possible 'extras' for 3D nodes and sidecar-files
| key | type | example (JSON) | function | existing compatibility |
|--------------|----------|------------------------|---------------------|----------------------------------------|
| `href` | string | `"href": "b.gltf"` | XR teleport | custom property in 3D fileformats |
# Level2: href links
(!Level2: href links)
Explicit href metadata ('extras') in a 3D object (of a 3D file), hint the viewer that the user ''can interact'' with that object :
| fragment | type | example value |
|`href`| string (uri or predefined view) | `#pyramid`
`#lastvisit`
`xrf://#-someobject`
`://somefile.gltf#foo`
|
## Interaction behaviour
When clicking an ''href''-value, the user(camera) is teleport to the referenced object.
The imported/teleported destination can be another object in the same scene-file, or a different file.
## XR Viewer implementation
| **spec** | **action** | **feature** |
|-|-|-|
| level0+1 | hover 3D file [href](#via-href-metadata) | show the preview PNG thumbnail (if any). |
| level0+1 | launch 3D file [href](#via-href-metadata) | replace the current scene with a new 3D file (`href: other.glb` e.g.) |
| level2 | click internal 3D file [href](#via-href-metadata) (`#roomB` e.g.) | teleport the camera to the origin of object(name `roomB`). See [[teleport camera]].|
| level2 | click external 3D file [href](#via-href-metadata) (`foo.glb` e.g.) | replace the current scene with a new 3D file (`href: other.glb` e.g.) |
| level2 | hover external 3D file [href](#via-href-metadata) | show the preview PNG thumbnail (if any sidecar, see level0) |
| level2 | click [href](#via-href-metadata) | hashbus: execute without changing the toplevel URL location (`href: xrf://#someObjectName` e.g.) |
| level3 | click [href](#via-href-metadata) | set the global 3D animation timeline to its Media Fragment value (`#t=2,3` e.g.) |
> NOTE: hashbus links (`xrf://#foo&bar`) don't change the toplevel URL, which makes it ideal for interactions (in contrast to typical `#roomC` navigation, which benefit back/forward browser-buttons), see hashbus for more info.
# Level3: Media Fragments
(!Level3: Media Fragments )
> these allow for XR Movies with a controllable timeline using `href` URI's with Media Fragments
Just like with 2D media-files, W3C mediafragments (`#t=1,2`) can be used to control a timeline via the [#t](##t) primitive.
XR Fragments Level3 makes the 3D timeline, as well as URL-referenced files **controllable** via Media Fragments like:
* level2 hrefs (`href: #t=4` e.g. to control 3D timeline)
* level4: `xrf:` URI scheme:
* `href: xrf:foo.wav#t=0` to play a wav
* `href: xrf:news.glb?clone#t=0` to instance and play another experience
## Animation(s) timeline
controls the animation(s) of the scene (or `src` resource which contains a timeline)
| fragment | type | functionality |
| #t=start,stop | [[vector2]] (default:`#t=0`) | start,stop (in seconds |
| Example Value | Explanation |
| `#t=1` | play (3D) animations from 1 seconds till end (and stop) |
| `#t=1,100` | play (3D) animations from 1 till 100 seconds (and stop) |
## Specify playback loopmode
This compensates a missing element from Media Fragments to enable/disable temporal looping. .
| fragment | type | functionality |
| #loop | string | enables animation/video/audio loop |
| #-loop | string | disables animation/video/audio loop |
## Controlling embedded content
use [[URI Templates]] to control embedded media, for example a simple video-player:
```
foo.usdz
│
├── ◻ loopbutton_enable
│ └ href: #loop <-- enable global loop
│
├── ◻ loopbutton_enable
│ └ href: #-loop <-- disable global loop
│
├── ◻ playbutton
│ └ href: #t=10&loop <-- play global 3D timeline (all anims) (looped)
│
└── ◻ playbutton_external
└ href: https://my.org/animation.glb#!&t=3,10 <-- import & play external anim
```
# Level4: prefix operators
(!Level4: prefix operators)
Prefixing objectnames with the following simple operators allow for **extremely powerful** XR interactions:
* #!
* #*
* #+ or #-
* #|
* xrf: URI scheme
> **Examples:** `#+menu` to show a object, `#-menu` to hide a menu, `#!menu` to teleport a menu, `#*block` to clone a grabbable block, `#|object` to share an object
## Object teleports (!)
Prefixing an object with an exclamation-symbol, will teleport a (local or remote) referenced object from/to its original/usercamera location.
[img[objecteleport.png]]
Usecases:
* show/hide objects/buttons (menu e.g.) in front of user
* embed remote (object within) 3D file via remote URL
* instance an interactive object near the user regardless of location
* instance HUD or semi-transparent-textured-sphere (LUT) around the user