<?xml version="1.0" encoding="utf-8"?> <!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" --> <rfc version="3" ipr="trust200902" docName="draft-XRFRAGMENTS-leonvankammen-00" submissionType="IETF" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" consensus="true"> <front> <title>XR Fragments</title><seriesInfo value="draft-XRFRAGMENTS-leonvankammen-00" stream="IETF" status="informational" name="XR-Fragments"></seriesInfo> <author initials="L.R." surname="van Kammen" fullname="L.R. van Kammen"><organization></organization><address><postal><street></street> </postal></address></author><date/> <area>Internet</area> <workgroup>Jens & Leon Internet Engineering Task Force</workgroup> <abstract> <t>This draft is a specification for 4D URI's & <eref target="https://github.com/coderofsalvation/hypermediatic">hypermediatic</eref> navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.<br /> The specification uses <eref target="https://www.w3.org/TR/media-frags/">W3C Media Fragments</eref> and <eref target="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</eref> to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.<br /> XR Fragments allows us to better use existing metadata inside 3D scene(files), by connecting it to proven technologies like <eref target="https://en.wikipedia.org/wiki/URI_fragment">URI Fragments</eref>.<br /> XR Fragments views spatial webs thru the lens of 3D scene URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).</t> <t>Almost every idea in this document is demonstrated at <eref target="https://xrfragment.org">https://xrfragment.org</eref></t> </abstract> </front> <middle> <section anchor="introduction"><name>Introduction</name> <t>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:</t> <t><strong>XR Fragments allows controlling of metadata in 3D scene(files) using URI's</strong></t> <t>It solves:</t> <ol spacing="compact"> <li>addressibility and <eref target="https://github.com/coderofsalvation/hypermediatic">hypermediatic</eref> navigation of 3D scenes/objects: <eref target="https://en.wikipedia.org/wiki/URI_fragment">URI Fragments</eref> using src/href spatial metadata</li> <li>Interlinking text & spatial objects by collapsing space into a Word Graph (XRWG) to show <eref target="#visible-links">visible links</eref></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><t>NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible</t> </blockquote></section> <section anchor="core-principle"><name>Core principle</name> <t><strong>XR Fragments allows controlling 3D models using URLs, based on (non)existing metadata via URI's</strong></t> <t>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 /> </t> <artwork> +───────────────────────────────────────────────────────────────────────────────────────────────+ │ │ │ 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 │ │ │ +───────────────────────────────────────────────────────────────────────────────────────────────+ </artwork> <t>Fact: our typical browser URL's are just <strong>a possible implementation</strong> of URI's (for untapped humancentric potential of URI's <eref target="https://interpeer.io">see interpeer.io</eref>)</t> <blockquote><t>XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.<br /> But approaches things from a higherlevel feedbackloop/hypermedia browser-perspective.</t> </blockquote><t>Below you can see how this translates back into good-old URLs:</t> <artwork> +───────────────────────────────────────────────────────────────────────────────────────────────+ │ │ │ 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 ─> #view ───> hashbus │ │ │ #filter │ │ │ │ #tag │ │ │ │ (hypermediatic) #material │ │ │ │ ( feedback ) #animation │ │ │ │ ( loop ) #texture │ │ │ │ #variable │ │ │ │ │ │ │ XRWG <─────────────────────<─────────────+ │ │ │ │ │ │ └─ objects ──────────────>─────────────+ │ │ │ │ │ +───────────────────────────────────────────────────────────────────────────────────────────────+ </artwork> <blockquote><t>?-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.</t> </blockquote><t>Traditional webbrowsers can become 4D document-ready by:</t> </section> <section anchor="hypermediatic-feedbackloop-for-xr-browsers"><name>Hypermediatic FeedbackLoop for XR browsers</name> <t><tt>href</tt> metadata traditionally implies <strong>click</strong> AND <strong>navigate</strong>, however XR Fragments adds stateless <strong>click</strong> (<tt>xrf://#....</tt>) or <strong>navigate</strong> (<tt>xrf://#pos=...</tt>) as well (which allows many extra interactions which otherwise need a scripting language). This is known as <strong>hashbus</strong>-only events (see image above).</t> <blockquote><t>Being able to use the same URI Fragment DSL for navigation (<tt>href: #foo</tt>) as well as interactions (<tt>href: xrf://#bar</tt>) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.</t> </blockquote><t>This opens up the following benefits for traditional & future webbrowsers:</t> <ul spacing="compact"> <li><eref target="https://github.com/coderofsalvation/hypermediatic">hypermediatic</eref> loading/clicking 3D assets (gltf/fbx e.g.) natively (with or without using HTML).</li> <li>allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the <tt>xrf://</tt> hashbus</li> <li>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> <t>XR Fragments itself are <eref target="https://github.com/coderofsalvation/hypermediatic">hypermediatic</eref> and HTML-agnostic, though pseudo-XR Fragment browsers <strong>can</strong> be implemented on top of HTML/Javascript.</t> <table> <thead> <tr> <th>principle</th> <th>XR 4D 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><t>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' (<tt>xrf://#.....</tt>). This decoupling between navigation and interaction prevents non-standard things like (<tt>href</tt>:<tt>javascript:dosomething()</tt>).</t> </blockquote></section> <section anchor="conventions-and-definitions"><name>Conventions and Definitions</name> <t>See appendix below in case certain terms are not clear.</t> <section anchor="xr-fragment-url-grammar"><name>XR Fragment URL Grammar</name> <t>For typical HTTP-like browsers/applications:</t> <artwork>reserved = gen-delims / sub-delims gen-delims = "#" / "&" sub-delims = "," / "=" </artwork> <blockquote><t>Example: <tt>://foo.com/my3d.gltf#pos=1,0,0&prio=-5&t=0,100</tt></t> </blockquote><table> <thead> <tr> <th>Demo</th> <th>Explanation</th> </tr> </thead> <tbody> <tr> <td><tt>pos=1,2,3</tt></td> <td>vector/coordinate argument e.g.</td> </tr> <tr> <td><tt>pos=1,2,3&rot=0,90,0&foo</tt></td> <td>combinators</td> </tr> </tbody> </table><blockquote><t>this is already implemented in all browsers</t> </blockquote><t>Pseudo (non-native) browser-implementations (supporting XR Fragments using HTML+JS e.g.) can use the <tt>?</tt> search-operator to address outbound content.<br /> In other words, the URL updates to: <tt>https://me.com?https://me.com/other.glb</tt> when navigating to <tt>https://me.com/other.glb</tt> from inside a <tt>https://me.com</tt> WebXR experience e.g.<br /> That way, if the link gets shared, the XR Fragments implementation at <tt>https://me.com</tt> can load the latter (and still indicates which XR Fragments entrypoint-experience/client was used).</t> </section> </section> <section anchor="spatial-referencing-3d"><name>Spatial Referencing 3D</name> <t>XR Fragments assume the following objectname-to-URIFragment mapping:</t> <artwork> 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) │ │ │ │ │ │ │ │ │ │ │ +─────────────────+ │ │ │ │ │ +─────────────────────+ │ │ │ +─────────────────────────+ │ +─────────────────────────────+ </artwork> <blockquote><t>Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).</t> </blockquote><t>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:</t> <ul spacing="compact"> <li>href: <tt>https://scene.fbx</tt></li> <li>src: <tt>https://otherworld.gltf#mainobject</tt></li> </ul> <blockquote><t>It also allows <strong>sourceportation</strong>, which basically means the enduser can teleport to the original XR Document of an <tt>src</tt> embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.</t> </blockquote></section> <section anchor="list-of-uri-fragments"><name>List of URI Fragments</name> <table> <thead> <tr> <th>fragment</th> <th>type</th> <th>example</th> <th>info</th> </tr> </thead> <tbody> <tr> <td><tt>#pos</tt></td> <td>vector3</td> <td><tt>#pos=0.5,0,0</tt></td> <td>positions camera (or XR floor) to xyz-coord 0.5,0,0,</td> </tr> <tr> <td><tt>#rot</tt></td> <td>vector3</td> <td><tt>#rot=0,90,0</tt></td> <td>rotates camera to xyz-coord 0.5,0,0</td> </tr> <tr> <td><eref target="https://www.w3.org/TR/media-frags/">Media Fragments</eref></td> <td><eref target="#media%20fragments%20and%20datatypes">media fragment</eref></td> <td><tt>#t=0,2&loop</tt></td> <td>play (and loop) 3D animation from 0 seconds till 2 seconds</td> </tr> <tr> <td></td> <td></td> <td></td> <td>but can also crop, animate & configure uv-coordinates/shader uniforms</td> </tr> </tbody> </table> <section anchor="list-of-metadata-for-3d-nodes"><name>List of metadata for 3D nodes</name> <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><tt>href</tt></td> <td>string</td> <td><tt>"href": "b.gltf"</tt></td> <td>XR teleport</td> <td>custom property in 3D fileformats</td> </tr> <tr> <td><tt>src</tt></td> <td>string</td> <td><tt>"src": "#cube"</tt></td> <td>XR embed / teleport</td> <td>custom property in 3D fileformats</td> </tr> <tr> <td><tt>tag</tt></td> <td>string</td> <td><tt>"tag": "cubes geo"</tt></td> <td>tag object (for filter-use / XRWG highlighting)</td> <td>custom property in 3D fileformats</td> </tr> <tr> <td><tt>#</tt></td> <td>string</td> <td><tt>"#": "#mypreset</tt></td> <td>trigger default fragment on load</td> <td>custom property in 3D fileformats</td> </tr> </tbody> </table><blockquote><t>Supported popular compatible 3D fileformats: <tt>.gltf</tt>, <tt>.obj</tt>, <tt>.fbx</tt>, <tt>.usdz</tt>, <tt>.json</tt> (THREE.js), <tt>.dae</tt> and so on.</t> </blockquote></section> <section anchor="fragment-to-metadata-mapping"><name>Fragment-to-metadata mapping</name> <t>These are automatic fragment-to-metadata mappings, which only trigger if the 3D scene metadata matches a specific identifier:</t> <table> <thead> <tr> <th></th> <th>fragment</th> <th>type</th> <th>example</th> <th>info</th> </tr> </thead> <tbody> <tr> <td><strong>PRESET</strong></td> <td><tt>#<preset></tt></td> <td>string</td> <td><tt>#cubes</tt></td> <td>evaluates preset (<tt>#foo&bar</tt>) defined in 3D Object metadata (<tt>#cubes: #foo&bar</tt> e.g.) while URL-browserbar reflects <tt>#cubes</tt>. Only works when metadata-key starts with <tt>#</tt></td> </tr> <tr> <td><strong>FOCUS</strong></td> <td><tt>#<tag_or_objectname></tt></td> <td>string</td> <td><tt>#person</tt></td> <td>(and show) object(s) with <tt>tag: person</tt> or name <tt>person</tt> (XRWG lookup)</td> </tr> <tr> <td><strong>FILTERS</strong></td> <td><tt>#[!][-]<tag_or_objectname>[*]</tt></td> <td>string</td> <td><tt>#person</tt> (<tt>#-person</tt>)</td> <td>will reset (<tt>!</tt>), show/focus or hide (<tt>-</tt>) focus object(s) with <tt>tag: person</tt> or name <tt>person</tt> by looking up XRWG (<tt>*</tt>=including children)</td> </tr> <tr> <td><strong>CAMERASWITCH</strong></td> <td><tt>#<cameraname></tt></td> <td>string</td> <td><tt>#cam01</tt></td> <td>sets camera with name <tt>cam01</tt> as active camera</td> </tr> <tr> <td><strong>MATERIALUPDATE</strong></td> <td><tt>#<tag_or_objectname>[*]=<materialname></tt></td> <td>string=string</td> <td><tt>#car=metallic</tt></td> <td>sets material of car to material with name <tt>metallic</tt> (<tt>*</tt>=including children)</td> </tr> <tr> <td></td> <td></td> <td></td> <td><tt>#soldout*=halfopacity</tt></td> <td>set material of objects tagged with <tt>product</tt> to material with name <tt>metallic</tt></td> </tr> <tr> <td><strong>VARIABLE UPDATE</strong></td> <td><tt>#<variable>=<metadata-key></tt></td> <td>string=string</td> <td><tt>#foo=bar</tt></td> <td>sets <eref target="https://www.rfc-editor.org/rfc/rfc6570">URI Template</eref> variable <tt>foo</tt> to the value <tt>#t=0</tt> from <strong>existing</strong> object metadata (<tt>bar</tt>:<tt>#t=0</tt> e.g.), This allows for reactive <eref target="https://www.rfc-editor.org/rfc/rfc6570">URI Template</eref> defined in object metadata elsewhere (<tt>src</tt>:<tt>://m.com/cat.mp4#{foo}</tt> e.g., to play media using <eref target="https://www.w3.org/TR/media-frags/#valid-uri">media fragment URI</eref>). NOTE: metadata-key should not start with <tt>#</tt></td> </tr> <tr> <td><strong>ANIMATION</strong></td> <td><tt>#<tag_or_objectname>=<animationname></tt></td> <td>string=string</td> <td><tt>#people=walk</tt> <tt>#people=noanim</tt></td> <td>assign a different animation to object(s)</td> </tr> </tbody> </table></section> <section anchor="media-fragments-and-datatypes"><name>media fragments and datatypes</name> <blockquote><t>NOTE: below the word 'play' applies to 3D animations embedded in the 3D scene(file) <strong>but also</strong> media defined in <tt>src</tt>-metadata like audio/video-files (mp3/mp4 e.g.)</t> </blockquote><table> <thead> <tr> <th>type</th> <th>syntax</th> <th>example</th> <th>info</th> </tr> </thead> <tbody> <tr> <td>vector2</td> <td>x,y</td> <td>2,3.0</td> <td>2-dimensional vector</td> </tr> <tr> <td>vector3</td> <td>x,y,z</td> <td>2,3.0,4</td> <td>3-dimensional vector</td> </tr> <tr> <td>temporal W3C media fragment</td> <td>t=x</td> <td>0</td> <td>play from 0 seconds to end (and stop)</td> </tr> <tr> <td>temporal W3C media fragment</td> <td>t=x,y</td> <td>0,2</td> <td>play from 0 seconds till 2 seconds (and stop)</td> </tr> <tr> <td>temporal W3C media fragment *</td> <td>s=x</td> <td>1</td> <td>set playback speed of audio/video/3D anim</td> </tr> <tr> <td>temporal W3C media fragment *</td> <td>[-]loop</td> <td>loop</td> <td>enable looped playback of audio/video/3D anim</td> </tr> <tr> <td></td> <td></td> <td>-loop</td> <td>disable looped playback (does not affect playbackstate of media)</td> </tr> <tr> <td>vector2</td> <td>uv=u,v,uspeed,vspeed</td> <td>0,0</td> <td>set uv offset instantly (default speed = <tt>1,1</tt>)</td> </tr> <tr> <td></td> <td></td> <td>+0.5,+0.5</td> <td>scroll instantly by adding 0.5 to the current uv coordinates</td> </tr> <tr> <td></td> <td></td> <td>0.2,1,0.1,0.1</td> <td>scroll (lerp) to uv coordinate <tt>0,2,1</tt> with <tt>0.1</tt> units per second</td> </tr> <tr> <td></td> <td></td> <td>0,0,0,+0.1</td> <td>scroll v coordinates with <tt>0.1</tt> units per second (infinitely)</td> </tr> <tr> <td></td> <td></td> <td>+0.5,+0.5</td> <td>scroll instantly by adding 0.5 to the current uv coordinates</td> </tr> <tr> <td>media parameter (shader uniform)</td> <td>u:<uniform>=<string</td> <td>float</td> <td>vec2</td> </tr> </tbody> </table><blockquote><t>* = this is extending the <eref target="https://www.w3.org/TR/media-frags/#mf-advanced">W3C media fragments</eref> with (missing) playback/viewport-control. Normally <tt>#t=0,2</tt> implies setting start/stop-values AND starting playback, whereas <tt>#s=0&loop</tt> allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping.</t> <t>The rationale for <tt>uv</tt> is that the <tt>xywh</tt> Media Fragment deals with rectangular media, which does not translate well to 3D models (which use triangular polygons, not rectangular) positioned by uv-coordinates. This also explains the absense of a <tt>scale</tt> or <tt>rotate</tt> primitive, which is challenged by this, as well as multiple origins (mesh- or texture).</t> </blockquote><t>Example URI's:</t> <ul spacing="compact"> <li><tt>https://images.org/credits.jpg#uv=0,0,0,+0.1</tt> (infinite vertical texturescrolling)</li> <li><tt>https://video.org/organogram.mp4#t=0&loop&uv=0.1,0.1,0.3,0.3</tt> (animated tween towards region in looped video)</li> <li><tt>https://shaders.org/plasma.glsl#t=0&u:col2=0,1,0</tt> (red-green shader plasma starts playing from time-offset 0)</li> </ul> <artwork> +──────────────────────────────────────────────────────────+ │ │ │ index.gltf#playall │ │ │ │ │ ├ # : #t=0&shared=play │ apply default XR Fragment on load (`t` plays global 3D animation timeline) │ ├ play : #t=0&loop │ variable for [URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) │ │ │ │ ├── ◻ plane (with material) │ │ │ └ #: #uv=0,0,0,+0.1 │ infinite texturescroll `v` of uv·coordinates with 0.1/fps │ │ │ │ ├── ◻ plane │ │ │ └ src: foo.jpg#uv=0,0,0,+0.1 │ infinite texturescroll `v` of uv·coordinates with 0.1/fps │ │ │ │ ├── ◻ media │ │ │ └ src: cat.mp4#t=l:2,10&uv=0.5,0.5 │ loop cat.mp4 (or mp3/wav/jpg) between 2 and 10 seconds (uv's shifted with 0.5,0.5) │ │ │ │ └── ◻ wall │ │ ├ href: #color=blue │ updates uniform values (IFS shader e.g.) │ ├ blue: t=0&u:col=0,0,1 │ variable for [Level1 URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) │ └ src: ://a.com/art.glsl#{color}&{shared} │ .fs/.vs/.glsl/.wgsl etc shader [Level1 URI Template (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) │ │ │ │ +──────────────────────────────────────────────────────────+ > NOTE: URI Template variables are immutable and respect scope: in other words, the end-user cannot modify `blue` by entering an URL like `#blue=.....` in the browser URL, and `blue` is not accessible by the plane/media-object (however `{play}` would work). </artwork> </section> </section> <section anchor="navigating-3d"><name>Navigating 3D</name> <table> <thead> <tr> <th>fragment</th> <th>type</th> <th>functionality</th> </tr> </thead> <tbody> <tr> <td><b>#pos</b>=0,0,0</td> <td>vector3 or string</td> <td>(re)position camera based on coordinates directly, or indirectly using objectname (its worldposition)</td> </tr> <tr> <td><b>#rot</b>=0,90,0</td> <td>vector3</td> <td>rotate camera</td> </tr> </tbody> </table><t><eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js">» example implementation</eref><br /> <eref target="https://github.com/coderofsalvation/xrfragment/issues/5">» discussion</eref><br /> </t> <ol spacing="compact"> <li>the Y-coordinate of <tt>pos</tt> identifies the floorposition. This means that desktop-projections usually need to add 1.5m (average person height) on top (which is done automatically by VR/AR headsets).</li> <li>set the position of the camera accordingly to the vector3 values of <tt>#pos</tt></li> <li><tt>rot</tt> sets the rotation of the camera (only for non-VR/AR headsets)</li> <li>mediafragment <tt>t</tt> in the top-URL sets the playbackspeed and animation-range of the global scene animation</li> <li>before scene load: the scene is cleared</li> <li>after scene load: in case the scene (rootnode) contains an <tt>#</tt> default view with a fragment value: execute non-positional fragments via the hashbus (no top-level URL change)</li> <li>after scene load: in case the scene (rootnode) contains an <tt>#</tt> default view with a fragment value: execute positional fragment via the hashbus + update top-level URL</li> <li>in case of no default <tt>#</tt> view on the scene (rootnode), default player(rig) position <tt>0,0,0</tt> is assumed.</li> <li>in case a <tt>href</tt> does not mention any <tt>pos</tt>-coordinate, the current position will be assumed</li> </ol> <t>Here's an ascii representation of a 3D scene-graph which contains 3D objects <tt>◻</tt> and their metadata:</t> <artwork> +────────────────────────────────────────────────────────+ │ │ │ index.gltf │ │ │ │ │ ├── ◻ buttonA │ │ │ └ href: #pos=1,0,1&t=100,200 │ │ │ │ │ └── ◻ buttonB │ │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc) │ │ +────────────────────────────────────────────────────────+ </artwork> <t>An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the <tt>buttonA</tt> and <tt>buttonB</tt>.<br /> In case of <tt>buttonA</tt> the end-user will be teleported to another location and time in the <strong>current loaded scene</strong>, but <tt>buttonB</tt> will <strong>replace the current scene</strong> with a new one, like <tt>other.fbx</tt>, and assume <tt>pos=0,0,0</tt>.</t> </section> <section anchor="top-level-url-processing"><name>Top-level URL processing</name> <blockquote><t>Example URL: <tt>://foo/world.gltf#cube&pos=0,0,0</tt></t> </blockquote><t>The URL-processing-flow for hypermedia browsers goes like this:</t> <ol spacing="compact"> <li>IF a <tt>#cube</tt> matches a custom property-key (of an object) in the 3D file/scene (<tt>#cube</tt>: <tt>#......</tt>) <b>THEN</b> execute that predefined_view.</li> <li>IF scene operators (<tt>pos</tt>) and/or animation operator (<tt>t</tt>) are present in the URL then (re)position the camera and/or animation-range accordingly.</li> <li>IF no camera-position has been set in <b>step 1 or 2</b> update the top-level URL with <tt>#pos=0,0,0</tt> (<eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/navigator.js#L31]]">example</eref>)</li> <li>IF a <tt>#cube</tt> matches the name (of an object) in the 3D file/scene then draw a line from the enduser('s heart) to that object (to highlight it).</li> <li>IF a <tt>#cube</tt> matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects).</li> </ol> </section> <section anchor="embedding-xr-content-using-src"><name>Embedding XR content using src</name> <t><tt>src</tt> is the 3D version of the <a target="_blank" href="https://www.w3.org/html/wiki/Elements/iframe">iframe</a>.<br /> It instances content (in objects) in the current scene/asset, and follows similar logic like the previous chapter, except that it does not modify the camera.</t> <table> <thead> <tr> <th>fragment</th> <th>type</th> <th>example value</th> </tr> </thead> <tbody> <tr> <td><tt>src</tt></td> <td>string (uri, hashtag/filter)</td> <td><tt>#cube</tt><br /> <tt>#sometag</tt><br /> #cube&-ball_inside_cube<tt><br></tt>#-sky&-rain<tt><br></tt>#-language&english<tt><br></tt>#price=>5<tt><br></tt><eref target="https://linux.org/penguin.png`">https://linux.org/penguin.png`</eref><br /> <tt>https://linux.world/distrowatch.gltf#t=1,100</tt><br /> <tt>linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply</tt><br /> <tt>androidapp://page1?tutorial#pos=0,0,1&t1,100</tt><br /> <tt>foo.mp3#0,0,0</tt></td> </tr> </tbody> </table><t>Here's an ascii representation of a 3D scene-graph with 3D objects <tt>◻</tt> which embeds remote & local 3D objects <tt>◻</tt> with/out using filters:</t> <artwork> +────────────────────────────────────────────────────────+ +─────────────────────────+ │ │ │ │ │ index.gltf │ │ ocean.com/aquarium.fbx │ │ │ │ │ ├ room │ │ ├── ◻ canvas │ │ └── ◻ fishbowl │ │ │ └ src: painting.png │ │ ├─ ◻ bass │ │ │ │ │ └─ ◻ tuna │ │ ├── ◻ aquariumcube │ │ │ │ │ └ src: ://rescue.com/fish.gltf#fishbowl │ +─────────────────────────+ │ │ │ │ ├── ◻ bedroom │ │ │ └ src: #canvas │ │ │ │ │ └── ◻ livingroom │ │ └ src: #canvas │ │ │ +────────────────────────────────────────────────────────+ </artwork> <t>An XR Fragment-compatible browser viewing this scene, lazy-loads and projects <tt>painting.png</tt> onto the (plane) object called <tt>canvas</tt> (which is copy-instanced in the bed and livingroom).<br /> Also, after lazy-loading <tt>ocean.com/aquarium.gltf</tt>, only the queried objects <tt>fishbowl</tt> (and <tt>bass</tt> and <tt>tuna</tt>) will be instanced inside <tt>aquariumcube</tt>.<br /> Resizing will be happen accordingly to its placeholder object <tt>aquariumcube</tt>, see chapter Scaling.<br /> </t> <blockquote><t>Instead of cherrypicking a rootobject <tt>#fishbowl</tt> with <tt>src</tt>, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.</t> </blockquote><t><strong>Specification</strong>:</t> <ol spacing="compact"> <li>local/remote content is instanced by the <tt>src</tt> (filter) value (and attaches it to the placeholder mesh containing the <tt>src</tt> property)</li> <li>by default all objects are loaded into the instanced src (scene) object (but not shown yet)</li> <li><b>local</b> <tt>src</tt> values (<tt>#...</tt> e.g.) starting with a non-negating filter (<tt>#cube</tt> e.g.) will (deep)reparent that object (with name <tt>cube</tt>) as the new root of the scene at position 0,0,0</li> <li><b>local</b> <tt>src</tt> values should respect (negative) filters (<tt>#-foo&price=>3</tt>)</li> <li>the instanced scene (from a <tt>src</tt> value) should be <b>scaled accordingly</b> to its placeholder object or <b>scaled relatively</b> based on the scale-property (of a geometry-less placeholder, an 'empty'-object in blender e.g.). For more info see Chapter Scaling.</li> <li><b>external</b> <tt>src</tt> values should be served with appropriate mimetype (so the XR Fragment-compatible browser will now how to render it). The bare minimum supported mimetypes are:</li> <li><tt>src</tt> values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see <eref target="#links">broken links</eref>)</li> <li><b>external</b> <tt>src</tt> values should respect the fallback link mechanism (see <eref target="#broken-links">broken links</eref></li> <li>when the placeholder object is a 2D plane, but the mimetype is 3D, then render the spatial content on that plane via a stencil buffer.</li> <li>src-values are non-recursive: when linking to an external object (<tt>src: foo.fbx#bar</tt>), then <tt>src</tt>-metadata on object <tt>bar</tt> should be ignored.</li> <li>an external <tt>src</tt>-value should always allow a sourceportation icon within 3 meter: teleporting to the origin URI to which the object belongs.</li> <li>when only one object was cherrypicked (<tt>#cube</tt> e.g.), set its position to <tt>0,0,0</tt></li> <li>when the enduser clicks an href with <tt>#t=1,0,0</tt> (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.)</li> <li>a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial <tt>src</tt>-values (an object <tt>#world3</tt> or URL <tt>world3.fbx</tt> e.g.).</li> </ol> <ul spacing="compact"> <li><tt>model/gltf-binary</tt></li> <li><tt>model/gltf+json</tt></li> <li><tt>image/png</tt></li> <li><tt>image/jpg</tt></li> <li><tt>text/plain;charset=utf-8</tt></li> </ul> <t><eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js">» example implementation</eref><br /> <eref target="https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/src.gltf#L192">» example 3D asset</eref><br /> <eref target="https://github.com/coderofsalvation/xrfragment/issues/4">» discussion</eref><br /> </t> </section> <section anchor="navigating-content-href-portals"><name>Navigating content href portals</name> <t>navigation, portals & mutations</t> <table> <thead> <tr> <th>fragment</th> <th>type</th> <th>example value</th> </tr> </thead> <tbody> <tr> <td><tt>href</tt></td> <td>string (uri or predefined view)</td> <td><tt>#pos=1,1,0</tt><br /> <tt>#pos=1,1,0&rot=90,0,0</tt><br /> <tt>://somefile.gltf#pos=1,1,0</tt><br /> </td> </tr> </tbody> </table> <ol> <li><t>clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes <tt>pos=0,0,0&rot=0,0,0</tt> by default (unless specified)</t> </li> <li><t>relocation/reorientation should happen locally for local URI's (<tt>#pos=....</tt>)</t> </li> <li><t>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.)</t> </li> <li><t>URL navigation should always be reflected in the client URL-bar (in case of javascript: see [<eref target="https://github.com/coderofsalvation/xrfragment/blob/dev/src/3rd/js/three/navigator.js">here</eref> for an example navigator), and only update the URL-bar after the scene (default fragment <tt>#</tt>) has been loaded.</t> </li> <li><t>In immersive XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [<eref target="https://github.com/coderofsalvation/xrfragment/blob/dev/example/aframe/sandbox/index.html#L26-L29">here</eref> for an example wearable)</t> </li> <li><t>make sure that the ''back-button'' of the ''browser-history'' always refers to the previous position (see [<eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js#L97">here</eref>)</t> </li> <li><t>ignore previous rule in special cases, like clicking an <tt>href</tt> using camera-portal collision (the back-button could cause a teleport-loop if the previous position is too close)</t> </li> <li><t>href-events should bubble upward the node-tree (from children to ancestors, so that ancestors can also contain an href), however only 1 href can be executed at the same time.</t> </li> <li><t>the end-user navigator back/forward buttons should repeat a back/forward action until a <tt>pos=...</tt> primitive is found (the stateless xrf:// href-values should not be pushed to the url-history)</t> </li> </ol> <t><eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js">» example implementation</eref><br /> <eref target="https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/href.gltf#L192">» example 3D asset</eref><br /> <eref target="https://github.com/coderofsalvation/xrfragment/issues/1">» discussion</eref><br /> </t> <section anchor="walking-surfaces"><name>Walking surfaces</name> <t>XR Fragment-compatible viewers can infer this data based scanning the scene for:</t> <ol spacing="compact"> <li>materialless (nameless & textureless) mesh-objects (without <tt>src</tt> and <tt>href</tt>)</li> </ol> <blockquote><t>optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.</t> </blockquote></section> <section anchor="ux-spec"><name>UX spec</name> <t>End-users should always have read/write access to:</t> <ol spacing="compact"> <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 <tt>href</tt> navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).</li> </ol> </section> <section anchor="scaling-instanced-content"><name>Scaling instanced content</name> <t>Sometimes embedded properties (like <tt>src</tt>) instance new objects.<br /> But what about their scale?<br /> How does the scale of the object (with the embedded properties) impact the scale of the referenced content?<br /> </t> <blockquote><t>Rule of thumb: visible placeholder objects act as a '3D canvas' for the referenced scene (a plane acts like a 2D canvas for images e, a cube as a 3D canvas e.g.).</t> </blockquote> <ol spacing="compact"> <li><b>IF</b> an embedded property (<tt>src</tt> e.g.) is set on an non-empty placeholder object (geometry of >2 vertices):</li> </ol> <ul spacing="compact"> <li>calculate the <b>bounding box</b> of the ''placeholder'' object (maxsize=1.4 e.g.)</li> <li>hide the ''placeholder'' object (material e.g.)</li> <li>instance the <tt>src</tt> scene as a child of the existing object</li> <li>calculate the <b>bounding box</b> of the instanced scene, and scale it accordingly (to 1.4 e.g.)</li> </ul> <blockquote><t>REASON: non-empty placeholder object can act as a protective bounding-box (for remote content of which might grow over time e.g.)</t> </blockquote> <ol spacing="compact" start="2"> <li>ELSE multiply the scale-vector of the instanced scene with the scale-vector (a common property of a 3D node) of the <b>placeholder</b> object.</li> </ol> <blockquote><t>TODO: needs intermediate visuals to make things more obvious</t> </blockquote></section> </section> <section anchor="xr-fragment-pos"><name>XR Fragment: pos</name> <t>[[» example implementation|<eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]">https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]</eref>]<br /> </t> </section> <section anchor="xr-fragment-rot"><name>XR Fragment: rot</name> <t>[[» example implementation|<eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]">https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]</eref>]<br /> </t> </section> <section anchor="xr-fragment-t"><name>XR Fragment: t</name> <t>[[» example implementation|<eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]">https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]</eref>]<br /> </t> </section> <section anchor="xr-audio-video-integration"><name>XR audio/video integration</name> <t>To play global audio/video items:</t> <ol spacing="compact"> <li>add a <tt>src: foo.mp3</tt> or <tt>src: bar.mp4</tt> metadata to a 3D object (<tt>cube</tt> e.g.)</li> <li>to enable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (<tt>src: bar.mp3#t=0&loop</tt> e.g.)</li> <li>to play it, add <tt>href: #cube</tt> somewhere else</li> <li>to enable enduser-triggered play, use a [[URI Template]] XR Fragment: (<tt>src: bar.mp3#{player}</tt> and <tt>play: t=0&loop</tt> and <tt>href: xrf://#player=play</tt> e.g.)</li> <li>when the enduser clicks the <tt>href</tt>, <tt>#t=0&loop</tt> (play) will be applied to the <tt>src</tt> value</li> </ol> <blockquote><t>NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].</t> </blockquote></section> <section anchor="xr-fragment-filters"><name>XR Fragment filters</name> <t>Include, exclude, hide/shows objects using space-separated strings:</t> <table> <thead> <tr> <th>example</th> <th>outcome</th> </tr> </thead> <tbody> <tr> <td><tt>#-sky</tt></td> <td>show everything except object named <tt>sky</tt></td> </tr> <tr> <td><tt>#-language&english</tt></td> <td>hide everything with tag <tt>language</tt>, but show all tag <tt>english</tt> objects</td> </tr> <tr> <td><tt>#-price&price=>10</tt></td> <td>hide all objects with property <tt>price</tt>, then only show object with price above 10</td> </tr> <tr> <td><tt>#-house*</tt></td> <td>hide <tt>house</tt> object and everything inside (=<tt>*</tt>)</td> </tr> </tbody> </table><t>It's simple but powerful syntax which allows filtering the scene using searchengine prompt-style feeling:</t> <ol spacing="compact"> <li>filters are a way to traverse a scene, and filter objects based on their name, tag- or property-values.</li> </ol> <ul spacing="compact"> <li>see <eref target="https://coderofsalvation.github.io/xrfragment.media/queries.mp4">an (outdated) example video here</eref> which used a dedicated <tt>q=</tt> variable (now deprecated and usable directly)</li> </ul> <section anchor="including-excluding"><name>including/excluding</name> <t>By default, selectors work like photoshop-layers: they scan for matching layer(name/properties) within the scene-graph. Each matched object (not their children) will be toggled (in)visible when selecting.</t> <table> <thead> <tr> <th>operator</th> <th>info</th> </tr> </thead> <tbody> <tr> <td><tt>-</tt></td> <td>hides object(s) (<tt>#-myobject&-objects</tt> e.g.</td> </tr> <tr> <td><tt>=</tt></td> <td>indicates an object-embedded custom property key/value (<tt>#price=4&category=foo</tt> e.g.)</td> </tr> <tr> <td><tt>=></tt> <tt>=<</tt></td> <td>compare float or int number (<tt>#price=>4</tt> e.g.)</td> </tr> <tr> <td><tt>*</tt></td> <td>deepselect: automatically select children of selected object, including local (nonremote) embedded objects (starting with <tt>#</tt>)</td> </tr> </tbody> </table><blockquote><t>NOTE 1: after an external embedded object has been instanced (<tt>src: https://y.com/bar.fbx#room</tt> e.g.), filters do not affect them anymore (reason: local tag/name collisions can be mitigated easily, but not in case of remote content).</t> <t>NOTE 2: depending on the used 3D framework, toggling objects (in)visible should happen by enabling/disableing writing to the colorbuffer (to allow children being still visible while their parents are invisible).</t> </blockquote><t><eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/q.js">» example implementation</eref> <eref target="https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/filter.gltf#L192">» example 3D asset</eref> <eref target="https://github.com/coderofsalvation/xrfragment/issues/3">» discussion</eref></t> </section> <section anchor="filter-parser"><name>Filter Parser</name> <t>Here's how to write a filter parser:</t> <ol spacing="compact"> <li>create an associative array/object to store filter-arguments as objects</li> <li>detect object id's & properties <tt>foo=1</tt> and <tt>foo</tt> (reference regex= <tt>~/^.*=[><=]?/</tt> )</li> <li>detect excluders like <tt>-foo</tt>,<tt>-foo=1</tt>,<tt>-.foo</tt>,<tt>-/foo</tt> (reference regex= <tt>/^-/</tt> )</li> <li>detect root selectors like <tt>/foo</tt> (reference regex= <tt>/^[-]?\//</tt> )</li> <li>detect number values like <tt>foo=1</tt> (reference regex= <tt>/^[0-9\.]+$/</tt> )</li> <li>detect operators so you can easily strip keys (reference regex= <tt>/(^-|\*$)/</tt> )</li> <li>detect exclude keys like <tt>-foo</tt> (reference regex= <tt>/^-/</tt> )</li> <li>for every filter token split string on <tt>=</tt></li> <li>and we set <tt>root</tt> to <tt>true</tt> or <tt>false</tt> (true=<tt>/</tt> root selector is present)</li> <li>therefore we we set <tt>show</tt> to <tt>true</tt> or <tt>false</tt> (false=excluder <tt>-</tt>)</li> </ol> <blockquote><t>An example filter-parser (which compiles to many languages) can be <eref target="https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Filter.hx">found here</eref></t> </blockquote></section> </section> <section anchor="visible-links"><name>Visible links</name> <t>When predefined views, XRWG fragments and ID fragments (<tt>#cube</tt> or <tt>#mytag</tt> e.g.) are triggered by the enduser (via toplevel URL or clicking <tt>href</tt>):</t> <ol spacing="compact"> <li>draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname)</li> <li>draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that <tt>tag</tt> value</li> <li>draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) containing that in their <tt>src</tt> or <tt>href</tt> value</li> </ol> <t>The obvious approach for this, is to consult the XRWG (<eref target="https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js">example</eref>), which basically has all these things already collected/organized for you during scene-load.</t> <t><strong>UX</strong></t> <ol spacing="compact" start="4"> <li>do not update the wires when the enduser moves, leave them as is</li> <li>offer a control near the back/forward button which allows the user to (turn off) control the correlation-intensity of the XRWG</li> </ol> </section> <section anchor="text-in-xr-tagging-linking-to-spatial-objects"><name>Text in XR (tagging,linking to spatial objects)</name> <t>How does XR Fragments interlink text with objects?</t> <blockquote><t>The XR Fragments does this by collapsing space into a <strong>Word Graph</strong> (the <strong>XRWG</strong> <eref target="https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js">example</eref>), augmented by Bib(s)Tex.</t> </blockquote><t>Instead of just throwing together all kinds media types into one experience (games), what about their tagged/semantical relationships?<br /> Perhaps the following question is related: why is HTML adopted less in games outside the browser?</t> <t>Hence:</t> <ol spacing="compact"> <li>XR Fragments promotes (de)serializing a scene to a (lowercase) XRWG (<eref target="https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js">example</eref>)</li> <li>XR Fragments primes the XRWG, by collecting words from the <tt>tag</tt> and name-property of 3D objects.</li> <li>XR Fragments primes the XRWG, by collecting words from <strong>optional</strong> metadata <strong>at the end of content</strong> of text (see default mimetype & Data URI)</li> <li>The XRWG should be recalculated when textvalues (in <tt>src</tt>) change</li> <li>HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they fit better in the application-layer, or as embedded src content)</li> <li>Applications don't have to be able to access the XRWG programmatically, as they can easily generate one themselves by traversing the scene-nodes.</li> <li>The XR Fragment focuses on fast and easy-to-generate end-user controllable word graphs (instead of complex implementations that try to defeat word ambiguity)</li> <li>Tags are the scope for now (supporting <eref target="https://github.com/WICG/scroll-to-text-fragment">https://github.com/WICG/scroll-to-text-fragment</eref> will be considered)</li> </ol> <t>Example of generating BiBTex out of the XRWG and textdata with hashtags:</t> <artwork> http://y.io/z.fbx | Derived XRWG (expressed as BibTex) ----------------------------------------------------------------------------+-------------------------------------- | @house{castle, +-[src: data:.....]----------------------+ +-[3D mesh]-+ | url = {https://y.io/z.fbx#castle} | Chapter one | | / \ | | } | | | / \ | | @baroque{castle, | John built houses in baroque style. | | / \ | | url = {https://y.io/z.fbx#castle} | | | |_____| | | } | | +-----│-----+ | @baroque{john} | | │ | | | ├─ name: castle | | | └─ tag: house baroque | +----------------------------------------+ | [3D mesh ] | | O ├─ name: john | | /|\ | | | / \ | | +--------+ | </artwork> <blockquote><t>the <tt>#john@baroque</tt>-bib associates both text <tt>John</tt> and objectname <tt>john</tt>, with tag <tt>baroque</tt></t> </blockquote><t>Another example of deriving a graphdata from the XRWG:</t> <artwork> http://y.io/z.fbx | Derived XRWG (expressed as BibTex) ----------------------------------------------------------------------------+-------------------------------------- | +-[src: data:.....]----------------------+ +-[3D mesh]-+ | @house{castle, | Chapter one | | / \ | | url = {https://y.io/z.fbx#castle} | | | / \ | | } | John built houses in baroque style. | | / \ | | @baroque{castle, | | | |_____| | | url = {https://y.io/z.fbx#castle} | #john@baroque | +-----│-----+ | } | @baroque{john} | │ | @baroque{john} | | ├─ name: castle | | | └─ tag: house baroque | +----------------------------------------+ | @house{baroque} [3D mesh ] | @todo{baroque} +-[remotestorage.io / localstorage]------+ | O + name: john | | #baroque@todo@house | | /|\ | | | ... | | / \ | | +----------------------------------------+ +--------+ | </artwork> <blockquote><t>both <tt>#john@baroque</tt>-bib and BibTex <tt>@baroque{john}</tt> result in the same XRWG, however on top of that 2 tages (<tt>house</tt> and <tt>todo</tt>) are now associated with text/objectname/tag 'baroque'.</t> </blockquote><t>As seen above, the XRWG can expand <eref target="https://github.com/coderofsalvation/hashtagbibs">bibs</eref> (and the whole scene) to BibTeX.<br /> This allows hasslefree authoring and copy-paste of associations <strong>for and by humans</strong>, but also makes these URLs possible:</t> <table> <thead> <tr> <th>URL example</th> <th>Result</th> </tr> </thead> <tbody> <tr> <td><tt>https://my.com/foo.gltf#baroque</tt></td> <td>draws lines between mesh <tt>john</tt>, 3D mesh <tt>castle</tt>, text <tt>John built(..)</tt></td> </tr> <tr> <td><tt>https://my.com/foo.gltf#john</tt></td> <td>draws lines between mesh <tt>john</tt>, and the text <tt>John built (..)</tt></td> </tr> <tr> <td><tt>https://my.com/foo.gltf#house</tt></td> <td>draws lines between mesh <tt>castle</tt>, and other objects with tag <tt>house</tt> or <tt>todo</tt></td> </tr> </tbody> </table><blockquote><t><eref target="https://github.com/coderofsalvation/hashtagbibs">hashtagbibs</eref> potentially allow the enduser to annotate text/objects by <strong>speaking/typing/scanning associations</strong>, which the XR Browser saves to remotestorage (or localStorage per toplevel URL). As well as, referencing BibTags per URI later on: <tt>https://y.io/z.fbx#@baroque@todo</tt> e.g.</t> </blockquote><t>The XRWG allows XR Browsers to show/hide relationships in realtime at various levels:</t> <ul spacing="compact"> <li>wordmatch <strong>inside</strong> <tt>src</tt> text</li> <li>wordmatch <strong>inside</strong> <tt>href</tt> text</li> <li>wordmatch object-names</li> <li>wordmatch object-tagnames</li> </ul> <t>Spatial wires can be rendered between words/objects etc.<br /> Some pointers for good UX (but not necessary to be XR Fragment compatible):</t> <ol spacing="compact" start="9"> <li>The XR Browser needs to adjust tag-scope based on the endusers needs/focus (infinite tagging only makes sense when environment is scaled down significantly)</li> <li>The XR Browser should always allow the human to view/edit the metadata, by clicking 'toggle metadata' on the 'back' (contextmenu e.g.) of any XR text, anywhere anytime.</li> <li>respect multi-line BiBTeX metadata in text because of <eref target="#core-principle">the core principle</eref></li> <li>Default font (unless specified otherwise) is a modern monospace font, for maximized tabular expressiveness (see <eref target="#core-principle">the core principle</eref>).</li> <li>anti-pattern: hardcoupling an XR Browser with a mandatory <strong>markup/scripting-language</strong> which departs from onubtrusive plain text (HTML/VRML/Javascript) (see <eref target="#core-principle">the core principle</eref>)</li> <li>anti-pattern: limiting human introspection, by abandoning plain text as first tag citizen.</li> </ol> <blockquote><t>The simplicity of appending metadata (and leveling the metadata-playfield between humans and machines) is also demonstrated by <eref target="https://visual-meta.info">visual-meta</eref> in greater detail.</t> </blockquote><t>Fictional chat:</t> <artwork><John> Hey what about this: https://my.com/station.gltf#pos=0,0,1&rot=90,2,0&t=500,1000 <Sarah> I'm checking it right now <Sarah> I don't see everything..where's our text from yesterday? <John> Ah wait, that's tagged with tag 'draft' (and hidden)..hold on, try this: <John> https://my.com/station.gltf#.draft&pos=0,0,1&rot=90,2,0&t=500,1000 <Sarah> how about we link the draft to the upcoming YELLO-event? <John> ok I'm adding #draft@YELLO <Sarah> Yesterday I also came up with other usefull assocations between other texts in the scene: #event#YELLO #2025@YELLO <John> thanks, added. <Sarah> Btw. I stumbled upon this spatial book which references station.gltf in some chapters: <Sarah> https://thecommunity.org/forum/foo/mytrainstory.txt <John> interesting, I'm importing mytrainstory.txt into station.gltf <John> ah yes, chapter three points to trainterminal_2A in the scene, cool </artwork> <section anchor="default-data-uri-mimetype"><name>Default Data URI mimetype</name> <t>The <tt>src</tt>-values work as expected (respecting mime-types), however:</t> <t>The XR Fragment specification advices to bump the traditional default browser-mimetype</t> <t><tt>text/plain;charset=US-ASCII</tt></t> <t>to a hashtagbib(tex)-friendly one:</t> <t><tt>text/plain;charset=utf-8;bib=^@</tt></t> <t>This indicates that:</t> <ul spacing="compact"> <li>utf-8 is supported by default</li> <li>lines beginning with <tt>@</tt> will not be rendered verbatim by default (<eref target="https://github.com/coderofsalvation/hashtagbibs#hashtagbib-mimetypes">read more</eref>)</li> <li>the XRWG should expand bibs to BibTex occurring in text (<tt>#contactjohn@todo@important</tt> e.g.)</li> </ul> <t>By doing so, the XR Browser (applications-layer) can interpret microformats (<eref target="https://visual-meta.info">visual-meta</eref> to connect text further with its environment ( setup links between textual/spatial objects automatically e.g.).</t> <blockquote><t>for more info on this mimetype see <eref target="https://github.com/coderofsalvation/hashtagbibs">bibs</eref></t> </blockquote><t>Advantages:</t> <ul spacing="compact"> <li>auto-expanding of <eref target="https://github.com/coderofsalvation/hashtagbibs">hashtagbibs</eref> associations</li> <li>out-of-the-box (de)multiplex human text and metadata in one go (see <eref target="#core-principle">the core principle</eref>)</li> <li>no network-overhead for metadata (see <eref target="#core-principle">the core principle</eref>)</li> <li>ensuring high FPS: HTML/RDF historically is too 'requesty'/'parsy' for game studios</li> <li>rich send/receive/copy-paste everywhere by default, metadata being retained (see <eref target="#core-principle">the core principle</eref>)</li> <li>netto result: less webservices, therefore less servers, and overall better FPS in XR</li> </ul> <blockquote><t>This significantly expands expressiveness and portability of human tagged text, by <strong>postponing machine-concerns to the end of the human text</strong> in contrast to literal interweaving of content and markupsymbols (or extra network requests, webservices e.g.).</t> </blockquote><t>For all other purposes, regular mimetypes can be used (but are not required by the spec).<br /> </t> </section> <section anchor="url-and-data-uri"><name>URL and Data URI</name> <artwork> +--------------------------------------------------------------+ +------------------------+ | | | author.com/article.txt | | index.gltf | +------------------------+ | │ | | | | ├── ◻ article_canvas | | Hello friends. | | │ └ src: ://author.com/article.txt | | | | │ | | @book{greatgatsby | | └── ◻ note_canvas | | ... | | └ src:`data:welcome human\n@book{sunday...}` | | } | | | +------------------------+ | | +--------------------------------------------------------------+ </artwork> <t>The enduser will only see <tt>welcome human</tt> and <tt>Hello friends</tt> rendered verbatim (see mimetype). The beauty is that text in Data URI automatically promotes rich copy-paste (retaining metadata). In both cases, the text gets rendered immediately (onto a plane geometry, hence the name '_canvas'). The XR Fragment-compatible browser can let the enduser access visual-meta(data)-fields after interacting with the object (contextmenu e.g.).</t> <blockquote><t>additional tagging using <eref target="https://github.com/coderofsalvation/hashtagbibs">bibs</eref>: to tag spatial object <tt>note_canvas</tt> with 'todo', the enduser can type or speak <tt>#note_canvas@todo</tt></t> </blockquote></section> <section anchor="xr-text-example-parser"><name>XR Text example parser</name> <t>To prime the XRWG with text from plain text <tt>src</tt>-values, here's an example XR Text (de)multiplexer in javascript (which supports inline bibs & bibtex):</t> <artwork>xrtext = { expandBibs: (text) => { let bibs = { regex: /(#[a-zA-Z0-9_+@\-]+(#)?)/g, tags: {}} text.replace( bibs.regex , (m,k,v) => { tok = m.substr(1).split("@") match = tok.shift() if( tok.length ) tok.map( (t) => bibs.tags[t] = `@${t}{${match},\n}` ) else if( match.substr(-1) == '#' ) bibs.tags[match] = `@{${match.replace(/#/,'')}}` else bibs.tags[match] = `@${match}{${match},\n}` }) return text.replace( bibs.regex, '') + Object.values(bibs.tags).join('\n') }, decode: (str) => { // bibtex: ↓@ ↓<tag|tag{phrase,|{ruler}> ↓property ↓end let pat = [ /@/, /^\S+[,{}]/, /},/, /}/ ] let tags = [], text='', i=0, prop='' let lines = xrtext.expandBibs(str).replace(/\r?\n/g,'\n').split(/\n/) for( let i = 0; i < lines.length && !String(lines[i]).match( /^@/ ); i++ ) text += lines[i]+'\n' bibtex = lines.join('\n').substr( text.length ) bibtex.split( pat[0] ).map( (t) => { try{ let v = {} if( !(t = t.trim()) ) return if( tag = t.match( pat[1] ) ) tag = tag[0] if( tag.match( /^{.*}$/ ) ) return tags.push({ruler:tag}) if( tag.match( /}$/ ) ) return tags.push({k: tag.replace(/}$/,''), v: {}}) t = t.substr( tag.length ) t.split( pat[2] ) .map( kv => { if( !(kv = kv.trim()) || kv == "}" ) return v[ kv.match(/\s?(\S+)\s?=/)[1] ] = kv.substr( kv.indexOf("{")+1 ) }) tags.push( { k:tag, v } ) }catch(e){ console.error(e) } }) return {text, tags} }, encode: (text,tags) => { let str = text+"\n" for( let i in tags ){ let item = tags[i] if( item.ruler ){ str += `@${item.ruler}\n` continue; } str += `@${item.k}\n` for( let j in item.v ) str += ` ${j} = {${item.v[j]}}\n` str += `}\n` } return str } } </artwork> <t>The above functions (de)multiplexe text/metadata, expands bibs, (de)serialize bibtex and vice versa</t> <blockquote><t>above can be used as a startingpoint for LLVM's to translate/steelman to a more formal form/language.</t> </blockquote> <artwork>str = ` hello world here are some hashtagbibs followed by bibtex: #world #hello@greeting #another-section# @{some-section} @flap{ asdf = {23423} }` var {tags,text} = xrtext.decode(str) // demultiplex text & bibtex tags.find( (t) => t.k == 'flap{' ).v.asdf = 1 // edit tag tags.push({ k:'bar{', v:{abc:123} }) // add tag console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back together </artwork> <t>This expands to the following (hidden by default) BibTex appendix:</t> <artwork>hello world here are some hashtagbibs followed by bibtex: @{some-section} @flap{ asdf = {1} } @world{world, } @greeting{hello, } @{another-section} @bar{ abc = {123} } </artwork> <blockquote><t>when an XR browser updates the human text, a quick scan for nonmatching tags (<tt>@book{nonmatchingbook</tt> e.g.) should be performed and prompt the enduser for deleting them.</t> </blockquote></section> </section> <section anchor="transclusion-broken-link-resolution"><name>Transclusion (broken link) resolution</name> <t>In spirit of Ted Nelson's 'transclusion resolution', there's a soft-mechanism to harden links & minimize broken links in various ways:</t> <ol spacing="compact"> <li>defining a different transport protocol (https vs ipfs or DAT) in <tt>src</tt> or <tt>href</tt> values can make a difference</li> <li>mirroring files on another protocol using (HTTP) errorcode tags in <tt>src</tt> or <tt>href</tt> properties</li> <li>in case of <tt>src</tt>: nesting a copy of the embedded object in the placeholder object (<tt>embeddedObject</tt>) will not be replaced when the request fails</li> </ol> <blockquote><t>due to the popularity, maturity and extensiveness of HTTP codes for client/server communication, non-HTTP protocols easily map to HTTP codes (ipfs ERR_NOT_FOUND maps to 404 e.g.)</t> </blockquote><t>For example:</t> <artwork> +────────────────────────────────────────────────────────+ │ │ │ index.gltf │ │ │ │ │ │ #: #-offlinetext │ │ │ │ │ ├── ◻ buttonA │ │ │ └ href: http://foo.io/campagne.fbx │ │ │ └ href@404: ipfs://foo.io/campagne.fbx │ │ │ └ href@400: #clienterrortext │ │ │ └ ◻ offlinetext │ │ │ │ │ └── ◻ embeddedObject <--------- the meshdata inside embeddedObject will (not) │ └ src: https://foo.io/bar.gltf │ be flushed when the request (does not) succeed. │ └ src@404: http://foo.io/bar.gltf │ So worstcase the 3D data (of the time of publishing index.gltf) │ └ src@400: https://archive.org/l2kj43.gltf │ will be displayed. │ │ +────────────────────────────────────────────────────────+ </artwork> </section> <section anchor="topic-based-index-less-webrings"><name>Topic-based index-less Webrings</name> <t>As hashtags in URLs map to the XWRG, <tt>href</tt>-values can be used to promote topic-based index-less webrings.<br /> Consider 3D scenes linking to eachother using these <tt>href</tt> values:</t> <ul spacing="compact"> <li><tt>href: schoolA.edu/projects.gltf#math</tt></li> <li><tt>href: schoolB.edu/projects.gltf#math</tt></li> <li><tt>href: university.edu/projects.gltf#math</tt></li> </ul> <t>These links would all show visible links to math-tagged objects in the scene.<br /> To filter out non-related objects one could take it a step further using filters:</t> <ul spacing="compact"> <li><tt>href: schoolA.edu/projects.gltf#math&-topics math</tt></li> <li><tt>href: schoolB.edu/projects.gltf#math&-courses math</tt></li> <li><tt>href: university.edu/projects.gltf#math&-theme math</tt></li> </ul> <blockquote><t>This would hide all object tagged with <tt>topic</tt>, <tt>courses</tt> or <tt>theme</tt> (including math) so that later only objects tagged with <tt>math</tt> will be visible</t> </blockquote><t>This makes spatial content multi-purpose, without the need to separate content into separate files, or show/hide things using a complex logiclayer like javascript.</t> </section> <section anchor="uri-templates-rfc6570"><name>URI Templates (RFC6570)</name> <t>XR Fragments adopts Level1 URI <strong>Fragment</strong> expansion to provide safe interactivity.<br /> The following demonstrates a simple video player:</t> <artwork> +─────────────────────────────────────────────+ │ │ │ foo.usdz │ │ │ │ │ │ │ │ ├── ◻ stopbutton │ │ │ ├ #: #-stopbutton │ │ │ └ href: #player=stop&-stopbutton │ (stop and hide stop-button) │ │ │ │ └── ◻ plane │ │ ├ play: #t=l:0,10 │ │ ├ stop: #t=0,0 │ │ ├ href: #player=play&stopbutton │ (play and show stop-button) │ └ src: cat.mp4#{player} │ │ │ │ │ +─────────────────────────────────────────────+ </artwork> </section> <section anchor="additional-scene-metadata"><name>Additional scene metadata</name> <t>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:</t> <ul spacing="compact"> <li><eref target="https://spdx.dev/">SPDX</eref> license information</li> <li><eref target="https://www.w3.org/WAI/standards-guidelines/aria/">ARIA</eref> attributes (<tt>aria-*: .....</tt>)</li> <li><eref target="https://ogp.me">Open Graph</eref> attributes (<tt>og:*: .....</tt>)</li> <li><eref target="https://www.dublincore.org/specifications/dublin-core/application-profile-guidelines/">Dublin-Core</eref> attributes(<tt>dc:*: .....</tt>)</li> <li><eref target="https://bibtex.eu/fields">BibTex</eref> when known bibtex-keys exist with values enclosed in <tt>{</tt> and <tt>},</tt></li> </ul> <t><strong>ARIA</strong> (<tt>aria-description</tt>) is the most important to support, as it promotes accessibility and allows scene transcripts. Please start <tt>aria-description</tt> with a verb to aid transcripts.</t> <blockquote><t>Example: object 'tryceratops' with <tt>aria-description: is a huge dinosaurus standing on a #mountain</tt> generates transcript <tt>#tryceratops is a huge dinosaurus standing on a #mountain</tt>, where the hashtags are clickable XR Fragments (activating the visible-links in the XR browser).</t> </blockquote><t>Individual nodes can be enriched with such metadata, but most importantly the scene node:</t> <table> <thead> <tr> <th>metadata key</th> <th>example value</th> </tr> </thead> <tbody> <tr> <td><tt>aria-description</tt>, <tt>og:description</tt>, <tt>dc:description</tt></td> <td><tt>An immersive experience about Triceratops</tt> (*)</td> </tr> <tr> <td><tt>SPDX</tt></td> <td><tt>CC0-1.0</tt></td> </tr> <tr> <td><tt>dc:creator</tt></td> <td><tt>John Doe</tt></td> </tr> <tr> <td><tt>dc:title</tt>, <tt>og:title</tt></td> <td>'Triceratops` (*)</td> </tr> <tr> <td><tt>og:site_name</tt></td> <td><tt>https://xrfragment.org</tt></td> </tr> <tr> <td><tt>dc.publisher</tt></td> <td><tt>NLNET</tt></td> </tr> <tr> <td><tt>dc.date</tt></td> <td><tt>2024-01-01</tt></td> </tr> <tr> <td><tt>dc.identifier</tt></td> <td><tt>XRFRAGMENT-001</tt></td> </tr> <tr> <td><tt>journal</tt> (bibTeX)</td> <td><tt>{Future Of Text Vol 3},</tt></td> </tr> </tbody> </table><blockquote><t>* = these are interchangable (only one needs to be defined)</t> </blockquote><t>There's no silver bullet when it comes to metadata, so one should support where the metadata is/goes.</t> <blockquote><t>These attributes can be scanned and presented during an <tt>href</tt> or <tt>src</tt> eye/mouse-over.</t> </blockquote></section> <section anchor="accessibility-interface"><name>Accessibility interface</name> <t>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></t> <ol spacing="compact"> <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 <tt>aria-descriptions</tt>, and its narration (Screenreader e.g.) can be skipped (via 2-button navigation)</li> <li>The <tt>back</tt> command should navigate back to the previous URL (alias for browser-backbutton)</li> <li>The <tt>forward</tt> command should navigate back to the next URL (alias for browser-nextbutton)</li> <li>A destination is a 3D node containing an <tt>href</tt> with a <tt>pos=</tt> XR fragment</li> <li>The <tt>go</tt> command should list all possible destinations</li> <li>The <tt>go left</tt> command should move the camera around 0.3 meters to the left</li> <li>The <tt>go right</tt> command should move the camera around 0.3 meters to the right</li> <li>The <tt>go forward</tt> command should move the camera 0.3 meters forward (direction of current rotation).</li> <li>The <tt>rotate left</tt> command should rotate the camera 0.3 to the left</li> <li>The <tt>rotate left</tt> command should rotate the camera 0.3 to the right</li> <li>The (dynamic) <tt>go abc</tt> command should navigate to <tt>#pos=scene2</tt> in case there's a 3D node with name <tt>abc</tt> and <tt>href</tt> value <tt>#pos=scene2</tt></li> <li>The <tt>look</tt> command should give an (contextual) 3D-to-text transcript, by scanning the <tt>aria-description</tt> values of the current <tt>pos=</tt> value (including its children)</li> <li>The <tt>do</tt> command should list all possible <tt>href</tt> values which don't contain an <tt>pos=</tt> XR Fragment</li> <li>The (dynamic) <tt>do abc</tt> command should navigate/execute <tt>https://.../...</tt> in case a 3D node exist with name <tt>abc</tt> and <tt>href</tt> value <tt>https://.../...</tt></li> </ol> <section anchor="two-button-navigation"><name>Two-button navigation</name> <t>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:</t> <ol spacing="compact"> <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> </section> </section> <section anchor="security-considerations"><name>Security Considerations</name> <t>The only dynamic parts are <eref target="https://www.w3.org/TR/media-frags/">W3C Media Fragments</eref> and <eref target="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</eref>.<br /> The use of URI Templates is limited to pre-defined variables and Level0 fragments-expansion only, which makes it quite safe.<br /> In fact, it is much safer than relying on a scripting language (javascript) which can change URN too.</t> </section> <section anchor="faq"><name>FAQ</name> <t><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 <tt>src</tt> values)</t> <t><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 <eref target="https://www.w3.org/TR/media-frags/">W3C Media Fragments</eref> and <eref target="https://www.rfc-editor.org/rfc/rfc6570">URI Templates (RFC6570)</eref>, 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).</t> </section> <section anchor="authors"><name>authors</name> <ul spacing="compact"> <li>Leon van Kammen (@lvk@mastodon.online)</li> <li>Jens Finkhäuser (@jens@social.finkhaeuser.de)</li> </ul> </section> <section anchor="iana-considerations"><name>IANA Considerations</name> <t>This document has no IANA actions.</t> </section> <section anchor="acknowledgments"><name>Acknowledgments</name> <ul spacing="compact"> <li><eref target="https://nlnet.nl">NLNET</eref></li> <li><eref target="https://futureoftext.org">Future of Text</eref></li> <li><eref target="https://visual-meta.info">visual-meta.info</eref></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> </section> <section anchor="appendix-definitions"><name>Appendix: Definitions</name> <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 (<tt>http://me.com/foo.glb#foo</tt> or <tt>e76f8efec8efce98e6f</tt> <eref target="https://interpeer.io">see interpeer.io</eref>)</td> </tr> <tr> <td>URL</td> <td>something somewhere via someprotocol (<tt>http://me.com/foo.glb</tt>)</td> </tr> <tr> <td>URN</td> <td>something at some domain (<tt>me.com/foo.glb</tt>)</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 like <tt>#pos=0,0,0&t=1,100</tt> e.g.</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 <tt>src</tt> 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 (<tt>#cube&-price=>3</tt>)</td> </tr> <tr> <td>visual-meta</td> <td><eref target="https://visual.meta.info">visual-meta</eref> 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><tt>◻</tt></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 (<eref target="https://github.com/coderofsalvation/hashtagbibs">see here</eref> which expands to BibTex/JSON/XML</td> </tr> </tbody> </table></section> </middle> </rfc>