<!-- for annotated version see: https://raw.githubusercontent.com/ietf-tools/rfcxml-templates-and-schemas/main/draft-rfcxml-general-template-annotated-00.xml -->
<styletype="text/css">
body{
font-family: monospace;
max-width: 1000px;
font-size: 15px;
padding: 0% 10%;
line-height: 30px;
color:#555;
background:#F7F7F7;
}
h1 { margin-top:40px; }
pre{ line-height:18px; }
a,a:visited,a:active{ color: #70f; }
code{
border: 1px solid #AAA;
border-radius: 3px;
padding: 0px 5px 2px 5px;
}
pre{
line-height: 18px;
overflow: auto;
padding: 12px;
}
pre + code {
background:#DDD;
}
pre>code{
border:none;
border-radius:0px;
padding:0;
}
blockquote{
padding-left: 30px;
margin: 0;
border-left: 5px solid #CCC;
}
th {
border-bottom: 1px solid #000;
text-align: left;
padding-right:45px;
padding-left:7px;
background: #DDD;
}
td {
border-bottom: 1px solid #CCC;
font-size:13px;
}
</style>
<br>
<h1>XR Fragments</h1>
<br>
<pre>
stream: IETF
area: Internet
status: informational
author: Leon van Kammen
date: 2023-04-12T00:00:00Z
workgroup: Internet Engineering Task Force
value: draft-XRFRAGMENTS-leonvankammen-00
</pre>
<h1class="special"id="abstract">Abstract</h1>
<blockquote>
<p>Version: 0.5</p>
</blockquote>
<p>An open specification for hyperlinking & deeplinking 3D fileformats.
This draft is a specification for interactive URI-controllable 3D files, enabling <ahref="https://github.com/coderofsalvation/hypermediatic">hypermediatic</a> navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.<br>
XR Fragments allows us to better use implicit metadata inside 3D scene(files), by mapping it to proven technologies like <ahref="https://en.wikipedia.org/wiki/URI_fragment">URI Fragments</a>.<br></p>
<blockquote>
<p>Almost every idea in this document is demonstrated at <ahref="https://xrfragment.org">https://xrfragment.org</a></p>
</blockquote>
<sectiondata-matter="main">
<h1id="quick-reference">Quick reference</h1>
<ol>
<li><ahref="#abstract">Abstract</a></li>
<li><ahref="#index">Index</a></li>
<li><ahref="#introduction">Introduction</a></li>
<li><ahref="#how-does-it-work">How does it work</a></li>
<li><ahref="#what-does-it-solve">What does it solve</a></li>
<li><ahref="#hfl-hypermediatic-feedback-loop-for-xr-browsers">HFL (Hypermediatic Feedback Loop) for XR Browsers</a></li>
<li><ahref="#conventions-and-definitions">Conventions and Definitions</a>
<ol>
<li><ahref="#xr-fragment-url-grammar">XR Fragment URL Grammar</a></li>
<p>Aspect 1 has been pioneered & implemented by (JanusXR’s) James Baicoianu (in <ahref="https://github.com/jbaicoianu/janusweb">janusweb</a>) before the spec existed, marking him as a semi-founding father of the spec. Thank you James.
“Aspect 1 was pioneered and implemented by JanusXR / James Baicoianu via <ahref="https://github.com/jbaicoianu/janusweb">janusweb</a> well before the formal specification was established. As a key architect of these early concepts, James’s work laid the groundwork for the standard we use today. We owe him a great deal of thanks for his early contributions.”</p>
<h1id="what-does-it-solve">What does it solve</h1>
<p>It solves:</p>
<ol>
<li>addressibility and <ahref="https://github.com/coderofsalvation/hypermediatic">hypermediatic</a> navigation of 3D scenes/objects: <ahref="https://en.wikipedia.org/wiki/URI_fragment">URI Fragments</a> using src/href spatial metadata</li>
<li>Interlinking text & spatial objects by collapsing space into a Word Graph (XRWG) to show <ahref="#visible-links">visible links</a></li>
<li>unlocking spatial potential of the (originally 2D) hashtag (which jumps to a chapter) for navigating XR documents</li>
<li>refraining from introducing scripting-engines for mundane tasks (and preventing its inevitable security-headaches)</li>
<li>the gap between text an 3d objects: object-names directly map to hashtags (=fragments), which allows 3D to text transcription.</li>
</ol>
<blockquote>
<p>NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible</p>
</blockquote>
<p>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 <ahref="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <ahref="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</a> to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.<br></p>
<blockquote>
<p>XR Fragments is in a sense, a <b>heuristical 3D format</b> 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.<br>
These heuristics, enable features that are both meaningful and consistent across different scene representations, allowing <b>higher interop</b> between fileformats, 3D editors, viewers and game-engines.</p>
</blockquote>
<h1id="hfl-hypermediatic-feedback-loop-for-xr-browsers">HFL (Hypermediatic Feedback Loop) for XR Browsers</h1>
<p><spanclass="index"id="idxref:2"></span> for XR Browsers)</p>
<p><code>href</code> metadata traditionally implies <strong>click</strong> AND <strong>navigate</strong>, however XR Fragments adds stateless <strong>click</strong> (<code>xrf://....</code>) via the <code>xrf://</code> 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 <strong>hashbus</strong>-only events/</p>
<blockquote>
<p>Being able to use the same URI Fragment DSL for navigation (<code>href: #foo</code>) as well as interactions (<code>href: xrf://#foo</code>) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.</p>
</blockquote>
<p>This opens up the following benefits for traditional & future webbrowsers:</p>
<ul>
<li><ahref="https://github.com/coderofsalvation/hypermediatic">hypermediatic</a> loading/clicking 3D assets (gltf/fbx e.g.) natively (with or without using HTML).</li>
<li>potentially allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the <code>xrf://</code> hashbus (<code>xrf://#person=walk</code> to trigger <code>walk</code>-animation for object <code>person</code>)</li>
<li>potentially collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus</li>
<li>completely bypassing the security-trap of loading external scripts (by loading 3D model-files, not HTML-javascriptable resources)</li>
</ul>
<p>XR Fragments itself are <ahref="https://github.com/coderofsalvation/hypermediatic">hypermediatic</a> and HTML-agnostic, though pseudo-XR Fragment browsers <strong>can</strong> be implemented on top of HTML/Javascript.</p>
<table>
<thead>
<tr>
<th>principle</th>
<th>3D URL</th>
<th>HTML 2D URL</th>
</tr>
</thead>
<tbody>
<tr>
<td>the XRWG</td>
<td>wordgraph (collapses 3D scene to tags)</td>
<td>Ctrl-F (find)</td>
</tr>
<tr>
<td>the hashbus</td>
<td>hashtags alter camera/scene/object-projections</td>
<td>hashtags alter document positions</td>
</tr>
<tr>
<td>src metadata</td>
<td>renders content and offers sourceportation</td>
<td>renders content</td>
</tr>
<tr>
<td>href metadata</td>
<td>teleports to other XR document</td>
<td>jumps to other HTML document</td>
</tr>
<tr>
<td>href metadata</td>
<td>triggers predefined view</td>
<td>Media fragments</td>
</tr>
<tr>
<td>href metadata</td>
<td>triggers camera/scene/object/projections</td>
<td>n/a</td>
</tr>
<tr>
<td>href metadata</td>
<td>draws visible connection(s) for XRWG ‘tag’</td>
<td>(this is non-standard, non-hypermediatic)</td>
</tr>
</tbody>
</table>
<blockquote>
<p>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’ (<code>xrf://#.....</code>). This decoupling between navigation and interaction prevents non-standard things like (<code>href</code>:<code>javascript:dosomething()</code>).</p>
</blockquote>
<h1id="conventions-and-definitions">Conventions and Definitions</h1>
<p><spanclass="index"id="idxref:3"></span></p>
<p>See appendix below in case certain terms are not clear.</p>
<h2id="xr-fragment-url-grammar">XR Fragment URL Grammar</h2>
<p>this is already implemented in all browsers</p>
</blockquote>
<p>Pseudo (non-native) browser-implementations (supporting XR Fragments using HTML+JS e.g.) can use the <code>?</code> search-operator to address outbound content.<br>
In other words, the URL updates to: <code>https://me.com?https://me.com/other.glb</code> when navigating to <code>https://me.com/other.glb</code> from inside a <code>https://me.com</code> WebXR experience e.g.<br>
That way, if the link gets shared, the XR Fragments implementation at <code>https://me.com</code> can load the latter (and still indicates which XR Fragments entrypoint-experience/client was used).</p>
<p>Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).</p>
</blockquote>
<p>Clever nested design of 3D scenes allow great ways for re-using content, and/or previewing scenes.<br>
For example, to render a portal with a preview-version of the scene, create an 3D object with:</p>
<ul>
<li>href: <code>https://scene.fbx</code></li>
</ul>
<blockquote>
<p>It also allows <strong>sourceportation</strong>, which basically means the enduser can teleport to the original XR Document of an <code>src</code> embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.</p>
</blockquote>
<h1id="level0-files">Level0: Files</h1>
<p><spanclass="index"id="idxref:6"></span>
<spanclass="index"id="idxref:7"></span></p>
<p>Compatible 3D fileformats: <ahref="https://www.khronos.org/gltf/">glTF</a>, <ahref="https://openusd.org/release/spec_usdz.html">usdz</a>, <ahref="https://en.wikipedia.org/wiki/Wavefront_.obj_file">obj</a>, <ahref="https://www.khronos.org/collada">collada</a>, <ahref="https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4">THREE.json</a>, <ahref="https://en.wikipedia.org/wiki/X3D">X3D</a> e.g.
<br></p>
<p>A 3D scene-file can be considered <b>XR Fragment-compatible</b> when it contains metadata:
1. implicit: there’s at least one object with a name (*)
2. explicit: (optional) object(s) have (level2) href extras.</p>
<blockquote>
<p>* = last wins in case of non-unique names</p>
</blockquote>
<p>There are <strong>optional</strong> auto-loaded <ahref="">side-car files</a> to enable hasslefree <ahref="#XR%20Movies">XR Movies</a>.<br>
they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a <code>.glb</code> e.g.).</p>
<p>NOTE: Linux’s <code>setfattr/getfattr</code> is <code>xattr</code> on mac, and <code>Set-Content/Get-content</code> on Windows. See <ahref="https://www.lesbonscomptes.com/pxattr/index.html">pxattr</a> for lowlevel access.</p>
</blockquote>
<h2id="json-sidecar-file">JSON sidecar-file</h2>
<p>For developers, sidecar-file can allow for defining <strong>explicit</strong> XR Fragments links (>level1), outside of the 3D file.<br>
This can be done via (objectname/metadata) key/value-pairs in a JSON <ahref="https://en.wikipedia.org/wiki/Sidecar_file">sidecar-file</a>:</p>
<ul>
<li>experience.glb</li>
<li>experience.json <code><----</code></li>
</ul>
<pre><codeclass="language-json">{
"aria-description": "description of scene",
"button": {
"href": "#roomB",
"aria-description": "description of room"
}
}
</code></pre>
<blockquote>
<p>This will make object <code>button</code> clickable, and teleport the user to object <code>roomB</code>.</p>
</blockquote>
<p>So after loading <code>experience.glb</code> the existence of <code>experience.json</code> is detected, to apply the explicit metadata.<br>
The sidecar will define (or <strong>override</strong> already existing) extras, which can be handy for multi-user platforms (offer 3D scene customization/personalization to users).</p>
<blockquote>
<p>In THREE.js-code this would boil down to:</p>
</blockquote>
<pre><codeclass="language-javascript"> scene.userData['aria-description'] = "description of scene"
// now the XR Fragments parser can process the XR Fragments userData 'extras' in the scene
</code></pre>
<h1id="level1-uri">Level1: URI</h1>
<p><spanclass="index"id="idxref:8"></span></p>
<blockquote>
<p><strong>XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments</strong></p>
</blockquote>
<p>XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.<br>
Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments <strong>integrates all</strong> which allows a universal viewing experience.<br></p>
<p>Fact: our typical browser URL’s are just <strong>a possible implementation</strong> of URI’s (for untapped humancentric potential of URI’s <ahref="https://interpeer.io">see interpeer.io</a> or <ahref="https://nextgraph.org">NextGraph</a> )</p>
<blockquote>
<p>XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.<br>But approaches things from a higherlevel local-first 3D hypermedia browser-perspective.</p>
</blockquote>
<p>Below you can see how this translates back into good-old URLs:</p>
<p>?-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.</p>
</blockquote>
<h2id="list-of-uri-fragments">List of URI Fragments</h2>
<p>Explicit href metadata (‘extras’) in a 3D object (of a 3D file), hint the viewer that the user “can interact” with that object :</p>
<p>NOTE: hashbus links (<code>xrf://#foo&bar</code>) don’t change the toplevel URL, which makes it ideal for interactions (in contrast to typical <code>#roomC</code> navigation, which benefit back/forward browser-buttons), see <ahref="#hashbus">hashbus</a> for more info.</p>
<p><strong>default camera (spawn) location</strong>: When a 3D file is loaded, it will position the user/camera at xyz: 0,0,0 OR to the location of (an object called) “spawn”.</p>
<p>Prefixing objectnames with the following simple operators allow for <strong>extremely powerful</strong> XR interactions:</p>
<ul>
<li>#!</li>
<li>#*</li>
<li>#+ or #-</li>
<li>#|</li>
<li>xrf: URI scheme</li>
</ul>
<blockquote>
<p><strong>Examples:</strong><code>#+menu</code> to show a object, <code>#-menu</code> to hide a menu, <code>#!menu</code> to teleport a menu, <code>#*block</code> to clone a grabbable block, <code>#|object</code> to share an object</p>
<p>Prefixing an object with an exclamation-symbol, will teleport a (local or remote) referenced object from/to its original/usercamera location.<br></p>
<p>[img[objecteleport.png]]</p>
<p>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</p>
<p>Clicking the <ahref="#via-href-metadata">href</a>-value above will:</p>
<ol>
<li><strong>reposition the referenced object</strong> (menu) to the usercamera’s-coordinates.</li>
<li><strong>zoom</strong> in case of (non-empty) mesh-object: rescale to 1 m³, and position 1m in front of the camera</li>
<li>toggle behaviour: revert values if <sup>1</sup>⁄<sub>2</sub> were already applied</li>
<li><code>#+</code> is always implied (objects are always made visible)</li>
</ol>
<p>This tiny but powerful symbol allows incredible interactive possibilities, by carefully positioning re-usable objects outside of a scene (below the usercamera’s floor e.g.).</p>
<p>Clicking the <ahref="#via-href-metadata">href</a>-value above will:</p>
<ol>
<li>replace the current scene with <code>foo.glb</code></li>
<li>teleport the user to #roomB inside <code>foo.glb</code></li>
<li><strong>instance the referenced object</strong> (bar inside foo.glb) in front of the user.</li>
<li>it will update the top-Level URL (because <code>xrf:</code> was not used)</li>
<li>hide the <strong>instanced object</strong> when clicked again (toggle visibility)</li>
</ol>
<blockquote>
<p><strong>NOTE</strong>: level2 teleportation links, as well as instancing mitigates the ‘broken embedded image’-issue of HTML: <strong>always</strong> attaching the href-values to <strong>a 3D (preview) object</strong> (that way broken links will not break the design).</p>
</blockquote>
<p><strong>Example:</strong> clicking a 3D button with title ‘menu’ and <ahref="#href">href</a>-value <code>xrf:menu.glb?instance#t=4,5</code> would instance a 3D menu (<code>menu.glb</code>) in front of the user, and loop its animation between from 4-5 seconds (<code>t=4,5</code>)</p>
<blockquote>
<p><strong>NOTE</strong>: combining instance-operators allows dynamic construction of 3D scenes (<code>#london&!welcomeMenu&!fadeBox</code> e.g.)</p>
<p>The star-prefix will clone a (local or remote) referenced object to the usercamera’s location, and make it grabbable.<br>
Usecases:
* object-picker (build stuff with objects)</p>
<blockquote>
<p><strong>NOTE</strong>: this is basically the <ahref="#%23%21">#! operator</a> which infinitely <strong>clones</strong> the referenced object (instead of repositioning the object).</p>
</blockquote>
<h2id="de-selectors-and">De/selectors (+ and -)</h2>
<blockquote>
<p>How to show/hide/group material- or object- or animations by name?</p>
</blockquote>
<p>Clicking href-values below will show/hide the targeted material- or animation or object-name (incl. children):</p>
<li>- and + prefix for exact matches (welcome e.g.)</li>
<li>* postfix for match beginning (VR_skybox VR_skyboxmat e.g.)</li>
</ul>
<blockquote>
<p>NOTE: to hide a skybox when importing/loading a 3D file (force AR) is possible by linking to `<code>https://my.org/foo.glb#-skybox</code> or <code>https://my.org/foo.glb#-skyboxmaterial</code></p>
</blockquote>
<h2id="sharing-object-or-file">Sharing object or file (#|)</h2>
<p>The pipe-symbol (<code>|</code>) sends a (targeted) object to the OS.
Clicking the href-value below will:</p>
<ol>
<li>share the (targeted object in the) file to a another application</li>
</ol>
<blockquote>
<p>This URL can be fed straight into <ahref="https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API">Web Share API</a> or <ahref="https://www.freedesktop.org/wiki/Software/xdg-utils/">xdg-open</a></p>
</blockquote>
<ul>
<li>href: <code>xrf://#|bar</code></li>
</ul>
<blockquote>
<p><strong>NOTE</strong>: sharing is limited to (internal objects) via <code>xrf:</code> scheme-only</p>
</blockquote>
<h2id="xrf-uri-scheme">xrf:// URI scheme</h2>
<p>Prefixing the <code>xrf:</code> to <ahref="#href">href</a>-values <strong>will prevent</strong><ahref="#📜%20level2:%20explicit%20links">level2</a><ahref="#href">href</a>-values from changing the top-Level URL.</p>
<blockquote>
<p><strong>Usecase</strong>: for non-shareable URLs like <code>href: xrf:#t=4,5</code>, to display a stateful msg e.g.).</p>
</blockquote>
<p><strong>Reason:</strong> XR Fragments is inspired by HTML’s <ahref="https://en.wikipedia.org/wiki/Hyperlink">href-attribute</a>, which does various things:</p>
<ol>
<li>it updates the browser-location</li>
<li>it makes something clickable</li>
<li>it jumps to another document / elsewhere in the same document</li>
<li>and more</li>
</ol>
<p>The <code>xrf:</code> scheme will just do 2 & 3 (so the URL-values will not leak into the top-level URL).</p>
<blockquote>
<p><strong>compliance with RFC 3986</strong>: unimplemented/unknown URI schemes (<code>xrf:...</code> e.g.) will not update the top-level URL</p>
</blockquote>
<h1id="level5-uri-templates-rfc6570">Level5: URI Templates (RFC6570)</h1>
<p><spanclass="index"id="idxref:12"></span>)</p>
<p>XR Fragments adopts Level1 URI <strong>Fragment</strong> expansion to provide safe interactivity.<br>
This is non-normative, and the draft spec is available on request.</p>
<p>The URL-processing-flow for hypermedia browsers goes like this:</p>
<ol>
<li>IF scene operators and/or animation operator (<code>t</code>) are present in the URL then (re)position the camera (to <code>room1</code>) and/or animation-range (<code>10</code>) accordingly.</li>
<li>IF no camera-position has been set in <b>step 1 or 2</b> assume <code>0,0,0</code> as camera coordinate (XR: add user-height) (<ahref="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/navigator.js#L31]]">example</a>)</li>
<li>IF a camera-object exists with name <code>cam</code> assume that user(camera) position</li>
</ol>
<h2id="ux">UX</h2>
<p>End-users should always have read/write access to:</p>
<ol>
<li>the current (toplevel) <b>URL</b> (an URLbar etc)</li>
<li>URL-history (a <b>back/forward</b> button e.g.)</li>
<li>Clicking/Touching an <code>href</code> navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).</li>
<li><p>clicking an outbound “external”- or “file URI” fully replaces the current scene and assumes <code>room2</code> by default (unless specified)</p></li>
<li><p>relocation/reorientation should happen locally for local URI’s (<code>#....</code>)</p></li>
<li><p>navigation should not happen “immediately” when user is more than 5 meter away from the portal/object containing the href (to prevent accidental navigation e.g.)</p></li>
<li><p>URL navigation should always be reflected in the client URL-bar (in case of javascript: see [<ahref="https://github.com/coderofsalvation/xrfragment/blob/dev/src/3rd/js/three/navigator.js">here</a> for an example navigator), and only update the URL-bar after the scene (default fragment <code>#</code>) has been loaded.</p></li>
<li><p>In immersive XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [<ahref="https://github.com/coderofsalvation/xrfragment/blob/dev/example/aframe/sandbox/index.html#L26-L29">here</a> for an example wearable)</p></li>
<li><p>make sure that the “back-button” of the “browser-history” always refers to the previous position (see [<ahref="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js#L97">here</a>)</p></li>
<li><p>ignore previous rule in special cases, like clicking an <code>href</code> using camera-portal collision (the back-button could cause a teleport-loop if the previous position is too close)</p></li>
<li><p>href-events should bubble upward the node-tree (from children to ancestors, so that ancestors can also conain an href), however only 1 href can be executed at the same time.</p></li>
<li><p>the end-user navigator back/forward buttons should repeat a back/forward action until a <code>#...</code> primitive is found (the stateless xrf:// href-values should not be pushed to the url-history)</p></li>
</ol>
<p><ahref="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js">» example implementation</a><br>
<ahref="https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/href.gltf#L192">» example 3D asset</a><br>
<li><ahref="https://datapackage.org">datapackage.json</a> findability, accessibility, interoperability, and reusability of data</li>
</ul>
<p>ARIA’s <code>aria-description</code>-metadata is normative, to aid accessibility and scene transcripts</p>
<blockquote>
<p><strong>NOTE</strong>: please always start <code>aria-description</code> with a verb to aid transcripts.</p>
</blockquote>
<p>The following metadata are non-normative but encouraged, since they are popular and cheap to parse:</p>
<ul>
<li><ahref="https://json-ld.org">RDF/JSON-LD</a> like <ahref="https://mvmd.org/standards/gltf/">this example</a> or via glTF’s <ahref="https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld">KHR_xmp_json_ld extension</a></li>
<li><ahref="https://bibtex.eu/fields">BibTex</a> when known bibtex-keys exist with values enclosed in <code>{</code> and <code>},</code></li>
</ul>
<blockquote>
<p>Example: object ‘tryceratops’ with <code>aria-description: is a huge dinosaurus standing on a #mountain</code> generates transcript <code>#tryceratops is a huge dinosaurus standing on a #mountain</code>, where the hashtags are clickable XR Fragments (activating the visible-links in the XR browser).</p>
</blockquote>
<p>Individual nodes can be enriched with such metadata, but most importantly the scene node:</p>
<p>The addressibility of XR Fragments allows for unique 3D-to-text transcripts, as well as an textual interface to navigate 3D content.<br>
Spec:<br><Br></p>
<ol>
<li>The enduser must be able to enable an accessibility-mode (which persists across application/webpage restarts)</li>
<li>Accessibility-mode must contain a text-input for the user to enter text</li>
<li>Accessibility-mode must contain a flexible textlog for the user to read (via screenreader, screen, or TTS e.g.)</li>
<li>the textlog contains <code>aria-descriptions</code>, and its narration (Screenreader e.g.) can be skipped (via 2-button navigation)</li>
<li>The <code>back</code> command should navigate back to the previous URL (alias for browser-backbutton)</li>
<li>The <code>forward</code> command should navigate back to the next URL (alias for browser-nextbutton)</li>
<li>A destination is a 3D node containing an <code>href</code> with a <code>#...</code> XR fragment (which matches a 3d object name)</li>
<li>The <code>go</code> command should list all possible destinations</li>
<li>The <code>go left</code> command should move the camera around 0.3 meters to the left</li>
<li>The <code>go right</code> command should move the camera around 0.3 meters to the right</li>
<li>The <code>go forward</code> command should move the camera 0.3 meters forward (direction of current rotation).</li>
<li>The <code>rotate left</code> command should rotate the camera 0.3 to the left</li>
<li>The <code>rotate left</code> command should rotate the camera 0.3 to the right</li>
<li>The (dynamic) <code>go abc</code> command should navigate to <code>#scene2</code> in case there’s a 3D node with name <code>abc</code> and <code>href</code> value <code>#scene2</code></li>
<li>The <code>look</code> command should give an (contextual) 3D-to-text transcript, by scanning the <code>aria-description</code> values of the current <code>#...</code> (3D object) value (including its children)</li>
<li>The <code>do</code> command should list all possible <code>href</code> values which don’t contain an <code>#...</code> XR Fragment</li>
<li>The (dynamic) <code>do abc</code> command should navigate/execute <code>https://.../...</code> in case a 3D node exist with name <code>abc</code> and <code>href</code> value <code>https://.../...</code></li>
<p>The XRF microformat is an <ahref="#Progressive%20enhancement">optional</a> text heuristics which applications can detect across various usecases.</p>
<h4id="via-html-webpage">via HTML webpage</h4>
<p>If the browser/application requests an webpage (<code>https://nlnet.nl</code> e.g.) it should check for the <ahref="https://gmpg.org/xfn/">rel-me microformat</a> :</p>
<p>The <code>type</code>-attribute is for fallback-purposes.<br>
Viewer-supported 3D file-extensions (<code>.glb</code> e.g.) will <strong>ALWAYS</strong> take precedence over the (non)presence of the <code>type</code> attribute.<br>
The reason is that platforms (Mastodon ‘labels’ e.g.) don’t allow specifying type-attributes.<br>
Another reason is that XR Fragments is filetype-agnostic, so flexibility is expected on the viewer-side.</p>
<blockquote>
<p>NOTE: in case of multiple 3D files mentioned in <code><link rel="me"</code>, only the first (supported 3D filetype) will be chosen.</p>
<p>This way the application will load <code>https://3d.john.foo.com/model/scene.glb</code> when the user types <code>john@foo.com</code> into the user field.</p>
<h4id="via-text-uri">via Text (URI)</h4>
<p>Another way for an application to trigger loading a 3D scene is by detecting URI’s of 3D scene-files any text:</p>
<ul>
<li><code>foo.glb</code> (or any other popular 3D extension)</li>
<li><code>https://foo.com/scene.glb</code> (or any other popular protocol)</li>
</ul>
<p>This way, the application can highlight the link whenever it detects the URI (in a text-file or text-section of a 3D model)</p>
If a glTF implementation does not support a particular extension, the (XRF) extras field can serve as a fallback. This way, metadata provided in extras can still be useful for applications that don’t handle certain extensions.</li>
</ol>
<blockquote>
<p><strong>Example 1</strong> In case of the OMI_LINK glTF extension (<code>href: https://nlnet.nl</code>) and an XR Fragment (<code>href: #otherroom</code> or <code>href: otherplanet.glb</code>), it is clear that <code>https://nlnet.nl</code> should open in a browsertab, whereas the XR Fragment links should teleport the user. If the OMI_LINK contains an XR Fragment (<code>#room1</code> e.g.) a teleport should be performed only (and other [overlapping] metadata should be ignored).</p>
<p><strong>Example 2</strong> If an Extensions uses XR Fragments in URI’s (<code>href: #otherroom</code> or <code>href: xrf://-walls</code> in OMI_LINK e.g.), then perform them according to XR Fragment spec (teleport user). But only once: ignore further overlapping metadata for that usecase.</p>
</blockquote>
<h1id="vendor-prefixes">Vendor Prefixes</h1>
<p><spanclass="index"id="idxref:18"></span></p>
<p>Vendor-specific metadata in a 3D scenefiles, are similar to vendor-specific <ahref="https://en.wikipedia.org/wiki/CSS#Vendor_prefixes">CSS-prefixes</a> (<code>-moz-opacity: 0.2</code> e.g.).
This allows popular 3D engines/frameworks, to initialize specific features when loading a scene/object, in a progressive enhanced way.</p>
<p>Vendor Prefixes allows embedding 3D engines/framework-specific features a 3D file via metadata:</p>
<table>
<thead>
<tr>
<th>what</th>
<th>XR metadata</th>
<th>Lowest common denominator</th>
</tr>
</thead>
<tbody>
<tr>
<td>CSS</td>
<td>vendor-agnostic</td>
<td>2D canvas + object referencing/styling</td>
</tr>
<tr>
<td>XR Fragments</td>
<td>vendor-agnostic</td>
<td>3D camera + object(file) load/embed/click/referencing</td>
<p>Why? Because not all XR interactions can/should be solved/standardized by embedding XR Fragments into any 3D file.
The lowest common denominator between 3D engines is the ‘entity’-part of their entity-component-system (ECS). The ‘component’-part can be progressively enhanced via vendor prefixes.</p>
</blockquote>
<p>For example, the following metadata can be added to a .glb file, to make an object grabbable in AFRAME:</p>
<p>String-templatevalues are evaluated as per <ahref="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</a> Level 1.</p>
<blockquote>
<p>This ‘separating of mechanism from policy’ (unix rule) does <strong>somewhat</strong> break portability of an XR experience, but still prevents (E-waste of) handcoded virtual worlds. It allows for (XR experience) metadata to survive in future 3D engines and scene-fileformats.</p>
<p>The only dynamic parts are <ahref="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <ahref="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</a>.<br>
The use of URI Templates is limited to pre-defined variables and Level0 fragments-expansion only, which makes it quite safe.<br>
n fact, it is much safer than relying on a scripting language (javascript) which can change URN too.</p>
<h1id="faq">FAQ</h1>
<p><spanclass="index"id="idxref:20"></span></p>
<p><strong>Q:</strong> Why is everything HTTP GET-based, what about POST/PUT/DELETE HATEOS<br>
<strong>A:</strong> Because it’s out of scope: XR Fragment specifies a read-only way to surf XR documents. These things belong in the application layer (for example, an XR Hypermedia browser can decide to support POST/PUT/DELETE requests for embedded HTML thru <code>src</code> values)</p>
<hr>
<p><strong>Q:</strong> Why isn’t there support for scripting, URI Template Fragments are so limited compared to WASM & javascript
<strong>A:</strong> This is out of scope as it unhyperifies hypermedia, and this is up to XR hypermedia browser-extensions.<br> Historically scripting/Javascript seems to been able to turn webpages from hypermedia documents into its opposite (hyperscripted nonhypermedia documents).<br>In order to prevent this backward-movement (hypermedia tends to liberate people from finnicky scripting) XR Fragment uses <ahref="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <ahref="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</a>, to prevent unhyperifying itself by hardcoupling to a particular markup or scripting language. <br>
XR Fragments supports filtering objects in a scene only, because in the history of the javascript-powered web, showing/hiding document-entities seems to be one of the most popular basic usecases.<br>
Doing advanced scripting & networkrequests under the hood are obviously interesting endavours, but this is something which should not be hardcoupled with XR Fragments or hypermedia.<br>This perhaps belongs more to browser extensions.<br>
Non-HTML Hypermedia browsers should make browser extensions the right place, to ‘extend’ experiences, in contrast to code/javascript inside hypermedia documents (this turned out as a hypermedia antipattern).</p>
<td>a sentient being who thinks fuzzy, absorbs, and shares thought (by plain text, not markuplanguage)</td>
</tr>
<tr>
<td>scene</td>
<td>a (local/remote) 3D scene or 3D file (index.gltf e.g.)</td>
</tr>
<tr>
<td>3D object</td>
<td>an object inside a scene characterized by vertex-, face- and customproperty data.</td>
</tr>
<tr>
<td>URI</td>
<td>some resource at something somewhere via someprotocol (<code>http://me.com/foo.glb#foo</code> or <code>e76f8efec8efce98e6f</code><ahref="https://interpeer.io">see interpeer.io</a>)</td>
</tr>
<tr>
<td>URL</td>
<td>something somewhere via someprotocol (<code>http://me.com/foo.glb</code>)</td>
</tr>
<tr>
<td>URN</td>
<td>something at some domain (<code>me.com/foo.glb</code>)</td>
</tr>
<tr>
<td>metadata</td>
<td>custom properties of text, 3D Scene or Object(nodes), relevant to machines and a human minority (academics/developers)</td>
</tr>
<tr>
<td>XR fragment</td>
<td>URI Fragment with spatial hints (which match the name of a 3D object-, camera-, animation-object)</td>