NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
But approaches things from a higherlevel feedbackloop/hypermedia browser-perspective.
?-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.
fragment | type | example | info |
---|---|---|---|
#pos | vector3 | #pos=0.5,0,0 #pos=room #pos=cam2 | positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera |
#rot | vector3 | #rot=0,90,0 | rotates camera to xyz-coord 0.5,0,0 |
#t=0,2&loop | play (and loop) 3D animation from 0 seconds till 2 seconds |
key | type | example (JSON) | function | existing compatibility |
---|---|---|---|---|
href | string | "href": "b.gltf" | XR teleport | custom property in 3D fileformats |
src | string | "src": "#cube" | XR embed / teleport | custom property in 3D fileformats |
tag | string | "tag": "cubes geo" | tag object (for filter-use / XRWG highlighting) | custom property in 3D fileformats |
# | string | "#": "#mypreset | trigger default fragment on load | custom property in 3D fileformats |
Supported popular compatible 3D fileformats: .gltf, .obj, .fbx, .usdz, .json (THREE.js), .dae and so on.
NOTE: sidecar-files break the portability of XR (Fragments) experiences, therefore side-car files are discouraged for consumer usage/sharing. However, they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a .glb e.g.).
This would mean: hide object(s) with name or tag-value 'penguin' upon scene-load, and show it when the user clicks the chair
In THREE.js-code this would boil down to:
Being able to use the same URI Fragment DSL for navigation (href: #foo) as well as interactions (href: xrf://#bar) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
principle | XR 4D URL | HTML 2D URL |
---|---|---|
the XRWG | wordgraph (collapses 3D scene to tags) | Ctrl-F (find) |
the hashbus | hashtags alter camera/scene/object-projections | hashtags alter document positions |
src metadata | renders content and offers sourceportation | renders content |
href metadata | teleports to other XR document | jumps to other HTML document |
href metadata | triggers predefined view | Media fragments |
href metadata | triggers camera/scene/object/projections | n/a |
href metadata | draws visible connection(s) for XRWG 'tag' | n/a |
href metadata | filters certain (in)visible objects | n/a |
href metadata | href="xrf://#-foo&bar" | href="javascript:hideFooAndShowBar()` |
(this does not update topLevel URI) | (this is non-standard, non-hypermediatic) |
An important aspect of HFL is that URI Fragments can be triggered without updating the top-level URI (default href-behaviour) thru their own 'bus' (xrf://#.....). This decoupling between navigation and interaction prevents non-standard things like (href:javascript:dosomething()).
Example: ://foo.com/my3d.gltf#pos=1,0,0&prio=-5&t=0,100
Demo | Explanation |
---|---|
pos=1,2,3 | vector/coordinate argument e.g. |
pos=1,2,3&rot=0,90,0&foo | combinators |
this is already implemented in all browsers
Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).
It also allows sourceportation, which basically means the enduser can teleport to the original XR Document of an src embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.
fragment | type | example | info | |
---|---|---|---|---|
PRESET | #<preset> | string | #cubes | evaluates preset (#foo&bar) when a scene contains extra (#cubes: #foo&bar e.g.) while URL-browserbar reflects #cubes. Only works when metadata-key starts with # |
FOCUS | #<tag_or_objectname> | string | #person | (and show) object(s) with tag: person or name person (XRWG lookup) |
FILTERS | #[!][-]<tag_or_objectname>[*] | string | #person (#-person) | will reset (!), show/focus or hide (-) focus object(s) with tag: person or name person by looking up XRWG (*=including children) |
MATERIALUPDATE | #<tag_or_objectname>[*]=<materialname> | string=string | #car=metallic | sets material of car to material with name metallic (*=including children) |
#soldout*=halfopacity | set material of objects tagged with product to material with name metallic | |||
VARIABLE UPDATE | #<variable>=<metadata-key> | string=string | #foo=bar | sets |
ANIMATION | #<tag_or_objectname>=<animationname> | string=string | #people=walk #people=noanim | assign a different animation to object(s) |
NOTE: below the word 'play' applies to 3D animations embedded in the 3D scene(file) but also media defined in src-metadata like audio/video-files (mp3/mp4 e.g.)
type | syntax | example | info |
---|---|---|---|
vector2 | x,y | 2,3.0 | 2-dimensional vector |
vector3 | x,y,z | 2,3.0,4 | 3-dimensional vector |
temporal W3C media fragment | t=x | 0 | play from 0 seconds to end (and stop) |
temporal W3C media fragment | t=x,y | 0,2 | play from 0 seconds till 2 seconds (and stop) |
temporal W3C media fragment * | s=x | 1 | set playback speed of audio/video/3D anim |
temporal W3C media fragment * | [-]loop | loop | enable looped playback of audio/video/3D anim |
-loop | disable looped playback (does not affect playbackstate of media) | ||
vector2 | uv=u,v,uspeed,vspeed | 0,0 | set uv offset instantly (default speed = 1,1) |
+0.5,+0.5 | scroll instantly by adding 0.5 to the current uv coordinates | ||
0.2,1,0.1,0.1 | scroll (lerp) to uv coordinate 0,2,1 with 0.1 units per second | ||
0,0,0,+0.1 | scroll v coordinates with 0.1 units per second (infinitely) | ||
+0.5,+0.5 | scroll instantly by adding 0.5 to the current uv coordinates | ||
media parameter (shader uniform) | u:<uniform>=<string | float | vec2 |
* = this is extending the W3C media fragments with (missing) playback/viewport-control. Normally #t=0,2 implies setting start/stop-values AND starting playback, whereas #s=0&loop allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping.The rationale for uv is that the xywh 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 scale or rotate primitive, which is challenged by this, as well as multiple origins (mesh- or texture).
fragment | type | functionality |
---|---|---|
<b>#pos</b>=0,0,0 | vector3 | position camera to 0,0,0 (+userheight in VR) |
<b>#pos</b>=room | string | position camera to position of objectname room (+userheight in VR) |
<b>#rot</b>=0,90,0 | vector3 | rotate camera |
Example URL: ://foo/world.gltf#cube&pos=0,0,0
fragment | type | example value |
---|---|---|
src | string (uri, hashtag/filter) | #cube #sometag #cube&-ball_inside_cube<br>#-sky&-rain<br>#-language&english<br>#price=>5<br> https://linux.world/distrowatch.gltf#t=1,100 linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply androidapp://page1?tutorial#pos=0,0,1&t1,100 foo.mp3#0,0,0 |
Instead of cherrypicking a rootobject #fishbowl with src, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
fragment | type | example value |
---|---|---|
href | string (uri or predefined view) | #pos=1,1,0 #pos=1,1,0&rot=90,0,0 ://somefile.gltf#pos=1,1,0 |
optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.
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.).
REASON: non-empty placeholder object can act as a protective bounding-box (for remote content of which might grow over time e.g.)
TODO: needs intermediate visuals to make things more obvious
NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].
example | outcome |
---|---|
#-sky | show everything except object named sky |
#-language&english | hide everything with tag language, but show all tag english objects |
#-price&price=>10 | hide all objects with property price, then only show object with price above 10 |
#-house* | hide house object and everything inside (=*) |
operator | info |
---|---|
- | hides object(s) (#-myobject&-objects e.g. |
= | indicates an object-embedded custom property key/value (#price=4&category=foo e.g.) |
=> =< | compare float or int number (#price=>4 e.g.) |
* | deepselect: automatically select children of selected object, including local (nonremote) embedded objects (starting with #) |
NOTE 1: after an external embedded object has been instanced (src: https://y.com/bar.fbx#room e.g.), filters do not affect them anymore (reason: local tag/name collisions can be mitigated easily, but not in case of remote content). 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).
An example filter-parser (which compiles to many languages) can be found here
The XR Fragments does this by collapsing space into a Word Graph (the XRWG example ), augmented by Bib(s)Tex.
URL example | Result |
---|---|
https://my.com/foo.gltf#baroque | draws lines between 3D mesh castle, and mydoc's text baroque |
https://my.com/foo.gltf#john | draws lines between mesh john, and the text John of mydoc |
https://my.com/foo.gltf#house | draws lines between mesh castle, and other objects with tag house or todo |
the URI fragment #john&mydoc&house would draw a connection between these 3 meshes.
This significantly expands expressiveness and portability of human tagged text, by postponing machine-concerns to the end of the human text in contrast to literal interweaving of content and markupsymbols (or extra network requests, webservices e.g.).
additional tagging using bibs : to tag spatial object note_canvas with 'todo', the enduser can type or speak #note_canvas@todo
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.)
This would hide all object tagged with topic, courses or theme (including math) so that later only objects tagged with math will be visible
Example: object 'tryceratops' with aria-description: is a huge dinosaurus standing on a #mountain generates transcript #tryceratops is a huge dinosaurus standing on a #mountain, where the hashtags are clickable XR Fragments (activating the visible-links in the XR browser).
metadata key | example value |
---|---|
aria-description, og:description, dc:description | An immersive experience about Triceratops (*) |
SPDX | CC0-1.0 |
dc:creator | John Doe |
dc:title, og:title | 'Triceratops` (*) |
og:site_name | https://xrfragment.org |
dc.publisher | NLNET |
dc.date | 2024-01-01 |
dc.identifier | XRFRAGMENT-001 |
journal (bibTeX) | {Future Of Text Vol 3}, |
* = these are interchangable (only one needs to be defined)
These attributes can be scanned and presented during an href or src eye/mouse-over.
Priority Order and Precedence, otherwise fallback applies
Example 1 In case of the OMI_LINK glTF extension (href: https://nlnet.nl) and an XR Fragment (href: #pos=otherroom or href: otherplanet.glb), it is clear that https://nlnet.nl should open in a browsertab, whereas the XR Fragment links should teleport the user. If the OMI_LINK contains an XR Fragment (#pos= e.g.) a teleport should be performed only (and other [overlapping] metadata should be ignored). Example 2 If an Extensions uses XR Fragments in URI's (href: #pos=otherroom or href: xrf://-walls 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.
what | XR metadata | Lowest common denominator |
---|---|---|
CSS | vendor-agnostic | 2D canvas + object referencing/styling |
XR Fragments | vendor-agnostic | 3D camera + object(file) load/embed/click/referencing |
Vendor prefixs | vendor-specific | Specialized Entity-Component implementation |
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.
This 'separating of mechanism from policy' (unix rule) does somewhat 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.
definition | explanation |
---|---|
human | a sentient being who thinks fuzzy, absorbs, and shares thought (by plain text, not markuplanguage) |
scene | a (local/remote) 3D scene or 3D file (index.gltf e.g.) |
3D object | an object inside a scene characterized by vertex-, face- and customproperty data. |
URI | some resource at something somewhere via someprotocol (http://me.com/foo.glb#foo or e76f8efec8efce98e6f |
URL | something somewhere via someprotocol (http://me.com/foo.glb) |
URN | something at some domain (me.com/foo.glb) |
metadata | custom properties of text, 3D Scene or Object(nodes), relevant to machines and a human minority (academics/developers) |
XR fragment | URI Fragment with spatial hints like #pos=0,0,0&t=1,100 e.g. |
the XRWG | wordgraph (collapses 3D scene to tags) |
the hashbus | hashtags map to camera/scene-projections |
spacetime hashtags | positions camera, triggers scene-preset/time |
teleportation | repositioning the enduser to a different position (or 3D scene/file) |
sourceportation | teleporting the enduser to the original XR Document of an src embedded object. |
placeholder object | a 3D object which with src-metadata (which will be replaced by the src-data.) |
src | (HTML-piggybacked) metadata of a 3D object which instances content |
href | (HTML-piggybacked) metadata of a 3D object which links to content |
filter | URI Fragment(s) which show/hide object(s) in a scene based on name/tag/property (#cube&-price=>3) |
visual-meta | |
requestless metadata | metadata which never spawns new requests (unlike RDF/HTML, which can cause framerate-dropping, hence not used a lot in games) |
FPS | frames per second in spatial experiences (games,VR,AR e.g.), should be as high as possible |
introspective | inward sensemaking ("I feel this belongs to that") |
extrospective | outward sensemaking ("I'm fairly sure John is a person who lives in oklahoma") |
◻ | ascii representation of an 3D object/mesh |
(un)obtrusive | obtrusive: wrapping human text/thought in XML/HTML/JSON obfuscates human text into a salad of machine-symbols and words |
flat 3D object | a 3D object of which all verticies share a plane |
BibTeX | simple tagging/citing/referencing standard for plaintext |
BibTag | a BibTeX tag |
(hashtag)bibs | an easy to speak/type/scan tagging SDL ( |