1640 lines
		
	
	
	
		
			69 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			1640 lines
		
	
	
	
		
			69 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						||
<html>
 | 
						||
<head>
 | 
						||
  <title>XR Fragments</title>
 | 
						||
  <meta name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl">
 | 
						||
  <meta charset="utf-8">
 | 
						||
</head>
 | 
						||
<body>
 | 
						||
 | 
						||
<!-- for annotated version see: https://raw.githubusercontent.com/ietf-tools/rfcxml-templates-and-schemas/main/draft-rfcxml-general-template-annotated-00.xml -->
 | 
						||
 | 
						||
 | 
						||
  <style type="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>  
 | 
						||
 | 
						||
 | 
						||
 | 
						||
<h1 class="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 <a href="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 <a href="https://en.wikipedia.org/wiki/URI_fragment">URI Fragments</a>.<br></p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>Almost every idea in this document is demonstrated at <a href="https://xrfragment.org">https://xrfragment.org</a></p>
 | 
						||
</blockquote>
 | 
						||
<section data-matter="main">
 | 
						||
<h1 id="quick-reference">Quick reference</h1>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#abstract">Abstract</a></li>
 | 
						||
<li><a href="#index">Index</a></li>
 | 
						||
<li><a href="#introduction">Introduction</a></li>
 | 
						||
<li><a href="#how-does-it-work">How does it work</a></li>
 | 
						||
<li><a href="#what-does-it-solve">What does it solve</a></li>
 | 
						||
<li><a href="#hfl-hypermediatic-feedback-loop-for-xr-browsers">HFL (Hypermediatic Feedback Loop) for XR Browsers</a></li>
 | 
						||
<li><a href="#conventions-and-definitions">Conventions and Definitions</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#xr-fragment-url-grammar">XR Fragment URL Grammar</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#spatial-referencing-3d">Spatial Referencing 3D</a></li>
 | 
						||
<li><a href="#level0-files">Level0: Files</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#via-href-metadata">via href metadata</a></li>
 | 
						||
<li><a href="#via-chained-extension">via chained extension</a></li>
 | 
						||
<li><a href="#via-subdocuments-xattr">via subdocuments/xattr</a></li>
 | 
						||
<li><a href="#json-sidecar-file">JSON sidecar-file</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#level1-uri">Level1: URI</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#list-of-uri-fragments">List of URI Fragments</a></li>
 | 
						||
<li><a href="#list-of-explicit-metadata">List of explicit metadata</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#level2-href-links">Level2: href links</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#interaction-behaviour">Interaction behaviour</a></li>
 | 
						||
<li><a href="#xr-viewer-implementation">XR Viewer implementation</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#level3-media-fragments">Level3: Media Fragments</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#animation-s-timeline">Animation(s) timeline</a></li>
 | 
						||
<li><a href="#specify-playback-loopmode">Specify playback loopmode</a></li>
 | 
						||
<li><a href="#controlling-embedded-content">Controlling embedded content</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#level4-prefix-operators">Level4: prefix operators</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#object-teleports">Object teleports</a></li>
 | 
						||
<li><a href="#object-multipliers">Object multipliers</a></li>
 | 
						||
<li><a href="#de-selectors-and">De/selectors (+ and -)</a></li>
 | 
						||
<li><a href="#sharing-object-or-file">Sharing object or file (#|)</a></li>
 | 
						||
<li><a href="#xrf-uri-scheme">xrf:// URI scheme</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#level5-uri-templates-rfc6570">Level5: URI Templates (RFC6570)</a></li>
 | 
						||
<li><a href="#top-level-url-processing">Top-level URL processing</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#ux">UX</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#example-navigating-content-href-portals">Example: Navigating content href portals</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#walking-surfaces">Walking surfaces</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#example-virtual-world-rings">Example: Virtual world rings</a></li>
 | 
						||
<li><a href="#additional-scene-metadata">Additional scene metadata</a></li>
 | 
						||
<li><a href="#accessibility-interface">Accessibility interface</a>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li><a href="#two-button-navigation">Two-button navigation</a></li>
 | 
						||
<li><a href="#overlap-with-fileformat-specific-extensions">Overlap with fileformat-specific extensions</a></li>
 | 
						||
</ol></li>
 | 
						||
<li><a href="#vendor-prefixes">Vendor Prefixes</a></li>
 | 
						||
<li><a href="#security-considerations">Security Considerations</a></li>
 | 
						||
<li><a href="#faq">FAQ</a></li>
 | 
						||
<li><a href="#authors">Authors</a></li>
 | 
						||
<li><a href="#iana-considerations">IANA Considerations</a></li>
 | 
						||
<li><a href="#acknowledgments">Acknowledgments</a></li>
 | 
						||
<li><a href="#appendix-definitions">Appendix: Definitions</a></li>
 | 
						||
</ol>
 | 
						||
 | 
						||
<h1 id="introduction">Introduction</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:0"></span></p>
 | 
						||
 | 
						||
<p>How can we add more control to existing text and 3D scenes, without introducing new dataformats?<br>
 | 
						||
Historically, there’s many attempts to create the ultimate 3D fileformat.<br>
 | 
						||
The lowest common denominator is: designers describing/tagging/naming things using <strong>plain text</strong>.<br>
 | 
						||
XR Fragments exploits the fact that all 3D models already contain such metadata:</p>
 | 
						||
 | 
						||
<p><strong>XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments</strong></p>
 | 
						||
 | 
						||
<h1 id="how-does-it-work">How does it work</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:1"></span></p>
 | 
						||
 | 
						||
<p>XR Fragments utilizes URLs:</p>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li>for 3D viewers/browser to manipulate the camera or objects (via URI fragments)</li>
 | 
						||
<li>implicitly: by mapping 3D objectnames (of a 3D scene/file) to URI fragments (3D deeplinking)</li>
 | 
						||
<li>explicitly: by scanning <code>href</code> metadata <strong>inside</strong> 3D scene-files to enable interactions</li>
 | 
						||
<li>externally: progressively enhance a 3D (file) into an experience via <a href="https://en.wikipedia.org/wiki/Sidecar_file">sidecarfiles</a></li>
 | 
						||
</ol>
 | 
						||
 | 
						||
<h1 id="what-does-it-solve">What does it solve</h1>
 | 
						||
 | 
						||
<p>It solves:</p>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li>addressibility and <a href="https://github.com/coderofsalvation/hypermediatic">hypermediatic</a> navigation of 3D scenes/objects: <a href="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 <a href="#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 <a href="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <a href="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>
 | 
						||
 | 
						||
<h1 id="hfl-hypermediatic-feedback-loop-for-xr-browsers">HFL (Hypermediatic Feedback Loop) for XR Browsers</h1>
 | 
						||
 | 
						||
<p><span class="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><a href="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 <a href="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>n/a</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>href metadata</td>
 | 
						||
<td>filters certain (in)visible objects</td>
 | 
						||
<td>n/a</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>href metadata</td>
 | 
						||
<td>href=“xrf://#-foo&bar”</td>
 | 
						||
<td>href=“javascript:hideFooAndShowBar()`</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td></td>
 | 
						||
<td>(this does not update topLevel URI)</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>
 | 
						||
 | 
						||
<h1 id="conventions-and-definitions">Conventions and Definitions</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:3"></span></p>
 | 
						||
 | 
						||
<p>See appendix below in case certain terms are not clear.</p>
 | 
						||
 | 
						||
<h2 id="xr-fragment-url-grammar">XR Fragment URL Grammar</h2>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:4"></span></p>
 | 
						||
 | 
						||
<p>For typical HTTP-like browsers/applications:</p>
 | 
						||
 | 
						||
<pre><code>reserved    = gen-delims / sub-delims
 | 
						||
gen-delims  = "#" / "&"
 | 
						||
sub-delims  = "," / "="
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>Example: <code>://foo.com/my3d.gltf#room1&prio=-5&t=0,100</code></p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>Demo</th>
 | 
						||
<th>Explanation</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td><code>room1</code></td>
 | 
						||
<td>vector/coordinate argument e.g.</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>room1&cam1</code></td>
 | 
						||
<td>combinators</td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<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>
 | 
						||
 | 
						||
<h1 id="spatial-referencing-3d">Spatial Referencing 3D</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:5"></span></p>
 | 
						||
 | 
						||
<p>3D files contain an hierarchy of objects.<br>
 | 
						||
XR Fragments assumes the following objectname-to-URI-Fragment mapping, in order to deeplink 3D objects:</p>
 | 
						||
 | 
						||
<pre><code>
 | 
						||
  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)
 | 
						||
  │ │ │ │                 │ │ │ │
 | 
						||
  │ │ │ +─────────────────+ │ │ │
 | 
						||
  │ │ +─────────────────────+ │ │
 | 
						||
  │ +─────────────────────────+ │
 | 
						||
  +─────────────────────────────+
 | 
						||
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<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>
 | 
						||
 | 
						||
<h1 id="level0-files">Level0: Files</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:6"></span>
 | 
						||
<span class="index" id="idxref:7"></span></p>
 | 
						||
 | 
						||
<p>Compatible 3D fileformats: <a href="https://www.khronos.org/gltf/">glTF</a>, <a href="https://openusd.org/release/spec_usdz.html">usdz</a>, <a href="https://en.wikipedia.org/wiki/Wavefront_.obj_file">obj</a>, <a href="https://www.khronos.org/collada">collada</a>, <a href="https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4">THREE.json</a>, <a href="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 <a href="">side-car files</a> to enable hasslefree <a href="#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>
 | 
						||
 | 
						||
<h2 id="via-href-metadata">via href metadata</h2>
 | 
						||
 | 
						||
<pre><code>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)
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<p><strong>heuristics</strong>:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>if at least one <code>href</code> custom property/extra is found in a 3D scene</li>
 | 
						||
<li>The viewer should poll for the above mentioned sidecar-file extensions (and present accordingly)</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<h2 id="via-chained-extension">via chained extension</h2>
 | 
						||
 | 
						||
<pre><code>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)
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>A fallback-mechanism to turn 3D files into <a href="#XR%20Movies">XR Movies</a> without editing them.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<p><strong>heuristics</strong>:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>the chained-extension heuristic <code>.xrf.</code> should be present in the filename (<code>scene.xrf.glb</code> e.g.)</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<h2 id="via-subdocuments-xattr">via subdocuments/xattr</h2>
 | 
						||
 | 
						||
<p>More secure protocols (Nextgraph e.g.) don’t allow for simply polling files.
 | 
						||
In such case, subdocuments or extended attributes should be polled:</p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>NOTE: in the examples below we use the href-heuristic, but also the <code>.xrf.</code> chained-extension applies here.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<pre><code>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)
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<p>If only extended attributes (xattr) are available, the respective referenced file can be embedded:</p>
 | 
						||
 | 
						||
<pre><code>$ 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
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>NOTE: Linux’s <code>setfattr/getfattr</code> is <code>xattr</code> on mac, and <code>Set-Content/Get-content</code> on Windows. See <a href="https://www.lesbonscomptes.com/pxattr/index.html">pxattr</a> for lowlevel access.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h2 id="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 <a href="https://en.wikipedia.org/wiki/Sidecar_file">sidecar-file</a>:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>experience.glb</li>
 | 
						||
<li>experience.json <code><----</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<pre><code class="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><code class="language-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 
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<h1 id="level1-uri">Level1: URI</h1>
 | 
						||
 | 
						||
<p><span class="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>
 | 
						||
 | 
						||
<pre><code>  +───────────────────────────────────────────────────────────────────────────────────────────────+
 | 
						||
  │                                                                                               │
 | 
						||
  │                          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                                                                 │
 | 
						||
  │                                                                                               │
 | 
						||
  +───────────────────────────────────────────────────────────────────────────────────────────────+
 | 
						||
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<p>Fact: our typical browser URL’s are just <strong>a possible implementation</strong> of URI’s (for untapped humancentric potential of URI’s <a href="https://interpeer.io">see interpeer.io</a> or <a href="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>
 | 
						||
 | 
						||
<pre><code> +───────────────────────────────────────────────────────────────────────────────────────────────+
 | 
						||
 │                                                                                               │
 | 
						||
 │   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  ──────────────>─────────────+      │
 | 
						||
 │                                                                                               │
 | 
						||
 │                                                                                               │
 | 
						||
 +───────────────────────────────────────────────────────────────────────────────────────────────+
 | 
						||
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<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>
 | 
						||
 | 
						||
<h2 id="list-of-uri-fragments">List of URI Fragments</h2>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>fragment</th>
 | 
						||
<th>type</th>
 | 
						||
<th>example</th>
 | 
						||
<th>info</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td><code>#......</code></td>
 | 
						||
<td>vector3</td>
 | 
						||
<td><code>#room1</code> <code>#room2</code> <code>#cam2</code></td>
 | 
						||
<td>positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><a href="https://www.w3.org/TR/media-frags/">Media Fragments</a></td>
 | 
						||
<td><a href="#media%20fragments%20and%20datatypes">media fragment</a></td>
 | 
						||
<td><code>#t=0,2&loop</code></td>
 | 
						||
<td>play (and loop) 3D animation from 0 seconds till 2 seconds</td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<h2 id="list-of-explicit-metadata">List of *<em>explicit</em> metadata</h2>
 | 
						||
 | 
						||
<p>These are the possible ‘extras’ for 3D nodes and sidecar-files</p>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>key</th>
 | 
						||
<th>type</th>
 | 
						||
<th>example (JSON)</th>
 | 
						||
<th>function</th>
 | 
						||
<th>existing compatibility</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td><code>href</code></td>
 | 
						||
<td>string</td>
 | 
						||
<td><code>"href": "b.gltf"</code></td>
 | 
						||
<td>XR teleport</td>
 | 
						||
<td>custom property in 3D fileformats</td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<h1 id="level2-href-links">Level2: href links</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:9"></span></p>
 | 
						||
 | 
						||
<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>| fragment | type |  example value |
 | 
						||
|<code>href</code>| string (uri or predefined view) | <code>#pyramid</code><br><code>#lastvisit</code><br><code>xrf://#-someobject</code><br><code>://somefile.gltf#foo</code><br> |</p>
 | 
						||
 | 
						||
<h2 id="interaction-behaviour">Interaction behaviour</h2>
 | 
						||
 | 
						||
<p>When clicking an “href”-value, the user(camera) is teleport to the referenced object.</p>
 | 
						||
 | 
						||
<p>The imported/teleported destination can be another object in the same scene-file, or a different file.</p>
 | 
						||
 | 
						||
<h2 id="xr-viewer-implementation">XR Viewer implementation</h2>
 | 
						||
 | 
						||
<p>| <strong>spec</strong> | <strong>action</strong> | <strong>feature</strong> |
 | 
						||
|-|-|-|
 | 
						||
| level0+1 | hover  3D file <a href="#via-href-metadata">href</a> | show the preview PNG thumbnail (if any).  |
 | 
						||
| level0+1 | launch 3D file <a href="#via-href-metadata">href</a> | replace the current scene with a new 3D file (<code>href: other.glb</code> e.g.) |
 | 
						||
| level2 | click internal 3D file <a href="#via-href-metadata">href</a> (<code>#roomB</code> e.g.) | teleport the camera to the origin of object(name <code>roomB</code>). See [[teleport camera]].|
 | 
						||
| level2 | click external 3D file <a href="#via-href-metadata">href</a> (<code>foo.glb</code> e.g.) | replace the current scene with a new 3D file (<code>href: other.glb</code> e.g.) |
 | 
						||
| level2 | hover external 3D file <a href="#via-href-metadata">href</a> | show the preview PNG thumbnail (if any sidecar, see level0) |
 | 
						||
| level2 | click <a href="#via-href-metadata">href</a> | hashbus: execute without changing the toplevel URL location (<code>href: xrf://#someObjectName</code> e.g.) |
 | 
						||
| level3 | click <a href="#via-href-metadata">href</a> | set the global 3D animation timeline to its Media Fragment value (<code>#t=2,3</code> e.g.) |</p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<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 <a href="#hashbus">hashbus</a> for more info.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h1 id="level3-media-fragments">Level3: Media Fragments</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:10"></span></p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>these allow for XR Movies with a controllable timeline using <code>href</code> URI’s with Media Fragments</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<p>Just like with 2D media-files, W3C mediafragments (<code>#t=1,2</code>) can be used to control a timeline via the <a href="##t">#t</a> primitive.
 | 
						||
XR Fragments Level3 makes the 3D timeline, as well as URL-referenced files <strong>controllable</strong> via Media Fragments like:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>level2 hrefs (<code>href: #t=4</code> e.g. to control 3D timeline)</li>
 | 
						||
<li>level4: <code>xrf:</code> URI scheme:
 | 
						||
 | 
						||
<ul>
 | 
						||
<li><code>href: xrf:foo.wav#t=0</code> to play a wav</li>
 | 
						||
<li><code>href: xrf:news.glb?clone#t=0</code> to instance and play another experience</li>
 | 
						||
</ul></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<h2 id="animation-s-timeline">Animation(s) timeline</h2>
 | 
						||
 | 
						||
<p>controls the animation(s) of the scene (or <code>src</code> resource which contains a timeline)</p>
 | 
						||
 | 
						||
<p>| fragment | type | functionality |
 | 
						||
| <b>#t</b>=start,stop | <a href="default:`#t=0`">[vector2]</a> | start,stop (in seconds |</p>
 | 
						||
 | 
						||
<p>| Example Value     | Explanation |
 | 
						||
| <code>#t=1</code> |  play (3D) animations from 1 seconds till end (and stop) |
 | 
						||
| <code>#t=1,100</code> |  play (3D) animations from 1 till 100 seconds (and stop) |</p>
 | 
						||
 | 
						||
<h2 id="specify-playback-loopmode">Specify playback loopmode</h2>
 | 
						||
 | 
						||
<p>This compensates a missing element from Media Fragments to enable/disable temporal looping. .</p>
 | 
						||
 | 
						||
<p>| fragment | type | functionality |
 | 
						||
| <b>#loop</b> | string | enables animation/video/audio loop |
 | 
						||
| <b>#-loop</b> | string | disables animation/video/audio loop |</p>
 | 
						||
 | 
						||
<h2 id="controlling-embedded-content">Controlling embedded content</h2>
 | 
						||
 | 
						||
<p>use [[URI Templates]] to control embedded media, for example a simple video-player:</p>
 | 
						||
 | 
						||
<pre><code> 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
 | 
						||
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<h1 id="level4-prefix-operators">Level4: prefix operators</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:11"></span></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>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h2 id="object-teleports">Object teleports (!)</h2>
 | 
						||
 | 
						||
<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><div class="border padding" style="border:4px solid #888">
 | 
						||
    <span class="big hi1">#!menu</span>
 | 
						||
</div>
 | 
						||
<br></p>
 | 
						||
 | 
						||
<p>Clicking the <a href="#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>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>href: <code>#whiteroom&!explainer&!exitmenu</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>This will teleport the user to <code>whiteroom</code> and moves object <code>explainer</code> and <code>exitmenu</code> in front of the user.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>href: `<a href="https://my.org/foo.glb#!">https://my.org/foo.glb#!</a></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>Clicking the <a href="#via-href-metadata">href</a>-value above will:</p>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li>import <code>foo.glb</code> from <code>my.org</code>’s webserver</li>
 | 
						||
<li>show it in front of the user (because <code>#!</code> indicates object teleport)</li>
 | 
						||
</ol>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>href: <code>https://foo.glb#roomB&!bar</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>Clicking the <a href="#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 <a href="#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>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h2 id="object-multipliers">Object multipliers (*)</h2>
 | 
						||
 | 
						||
<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 <a href="#%23%21">#! operator</a> which infinitely <strong>clones</strong> the referenced object (instead of repositioning the object).</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h2 id="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>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li><code>#-welcome</code></li>
 | 
						||
<li><code>#+welcome</code></li>
 | 
						||
<li><code>#-VR*</code></li>
 | 
						||
<li><code>https://foo.glb#bar&-welcome</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>Matching logic:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<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>
 | 
						||
 | 
						||
<h2 id="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 <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API">Web Share API</a> or <a href="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>
 | 
						||
 | 
						||
<h2 id="xrf-uri-scheme">xrf:// URI scheme</h2>
 | 
						||
 | 
						||
<p>Prefixing the <code>xrf:</code> to <a href="#href">href</a>-values <strong>will prevent</strong> <a href="#📜%20level2:%20explicit%20links">level2</a> <a href="#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 <a href="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>
 | 
						||
 | 
						||
<h1 id="level5-uri-templates-rfc6570">Level5: URI Templates (RFC6570)</h1>
 | 
						||
 | 
						||
<p><span class="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>
 | 
						||
 | 
						||
<h1 id="top-level-url-processing">Top-level URL processing</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:13"></span></p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>Example URL:  <code>://foo/world.gltf#room1&t=10&cam</code></p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<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) (<a href="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>
 | 
						||
 | 
						||
<h2 id="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>
 | 
						||
</ol>
 | 
						||
 | 
						||
<h1 id="example-navigating-content-href-portals">Example: Navigating content href portals</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:14"></span></p>
 | 
						||
 | 
						||
<p>navigation, portals & mutations</p>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>fragment</th>
 | 
						||
<th>type</th>
 | 
						||
<th>example value</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td><code>href</code></td>
 | 
						||
<td>string (uri or predefined view)</td>
 | 
						||
<td><code>#room1</code><br><code>#room1</code><br><code>://somefile.gltf#room1</code><br></td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<ol>
 | 
						||
<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 [<a href="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 [<a href="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 [<a href="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><a href="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js">» example implementation</a><br>
 | 
						||
<a href="https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/href.gltf#L192">» example 3D asset</a><br>
 | 
						||
<a href="https://github.com/coderofsalvation/xrfragment/issues/1">» discussion</a><br></p>
 | 
						||
 | 
						||
<h2 id="walking-surfaces">Walking surfaces</h2>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>By default position <code>0,0,0</code> of the 3D scene represents the walkable plane, however this is overridden when the following applies:</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<p>XR Fragment-compatible viewers can infer this data based scanning the scene for:</p>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li>materialless (nameless & textureless) mesh-objects (without <code>href</code> and >0 faces)</li>
 | 
						||
</ol>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h1 id="example-virtual-world-rings">Example: Virtual world rings</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:15"></span></p>
 | 
						||
 | 
						||
<p>Consider 3D scenes linking to eachother using these <code>href</code> values, attached to 3D button-objects:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li><code>href: schoolA.edu/projects.gltf#math</code></li>
 | 
						||
<li><code>href: schoolB.edu/projects.gltf#math</code></li>
 | 
						||
<li><code>href: university.edu/projects.gltf#math</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>This would teleport users to the math-projects of those universities.<br>
 | 
						||
Now consider adding a ‘webring index’-button to each file, with this href-value:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>href: workgroup.edu/webrings.glb#!webringmenu</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>This would allow displaying the (remote 3D file) webring menu with various href-buttons inside, all centrally curated by the workgroup.</p>
 | 
						||
 | 
						||
<h1 id="additional-scene-metadata">Additional scene metadata</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:16"></span></p>
 | 
						||
 | 
						||
<p>XR Fragments does not aim to redefine the metadata-space or accessibility-space by introducing its own cataloging-metadata fields.
 | 
						||
Instead, it encourages browsers to scan nodes for the following custom properties:</p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li><a href="https://spdx.dev/">SPDX</a> license information</li>
 | 
						||
<li><a href="https://www.w3.org/WAI/standards-guidelines/aria/">ARIA</a> attributes (<code>aria-*: .....</code>)</li>
 | 
						||
<li><a href="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><a href="https://json-ld.org">RDF/JSON-LD</a> like <a href="https://mvmd.org/standards/gltf/">this example</a> or via glTF’s <a href="https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld">KHR_xmp_json_ld extension</a></li>
 | 
						||
<li><a href="https://ogp.me">Open Graph</a> attributes (<code>og:*: .....</code>)</li>
 | 
						||
<li><a href="https://www.dublincore.org/specifications/dublin-core/application-profile-guidelines/">Dublin-Core</a> attributes(<code>dc:*: .....</code>)</li>
 | 
						||
<li><a href="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>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>metadata key</th>
 | 
						||
<th>example value</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td><code>aria-description</code>, <code>og:description</code>, <code>dc:description</code></td>
 | 
						||
<td><code>An immersive experience about Triceratops</code> (*)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>SPDX</code></td>
 | 
						||
<td><code>CC0-1.0</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>dc:creator</code></td>
 | 
						||
<td><code>John Doe</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>dc:title</code>, <code>og:title</code></td>
 | 
						||
<td>‘Triceratops` (*)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>og:site_name</code></td>
 | 
						||
<td><code>https://xrfragment.org</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>dc.publisher</code></td>
 | 
						||
<td><code>NLNET</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>dc.date</code></td>
 | 
						||
<td><code>2024-01-01</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>dc.identifier</code></td>
 | 
						||
<td><code>XRFRAGMENT-001</code></td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>journal</code> (bibTeX)</td>
 | 
						||
<td><code>{Future Of Text Vol 3},</code></td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>* = these are interchangable (only one needs to be defined)</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<p>There’s no silver bullet when it comes to metadata, so XR Fragment-implementations should support where the metadata is/goes.</p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>These attributes can be scanned and presented during an <code>href</code> or <code>src</code> eye/mouse-over.</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h1 id="accessibility-interface">Accessibility interface</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:17"></span></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>
 | 
						||
</ol>
 | 
						||
 | 
						||
<h2 id="two-button-navigation">Two-button navigation</h2>
 | 
						||
 | 
						||
<p>For specific user-profiles, gyroscope/mouse/keyboard/audio/visuals will not be available.<br>
 | 
						||
Therefore a 2-button navigation-interface is the bare minimum interface:</p>
 | 
						||
 | 
						||
<ol>
 | 
						||
<li>objects with href metadata can be cycled via a key (tab on a keyboard)</li>
 | 
						||
<li>objects with href metadata can be activated via a key (enter on a keyboard)</li>
 | 
						||
<li>the TTS reads the href-value (and/or aria-description if available)</li>
 | 
						||
</ol>
 | 
						||
 | 
						||
<h2 id="overlap-with-fileformat-specific-extensions">Overlap with fileformat-specific extensions</h2>
 | 
						||
 | 
						||
<p>Some 3D scene-fileformats have support for extensions.
 | 
						||
What if the functionality of those overlap?
 | 
						||
For example, GLTF has the <code>OMI_LINK</code> extension which might overlap with XR Fragment’s <code>href</code>:</p>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<p>Priority Order and Precedence, otherwise fallback applies</p>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<p>1.<strong>Extensions Take Precedence</strong>: Since glTF-specific extensions are designed with the format’s
 | 
						||
specific needs and optimizations in mind, they should take precedence over extras metadata
 | 
						||
in cases where both contain overlapping functionality.
 | 
						||
This approach aligns with the idea that extensions are more likely to be interpreted uniformly by glTF-compatible software.</p>
 | 
						||
 | 
						||
<ol start="2">
 | 
						||
<li><strong>Fallback Fall-through Mechanism</strong>:
 | 
						||
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>
 | 
						||
 | 
						||
<h1 id="vendor-prefixes">Vendor Prefixes</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:18"></span></p>
 | 
						||
 | 
						||
<p>Vendor-specific metadata in a 3D scenefiles, are similar to vendor-specific <a href="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>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>Vendor prefixs</td>
 | 
						||
<td>vendor-<strong>specific</strong></td>
 | 
						||
<td>Specialized Entity-Component implementation</td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
 | 
						||
<blockquote>
 | 
						||
<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>
 | 
						||
 | 
						||
<pre><code>+────────────────────────────────────────────────────────────────────────────────────────────────────────+ 
 | 
						||
│ http://y.io/z.glb                             | AFRAME app                                             │ 
 | 
						||
│-----------------------------------------------+--------------------------------------------------------│ 
 | 
						||
│                                               |                                                        │
 | 
						||
│                                               | after loading the glb, john can be placed into the     │ 
 | 
						||
│     +-[3D mesh]-+                             | castle via hands, because the author added metadata to │  
 | 
						||
│     |    / \    |                             | john via either:                                       │  
 | 
						||
│     |   /   \   |                             |                                                        │ 
 | 
						||
│     |  /     \  |                             | 1. Blender (custom property-box, no plugins needed)    │ 
 | 
						||
│     |  |_____|  |                             |                                                        │  
 | 
						||
│     +-----│-----+                             | 2. javascript-code:                                    │  
 | 
						||
│           │                                   |                                                        │  
 | 
						||
│           ├─ name: castle                     |     for( var com in this.el.components ){              │  
 | 
						||
│           └─ tag: house baroque               |       this.el.object3D.userData[`-AFRAME-${com}`] = '' │  
 | 
						||
│                                               |     }                                                  │  
 | 
						||
│ [3D mesh-+                                    |     // save to z.glb in AFRAME inspector               │ 
 | 
						||
│ |        ├─ name: john                        |                                                        │  
 | 
						||
│ |    O   ├─ age: 23                           |                                                        │  
 | 
						||
│ |   /|\  ├─ -aframe-grabbable:      ''        | > inits 'grabbable' component on object john           │ 
 | 
						||
│ |   / \  ├─ -aframe-material.color: '#F0A'    | > inits 'material' component on object john            │  
 | 
						||
│ |        ├─ -aframe-text.value:  '{name}{age}'| > inits 'text' component (*) with value 'john'         │  
 | 
						||
│ |        ├─ -three-material.fog: false        | > changes material settings in THREE.js app            │ 
 | 
						||
│ |        ├─ -godot-Label3D.text: '{name}{age}'| > inits 'Label3D' component (*) in Godot               │  
 | 
						||
│ +--------+                                    |                                                        │
 | 
						||
│                                               |                                                        │
 | 
						||
├─ -GODOT-version:  '4.3'                       | > exporters/authors can report targeted version        │
 | 
						||
├─ -AFRAME-version: '1.6.0'                     |                    and (optionally) hint component-repo│
 | 
						||
├─ -AFRAME-info:    'https://git.benetou.fr/comps'                                                       │       
 | 
						||
│                                               |                                                        │
 | 
						||
+────────────────────────────────────────────────────────────────────────────────────────────────────────+ 
 | 
						||
</code></pre>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>key/value syntax: -<code><vendorname></code>-<code><component|version></code>.<code><key></code>  <code>[string/boolean/float/int]</code>-value</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<p>String-templatevalues are evaluated as per <a href="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>
 | 
						||
</blockquote>
 | 
						||
 | 
						||
<h1 id="security-considerations">Security Considerations</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:19"></span></p>
 | 
						||
 | 
						||
<p>The only dynamic parts are <a href="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <a href="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>
 | 
						||
 | 
						||
<h1 id="faq">FAQ</h1>
 | 
						||
 | 
						||
<p><span class="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 <a href="https://www.w3.org/TR/media-frags/">W3C Media Fragments</a> and <a href="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>
 | 
						||
 | 
						||
<h1 id="authors">authors</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:21"></span></p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li>Leon van Kammen (@lvk@mastodon.online)</li>
 | 
						||
<li>Jens Finkhäuser (@jens@social.finkhaeuser.de)</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<h1 id="iana-considerations">IANA Considerations</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:22"></span></p>
 | 
						||
 | 
						||
<p>This document has no IANA actions.</p>
 | 
						||
 | 
						||
<h1 id="acknowledgments">Acknowledgments</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:23"></span></p>
 | 
						||
 | 
						||
<ul>
 | 
						||
<li><a href="https://nlnet.nl">NLNET</a></li>
 | 
						||
<li><a href="https://futureoftext.org">Future of Text</a></li>
 | 
						||
<li><a href="https://visual-meta.info">visual-meta.info</a></li>
 | 
						||
<li>Michiel Leenaars</li>
 | 
						||
<li>Gerben van der Broeke</li>
 | 
						||
<li>Mauve</li>
 | 
						||
<li>Jens Finkhäuser</li>
 | 
						||
<li>Marc Belmont</li>
 | 
						||
<li>Tim Gerritsen</li>
 | 
						||
<li>Frode Hegland</li>
 | 
						||
<li>Brandel Zackernuk</li>
 | 
						||
<li>Mark Anderson</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
<h1 id="appendix-definitions">Appendix: Definitions</h1>
 | 
						||
 | 
						||
<p><span class="index" id="idxref:24"></span></p>
 | 
						||
 | 
						||
<table>
 | 
						||
<thead>
 | 
						||
<tr>
 | 
						||
<th>definition</th>
 | 
						||
<th>explanation</th>
 | 
						||
</tr>
 | 
						||
</thead>
 | 
						||
 | 
						||
<tbody>
 | 
						||
<tr>
 | 
						||
<td>human</td>
 | 
						||
<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> <a href="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>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>the XRWG</td>
 | 
						||
<td>wordgraph (collapses 3D scene to tags)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>the hashbus</td>
 | 
						||
<td>hashtags map to camera/scene-projections</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>spacetime hashtags</td>
 | 
						||
<td>positions camera, triggers scene-preset/time</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>teleportation</td>
 | 
						||
<td>repositioning the enduser to a different position (or 3D scene/file)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>sourceportation</td>
 | 
						||
<td>teleporting the enduser to the original XR Document of an <code>src</code> embedded object.</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>placeholder object</td>
 | 
						||
<td>a 3D object which with src-metadata (which will be replaced by the src-data.)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>src</td>
 | 
						||
<td>(HTML-piggybacked) metadata of a 3D object which instances content</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>href</td>
 | 
						||
<td>(HTML-piggybacked) metadata of a 3D object which links to content</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>filter</td>
 | 
						||
<td>URI Fragment(s) which show/hide object(s) in a scene based on name/tag/property (<code>#cube&-price=>3</code>)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>visual-meta</td>
 | 
						||
<td><a href="https://visual.meta.info">visual-meta</a> data appended to text/books/papers which is indirectly visible/editable in XR.</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>requestless metadata</td>
 | 
						||
<td>metadata which never spawns new requests (unlike RDF/HTML, which can cause framerate-dropping, hence not used a lot in games)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>FPS</td>
 | 
						||
<td>frames per second in spatial experiences (games,VR,AR e.g.), should be as high as possible</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>introspective</td>
 | 
						||
<td>inward sensemaking (“I feel this belongs to that”)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>extrospective</td>
 | 
						||
<td>outward sensemaking (“I’m fairly sure John is a person who lives in oklahoma”)</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td><code>◻</code></td>
 | 
						||
<td>ascii representation of an 3D object/mesh</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>(un)obtrusive</td>
 | 
						||
<td>obtrusive: wrapping human text/thought in XML/HTML/JSON obfuscates human text into a salad of machine-symbols and words</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>flat 3D object</td>
 | 
						||
<td>a 3D object of which all verticies share a plane</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>BibTeX</td>
 | 
						||
<td>simple tagging/citing/referencing standard for plaintext</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>BibTag</td>
 | 
						||
<td>a BibTeX tag</td>
 | 
						||
</tr>
 | 
						||
 | 
						||
<tr>
 | 
						||
<td>(hashtag)bibs</td>
 | 
						||
<td>an easy to speak/type/scan tagging SDL (<a href="https://github.com/coderofsalvation/hashtagbibs">see here</a> which expands to BibTex/JSON/XML</td>
 | 
						||
</tr>
 | 
						||
</tbody>
 | 
						||
</table>
 | 
						||
<h1 id="index-section">Index</h1>
 | 
						||
<div class="index">
 | 
						||
<dl>
 | 
						||
<dt>A</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Accessibility interface <a class="index-return" href="#idxref:17"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Acknowledgments <a class="index-return" href="#idxref:23"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Additional scene metadata <a class="index-return" href="#idxref:16"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Appendix: Definitions <a class="index-return" href="#idxref:24"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>C</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Conventions and Definitions <a class="index-return" href="#idxref:3"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>E</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Example: Navigating content href portals <a class="index-return" href="#idxref:14"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Example: Virtual world rings <a class="index-return" href="#idxref:15"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>F</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
FAQ <a class="index-return" href="#idxref:20"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>H</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
HFL (Hypermediatic Feedback Loop <a class="index-return" href="#idxref:2"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>I</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
IANA Considerations <a class="index-return" href="#idxref:22"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Introduction <a class="index-return" href="#idxref:0"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>L</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Level0: Files <a class="index-return" href="#idxref:6"><sup>[go]</sup></a> <a class="index-return" href="#idxref:7"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Level1: URI <a class="index-return" href="#idxref:8"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Level2: href links <a class="index-return" href="#idxref:9"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Level3: Media Fragments <a class="index-return" href="#idxref:10"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Level4: prefix operators <a class="index-return" href="#idxref:11"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Level5: URI Templates (RFC6570 <a class="index-return" href="#idxref:12"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>S</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Security Considerations <a class="index-return" href="#idxref:19"><sup>[go]</sup></a></li>
 | 
						||
<li>
 | 
						||
Spatial Referencing 3D <a class="index-return" href="#idxref:5"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>T</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Top-level URL processing <a class="index-return" href="#idxref:13"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>V</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
Vendor Prefixes <a class="index-return" href="#idxref:18"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>W</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
What is XR Fragments <a class="index-return" href="#idxref:1"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>X</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
XR Fragment URL Grammar <a class="index-return" href="#idxref:4"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
<dl>
 | 
						||
<dt>a</dt>
 | 
						||
<dd>
 | 
						||
<ul>
 | 
						||
<li>
 | 
						||
authors <a class="index-return" href="#idxref:21"><sup>[go]</sup></a></li>
 | 
						||
</ul>
 | 
						||
</dd>
 | 
						||
</dl>
 | 
						||
 | 
						||
</div>
 | 
						||
</section>
 | 
						||
 | 
						||
</body>
 | 
						||
</html>
 | 
						||
 |