diff --git a/doc/RFC_XR_Fragments.html b/doc/RFC_XR_Fragments.html index 5f10a2e..b3c61e6 100644 --- a/doc/RFC_XR_Fragments.html +++ b/doc/RFC_XR_Fragments.html @@ -82,12 +82,12 @@ value: draft-XRFRAGMENTS-leonvankammen-00
An open specification for hyperlinking & deeplinking 3D fileformats.
This draft is a specification for interactive URI-controllable 3D files, enabling hypermediatic navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.
-The specification uses W3C Media Fragments and URI Templates (RFC6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
XR Fragments allows us to better use implicit metadata inside 3D scene(files), by mapping it to proven technologies like URI Fragments.
-XR Fragments views XR experiences thru the lens of 3D object URI’s, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
--XR Fragments is a heuristical 3D format which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
+XR Fragments is in a sense, a heuristical 3D format or meta-format, which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
These heuristics, enable features that are both meaningful and consistent across different scene representations, allowing higher interop between fileformats, 3D editors, viewers and game-engines.Almost every idea in this document is demonstrated at https://xrfragment.org
@@ -100,7 +100,7 @@ Historically, there’s many attempts to create the ultimate 3D fileformat.< The lowest common denominator is: designers describing/tagging/naming things using plain text.
XR Fragments exploits the fact that all 3D models already contain such metadata: -XR Fragments allows controlling of metadata in 3D scene(files) using URI’s
+XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments
It solves:
@@ -116,153 +116,33 @@ XR Fragments exploits the fact that all 3D models already contain such metadata:NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
XR Fragments allows controlling 3D models using URLs, based on (non)existing metadata via URI’s
- -XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
-Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments integrates all which allows a universal viewing experience.
+───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ U R N │
- │ U R L | │
- │ | |-----------------+--------| │
- │ +--------------------------------------------------| │
- │ | │
- │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │
- │ | │
- │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │
- │ │
- │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │
- │ │
- │ │
- │ |------------------------+-------------------------| │
- │ | │
- │ U R I │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
-
-
-Fact: our typical browser URL’s are just a possible implementation of URI’s (for untapped humancentric potential of URI’s see interpeer.io)
- --- -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.
Below you can see how this translates back into good-old URLs:
- - +───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ the soul of any URL: ://macro /meso ?micro #nano │
- │ │
- │ 2D URL: ://library.com /document ?search #chapter │
- │ xrf:// │
- │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #view ───> hashbus │
- │ │ #filter │ │
- │ │ #tag │ │
- │ │ (hypermediatic) #material │ │
- │ │ ( feedback ) #animation │ │
- │ │ ( loop ) #texture │ │
- │ │ #variable │ │
- │ │ │ │
- │ XRWG <─────────────────────<─────────────+ │
- │ │ │ │
- │ └─ objects ──────────────>─────────────+ │
- │ │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
-
-
--- -?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
-
Traditional webbrowsers can become 4D document-ready by:
- -XR Fragments utilizes URLs:
href metadata inside 3D scene-files to enable interactions| fragment | -type | -example | -info | -
|---|---|---|---|
#...... |
-vector3 | -#room1 #room2 #cam2 |
-positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector | -
| Media Fragments | -media fragment | -#t=0,2&loop |
-play (and loop) 3D animation from 0 seconds till 2 seconds | -
These are the possible ‘extras’ for 3D nodes and sidecar-files
- -| key | -type | -example (JSON) | -function | -existing compatibility | -
|---|---|---|---|---|
href |
-string | -"href": "b.gltf" |
-XR teleport | -custom property in 3D fileformats | -
href metadata traditionally implies click AND navigate, however XR Fragments adds stateless click (xrf://#....) or navigate (xrf://#...)
- as well (which allows many extra interactions which otherwise need a scripting language). This is known as hashbus-only events (see image above).
href metadata traditionally implies click AND navigate, however XR Fragments adds stateless click (xrf://....) via the xrf:// scheme, which does not change the top-level URL-adress (of the browser).
+This allows for many extra interactions via URLs, which otherwise needs a scripting language.
+These are called hashbus-only events/
-Being able to use the same URI Fragment DSL for navigation (
+href: #foo) as well as interactions (href: xrf://#bar) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.Being able to use the same URI Fragment DSL for navigation (
href: #foo) as well as interactions (href: xrf://#foo) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
This opens up the following benefits for traditional & future webbrowsers:
xrf:// hashbus (xrf://#person=walk to trigger walk-animation for object person)xrf:// hashbus (xrf://#person=walk to trigger walk-animation for object person)room1&rot=0,90,0&cam1room1&cam1http
Spatial Referencing 3D
-XR Fragments assume the following objectname-to-URIFragment mapping:
+3D files contain an hierarchy of objects.
+XR Fragments assumes the following objectname-to-URI-Fragment mapping, in order to deeplink 3D objects:
my.io/scene.fbx
@@ -421,57 +302,102 @@ For example, to render a portal with a preview-version of the scene, create an 3
- href:
https://scene.fbx
-- src:
https://otherworld.gltf#mainobject
It also allows sourceportation, which basically means the enduser can teleport to the original XR Document of an src embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.
-
+Level0: Files
-non-normative
+These are optional auto-loaded side-car files to enable hasslefree XR Movies.
+they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a .glb e.g.).
-The following below is non-normative heuristics which are not part officially part of the spec.
+via href metadata
-additional explicit metadata
+scene.glb <--- 'href' extra [heuristic] detected inside!
+scene.png (preview thumbnail)
+scene.ogg (soundtrack to plays when global 3D animation starts)
+scene.vtt (subtitles for accessibility or screenreaders)
+scene.json (sidecar JSON-file with explicit metadata)
+
-| #rot | vector3 | #rot=0,90,0 | rotates camera to xyz-coord 0.5,0,0 |
-| 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 |
+heuristics:
+
+
+- if at least one
href custom property/extra is found in a 3D scene
+- The viewer should poll for the above mentioned sidecar-file extensions (and present accordingly)
+
+
+via chained extension
+
+scene.xrf.glb <--- '.xrf.' sidecar file heuristic detected!
+scene.xrf.png (preview thumbnail)
+scene.xrf.ogg (soundtrack to plays when global 3D animation starts)
+scene.xrf.vtt (subtitles for accessibility or screenreaders)
+scene.xrf.json (sidecar JSON-file with explicit metadata)
+
-Supported popular compatible 3D fileformats: .gltf, .obj, .fbx, .usdz, .json (THREE.js), .dae and so on.
+A fallback-mechanism to turn 3D files into XR Movies without editing them.
-Sidecar-file
+heuristics:
+
+
+- the chained-extension heuristic
.xrf. should be present in the filename (scene.xrf.glb e.g.)
+
+
+via subdocuments/xattr
+
+More secure protocols (Nextgraph e.g.) don’t allow for simply polling files.
+In such case, subdocuments or extended attributes should be polled:
-NOTE: 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.).
+NOTE: in the examples below we use the href-heuristic, but also the .xrf. chained-extension applies here.
-For developers, sidecar-file can allow for defining explicit XR Fragments metadata, outside of the 3D file.
-This can be done via a JSON-pointers RFC6901 in a JSON sidecar-file:
+myspreadsheet.ods
+└── explainer.glb <--- 'href' extra [heuristic] detected inside!
+ ├── explainer.ogg (soundtrack to play when global 3D animation starts)
+ ├── explainer.png (preview thumnbnail)
+ ├── explainer.json (sidecar JSON-file with explicit metadata)
+ └── explainer.vtt (subtitles for accessibility or screenreaders)
+
+
+If only extended attributes (xattr) are available, the respective referenced file can be embedded:
+
+$ setfattr -n explainer.ogg -v "soundtrack.ogg" explainer.glb
+$ setfattr -n explainer.png -v "thumbnail.png" explainer.glb
+$ setfattr -n explainer.vtt -v "subtitles.vtt" explainer.glb
+
+
+
+NOTE: Linux’s setfattr/getfattr is xattr on mac, and Set-Content/Get-content on Windows. See pxattr for lowlevel access.
+
+
+JSON sidecar-file
+
+For developers, sidecar-file can allow for defining explicit XR Fragments links (>level1), outside of the 3D file.
+This can be done via (objectname/metadata) key/value-pairs in a JSON sidecar-file:
- experience.glb
-- experience.json
+- experience.json
<----
{
- "/":{
- "#": "#-penguin",
+ "/":
"aria-description": "description of scene",
},
- "/room/chair": {
- "href": "#penguin"
+ "button": {
+ "href": "#roomB"
}
}
-This would mean: hide object(s) with name or tag-value ‘penguin’ upon scene-load, and show it when the user clicks the chair
+This will make object button clickable, and teleport the user to object roomB.
So after loading experience.glb the existence of experience.json is detected, to apply the explicit metadata.
@@ -481,25 +407,83 @@ The sidecar will define (or override already existing) extras,
In THREE.js-code this would boil down to:
- scene.userData['#'] = "#chair&penguin"
- scene.userData['aria-description'] = "description of scene"
- scene.getObjectByName("room").getObjectByName("chair").userData.href = "#penguin"
+ 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
-Level2: Implicit URI Fragments
+Level1: URI
-Warning: non-normative
+XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments
-These fragments are derived from objectnames (or their extras) within a 3D scene, and trigger certain actions when evaluated by the browser:
+XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
+Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments integrates all which allows a universal viewing experience.
+
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ U R N │
+ │ U R L | │
+ │ | |-----------------+--------| │
+ │ +--------------------------------------------------| │
+ │ | │
+ │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │
+ │ | │
+ │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │
+ │ │
+ │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │
+ │ │
+ │ │
+ │ |------------------------+-------------------------| │
+ │ | │
+ │ U R I │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+
+
+
+Fact: our typical browser URL’s are just a possible implementation of URI’s (for untapped humancentric potential of URI’s see interpeer.io or NextGraph )
+
+
+XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
But approaches things from a higherlevel local-first 3D hypermedia browser-perspective.
+
+
+Below you can see how this translates back into good-old URLs:
+
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ the soul of any URL: ://macro /meso ?micro #nano │
+ │ │
+ │ 2D URL: ://library.com /document ?search #chapter │
+ │ xrf:// │
+ │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #object ─> hashbus │
+ │ │ #filter │ │
+ │ │ #tag │ │
+ │ │ (hypermediatic) #material │ │
+ │ │ ( feedback ) #animation │ │
+ │ │ ( loop ) #texture │ │
+ │ │ #variable │ │
+ │ │ │ │
+ │ XRWG <─────────────────────<─────────────+ │
+ │ │ │ │
+ │ └─ objects ──────────────>─────────────+ │
+ │ │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+
+
+
+
+?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
+
+
+List of URI Fragments
-
fragment
type
example
@@ -509,385 +493,325 @@ The sidecar will define (or override already existing) extras,
-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 #
+#......
+vector3
+#room1 #room2 #cam2
+positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector
-FOCUS
-xrf://#<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 URI Template variable foo to the value #t=0 from existing object metadata (bar:#t=0 e.g.), This allows for reactive URI Template defined in object metadata elsewhere (src:://m.com/cat.mp4#{foo} e.g., to play media using media fragment URI). NOTE: metadata-key should not start with #
-
-
-
-ANIMATION
-#<tag_or_objectname>=<animationname>
-string=string
-#people=walk #people=noanim
-assign a different animation to object(s)
+Media Fragments
+media fragment
+#t=0,2&loop
+play (and loop) 3D animation from 0 seconds till 2 seconds
-media fragments and datatypes
+List of *explicit metadata
-
-Warning: non-normative (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.))
-
+These are the possible ‘extras’ for 3D nodes and sidecar-files
+key
type
-syntax
-example
-info
+example (JSON)
+function
+existing compatibility
-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:=
-float
-vec2
+href
+string
+"href": "b.gltf"
+XR teleport
+custom property in 3D fileformats
-
-* = 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.
+Level2: href links
-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).
+Explicit href metadata (‘extras’) in a 3D object (of a 3D file), hint the viewer that the user “can interact” with that object :
+
+| fragment | type | example value |
+|href| string (uri or predefined view) | #pyramid
#lastvisit
xrf://#-someobject
://somefile.gltf#foo
|
+
+Interaction behaviour
+
+When clicking an “href”-value, the user(camera) is teleport to the referenced object.
+
+The imported/teleported destination can be another object in the same scene-file, or a different file.
+
+XR Viewer implementation
+
+| spec | action | feature |
+|-|-|-|
+| level0+1 | hover 3D file href | show the preview PNG thumbnail (if any). |
+| level0+1 | launch 3D file href | replace the current scene with a new 3D file (href: other.glb e.g.) |
+| level2 | click internal 3D file href (#roomB e.g.) | teleport the camera to the origin of object(name roomB). See [[teleport camera]].|
+| level2 | click external 3D file href (foo.glb e.g.) | replace the current scene with a new 3D file (href: other.glb e.g.) |
+| level2 | hover external 3D file href | show the preview PNG thumbnail (if any sidecar, see level0) |
+| level2 | click href | hashbus: execute without changing the toplevel URL location (href: xrf://#someObjectName e.g.) |
+| level3 | click href | set the global 3D animation timeline to its Media Fragment value (#t=2,3 e.g.) |
+
+
+NOTE: hashbus links (xrf://#foo&bar) don’t change the toplevel URL, which makes it ideal for interactions (in contrast to typical #roomC navigation, which benefit back/forward browser-buttons), see hashbus for more info.
-Example URI’s:
+Level3: Media Fragments
+
+
+these allow for XR Movies with a controllable timeline using href URI’s with Media Fragments
+
+
+Just like with 2D media-files, W3C mediafragments (#t=1,2) can be used to control a timeline via the #t primitive.
+XR Fragments Level3 makes the 3D timeline, as well as URL-referenced files controllable via Media Fragments like:
-https://images.org/credits.jpg#uv=0,0,0,+0.1 (infinite vertical texturescrolling)
-https://video.org/organogram.mp4#t=0&loop&uv=0.1,0.1,0.3,0.3 (animated tween towards region in looped video)
-https://shaders.org/plasma.glsl#t=0&u:col2=0,1,0 (red-green shader plasma starts playing from time-offset 0)
+- level2 hrefs (
href: #t=4 e.g. to control 3D timeline)
+- level4:
xrf: URI scheme:
+
+
+href: xrf:foo.wav#t=0 to play a wav
+href: xrf:news.glb?clone#t=0 to instance and play another experience
+
- +──────────────────────────────────────────────────────────+
- │ │
- │ 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)
- │ │
- │ │
- +──────────────────────────────────────────────────────────+
+Animation(s) timeline
-> 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).
+controls the animation(s) of the scene (or src resource which contains a timeline)
+
+| fragment | type | functionality |
+| #t=start,stop | [vector2] | start,stop (in seconds |
+
+| Example Value | Explanation |
+| #t=1 | play (3D) animations from 1 seconds till end (and stop) |
+| #t=1,100 | play (3D) animations from 1 till 100 seconds (and stop) |
+| #t=0,0 | stop (3D) animations at frame 0 |
+
+
+Use [[#s 🌱]] to control playback speed
+
+
+Specify playback loopmode
+
+This compensates a missing element from Media Fragments to enable/disable temporal looping. .
+
+| fragment | type | functionality |
+| #loop | string | enables animation/video/audio loop |
+| #-loop | string | disables animation/video/audio loop |
+
+Controlling embedded content
+
+use [[URI Templates]] to control embedded media, for example a simple video-player:
+
+ foo.usdz
+ │
+ ├── ◻ loopbutton_enable
+ │ └ href: #loop <-- enable global loop
+ │
+ ├── ◻ loopbutton_enable
+ │ └ href: #-loop <-- disable global loop
+ │
+ ├── ◻ playbutton
+ │ └ href: #t=10&loop <-- play global 3D timeline (all anims) (looped)
+ │
+ └── ◻ playbutton_external
+ └ href: https://my.org/animation.glb#!&t=3,10 <-- import & play external anim
-Navigating 3D
+Level4: prefix operators
-
-
-
-fragment
-type
-functionality
-
-
+Prefixing objectnames with the following simple operators allow for extremely powerful XR interactions:
-
-
-#=room1
-string
-position camera to position and upvector of objectname room1 (+userheight in VR)
-
-
-
-» example implementation
-» discussion
+
+- #!
+- #*
+- #+ or #-
+- #|
+- xrf: URI scheme
+
-Here’s the basic level1 flow (with optional level2 features):
+
+Examples: #+menu to show a object, #-menu to hide a menu, #!menu to teleport a menu, #*block to clone a grabbable block, #|object to share an object
+
+
+Object teleports (!)
+
+Prefixing an object with an exclamation-symbol, will teleport a (local or remote) referenced object from/to its original/usercamera location.
+
+[img[objecteleport.png]]
+
+Usecases:
+* show/hide objects/buttons (menu e.g.) in front of user
+* embed remote (object within) 3D file via remote URL
+* instance an interactive object near the user regardless of location
+* instance HUD or semi-transparent-textured-sphere (LUT) around the user
+
+
+ #!menu
+
+
+
+Clicking the href-value above will:
-- the Y-coordinate of `room1 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), except in case of camera-switching.
-- set the position of the camera accordingly to the vector3 values of
room1
-- set the upvector of the camera accordingly to the vector3 values of
room1 (local gravity as pioneered by Patrick Lichty)
-- if the referenced
#room1 object is animated, parent the current camera to that object (so it animates too)
-- in case a
href does not mention any 3D object, the current position will be assumed
+- reposition the referenced object (menu) to the usercamera’s-coordinates.
+- zoom in case of (non-empty) mesh-object: rescale to 1 m³, and position 1m in front of the camera
+- toggle behaviour: revert values if 1⁄2 were already applied
+#+ is always implied (objects are always made visible)
-Here’s an ascii representation of a 3D scene-graph which contains 3D objects ◻ and their metadata:
+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.).
- +────────────────────────────────────────────────────────+
- │ │
- │ index.gltf │
- │ │ │
- │ ├── ◻ buttonA │
- │ │ └ href: #room1&t=100,200 │
- │ │ │
- │ └── ◻ buttonB │
- │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc)
- │ │
- +────────────────────────────────────────────────────────+
+
+- href:
#whiteroom&!explainer&!exitmenu
+
-
+
+This will teleport the user to whiteroom and moves object explainer and exitmenu in front of the user.
+
-An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the buttonA and buttonB.
-In case of buttonA the end-user will be teleported to another location and time in the current loaded scene, but buttonB will replace the current scene with a new one, like other.fbx, and assume camera coordinate 0,0,0
+
+- href: `https://my.org/foo.glb#!
+
-Non-normative:
+Clicking the href-value above will:
-
-rot sets the rotation of the camera (only for non-VR/AR headsets, however a camera-value overrules this)
-- level2: mediafragment
t in the top-URL sets the playbackspeed and animation-range of the global scene animation
-- before scene load: the scene is cleared
-- level2: after scene load: in case the scene (rootnode) contains an
# default view with a fragment value: execute non-positional fragments via the hashbus (no top-level URL change)
-- level2: after scene load: in case the scene (rootnode) contains an
# default view with a fragment value: execute positional fragment via the hashbus + update top-level URL
-- level2: in case of no default
# view on the scene (rootnode), default player(rig) position 0,0,0 is assumed.
+
+- import
foo.glb from my.org’s webserver
+- show it in front of the user (because
#! indicates object teleport)
+
+- href:
https://foo.glb#roomB&!bar
+
+
+Clicking the href-value above will:
+
+
+- replace the current scene with
foo.glb
+- teleport the user to #roomB inside
foo.glb
+- instance the referenced object (bar inside foo.glb) in front of the user.
+- it will update the top-Level URL (because
xrf: was not used)
+- hide the instanced object when clicked again (toggle visibility)
+
+
+
+NOTE: level2 teleportation links, as well as instancing mitigates the ‘broken embedded image’-issue of HTML: always attaching the href-values to a 3D (preview) object (that way broken links will not break the design).
+
+
+Example: clicking a 3D button with title ‘menu’ and href-value xrf:menu.glb?instance#t=4,5 would instance a 3D menu (menu.glb) in front of the user, and loop its animation between from 4-5 seconds (t=4,5)
+
+
+NOTE: combining instance-operators allows dynamic construction of 3D scenes (#london&!welcomeMenu&!fadeBox e.g.)
+
+
+Object multipliers (*)
+
+The star-prefix will clone a (local or remote) referenced object to the usercamera’s location, and make it grabbable.
+Usecases:
+* object-picker (build stuff with objects)
+
+
+NOTE: this is basically the #! operator which infinitely clones the referenced object (instead of repositioning the object).
+
+
+De/selectors (+ and -)
+
+
+- href:
#-welcome (or #+welcome)
+
+
+Clicking href-value above will do:
+
+
+- show/hide the target object (and children)
+
+
+
+- href:
#https://my.org/foo.glb/#bar&-welcome
+
+
+
+NOTE: the latter shows that (de)selectors can also be with regular href-values
+
+
+Sharing object or file (#|)
+
+The pipe-symbol (|) sends a (targeted) object to the OS.
+Clicking the href-value below will:
+
+
+- share the (targeted object in the) file to a another application
+
+
+
+This URL can be fed straight into Web Share API or xdg-open
+
+
+
+- href:
xrf://#|bar
+
+
+
+NOTE: sharing is limited to (internal objects) via xrf: scheme-only
+
+
+xrf:// URI scheme
+
+Prefixing the xrf: to href-values will prevent level2 href-values from changing the top-Level URL.
+
+
+Usecase: for non-shareable URLs like href: xrf:#t=4,5, to display a stateful msg e.g.).
+
+
+Reason: XR Fragments is inspired by HTML’s href-attribute, which does various things:
+
+
+- it updates the browser-location
+- it makes something clickable
+- it jumps to another document / elsewhere in the same document
+- and more
+
+
+The xrf: scheme will just do 2 & 3 (so the URL-values will not leak into the top-level URL).
+
+
+compliance with RFC 3986: unimplemented/unknown URI schemes (xrf:... e.g.) will not update the top-level URL
+
+
Top-level URL processing
-Example URL: ://foo/world.gltf#room1&t=10
+Example URL: ://foo/world.gltf#room1&t=10&cam
The URL-processing-flow for hypermedia browsers goes like this:
-- IF a
#room1 matches a custom property-key (of an object) in the 3D file/scene (#room1: #......) THEN execute that predefined_view.
- IF scene operators and/or animation operator (
t) are present in the URL then (re)position the camera (to room1) and/or animation-range (10) accordingly.
- IF no camera-position has been set in step 1 or 2 assume
0,0,0 as camera coordinate (XR: add user-height) (example)
+- IF a camera-object exists with name
cam assume that user(camera) position
-Non-normative / Deprecated:
+UX
-
-- IF a
#cube 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).
-- IF a
#cube matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects).
-
-
-Embedding XR content using src
-
-
-NOTE: only adviced for local-first experiences (where resources can be cached).
-
-
-src is the 3D version of the iframe.
-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.
-
-
-
-
-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.org/penguin.png`
https://linux.world/distrowatch.gltf#t=1,100
linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply
androidapp://page1?tutorial#room1&t1,100
foo.mp3#0,0,0
-
-
-
-Here’s an ascii representation of a 3D scene-graph with 3D objects ◻ which embeds remote & local 3D objects ◻ with/out using filters:
-
- +────────────────────────────────────────────────────────+ +─────────────────────────+
- │ │ │ │
- │ 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 │
- │ │
- +────────────────────────────────────────────────────────+
-
-
-An XR Fragment-compatible browser viewing this scene, lazy-loads and projects painting.png onto the (plane) object called canvas (which is copy-instanced in the bed and livingroom).
-Also, after lazy-loading ocean.com/aquarium.gltf, only the queried objects fishbowl (and bass and tuna) will be instanced inside aquariumcube.
-Resizing will be happen accordingly to its placeholder object aquariumcube, see chapter Scaling.
-
-
-Instead of cherrypicking a rootobject #fishbowl with src, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
-
-
-Specification:
+End-users should always have read/write access to:
-- local/remote content is instanced by the
src (filter) value (and attaches it to the placeholder mesh containing the src property)
-- by default all objects are loaded into the instanced src (scene) object (but not shown yet)
-- local
src values (#... e.g.) starting with a non-negating filter (#cube e.g.) will (deep)reparent that object (with name cube) as the new root of the scene at position 0,0,0
-- local
src values should respect (negative) filters (#-foo&price=>3)
-- the instanced scene (from a
src value) should be scaled accordingly to its placeholder object or scaled relatively based on the scale-property (of a geometry-less placeholder, an ‘empty’-object in blender e.g.). For more info see Chapter Scaling.
-- external
src 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:
-src values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see broken links)
-- external
src values should respect the fallback link mechanism (see broken links
-- 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.
-- src-values are non-recursive: when linking to an external object (
src: foo.fbx#bar), then src-metadata on object bar should be ignored.
-- an external
src-value should always allow a sourceportation icon within 3 meter: teleporting to the origin URI to which the object belongs.
-- when only one object was cherrypicked (
#cube e.g.), set its position to 0,0,0
-- when the enduser clicks an href with
#t=1,0,0 (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.)
-- a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial
src-values (an object #world3 or URL world3.fbx e.g.).
+- the current (toplevel) URL (an URLbar etc)
+- URL-history (a back/forward button e.g.)
+- Clicking/Touching an
href navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-
-model/gltf-binary
-model/gltf+json
-image/png
-image/jpg
-text/plain;charset=utf-8
-
-
-» example implementation
-» example 3D asset
-» discussion
-
-Navigating content href portals
+Example: Navigating content href portals
navigation, portals & mutations
@@ -904,13 +828,13 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
href
string (uri or predefined view)
-#room1
#room1&rot=90,0,0
://somefile.gltf#room1
+#room1
#room1
://somefile.gltf#room1
-clicking an outbound “external”- or “file URI” fully replaces the current scene and assumes room2&rot=0,0,0 by default (unless specified)
+clicking an outbound “external”- or “file URI” fully replaces the current scene and assumes room2 by default (unless specified)
relocation/reorientation should happen locally for local URI’s (#....)
@@ -935,457 +859,23 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
Walking surfaces
+
+By default position 0,0,0 of the 3D scene represents the walkable plane, however this is overridden when the following applies:
+
+
XR Fragment-compatible viewers can infer this data based scanning the scene for:
-- materialless (nameless & textureless) mesh-objects (without
src and href)
+- materialless (nameless & textureless) mesh-objects (without
href and >0 faces)
optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.
-UX spec
+Virtual world rings
-End-users should always have read/write access to:
-
-
-- the current (toplevel) URL (an URLbar etc)
-- URL-history (a back/forward button e.g.)
-- Clicking/Touching an
href navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-
-
-Scaling instanced content
-
-Sometimes embedded properties (like src) instance new objects.
-But what about their scale?
-How does the scale of the object (with the embedded properties) impact the scale of the referenced content?
-
-
-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.).
-
-
-
-- IF an embedded property (
src e.g.) is set on an non-empty placeholder object (geometry of >2 vertices):
-
-
-
-- calculate the bounding box of the “placeholder” object (maxsize=1.4 e.g.)
-- hide the “placeholder” object (material e.g.)
-- instance the
src scene as a child of the existing object
-- calculate the bounding box of the instanced scene, and scale it accordingly (to 1.4 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.)
-
-
-
-- ELSE multiply the scale-vector of the instanced scene with the scale-vector (a common property of a 3D node) of the placeholder object.
-
-
-
-TODO: needs intermediate visuals to make things more obvious
-
-
-XR Fragment: pos
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]]
-
-XR Fragment: rot
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]]
-
-XR Fragment: t
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]]
-
-XR audio/video integration
-
-To play global audio/video items:
-
-
-- add a
src: foo.mp3 or src: bar.mp4 metadata to a 3D object (cube e.g.)
-- to enable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (
src: bar.mp3#t=0&loop e.g.)
-- to play it, add
href: #cube somewhere else
-- to enable enduser-triggered play, use a [[URI Template]] XR Fragment: (
src: bar.mp3#{player} and play: t=0&loop and href: xrf://#player=play e.g.)
-- when the enduser clicks the
href, #t=0&loop (play) will be applied to the src value
-
-
-
-NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].
-
-
-XR Fragment filters
-
-Include, exclude, hide/shows objects using space-separated strings:
-
-
-
-
-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 (=*)
-
-
-
-It’s simple but powerful syntax which allows filtering the scene using searchengine prompt-style feeling:
-
-
-- filters are a way to traverse a scene, and filter objects based on their name, tag- or property-values.
-
-
-
-- see an (outdated) example video here which used a dedicated
q= variable (now deprecated and usable directly)
-
-
-including/excluding
-
-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.
-
-
-
-
-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).
-
-
-» example implementation
-» example 3D asset
-» discussion
-
-Filter Parser
-
-Here’s how to write a filter parser:
-
-
-- create an associative array/object to store filter-arguments as objects
-- detect object id’s & properties
foo=1 and foo (reference regex= ~/^.*=[><=]?/ )
-- detect excluders like
-foo,-foo=1,-.foo,-/foo (reference regex= /^-/ )
-- detect root selectors like
/foo (reference regex= /^[-]?\// )
-- detect number values like
foo=1 (reference regex= /^[0-9\.]+$/ )
-- detect operators so you can easily strip keys (reference regex=
/(^-|\*$)/ )
-- detect exclude keys like
-foo (reference regex= /^-/ )
-- for every filter token split string on
=
-- and we set
root to true or false (true=/ root selector is present)
-- therefore we we set
show to true or false (false=excluder -)
-
-
-
-An example filter-parser (which compiles to many languages) can be found here
-
-
-Visible links
-
-When predefined views, XRWG fragments and ID fragments (#cube or #mytag e.g.) are triggered by the enduser (via toplevel URL or clicking href):
-
-
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname)
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that
tag value
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) containing that in their
src or href value
-
-
-The obvious approach for this, is to consult the XRWG (example), which basically has all these things already collected/organized for you during scene-load.
-
-UX
-
-
-- do not update the wires when the enduser moves, leave them as is
-- offer a control near the back/forward button which allows the user to (turn off) control the correlation-intensity of the XRWG
-
-
-Text in XR (tagging,linking to spatial objects)
-
-How does XR Fragments interlink text with objects?
-
-
-The XR Fragments does this by collapsing space into a Word Graph (the XRWG example), augmented by Bib(s)Tex.
-
-
-Instead of just throwing together all kinds media types into one experience (games), what about their tagged/semantical relationships?
-Perhaps the following question is related: why is HTML adopted less in games outside the browser?
-
-Hence:
-
-
-- XR Fragments promotes (de)serializing a scene to a (lowercase) XRWG (example)
-- XR Fragments primes the XRWG, by collecting words from the
tag and name-property of 3D objects.
-- XR Fragments primes the XRWG, by collecting words from optional metadata at the end of content of text (see default mimetype & Data URI)
-- XR Fragments primes the XRWG, by collecting tags/id’s from linked hypermedia (URI fragments for HTML e.g.)
-- The XRWG should be recalculated when textvalues (in
src) change
-- HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they fit better in the application-layer, or as embedded src content)
-- Applications don’t have to be able to access the XRWG programmatically, as they can easily generate one themselves by traversing the scene-nodes.
-- 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)
-- Instead of exact lowercase word-matching, levensteihn-distance-based matching is preferred
-
-
-Example of generating XRWG out of the XRWG and textdata with hashtags:
-
- http://y.io/z.fbx | Derived XRWG (expressed as JSON)
- ----------------------------------------------------------------------------+--------------------------------------
- | Chapter: ['#mydoc']
- +-[src: data:.....]----------------------+ +-[3D mesh]-+ | one: ['#mydoc']
- | Chapter one | | / \ | | houses: ['#castle','#mydoc','#house']
- | | | / \ | | baroque: ['#mydoc','#castle']
- | John built houses in baroque style. | | / \ | | castle: ['#baroque','#house']
- | | | |_____| | | john: ['#john','#mydoc']
- | | +-----│-----+ | mydoc: ['#mydoc']
- | | │ |
- | | ├─ name: castle |
- | | └─ tag: house baroque |
- +----------------------------------------+ |
- └─ name: mydoc [3D mesh-+ |
- | O ├─ name: john |
- | /|\ | |
- | / \ | | ^ ^ ^
- +--------+ | | | |
- |
- [remotestorage.io]+ [ localstorage]-+ | <- the XR Fragment-compatible
- | XRWG (JSON) | | XRWG (JSON | | <- 3D hypermedia viewer should
- | | | | | <- be able to select the active XRWG
- +-----------------+ +---------------+ |
-
-
-This allows hasslefree authoring and copy-paste of associations for and by humans, but also makes these URLs possible:
-
-
-
-
-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.
-
-
-The XRWG allows endusers to show/hide relationships in realtime in XR Browsers at various levels:
-
-
-- wordmatch inside
src text
-- wordmatch inside
href text
-- wordmatch object-names
-- wordmatch object-tagnames
-
-
-Spatial wires can be rendered between words/objects etc.
-Some pointers for good UX (but not necessary to be XR Fragment compatible):
-
-
-- 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)
-- 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.
-- respect multi-line BiBTeX metadata in text because of the core principle
-- Default font (unless specified otherwise) is a modern monospace font, for maximized tabular expressiveness (see the core principle).
-- anti-pattern: hardcoupling an XR Browser with a mandatory markup/scripting-language which departs from onubtrusive plain text (HTML/VRML/Javascript) (see the core principle)
-- anti-pattern: limiting human introspection, by abandoning plain text as first tag citizen.
-
-
-Default Data URI mimetype
-
-The src-values work as expected (respecting mime-types), however:
-
-The XR Fragment specification advices to bump the traditional default browser-mimetype
-
-text/plain;charset=US-ASCII
-
-to a hashtag-friendly one:
-
-text/plain;charset=utf-8;hashtag
-
-This indicates that:
-
-
-- utf-8 is supported by default
-- words beginning with
# (hashtags) will prime the XRWG by adding the hashtag to the XRWG, linking to the current sentence/paragraph/alltext (depending on ‘.’) to the XRWG
-
-
-Advantages:
-
-
-- out-of-the-box (de)multiplex human text and metadata in one go (see the core principle)
-- no network-overhead for metadata (see the core principle)
-- ensuring high FPS: realtime HTML/RDF historically is too ‘requesty’/‘parsy’ for game studios
-- rich send/receive/copy-paste everywhere by default, metadata being retained (see the core principle)
-- netto result: less webservices, therefore less servers, and overall better FPS in XR
-
-
-
-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.).
-
-
-For all other purposes, regular mimetypes can be used (but are not required by the spec).
-
-URL and Data URI
-
- +--------------------------------------------------------------+ +------------------------+
- | | | author.com/article.txt |
- | index.gltf | +------------------------+
- | │ | | |
- | ├── ◻ article_canvas | | Hello #friends |
- | │ └ src: ://author.com/article.txt | | |
- | │ | +------------------------+
- | └── ◻ note_canvas |
- | └ src:`data:welcome human\n@book{sunday...}` |
- | |
- | |
- +--------------------------------------------------------------+
-
-
-The enduser will only see welcome human and Hello friends 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.).
-
-
-additional tagging using bibs: to tag spatial object note_canvas with ‘todo’, the enduser can type or speak #note_canvas@todo
-
-
-Importing/exporting
-
-For usecases like importing/exporting/p2p casting a scene, the issue of external files comes into play.
-
-
-- export: if the 3D scene contains relative src/href values, rewrite them into absolute URL values.
-
-
-Reflection Mapping
-
-Environment mapping is crucial for creating realistic reflections and lighting effects on 3D objects.
-To apply environment mapping efficiently in a 3D scene, traverse the scene graph and assign each object’s environment map based on the nearest ancestor’s texture map. This ensures that objects inherit the correct environment mapping from their closest parent with a texture, enhancing the visual consistency and realism.
-
- +--------------------------------+
- | |
- | index.usdz |
- | │ |
- | └── ◻ sphere (texture:foo) |
- | └ ◻ cube (texture:bar) | envMap = foo
- | └ ◻ cylinder | envMap = bar
- +--------------------------------+
-
-
-Most 3D viewers apply one and the same environment map for various models, however this logic
-allows a more natural & automatic strategy for reflection mapping:
-
-
-- traverse the scene graph depth-first
-- remember the most recent parentnode (P) with a texture material
-- for every non-root node with a texture material
-3.1 clone that material (as materials might be shared across objects)
-3.2 set the environmentmap to the last known parent texture (P)
-
-
-Transclusion (broken link) resolution
-
-In spirit of Ted Nelson’s ‘transclusion resolution’, there’s a soft-mechanism to harden links & minimize broken links in various ways:
-
-
-- defining a different transport protocol (https vs ipfs or DAT) in
src or href values can make a difference
-- mirroring files on another protocol using (HTTP) errorcode tags in
src or href properties
-- in case of
src: nesting a copy of the embedded object in the placeholder object (embeddedObject) will not be replaced when the request fails
-
-
-
-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.)
-
-
-For example:
-
- +────────────────────────────────────────────────────────+
- │ │
- │ 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.
- │ │
- +────────────────────────────────────────────────────────+
-
-
-
-Topic-based index-less Webrings
-
-As hashtags in URLs map to the XWRG, href-values can be used to promote topic-based index-less webrings.
-Consider 3D scenes linking to eachother using these href values:
+Consider 3D scenes linking to eachother using these href values, attached to 3D button-objects:
href: schoolA.edu/projects.gltf#math
@@ -1393,47 +883,19 @@ Consider 3D scenes linking to eachother using these href values:href: university.edu/projects.gltf#math
-These links would all show visible links to math-tagged objects in the scene.
-To filter out non-related objects one could take it a step further using filters:
+This would teleport users to the math-projects of those universities.
+Now consider adding a ‘webring index’-button to each file, with this href-value:
-href: schoolA.edu/projects.gltf#math&-topics math
-href: schoolB.edu/projects.gltf#math&-courses math
-href: university.edu/projects.gltf#math&-theme math
+- href: workgroup.edu/webrings.glb#!webringmenu
-
-This would hide all object tagged with topic, courses or theme (including math) so that later only objects tagged with math will be visible
-
+This would allow displaying the (remote 3D file) webring menu with various href-buttons inside, all centrally curated by the workgroup.
-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.
-
-URI Templates (RFC6570)
+Level5: URI Templates (RFC6570)
XR Fragments adopts Level1 URI Fragment expansion to provide safe interactivity.
-The following demonstrates a simple video player:
-
-
- +─────────────────────────────────────────────+
- │ │
- │ 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} │
- │ │
- │ │
- +─────────────────────────────────────────────+
-
-
-
+This is non-normative, and the draft spec is available on request.
Additional scene metadata
@@ -1443,10 +905,13 @@ Instead, it encourages browsers to scan nodes for the following custom propertie
- SPDX license information
- ARIA attributes (
aria-*: .....)
+- datapackage.json findability, accessibility, interoperability, and reusability of data
+ARIA’s aria-description-metadata is normative, to aid accessibility and scene transcripts
+
-SPDX and ARIA’s aria-description are normative, as they promote accessibility and scene transcripts: please start aria-description with a verb to aid transcripts.
+NOTE: please always start aria-description with a verb to aid transcripts.
The following metadata are non-normative but encouraged, since they are popular and cheap to parse:
diff --git a/doc/RFC_XR_Fragments.md b/doc/RFC_XR_Fragments.md
index 4bf3471..abee146 100644
--- a/doc/RFC_XR_Fragments.md
+++ b/doc/RFC_XR_Fragments.md
@@ -95,11 +95,11 @@ value: draft-XRFRAGMENTS-leonvankammen-00
An open specification for hyperlinking & deeplinking 3D fileformats.
This draft is a specification for interactive URI-controllable 3D files, enabling [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.
-The specification uses [W3C Media Fragments](https://www.w3.org/TR/media-frags/) and [URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
XR Fragments allows us to better use implicit metadata inside 3D scene(files), by mapping it to proven technologies like [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment).
-XR Fragments views XR experiences thru the lens of 3D object URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
+XR Fragments views XR experiences thru the lens of 3D deeplinked URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
+The standard comprises of various (optional) support levels, which also include [W3C Media Fragments](https://www.w3.org/TR/media-frags/) and [URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
-> XR Fragments is a heuristical 3D format which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
+> XR Fragments is in a sense, a heuristical 3D format or meta-format, which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
These heuristics, enable features that are both meaningful and consistent across different scene representations, allowing higher interop between fileformats, 3D editors, viewers and game-engines.
> Almost every idea in this document is demonstrated at [https://xrfragment.org](https://xrfragment.org)
@@ -113,7 +113,7 @@ Historically, there's many attempts to create the ultimate 3D fileformat.
The lowest common denominator is: designers describing/tagging/naming things using **plain text**.
XR Fragments exploits the fact that all 3D models already contain such metadata:
-**XR Fragments allows controlling of metadata in 3D scene(files) using URI's**
+**XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments**
It solves:
@@ -125,113 +125,35 @@ It solves:
> NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
-# Core principle
-
-**XR Fragments allows controlling 3D models using URLs, based on (non)existing metadata via URI's**
-
-XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
-Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments **integrates all** which allows a universal viewing experience.
-
-```
- +───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ U R N │
- │ U R L | │
- │ | |-----------------+--------| │
- │ +--------------------------------------------------| │
- │ | │
- │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │
- │ | │
- │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │
- │ │
- │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │
- │ │
- │ │
- │ |------------------------+-------------------------| │
- │ | │
- │ U R I │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
-```
-
-Fact: our typical browser URL's are just **a possible implementation** of URI's (for untapped humancentric potential of URI's [see interpeer.io](https://interpeer.io))
-
-> 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.
-
-Below you can see how this translates back into good-old URLs:
-
-```
- +───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ the soul of any URL: ://macro /meso ?micro #nano │
- │ │
- │ 2D URL: ://library.com /document ?search #chapter │
- │ xrf:// │
- │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #view ───> hashbus │
- │ │ #filter │ │
- │ │ #tag │ │
- │ │ (hypermediatic) #material │ │
- │ │ ( feedback ) #animation │ │
- │ │ ( loop ) #texture │ │
- │ │ #variable │ │
- │ │ │ │
- │ XRWG <─────────────────────<─────────────+ │
- │ │ │ │
- │ └─ objects ──────────────>─────────────+ │
- │ │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
-```
-
-> ?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
-
-Traditional webbrowsers can become 4D document-ready by:
-
-# The XR Fragments Trinity
+# What is XR Fragments
XR Fragments utilizes URLs:
-1. for 3D viewers/browser to manipulate the camera or objects (via URLbar)
-2. as **implicit** metadata to reference (nested) objects **inside** 3D scene-file (local and remote)
-3. via **explicit** metadata ('extras') **inside** 3D scene-files (interaction e.g.) or
-4. [optionally for developers] via **explicit** metadata **outside** 3D scene-files (via [sidecarfile](https://en.wikipedia.org/wiki/Sidecar_file))
+1. for 3D viewers/browser to manipulate the camera or objects (via URI fragments)
+2. implicitly: by mapping 3D objectnames (of a 3D scene/file) to URI fragments (3D deeplinking)
+3. explicitly: by scanning `href` metadata **inside** 3D scene-files to enable interactions
+4. externally: progressively enhance a 3D (file) into an experience via [sidecarfiles](https://en.wikipedia.org/wiki/Sidecar_file)
-# List of URI Fragments
-
-| fragment | type | example | info |
-|-------------------|------------|--------------------|----------------------------------------------------------------------|
-| `#......` | vector3 | `#room1` `#room2` `#cam2` | positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector |
-| [Media Fragments](https://www.w3.org/TR/media-frags/) | [media fragment](#media%20fragments%20and%20datatypes) | `#t=0,2&loop` | play (and loop) 3D animation from 0 seconds till 2 seconds|
-
-
-# List of **explicit* metadata
-
-These are the possible 'extras' for 3D nodes and sidecar-files
-
-| key | type | example (JSON) | function | existing compatibility |
-|--------------|----------|------------------------|---------------------|----------------------------------------|
-| `href` | string | `"href": "b.gltf"` | XR teleport | custom property in 3D fileformats |
# HFL (Hypermediatic Feedback Loop) for XR Browsers
-`href` metadata traditionally implies **click** AND **navigate**, however XR Fragments adds stateless **click** (`xrf://#....`) or **navigate** (`xrf://#...`)
- as well (which allows many extra interactions which otherwise need a scripting language). This is known as **hashbus**-only events (see image above).
+`href` metadata traditionally implies **click** AND **navigate**, however XR Fragments adds stateless **click** (`xrf://....`) via the `xrf://` scheme, which does not change the top-level URL-adress (of the browser).
+This allows for many extra interactions via URLs, which otherwise needs a scripting language.
+These are called **hashbus**-only events/
-> Being able to use the same URI Fragment DSL for navigation (`href: #foo`) as well as interactions (`href: xrf://#bar`) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
+> Being able to use the same URI Fragment DSL for navigation (`href: #foo`) as well as interactions (`href: xrf://#foo`) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
This opens up the following benefits for traditional & future webbrowsers:
* [hypermediatic](https://github.com/coderofsalvation/hypermediatic) loading/clicking 3D assets (gltf/fbx e.g.) natively (with or without using HTML).
-* allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the `xrf://` hashbus (`xrf://#person=walk` to trigger `walk`-animation for object `person`)
-* collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
+* potentially allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the `xrf://` hashbus (`xrf://#person=walk` to trigger `walk`-animation for object `person`)
+* potentially collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
* completely bypassing the security-trap of loading external scripts (by loading 3D model-files, not HTML-javascriptable resources)
XR Fragments itself are [hypermediatic](https://github.com/coderofsalvation/hypermediatic) and HTML-agnostic, though pseudo-XR Fragment browsers **can** be implemented on top of HTML/Javascript.
-| principle | XR 4D URL | HTML 2D URL |
+| principle | 3D URL | HTML 2D URL |
|-----------------------------|-------------------------------------------------|---------------------------------------|
| the XRWG | wordgraph (collapses 3D scene to tags) | Ctrl-F (find) |
| the hashbus | hashtags alter camera/scene/object-projections | hashtags alter document positions |
@@ -265,7 +187,7 @@ sub-delims = "," / "="
| Demo | Explanation |
|-------------------------------|---------------------------------|
| `room1` | vector/coordinate argument e.g. |
-| `room1&rot=0,90,0&cam1` | combinators |
+| `room1&cam1` | combinators |
> this is already implemented in all browsers
@@ -275,7 +197,8 @@ That way, if the link gets shared, the XR Fragments implementation at `https://m
# Spatial Referencing 3D
-XR Fragments assume the following objectname-to-URIFragment mapping:
+3D files contain an hierarchy of objects.
+XR Fragments assumes the following objectname-to-URI-Fragment mapping, in order to deeplink 3D objects:
```
@@ -302,50 +225,92 @@ Clever nested design of 3D scenes allow great ways for re-using content, and/or
For example, to render a portal with a preview-version of the scene, create an 3D object with:
* href: `https://scene.fbx`
-* src: `https://otherworld.gltf#mainobject`
> It also allows **sourceportation**, which basically means the enduser can teleport to the original XR Document of an `src` embedded object, and see a visible connection to the particular embedded object. Basically an embedded link becoming an outbound link by activating it.
+# Level0: Files
----
+These are **optional** auto-loaded [side-car files]() to enable hasslefree [XR Movies](#XR%20Movies).
+they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a `.glb` e.g.).
-# non-normative
+## via href metadata
-The following below is non-normative heuristics which are not part officially part of the spec.
+```
+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)
+```
-# additional **explicit** metadata
+**heuristics**:
-| `#rot` | vector3 | `#rot=0,90,0` | rotates camera to xyz-coord 0.5,0,0 |
-| `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 |
+* if at least one `href` custom property/extra is found in a 3D scene
+* The viewer should poll for the above mentioned sidecar-file extensions (and present accordingly)
-> Supported popular compatible 3D fileformats: `.gltf`, `.obj`, `.fbx`, `.usdz`, `.json` (THREE.js), `.dae` and so on.
+## via chained extension
-## Sidecar-file
+```
+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)
+```
-> 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.).
+> A fallback-mechanism to turn 3D files into [XR Movies](#XR%20Movies) without editing them.
-For developers, sidecar-file can allow for defining **explicit** XR Fragments metadata, outside of the 3D file.
-This can be done via a JSON-pointers [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) in a JSON [sidecar-file](https://en.wikipedia.org/wiki/Sidecar_file):
+**heuristics**:
+
+* the chained-extension heuristic `.xrf.` should be present in the filename (`scene.xrf.glb` e.g.)
+
+## via subdocuments/xattr
+
+More secure protocols (Nextgraph e.g.) don't allow for simply polling files.
+In such case, subdocuments or extended attributes should be polled:
+
+> NOTE: in the examples below we use the href-heuristic, but also the `.xrf.` chained-extension applies here.
+
+```
+myspreadsheet.ods
+└── explainer.glb <--- 'href' extra [heuristic] detected inside!
+ ├── explainer.ogg (soundtrack to play when global 3D animation starts)
+ ├── explainer.png (preview thumnbnail)
+ ├── explainer.json (sidecar JSON-file with explicit metadata)
+ └── explainer.vtt (subtitles for accessibility or screenreaders)
+```
+
+If only extended attributes (xattr) are available, the respective referenced file can be embedded:
+
+```
+$ setfattr -n explainer.ogg -v "soundtrack.ogg" explainer.glb
+$ setfattr -n explainer.png -v "thumbnail.png" explainer.glb
+$ setfattr -n explainer.vtt -v "subtitles.vtt" explainer.glb
+```
+
+> NOTE: Linux's `setfattr/getfattr` is `xattr` on mac, and `Set-Content/Get-content` on Windows. See [pxattr](https://www.lesbonscomptes.com/pxattr/index.html) for lowlevel access.
+
+## JSON sidecar-file
+
+For developers, sidecar-file can allow for defining **explicit** XR Fragments links (>level1), outside of the 3D file.
+This can be done via (objectname/metadata) key/value-pairs in a JSON [sidecar-file](https://en.wikipedia.org/wiki/Sidecar_file):
* experience.glb
-* experience.json
+* experience.json `<----`
```json
{
- "/":{
- "#": "#-penguin",
+ "/":
"aria-description": "description of scene",
},
- "/room/chair": {
- "href": "#penguin"
+ "button": {
+ "href": "#roomB"
}
}
```
-> This would mean: hide object(s) with name or `tag`-value 'penguin' upon scene-load, and show it when the user clicks the chair
+> This will make object `button` clickable, and teleport the user to object `roomB`.
So after loading `experience.glb` the existence of `experience.json` is detected, to apply the explicit metadata.
The sidecar will define (or **override** already existing) extras, which can be handy for multi-user platforms (offer 3D scene customization/personalization to users).
@@ -353,227 +318,319 @@ The sidecar will define (or **override** already existing) extras, which can be
> In THREE.js-code this would boil down to:
```javascript
- scene.userData['#'] = "#chair&penguin"
scene.userData['aria-description'] = "description of scene"
- scene.getObjectByName("room").getObjectByName("chair").userData.href = "#penguin"
+ scene.getObjectByName("button").userData.href = "#roomB"
// now the XR Fragments parser can process the XR Fragments userData 'extras' in the scene
```
+# Level1: URI
+> **XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments**
-
-## Level2: Implicit URI Fragments
-
-> Warning: non-normative
-
-These fragments are derived from objectnames (or their extras) within a 3D scene, and trigger certain actions when evaluated by the browser:
-
-| |fragment | type | example | info |
-|------|------------------|----------|-------------------|-------------------------------------------------------------------------------|
-| **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** | `xrf://#` | string | `#person` | (and show) object(s) with `tag: person` or name `person` (XRWG lookup) |
-| **FILTERS** | `#[!][-][*]` | 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** | `#[*]=` | 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** | `#=` | string=string | `#foo=bar` | sets [URI Template](https://www.rfc-editor.org/rfc/rfc6570) variable `foo` to the value `#t=0` from **existing** object metadata (`bar`:`#t=0` e.g.), This allows for reactive [URI Template](https://www.rfc-editor.org/rfc/rfc6570) defined in object metadata elsewhere (`src`:`://m.com/cat.mp4#{foo}` e.g., to play media using [media fragment URI](https://www.w3.org/TR/media-frags/#valid-uri)). NOTE: metadata-key should not start with `#` |
-| **ANIMATION** | `#=` | string=string | `#people=walk` `#people=noanim` | assign a different animation to object(s) |
-
-## media fragments and datatypes
-
-> Warning: **non-normative** (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:= | u:color=1,0,0 | set shader uniform value |
-
-> \* = this is extending the [W3C media fragments](https://www.w3.org/TR/media-frags/#mf-advanced) 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).
-
-Example URI's:
-
-* `https://images.org/credits.jpg#uv=0,0,0,+0.1` (infinite vertical texturescrolling)
-* `https://video.org/organogram.mp4#t=0&loop&uv=0.1,0.1,0.3,0.3` (animated tween towards region in looped video)
-* `https://shaders.org/plasma.glsl#t=0&u:col2=0,1,0` (red-green shader plasma starts playing from time-offset 0)
+XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
+Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments **integrates all** which allows a universal viewing experience.
```
- +──────────────────────────────────────────────────────────+
- │ │
- │ 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).
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ 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 │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
```
-# Navigating 3D
+Fact: our typical browser URL's are just **a possible implementation** of URI's (for untapped humancentric potential of URI's [see interpeer.io](https://interpeer.io) or [NextGraph](https://nextgraph.org) )
+
+> XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
But approaches things from a higherlevel local-first 3D hypermedia browser-perspective.
+
+Below you can see how this translates back into good-old URLs:
+
+```
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ the soul of any URL: ://macro /meso ?micro #nano │
+ │ │
+ │ 2D URL: ://library.com /document ?search #chapter │
+ │ xrf:// │
+ │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #object ─> hashbus │
+ │ │ #filter │ │
+ │ │ #tag │ │
+ │ │ (hypermediatic) #material │ │
+ │ │ ( feedback ) #animation │ │
+ │ │ ( loop ) #texture │ │
+ │ │ #variable │ │
+ │ │ │ │
+ │ XRWG <─────────────────────<─────────────+ │
+ │ │ │ │
+ │ └─ objects ──────────────>─────────────+ │
+ │ │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+
+```
+
+> ?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
+
+# List of URI Fragments
+
+| fragment | type | example | info |
+|-------------------|------------|--------------------|----------------------------------------------------------------------|
+| `#......` | vector3 | `#room1` `#room2` `#cam2` | positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector |
+| [Media Fragments](https://www.w3.org/TR/media-frags/) | [media fragment](#media%20fragments%20and%20datatypes) | `#t=0,2&loop` | play (and loop) 3D animation from 0 seconds till 2 seconds|
+
+
+# List of **explicit* metadata
+
+These are the possible 'extras' for 3D nodes and sidecar-files
+
+| key | type | example (JSON) | function | existing compatibility |
+|--------------|----------|------------------------|---------------------|----------------------------------------|
+| `href` | string | `"href": "b.gltf"` | XR teleport | custom property in 3D fileformats |
+
+
+# Level2: href links
+
+Explicit href metadata ('extras') in a 3D object (of a 3D file), hint the viewer that the user ''can interact'' with that object :
+
+| fragment | type | example value |
+|`href`| string (uri or predefined view) | `#pyramid`
`#lastvisit`
`xrf://#-someobject`
`://somefile.gltf#foo`
|
+
+## Interaction behaviour
+
+When clicking an ''href''-value, the user(camera) is teleport to the referenced object.
+
+The imported/teleported destination can be another object in the same scene-file, or a different file.
+
+## XR Viewer implementation
+
+| **spec** | **action** | **feature** |
+|-|-|-|
+| level0+1 | hover 3D file [href](#via-href-metadata) | show the preview PNG thumbnail (if any). |
+| level0+1 | launch 3D file [href](#via-href-metadata) | replace the current scene with a new 3D file (`href: other.glb` e.g.) |
+| level2 | click internal 3D file [href](#via-href-metadata) (`#roomB` e.g.) | teleport the camera to the origin of object(name `roomB`). See [[teleport camera]].|
+| level2 | click external 3D file [href](#via-href-metadata) (`foo.glb` e.g.) | replace the current scene with a new 3D file (`href: other.glb` e.g.) |
+| level2 | hover external 3D file [href](#via-href-metadata) | show the preview PNG thumbnail (if any sidecar, see level0) |
+| level2 | click [href](#via-href-metadata) | hashbus: execute without changing the toplevel URL location (`href: xrf://#someObjectName` e.g.) |
+| level3 | click [href](#via-href-metadata) | set the global 3D animation timeline to its Media Fragment value (`#t=2,3` e.g.) |
+
+> NOTE: hashbus links (`xrf://#foo&bar`) don't change the toplevel URL, which makes it ideal for interactions (in contrast to typical `#roomC` navigation, which benefit back/forward browser-buttons), see hashbus for more info.
+
+# Level3: Media Fragments
+
+> these allow for XR Movies with a controllable timeline using `href` URI's with Media Fragments
+
+Just like with 2D media-files, W3C mediafragments (`#t=1,2`) can be used to control a timeline via the [#t](##t) primitive.
+XR Fragments Level3 makes the 3D timeline, as well as URL-referenced files **controllable** via Media Fragments like:
+
+* level2 hrefs (`href: #t=4` e.g. to control 3D timeline)
+* level4: `xrf:` URI scheme:
+ * `href: xrf:foo.wav#t=0` to play a wav
+ * `href: xrf:news.glb?clone#t=0` to instance and play another experience
+
+## Animation(s) timeline
+
+controls the animation(s) of the scene (or `src` resource which contains a timeline)
| fragment | type | functionality |
-|----------|--------|------------------------------|
-| #=room1 | string | position camera to position and upvector of objectname `room1` (+userheight in VR) |
+| #t=start,stop | [[vector2]] (default:`#t=0,0`) | start,stop (in seconds |
-[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js)
-[» discussion](https://github.com/coderofsalvation/xrfragment/issues/5)
-Here's the basic **level1** flow (with optional level2 features):
+| Example Value | Explanation |
+| `#t=1` | play (3D) animations from 1 seconds till end (and stop) |
+| `#t=1,100` | play (3D) animations from 1 till 100 seconds (and stop) |
+| `#t=0,0` | stop (3D) animations at frame 0 |
-1. the Y-coordinate of `room1 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), except in case of camera-switching.
-2. set the position of the camera accordingly to the vector3 values of `room1`
-3. set the upvector of the camera accordingly to the vector3 values of `room1` (local gravity as pioneered by Patrick Lichty)
-3. if the referenced `#room1` object is animated, parent the current camera to that object (so it animates too)
-4. in case a `href` does not mention any 3D object, the current position will be assumed
+> Use [[#s 🌱]] to control playback speed
-Here's an ascii representation of a 3D scene-graph which contains 3D objects `◻` and their metadata:
+## Specify playback loopmode
+
+This compensates a missing element from Media Fragments to enable/disable temporal looping. .
+
+| fragment | type | functionality |
+| #loop | string | enables animation/video/audio loop |
+| #-loop | string | disables animation/video/audio loop |
+
+
+## Controlling embedded content
+
+use [[URI Templates]] to control embedded media, for example a simple video-player:
```
- +────────────────────────────────────────────────────────+
- │ │
- │ index.gltf │
- │ │ │
- │ ├── ◻ buttonA │
- │ │ └ href: #room1&t=100,200 │
- │ │ │
- │ └── ◻ buttonB │
- │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc)
- │ │
- +────────────────────────────────────────────────────────+
+ 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
```
-An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the `buttonA` and `buttonB`.
-In case of `buttonA` the end-user will be teleported to another location and time in the **current loaded scene**, but `buttonB` will **replace the current scene** with a new one, like `other.fbx`, and assume camera coordinate `0,0,0`
+# Level4: prefix operators
-**Non-normative**:
+Prefixing objectnames with the following simple operators allow for **extremely powerful** XR interactions:
-5. `rot` sets the rotation of the camera (only for non-VR/AR headsets, however a camera-value overrules this)
-6. **level2**: mediafragment `t` in the top-URL sets the playbackspeed and animation-range of the global scene animation
-7. before scene load: the scene is cleared
-8. **level2**: after scene load: in case the scene (rootnode) contains an `#` default view with a fragment value: execute non-positional fragments via the hashbus (no top-level URL change)
-9. **level2**: after scene load: in case the scene (rootnode) contains an `#` default view with a fragment value: execute positional fragment via the hashbus + update top-level URL
-10. **level2**: in case of no default `#` view on the scene (rootnode), default player(rig) position `0,0,0` is assumed.
+* #!
+* #*
+* #+ or #-
+* #|
+* xrf: URI scheme
+
+> **Examples:** `#+menu` to show a object, `#-menu` to hide a menu, `#!menu` to teleport a menu, `#*block` to clone a grabbable block, `#|object` to share an object
+
+
+## Object teleports (!)
+
+Prefixing an object with an exclamation-symbol, will teleport a (local or remote) referenced object from/to its original/usercamera location.
+
+[img[objecteleport.png]]
+
+Usecases:
+* show/hide objects/buttons (menu e.g.) in front of user
+* embed remote (object within) 3D file via remote URL
+* instance an interactive object near the user regardless of location
+* instance HUD or semi-transparent-textured-sphere (LUT) around the user
+
+
+ #!menu
+
+
+
+Clicking the [href](#via-href-metadata)-value above will:
+
+1. **reposition the referenced object** (menu) to the usercamera's-coordinates.
+2. **zoom** in case of (non-empty) mesh-object: rescale to 1 m³, and position 1m in front of the camera
+3. toggle behaviour: revert values if 1/2 were already applied
+4. `#+` is always implied (objects are always made visible)
+
+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.).
+
+* href: `#whiteroom&!explainer&!exitmenu`
+
+> This will teleport the user to `whiteroom` and moves object `explainer` and `exitmenu` in front of the user.
+
+* href: `https://my.org/foo.glb#!
+
+Clicking the [href](#via-href-metadata)-value above will:
+
+1. import `foo.glb` from `my.org`'s webserver
+2. show it in front of the user (because `#!` indicates object teleport)
+
+* href: `https://foo.glb#roomB&!bar`
+
+Clicking the [href](#via-href-metadata)-value above will:
+
+1. replace the current scene with `foo.glb`
+2. teleport the user to #roomB inside `foo.glb`
+3. **instance the referenced object** (bar inside foo.glb) in front of the user.
+4. it will update the top-Level URL (because `xrf:` was not used)
+5. hide the **instanced object** when clicked again (toggle visibility)
+
+> **NOTE**: level2 teleportation links, as well as instancing mitigates the 'broken embedded image'-issue of HTML: **always** attaching the href-values to **a 3D (preview) object** (that way broken links will not break the design).
+
+**Example:** clicking a 3D button with title 'menu' and [href](#href)-value `xrf:menu.glb?instance#t=4,5` would instance a 3D menu (`menu.glb`) in front of the user, and loop its animation between from 4-5 seconds (`t=4,5`)
+
+> **NOTE**: combining instance-operators allows dynamic construction of 3D scenes (`#london&!welcomeMenu&!fadeBox` e.g.)
+
+## Object multipliers (*)
+
+The star-prefix will clone a (local or remote) referenced object to the usercamera's location, and make it grabbable.
+Usecases:
+* object-picker (build stuff with objects)
+
+> **NOTE**: this is basically the [#! operator](#%23%21) which infinitely **clones** the referenced object (instead of repositioning the object).
+
+## De/selectors (+ and -)
+
+* href: `#-welcome` (or `#+welcome`)
+
+Clicking href-value above will do:
+
+1. show/hide the target object (and children)
+
+* href: `#https://my.org/foo.glb/#bar&-welcome`
+
+> **NOTE:** the latter shows that (de)selectors can also be with regular [href](#href)-values
+
+## Sharing object or file (#|)
+
+The pipe-symbol (`|`) sends a (targeted) object to the OS.
+Clicking the href-value below will:
+
+1. share the (targeted object in the) file to a another application
+
+> This URL can be fed straight into [Web Share API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API) or [xdg-open](https://www.freedesktop.org/wiki/Software/xdg-utils/)
+
+* href: `xrf://#|bar`
+
+> **NOTE**: sharing is limited to (internal objects) via `xrf:` scheme-only
+
+## xrf:// URI scheme
+
+Prefixing the `xrf:` to [href](#href)-values **will prevent** [level2](#📜%20level2:%20explicit%20links) [href](#href)-values from changing the top-Level URL.
+
+> **Usecase**: for non-shareable URLs like `href: xrf:#t=4,5`, to display a stateful msg e.g.).
+
+**Reason:** XR Fragments is inspired by HTML's [href-attribute](https://en.wikipedia.org/wiki/Hyperlink), which does various things:
+
+1. it updates the browser-location
+2. it makes something clickable
+3. it jumps to another document / elsewhere in the same document
+4. and more
+
+The `xrf:` scheme will just do 2 & 3 (so the URL-values will not leak into the top-level URL).
+
+> **compliance with RFC 3986**: unimplemented/unknown URI schemes (`xrf:...` e.g.) will not update the top-level URL
# Top-level URL processing
-> Example URL: `://foo/world.gltf#room1&t=10`
+> Example URL: `://foo/world.gltf#room1&t=10&cam`
The URL-processing-flow for hypermedia browsers goes like this:
-1. IF a `#room1` matches a custom property-key (of an object) in the 3D file/scene (`#room1`: `#......`) THEN execute that predefined_view.
-2. IF scene operators and/or animation operator (`t`) are present in the URL then (re)position the camera (to `room1`) and/or animation-range (`10`) accordingly.
-3. IF no camera-position has been set in step 1 or 2 assume `0,0,0` as camera coordinate (XR: add user-height) ([example](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/navigator.js#L31]]))
+1. IF scene operators and/or animation operator (`t`) are present in the URL then (re)position the camera (to `room1`) and/or animation-range (`10`) accordingly.
+2. IF no camera-position has been set in step 1 or 2 assume `0,0,0` as camera coordinate (XR: add user-height) ([example](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/navigator.js#L31]]))
+3. IF a camera-object exists with name `cam` assume that user(camera) position
-**Non-normative / Deprecated**:
+## UX
-4. IF a `#cube` 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).
-5. IF a `#cube` matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects).
+End-users should always have read/write access to:
-# Embedding XR content using src
+1. the current (toplevel) URL (an URLbar etc)
+2. URL-history (a back/forward button e.g.)
+3. Clicking/Touching an `href` navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-> NOTE: only adviced for local-first experiences (where resources can be cached).
-`src` is the 3D version of the iframe.
-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.
-
-| fragment | type | example value |
-|----------|------|---------------|
-|`src`| string (uri, hashtag/filter) | `#cube`
`#sometag`
#cube&-ball_inside_cube`
`#-sky&-rain`
`#-language&english`
`#price=>5`
`https://linux.org/penguin.png`
`https://linux.world/distrowatch.gltf#t=1,100`
`linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply`
`androidapp://page1?tutorial#room1&t1,100`
`foo.mp3#0,0,0`|
-
-Here's an ascii representation of a 3D scene-graph with 3D objects `◻` which embeds remote & local 3D objects `◻` with/out using filters:
-
-```
- +────────────────────────────────────────────────────────+ +─────────────────────────+
- │ │ │ │
- │ 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 │
- │ │
- +────────────────────────────────────────────────────────+
-```
-
-An XR Fragment-compatible browser viewing this scene, lazy-loads and projects `painting.png` onto the (plane) object called `canvas` (which is copy-instanced in the bed and livingroom).
-Also, after lazy-loading `ocean.com/aquarium.gltf`, only the queried objects `fishbowl` (and `bass` and `tuna`) will be instanced inside `aquariumcube`.
-Resizing will be happen accordingly to its placeholder object `aquariumcube`, see chapter Scaling.
-
-> Instead of cherrypicking a rootobject `#fishbowl` with `src`, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
-
-**Specification**:
-
-1. local/remote content is instanced by the `src` (filter) value (and attaches it to the placeholder mesh containing the `src` property)
-2. by default all objects are loaded into the instanced src (scene) object (but not shown yet)
-2. local `src` values (`#...` e.g.) starting with a non-negating filter (`#cube` e.g.) will (deep)reparent that object (with name `cube`) as the new root of the scene at position 0,0,0
-3. local `src` values should respect (negative) filters (`#-foo&price=>3`)
-4. the instanced scene (from a `src` value) should be scaled accordingly to its placeholder object or scaled relatively based on the scale-property (of a geometry-less placeholder, an 'empty'-object in blender e.g.). For more info see Chapter Scaling.
-5. external `src` 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:
-6. `src` values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see [broken links](#links))
-7. external `src` values should respect the fallback link mechanism (see [broken links](#broken-links)
-8. 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.
-9. src-values are non-recursive: when linking to an external object (`src: foo.fbx#bar`), then `src`-metadata on object `bar` should be ignored.
-10. an external `src`-value should always allow a sourceportation icon within 3 meter: teleporting to the origin URI to which the object belongs.
-11. when only one object was cherrypicked (`#cube` e.g.), set its position to `0,0,0`
-12. when the enduser clicks an href with `#t=1,0,0` (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.)
-13. a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial `src`-values (an object `#world3` or URL `world3.fbx` e.g.).
-
-* `model/gltf-binary`
-* `model/gltf+json`
-* `image/png`
-* `image/jpg`
-* `text/plain;charset=utf-8`
-
-[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js)
-[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/src.gltf#L192)
-[» discussion](https://github.com/coderofsalvation/xrfragment/issues/4)
-
-# Navigating content href portals
+# Example: Navigating content href portals
navigation, portals & mutations
| fragment | type | example value |
|----------|---------------------------------|---------------------------------------------------------------------------------------------------------------------------|
-|`href` | string (uri or predefined view) | `#room1`
`#room1&rot=90,0,0`
`://somefile.gltf#room1`
|
+|`href` | string (uri or predefined view) | `#room1`
`#room1`
`://somefile.gltf#room1`
|
-1. clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes `room2&rot=0,0,0` by default (unless specified)
+1. clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes `room2` by default (unless specified)
2. relocation/reorientation should happen locally for local URI's (`#....`)
@@ -597,377 +654,34 @@ navigation, portals & mutations
## Walking surfaces
+> By default position `0,0,0` of the 3D scene represents the walkable plane, however this is overridden when the following applies:
+
XR Fragment-compatible viewers can infer this data based scanning the scene for:
-1. materialless (nameless & textureless) mesh-objects (without `src` and `href`)
+1. materialless (nameless & textureless) mesh-objects (without `href` and >0 faces)
> optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.
-## UX spec
+# Virtual world rings
-End-users should always have read/write access to:
-
-1. the current (toplevel) URL (an URLbar etc)
-2. URL-history (a back/forward button e.g.)
-3. Clicking/Touching an `href` navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-
-
-## Scaling instanced content
-
-Sometimes embedded properties (like `src`) instance new objects.
-But what about their scale?
-How does the scale of the object (with the embedded properties) impact the scale of the referenced content?
-
-> 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.).
-
-1. IF an embedded property (`src` e.g.) is set on an non-empty placeholder object (geometry of >2 vertices):
-
-* calculate the bounding box of the ''placeholder'' object (maxsize=1.4 e.g.)
-* hide the ''placeholder'' object (material e.g.)
-* instance the `src` scene as a child of the existing object
-* calculate the bounding box of the instanced scene, and scale it accordingly (to 1.4 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.)
-
-2. ELSE multiply the scale-vector of the instanced scene with the scale-vector (a common property of a 3D node) of the placeholder object.
-
-> TODO: needs intermediate visuals to make things more obvious
-
-# XR Fragment: pos
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]]
-
-# XR Fragment: rot
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js]]
-
-# XR Fragment: t
-
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]]
-
-# XR audio/video integration
-
-To play global audio/video items:
-
-1. add a `src: foo.mp3` or `src: bar.mp4` metadata to a 3D object (`cube` e.g.)
-1. to enable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (`src: bar.mp3#t=0&loop` e.g.)
-1. to play it, add `href: #cube` somewhere else
-1. to enable enduser-triggered play, use a [[URI Template]] XR Fragment: (`src: bar.mp3#{player}` and `play: t=0&loop` and `href: xrf://#player=play` e.g.)
-1. when the enduser clicks the `href`, `#t=0&loop` (play) will be applied to the `src` value
-
-> NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].
-
-# XR Fragment filters
-
-Include, exclude, hide/shows objects using space-separated strings:
-
-| 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 (=`*`) |
-
-It's simple but powerful syntax which allows filtering the scene using searchengine prompt-style feeling:
-
-1. filters are a way to traverse a scene, and filter objects based on their name, tag- or property-values.
-
-* see [an (outdated) example video here](https://coderofsalvation.github.io/xrfragment.media/queries.mp4) which used a dedicated `q=` variable (now deprecated and usable directly)
-
-## including/excluding
-
-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.
-
-| 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).
-
-[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/q.js)
-[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/filter.gltf#L192)
-[» discussion](https://github.com/coderofsalvation/xrfragment/issues/3)
-
-## Filter Parser
-
-Here's how to write a filter parser:
-
-1. create an associative array/object to store filter-arguments as objects
-1. detect object id's & properties `foo=1` and `foo` (reference regex= `~/^.*=[><=]?/` )
-1. detect excluders like `-foo`,`-foo=1`,`-.foo`,`-/foo` (reference regex= `/^-/` )
-1. detect root selectors like `/foo` (reference regex= `/^[-]?\//` )
-1. detect number values like `foo=1` (reference regex= `/^[0-9\.]+$/` )
-1. detect operators so you can easily strip keys (reference regex= `/(^-|\*$)/` )
-1. detect exclude keys like `-foo` (reference regex= `/^-/` )
-1. for every filter token split string on `=`
-1. and we set `root` to `true` or `false` (true=`/` root selector is present)
-1. therefore we we set `show` to `true` or `false` (false=excluder `-`)
-
-> An example filter-parser (which compiles to many languages) can be [found here](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Filter.hx)
-
-# Visible links
-
-When predefined views, XRWG fragments and ID fragments (`#cube` or `#mytag` e.g.) are triggered by the enduser (via toplevel URL or clicking `href`):
-
-1. draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname)
-2. draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that `tag` value
-3. draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) containing that in their `src` or `href` value
-
-The obvious approach for this, is to consult the XRWG ([example](https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js)), which basically has all these things already collected/organized for you during scene-load.
-
-**UX**
-
-4. do not update the wires when the enduser moves, leave them as is
-5. offer a control near the back/forward button which allows the user to (turn off) control the correlation-intensity of the XRWG
-
-# Text in XR (tagging,linking to spatial objects)
-
-How does XR Fragments interlink text with objects?
-
-> The XR Fragments does this by collapsing space into a **Word Graph** (the **XRWG** [example](https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js)), augmented by Bib(s)Tex.
-
-Instead of just throwing together all kinds media types into one experience (games), what about their tagged/semantical relationships?
-Perhaps the following question is related: why is HTML adopted less in games outside the browser?
-
-Hence:
-
-1. XR Fragments promotes (de)serializing a scene to a (lowercase) XRWG ([example](https://github.com/coderofsalvation/xrfragment/blob/feat/macros/src/3rd/js/XRWG.js))
-2. XR Fragments primes the XRWG, by collecting words from the `tag` and name-property of 3D objects.
-3. XR Fragments primes the XRWG, by collecting words from **optional** metadata **at the end of content** of text (see default mimetype & Data URI)
-4. XR Fragments primes the XRWG, by collecting tags/id's from linked hypermedia (URI fragments for HTML e.g.)
-5. The XRWG should be recalculated when textvalues (in `src`) change
-6. HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they fit better in the application-layer, or as embedded src content)
-7. Applications don't have to be able to access the XRWG programmatically, as they can easily generate one themselves by traversing the scene-nodes.
-8. 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)
-9. Instead of exact lowercase word-matching, levensteihn-distance-based matching is preferred
-
-Example of generating XRWG out of the XRWG and textdata with hashtags:
-
-```
- http://y.io/z.fbx | Derived XRWG (expressed as JSON)
- ----------------------------------------------------------------------------+--------------------------------------
- | Chapter: ['#mydoc']
- +-[src: data:.....]----------------------+ +-[3D mesh]-+ | one: ['#mydoc']
- | Chapter one | | / \ | | houses: ['#castle','#mydoc','#house']
- | | | / \ | | baroque: ['#mydoc','#castle']
- | John built houses in baroque style. | | / \ | | castle: ['#baroque','#house']
- | | | |_____| | | john: ['#john','#mydoc']
- | | +-----│-----+ | mydoc: ['#mydoc']
- | | │ |
- | | ├─ name: castle |
- | | └─ tag: house baroque |
- +----------------------------------------+ |
- └─ name: mydoc [3D mesh-+ |
- | O ├─ name: john |
- | /|\ | |
- | / \ | | ^ ^ ^
- +--------+ | | | |
- |
- [remotestorage.io]+ [ localstorage]-+ | <- the XR Fragment-compatible
- | XRWG (JSON) | | XRWG (JSON | | <- 3D hypermedia viewer should
- | | | | | <- be able to select the active XRWG
- +-----------------+ +---------------+ |
-```
-
-
-This allows hasslefree authoring and copy-paste of associations **for and by humans**, but also makes these URLs possible:
-
-| 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.
-
-The XRWG allows endusers to show/hide relationships in realtime in XR Browsers at various levels:
-
-* wordmatch **inside** `src` text
-* wordmatch **inside** `href` text
-* wordmatch object-names
-* wordmatch object-tagnames
-
-Spatial wires can be rendered between words/objects etc.
-Some pointers for good UX (but not necessary to be XR Fragment compatible):
-
-9. 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)
-10. 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.
-12. respect multi-line BiBTeX metadata in text because of [the core principle](#core-principle)
-13. Default font (unless specified otherwise) is a modern monospace font, for maximized tabular expressiveness (see [the core principle](#core-principle)).
-14. anti-pattern: hardcoupling an XR Browser with a mandatory **markup/scripting-language** which departs from onubtrusive plain text (HTML/VRML/Javascript) (see [the core principle](#core-principle))
-15. anti-pattern: limiting human introspection, by abandoning plain text as first tag citizen.
-
-## Default Data URI mimetype
-
-The `src`-values work as expected (respecting mime-types), however:
-
-The XR Fragment specification advices to bump the traditional default browser-mimetype
-
-`text/plain;charset=US-ASCII`
-
-to a hashtag-friendly one:
-
-`text/plain;charset=utf-8;hashtag`
-
-This indicates that:
-
-* utf-8 is supported by default
-* words beginning with `#` (hashtags) will prime the XRWG by adding the hashtag to the XRWG, linking to the current sentence/paragraph/alltext (depending on '.') to the XRWG
-
-Advantages:
-
-* out-of-the-box (de)multiplex human text and metadata in one go (see [the core principle](#core-principle))
-* no network-overhead for metadata (see [the core principle](#core-principle))
-* ensuring high FPS: realtime HTML/RDF historically is too 'requesty'/'parsy' for game studios
-* rich send/receive/copy-paste everywhere by default, metadata being retained (see [the core principle](#core-principle))
-* netto result: less webservices, therefore less servers, and overall better FPS in XR
-
-> 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.).
-
-For all other purposes, regular mimetypes can be used (but are not required by the spec).
-
-## URL and Data URI
-
-```
- +--------------------------------------------------------------+ +------------------------+
- | | | author.com/article.txt |
- | index.gltf | +------------------------+
- | │ | | |
- | ├── ◻ article_canvas | | Hello #friends |
- | │ └ src: ://author.com/article.txt | | |
- | │ | +------------------------+
- | └── ◻ note_canvas |
- | └ src:`data:welcome human\n@book{sunday...}` |
- | |
- | |
- +--------------------------------------------------------------+
-```
-
-The enduser will only see `welcome human` and `Hello friends` 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.).
-
-> additional tagging using [bibs](https://github.com/coderofsalvation/hashtagbibs): to tag spatial object `note_canvas` with 'todo', the enduser can type or speak `#note_canvas@todo`
-
-# Importing/exporting
-
-For usecases like importing/exporting/p2p casting a scene, the issue of external files comes into play.
-
-1. export: if the 3D scene contains relative src/href values, rewrite them into absolute URL values.
-
-# Reflection Mapping
-
-Environment mapping is crucial for creating realistic reflections and lighting effects on 3D objects.
-To apply environment mapping efficiently in a 3D scene, traverse the scene graph and assign each object's environment map based on the nearest ancestor's texture map. This ensures that objects inherit the correct environment mapping from their closest parent with a texture, enhancing the visual consistency and realism.
-
-```
- +--------------------------------+
- | |
- | index.usdz |
- | │ |
- | └── ◻ sphere (texture:foo) |
- | └ ◻ cube (texture:bar) | envMap = foo
- | └ ◻ cylinder | envMap = bar
- +--------------------------------+
-```
-
-Most 3D viewers apply one and the same environment map for various models, however this logic
-allows a more natural & automatic strategy for reflection mapping:
-
-1. traverse the scene graph depth-first
-2. remember the most recent parentnode (P) with a texture material
-3. for every non-root node with a texture material
-3.1 clone that material (as materials might be shared across objects)
-3.2 set the environmentmap to the last known parent texture (P)
-
-# Transclusion (broken link) resolution
-
-In spirit of Ted Nelson's 'transclusion resolution', there's a soft-mechanism to harden links & minimize broken links in various ways:
-
-1. defining a different transport protocol (https vs ipfs or DAT) in `src` or `href` values can make a difference
-2. mirroring files on another protocol using (HTTP) errorcode tags in `src` or `href` properties
-3. in case of `src`: nesting a copy of the embedded object in the placeholder object (`embeddedObject`) will not be replaced when the request fails
-
-> 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.)
-
-For example:
-
-```
- +────────────────────────────────────────────────────────+
- │ │
- │ 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.
- │ │
- +────────────────────────────────────────────────────────+
-
-```
-
-# Topic-based index-less Webrings
-
-As hashtags in URLs map to the XWRG, `href`-values can be used to promote topic-based index-less webrings.
-Consider 3D scenes linking to eachother using these `href` values:
+Consider 3D scenes linking to eachother using these `href` values, attached to 3D button-objects:
* `href: schoolA.edu/projects.gltf#math`
* `href: schoolB.edu/projects.gltf#math`
* `href: university.edu/projects.gltf#math`
-These links would all show visible links to math-tagged objects in the scene.
-To filter out non-related objects one could take it a step further using filters:
+This would teleport users to the math-projects of those universities.
+Now consider adding a 'webring index'-button to each file, with this href-value:
-* `href: schoolA.edu/projects.gltf#math&-topics math`
-* `href: schoolB.edu/projects.gltf#math&-courses math`
-* `href: university.edu/projects.gltf#math&-theme math`
-> This would hide all object tagged with `topic`, `courses` or `theme` (including math) so that later only objects tagged with `math` will be visible
+* href: workgroup.edu/webrings.glb#!webringmenu
-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.
+This would allow displaying the (remote 3D file) webring menu with various href-buttons inside, all centrally curated by the workgroup.
-# URI Templates (RFC6570)
+# Level5: URI Templates (RFC6570)
XR Fragments adopts Level1 URI **Fragment** expansion to provide safe interactivity.
-The following demonstrates a simple video player:
-
-```
-
- +─────────────────────────────────────────────+
- │ │
- │ 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} │
- │ │
- │ │
- +─────────────────────────────────────────────+
-
-
-```
+This is non-normative, and the draft spec is available on request.
# Additional scene metadata
@@ -976,8 +690,11 @@ Instead, it encourages browsers to scan nodes for the following custom propertie
* [SPDX](https://spdx.dev/) license information
* [ARIA](https://www.w3.org/WAI/standards-guidelines/aria/) attributes (`aria-*: .....`)
+* [datapackage.json](https://datapackage.org) findability, accessibility, interoperability, and reusability of data
-> SPDX and ARIA's `aria-description` are normative, as they promote accessibility and scene transcripts: please start `aria-description` with a verb to aid transcripts.
+ARIA's `aria-description`-metadata is normative, to aid accessibility and scene transcripts
+
+> **NOTE**: please always start `aria-description` with a verb to aid transcripts.
The following metadata are non-normative but encouraged, since they are popular and cheap to parse:
diff --git a/doc/RFC_XR_Fragments.txt b/doc/RFC_XR_Fragments.txt
index f200296..638cb7b 100644
--- a/doc/RFC_XR_Fragments.txt
+++ b/doc/RFC_XR_Fragments.txt
@@ -3,7 +3,7 @@
Jens & Leon Internet Engineering Task Force L.R. van Kammen
-Internet-Draft 1 September 2025
+Internet-Draft 19 September 2025
Intended status: Informational
@@ -18,20 +18,22 @@ Abstract
files, enabling hypermediatic (https://github.com/coderofsalvation/
hypermediatic) navigation, to enable a spatial web for hypermedia
browsers with- or without a network-connection.
- The specification uses W3C Media Fragments (https://www.w3.org/TR/
- media-frags/) and URI Templates (RFC6570) (https://www.rfc-
- editor.org/rfc/rfc6570) to promote spatial addressibility, sharing,
- navigation, filtering and databinding objects for (XR) Browsers.
XR Fragments allows us to better use implicit metadata inside 3D
scene(files), by mapping it to proven technologies like URI Fragments
(https://en.wikipedia.org/wiki/URI_fragment).
- XR Fragments views XR experiences thru the lens of 3D object URI's,
- rather than thru code(frameworks) or protocol-specific browsers
- (webbrowser e.g.).
+ XR Fragments views XR experiences thru the lens of 3D deeplinked
+ URI's, rather than thru code(frameworks) or protocol-specific
+ browsers (webbrowser e.g.). The standard comprises of various
+ (optional) support levels, which also include W3C Media Fragments
+ (https://www.w3.org/TR/media-frags/) and URI Templates (RFC6570)
+ (https://www.rfc-editor.org/rfc/rfc6570) to promote spatial
+ addressibility, sharing, navigation, filtering and databinding
+ objects for (XR) Browsers.
- XR Fragments is a heuristical 3D format which leverages
- heuristic rules derived from any 3D scene or well-established 3D file
- formats, to extract meaningful features from scene hierarchies.
+ XR Fragments is in a sense, a heuristical 3D format or meta-
+ format, which leverages heuristic rules derived from any 3D scene or
+ well-established 3D file formats, to extract meaningful features from
+ scene hierarchies.
These heuristics, enable features that are both meaningful and
consistent across different scene representations, allowing higher
interop between fileformats, 3D editors, viewers and game-
@@ -45,25 +47,28 @@ Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
+
+
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 1]
+
+Internet-Draft XR Fragments September 2025
+
+
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
-
-
-
-van Kammen Expires 5 March 2026 [Page 1]
-
-Internet-Draft XR Fragments September 2025
-
-
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
- This Internet-Draft will expire on 5 March 2026.
+ This Internet-Draft will expire on 23 March 2026.
Copyright Notice
@@ -82,61 +87,57 @@ Copyright Notice
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Core principle . . . . . . . . . . . . . . . . . . . . . . . 4
- 3. The XR Fragments Trinity . . . . . . . . . . . . . . . . . . 5
- 4. List of URI Fragments . . . . . . . . . . . . . . . . . . . . 6
- 5. List of *_explicit_ metadata . . . . . . . . . . . . . . . . 6
- 6. HFL (Hypermediatic Feedback Loop) for XR Browsers . . . . . . 6
- 7. Conventions and Definitions . . . . . . . . . . . . . . . . . 9
- 7.1. XR Fragment URL Grammar . . . . . . . . . . . . . . . . . 9
- 8. Spatial Referencing 3D . . . . . . . . . . . . . . . . . . . 9
- 9. non-normative . . . . . . . . . . . . . . . . . . . . . . . . 10
- 10. additional *explicit* metadata . . . . . . . . . . . . . . . 10
- 10.1. Sidecar-file . . . . . . . . . . . . . . . . . . . . . . 11
- 10.2. Level2: Implicit URI Fragments . . . . . . . . . . . . . 11
- 10.3. media fragments and datatypes . . . . . . . . . . . . . 13
- 11. Navigating 3D . . . . . . . . . . . . . . . . . . . . . . . . 16
- 12. Top-level URL processing . . . . . . . . . . . . . . . . . . 18
- 13. Embedding XR content using src . . . . . . . . . . . . . . . 18
- 14. Navigating content href portals . . . . . . . . . . . . . . . 21
- 14.1. Walking surfaces . . . . . . . . . . . . . . . . . . . . 22
- 14.2. UX spec . . . . . . . . . . . . . . . . . . . . . . . . 22
- 14.3. Scaling instanced content . . . . . . . . . . . . . . . 23
- 15. XR Fragment: pos . . . . . . . . . . . . . . . . . . . . . . 23
- 16. XR Fragment: rot . . . . . . . . . . . . . . . . . . . . . . 23
- 17. XR Fragment: t . . . . . . . . . . . . . . . . . . . . . . . 24
- 18. XR audio/video integration . . . . . . . . . . . . . . . . . 24
+ 2. What is XR Fragments . . . . . . . . . . . . . . . . . . . . 4
+ 3. HFL (Hypermediatic Feedback Loop) for XR Browsers . . . . . . 4
+ 4. Conventions and Definitions . . . . . . . . . . . . . . . . . 6
+ 4.1. XR Fragment URL Grammar . . . . . . . . . . . . . . . . . 6
+ 5. Spatial Referencing 3D . . . . . . . . . . . . . . . . . . . 6
+ 6. Level0: Files . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 6.1. via href metadata . . . . . . . . . . . . . . . . . . . . 7
+ 6.2. via chained extension . . . . . . . . . . . . . . . . . . 8
+ 6.3. via subdocuments/xattr . . . . . . . . . . . . . . . . . 8
+ 6.4. JSON sidecar-file . . . . . . . . . . . . . . . . . . . . 9
+ 7. Level1: URI . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 8. List of URI Fragments . . . . . . . . . . . . . . . . . . . . 11
+ 9. List of *_explicit_ metadata . . . . . . . . . . . . . . . . 12
+ 10. Level2: href links . . . . . . . . . . . . . . . . . . . . . 12
+ 10.1. Interaction behaviour . . . . . . . . . . . . . . . . . 12
+ 10.2. XR Viewer implementation . . . . . . . . . . . . . . . . 12
+ 11. Level3: Media Fragments . . . . . . . . . . . . . . . . . . . 13
+ 11.1. Animation(s) timeline . . . . . . . . . . . . . . . . . 13
+ 11.2. Specify playback loopmode . . . . . . . . . . . . . . . 13
-van Kammen Expires 5 March 2026 [Page 2]
+van Kammen Expires 23 March 2026 [Page 2]
Internet-Draft XR Fragments September 2025
- 19. XR Fragment filters . . . . . . . . . . . . . . . . . . . . . 24
- 19.1. including/excluding . . . . . . . . . . . . . . . . . . 25
- 19.2. Filter Parser . . . . . . . . . . . . . . . . . . . . . 26
- 20. Visible links . . . . . . . . . . . . . . . . . . . . . . . . 26
- 21. Text in XR (tagging,linking to spatial objects) . . . . . . . 27
- 21.1. Default Data URI mimetype . . . . . . . . . . . . . . . 29
- 21.2. URL and Data URI . . . . . . . . . . . . . . . . . . . . 30
- 22. Importing/exporting . . . . . . . . . . . . . . . . . . . . . 31
- 23. Reflection Mapping . . . . . . . . . . . . . . . . . . . . . 31
- 24. Transclusion (broken link) resolution . . . . . . . . . . . . 31
- 25. Topic-based index-less Webrings . . . . . . . . . . . . . . . 32
- 26. URI Templates (RFC6570) . . . . . . . . . . . . . . . . . . . 33
- 27. Additional scene metadata . . . . . . . . . . . . . . . . . . 33
- 28. Accessibility interface . . . . . . . . . . . . . . . . . . . 35
- 28.1. Two-button navigation . . . . . . . . . . . . . . . . . 36
- 28.2. Overlap with fileformat-specific extensions . . . . . . 36
- 28.3. Vendor Prefixes . . . . . . . . . . . . . . . . . . . . 37
- 29. Security Considerations . . . . . . . . . . . . . . . . . . . 39
- 30. FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
- 31. authors . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
- 32. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 40
- 33. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 40
- 34. Appendix: Definitions . . . . . . . . . . . . . . . . . . . . 40
+ 11.3. Controlling embedded content . . . . . . . . . . . . . . 14
+ 12. Level4: prefix operators . . . . . . . . . . . . . . . . . . 14
+ 12.1. Object teleports (!) . . . . . . . . . . . . . . . . . . 14
+ 12.2. Object multipliers (*) . . . . . . . . . . . . . . . . . 16
+ 12.3. De/selectors (+ and -) . . . . . . . . . . . . . . . . . 16
+ 12.4. Sharing object or file (#|) . . . . . . . . . . . . . . 16
+ 12.5. xrf:// URI scheme . . . . . . . . . . . . . . . . . . . 17
+ 13. Top-level URL processing . . . . . . . . . . . . . . . . . . 17
+ 13.1. UX . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 14. Example: Navigating content href portals . . . . . . . . . . 18
+ 14.1. Walking surfaces . . . . . . . . . . . . . . . . . . . . 19
+ 15. Virtual world rings . . . . . . . . . . . . . . . . . . . . . 19
+ 16. Level5: URI Templates (RFC6570) . . . . . . . . . . . . . . . 20
+ 17. Additional scene metadata . . . . . . . . . . . . . . . . . . 20
+ 18. Accessibility interface . . . . . . . . . . . . . . . . . . . 21
+ 18.1. Two-button navigation . . . . . . . . . . . . . . . . . 22
+ 18.2. Overlap with fileformat-specific extensions . . . . . . 22
+ 18.3. Vendor Prefixes . . . . . . . . . . . . . . . . . . . . 23
+ 19. Security Considerations . . . . . . . . . . . . . . . . . . . 26
+ 20. FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
+ 21. authors . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
+ 22. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 27
+ 23. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 27
+ 24. Appendix: Definitions . . . . . . . . . . . . . . . . . . . . 27
1. Introduction
@@ -149,8 +150,8 @@ Internet-Draft XR Fragments September 2025
XR Fragments exploits the fact that all 3D models already contain
such metadata:
- *XR Fragments allows controlling of metadata in 3D scene(files) using
- URI's*
+ *XR Fragments allows deeplinking of 3D objects by mapping objectnames
+ to URI fragments*
It solves:
@@ -160,16 +161,17 @@ Internet-Draft XR Fragments September 2025
URI_fragment) using src/href spatial metadata
2. Interlinking text & spatial objects by collapsing space into a
Word Graph (XRWG) to show visible links (#visible-links)
- 3. unlocking spatial potential of the (originally 2D) hashtag (which
- jumps to a chapter) for navigating XR documents
-van Kammen Expires 5 March 2026 [Page 3]
+
+van Kammen Expires 23 March 2026 [Page 3]
Internet-Draft XR Fragments September 2025
+ 3. unlocking spatial potential of the (originally 2D) hashtag (which
+ jumps to a chapter) for navigating XR documents
4. refraining from introducing scripting-engines for mundane tasks
(and preventing its inevitable security-headaches)
5. the gap between text an 3d objects: object-names directly map to
@@ -178,168 +180,30 @@ Internet-Draft XR Fragments September 2025
| NOTE: The chapters in this document are ordered from highlevel to
| lowlevel (technical) as much as possible
-2. Core principle
-
- *XR Fragments allows controlling 3D models using URLs, based on
- (non)existing metadata via URI's*
-
- XR Fragments tries to seek to connect the world of text (semantical
- web / RDF), and the world of pixels.
- Instead of forcing authors to combine 3D/2D objects programmatically
- (publishing thru a game-editor e.g.), XR Fragments *integrates all*
- which allows a universal viewing experience.
-
- +───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ U R N │
- │ U R L | │
- │ | |-----------------+--------| │
- │ +--------------------------------------------------| │
- │ | │
- │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │
- │ | │
- │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │
- │ │
- │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │
- │ │
- │ │
- │ |------------------------+-------------------------| │
- │ | │
- │ U R I │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
- Fact: our typical browser URL's are just *a possible implementation*
- of URI's (for untapped humancentric potential of URI's see
- interpeer.io (https://interpeer.io))
-
- | 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.
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 4]
-
-Internet-Draft XR Fragments September 2025
-
-
- Below you can see how this translates back into good-old URLs:
-
- +───────────────────────────────────────────────────────────────────────────────────────────────+
- │ │
- │ the soul of any URL: ://macro /meso ?micro #nano │
- │ │
- │ 2D URL: ://library.com /document ?search #chapter │
- │ xrf:// │
- │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #view ───> hashbus │
- │ │ #filter │ │
- │ │ #tag │ │
- │ │ (hypermediatic) #material │ │
- │ │ ( feedback ) #animation │ │
- │ │ ( loop ) #texture │ │
- │ │ #variable │ │
- │ │ │ │
- │ XRWG <─────────────────────<─────────────+ │
- │ │ │ │
- │ └─ objects ──────────────>─────────────+ │
- │ │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
- | ?-linked and #-linked navigation are JUST one possible way to
- | implement XR Fragments: the essential goal is to allow a
- | Hypermediatic FeedbackLoop (HFL) between external and internal 4D
- | navigation.
-
- Traditional webbrowsers can become 4D document-ready by:
-
-3. The XR Fragments Trinity
+2. What is XR Fragments
XR Fragments utilizes URLs:
1. for 3D viewers/browser to manipulate the camera or objects (via
- URLbar)
- 2. as *implicit* metadata to reference (nested) objects *inside* 3D
- scene-file (local and remote)
- 3. via *explicit* metadata ('extras') *inside* 3D scene-files
- (interaction e.g.) or
- 4. [optionally for developers] via *explicit* metadata *outside* 3D
- scene-files (via sidecarfile (https://en.wikipedia.org/wiki/
- Sidecar_file))
+ URI fragments)
+ 2. implicitly: by mapping 3D objectnames (of a 3D scene/file) to URI
+ fragments (3D deeplinking)
+ 3. explicitly: by scanning href metadata *inside* 3D scene-files to
+ enable interactions
+ 4. externally: progressively enhance a 3D (file) into an experience
+ via sidecarfiles (https://en.wikipedia.org/wiki/Sidecar_file)
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 5]
-
-Internet-Draft XR Fragments September 2025
-
-
-4. List of URI Fragments
-
- +=======================+======================================+===========+=============+
- |fragment |type |example |info |
- +=======================+======================================+===========+=============+
- |#...... |vector3 |#room1 |positions/ |
- | | |#room2 |parents |
- | | |#cam2 |camera(rig) |
- | | | |(or XR floor)|
- | | | |to xyz- |
- | | | |coord/object/|
- | | | |camera and |
- | | | |upvector |
- +-----------------------+--------------------------------------+-----------+-------------+
- |Media Fragments |media fragment |#t=0,2&loop|play (and |
- |(https://www.w3.org/TR/|(#media%20fragments%20and%20datatypes)| |loop) 3D |
- |media-frags/) | | |animation |
- | | | |from 0 |
- | | | |seconds till |
- | | | |2 seconds |
- +-----------------------+--------------------------------------+-----------+-------------+
-
- Table 1
-
-5. List of *_explicit_ metadata
-
- These are the possible 'extras' for 3D nodes and sidecar-files
-
- +======+========+================+==========+===================+
- | key | type | example (JSON) | function | existing |
- | | | | | compatibility |
- +======+========+================+==========+===================+
- | href | string | "href": | XR | custom property |
- | | | "b.gltf" | teleport | in 3D fileformats |
- +------+--------+----------------+----------+-------------------+
-
- Table 2
-
-6. HFL (Hypermediatic Feedback Loop) for XR Browsers
+3. HFL (Hypermediatic Feedback Loop) for XR Browsers
href metadata traditionally implies *click* AND *navigate*, however
- XR Fragments adds stateless *click* (xrf://#....) or *navigate*
- (xrf://#...) as well (which allows many extra interactions which
- otherwise need a scripting language). This is known as *hashbus*-
- only events (see image above).
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 6]
-
-Internet-Draft XR Fragments September 2025
-
+ XR Fragments adds stateless *click* (xrf://....) via the xrf://
+ scheme, which does not change the top-level URL-adress (of the
+ browser). This allows for many extra interactions via URLs, which
+ otherwise needs a scripting language. These are called *hashbus*-
+ only events/
| Being able to use the same URI Fragment DSL for navigation (href:
- | #foo) as well as interactions (href: xrf://#bar) greatly
+ | #foo) as well as interactions (href: xrf://#foo) greatly
| simplifies implementation, increases HFL, and reduces need for
| scripting languages.
@@ -349,11 +213,19 @@ Internet-Draft XR Fragments September 2025
* hypermediatic (https://github.com/coderofsalvation/hypermediatic)
loading/clicking 3D assets (gltf/fbx e.g.) natively (with or
without using HTML).
- * allowing 3D assets/nodes to publish XR Fragments to themselves/
- eachother using the xrf:// hashbus (xrf://#person=walk to trigger
- walk-animation for object person)
- * collapsing the 3D scene to an wordgraph (for essential navigation
- purposes) controllable thru a hash(tag)bus
+ * potentially allowing 3D assets/nodes to publish XR Fragments to
+ themselves/eachother using the xrf:// hashbus (xrf://#person=walk
+ to trigger walk-animation for object person)
+ * potentially collapsing the 3D scene to an wordgraph (for essential
+ navigation purposes) controllable thru a hash(tag)bus
+
+
+
+van Kammen Expires 23 March 2026 [Page 4]
+
+Internet-Draft XR Fragments September 2025
+
+
* completely bypassing the security-trap of loading external scripts
(by loading 3D model-files, not HTML-javascriptable resources)
@@ -362,40 +234,8 @@ Internet-Draft XR Fragments September 2025
agnostic, though pseudo-XR Fragment browsers *can* be implemented on
top of HTML/Javascript.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 7]
-
-Internet-Draft XR Fragments September 2025
-
-
+=========+======================+=====================================+
- |principle|XR 4D URL |HTML 2D URL |
+ |principle|3D URL |HTML 2D URL |
+=========+======================+=====================================+
|the XRWG |wordgraph (collapses |Ctrl-F (find) |
| |3D scene to tags) | |
@@ -431,7 +271,16 @@ Internet-Draft XR Fragments September 2025
| |topLevel URI) |hypermediatic) |
+---------+----------------------+-------------------------------------+
- Table 3
+ Table 1
+
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 5]
+
+Internet-Draft XR Fragments September 2025
+
| An important aspect of HFL is that URI Fragments can be triggered
| without updating the top-level URI (default href-behaviour) thru
@@ -439,22 +288,11 @@ Internet-Draft XR Fragments September 2025
| navigation and interaction prevents non-standard things like
| (href:javascript:dosomething()).
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 8]
-
-Internet-Draft XR Fragments September 2025
-
-
-7. Conventions and Definitions
+4. Conventions and Definitions
See appendix below in case certain terms are not clear.
-7.1. XR Fragment URL Grammar
+4.1. XR Fragment URL Grammar
For typical HTTP-like browsers/applications:
@@ -464,15 +302,15 @@ Internet-Draft XR Fragments September 2025
| Example: ://foo.com/my3d.gltf#room1&prio=-5&t=0,100
- +=======================+=================================+
- | Demo | Explanation |
- +=======================+=================================+
- | room1 | vector/coordinate argument e.g. |
- +-----------------------+---------------------------------+
- | room1&rot=0,90,0&cam1 | combinators |
- +-----------------------+---------------------------------+
+ +============+=================================+
+ | Demo | Explanation |
+ +============+=================================+
+ | room1 | vector/coordinate argument e.g. |
+ +------------+---------------------------------+
+ | room1&cam1 | combinators |
+ +------------+---------------------------------+
- Table 4
+ Table 2
| this is already implemented in all browsers
@@ -486,22 +324,16 @@ Internet-Draft XR Fragments September 2025
https://me.com can load the latter (and still indicates which XR
Fragments entrypoint-experience/client was used).
-8. Spatial Referencing 3D
+5. Spatial Referencing 3D
- XR Fragments assume the following objectname-to-URIFragment mapping:
+ 3D files contain an hierarchy of objects.
+ XR Fragments assumes the following objectname-to-URI-Fragment
+ mapping, in order to deeplink 3D objects:
-
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 9]
+van Kammen Expires 23 March 2026 [Page 6]
Internet-Draft XR Fragments September 2025
@@ -530,7 +362,6 @@ Internet-Draft XR Fragments September 2025
create an 3D object with:
* href: https://scene.fbx
- * src: https://otherworld.gltf#mainobject
| It also allows *sourceportation*, which basically means the
| enduser can teleport to the original XR Document of an src
@@ -538,59 +369,108 @@ Internet-Draft XR Fragments September 2025
| embedded object. Basically an embedded link becoming an outbound
| link by activating it.
-9. non-normative
+6. Level0: Files
- The following below is non-normative heuristics which are not part
- officially part of the spec.
+ These are *optional* auto-loaded side-car files to enable hasslefree
+ XR Movies (#XR%20Movies).
+ they can accomodate developers or applications who (for whatever
+ reason) must not modify the 3D scene-file (a .glb e.g.).
-10. additional *explicit* metadata
+6.1. via href metadata
- | #rot | vector3 | #rot=0,90,0 | rotates camera to xyz-coord
- 0.5,0,0 | | 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 |
+ 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)
- | Supported popular compatible 3D fileformats: .gltf, .obj, .fbx,
- | .usdz, .json (THREE.js), .dae and so on.
+ *heuristics*:
-van Kammen Expires 5 March 2026 [Page 10]
+
+van Kammen Expires 23 March 2026 [Page 7]
Internet-Draft XR Fragments September 2025
-10.1. Sidecar-file
+ * if at least one href custom property/extra is found in a 3D scene
+ * The viewer should poll for the above mentioned sidecar-file
+ extensions (and present accordingly)
- | 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.).
+6.2. via chained extension
+
+ scene.xrf.glb <--- '.xrf.' sidecar file heuristic detected!
+ scene.xrf.png (preview thumbnail)
+ scene.xrf.ogg (soundtrack to plays when global 3D animation starts)
+ scene.xrf.vtt (subtitles for accessibility or screenreaders)
+ scene.xrf.json (sidecar JSON-file with explicit metadata)
+
+ | A fallback-mechanism to turn 3D files into XR Movies
+ | (#XR%20Movies) without editing them.
+
+ *heuristics*:
+
+ * the chained-extension heuristic .xrf. should be present in the
+ filename (scene.xrf.glb e.g.)
+
+6.3. via subdocuments/xattr
+
+ More secure protocols (Nextgraph e.g.) don't allow for simply polling
+ files. In such case, subdocuments or extended attributes should be
+ polled:
+
+ | NOTE: in the examples below we use the href-heuristic, but also
+ | the .xrf. chained-extension applies here.
+
+myspreadsheet.ods
+└── explainer.glb <--- 'href' extra [heuristic] detected inside!
+ ├── explainer.ogg (soundtrack to play when global 3D animation starts)
+ ├── explainer.png (preview thumnbnail)
+ ├── explainer.json (sidecar JSON-file with explicit metadata)
+ └── explainer.vtt (subtitles for accessibility or screenreaders)
+
+ If only extended attributes (xattr) are available, the respective
+ referenced file can be embedded:
+
+ $ setfattr -n explainer.ogg -v "soundtrack.ogg" explainer.glb
+ $ setfattr -n explainer.png -v "thumbnail.png" explainer.glb
+ $ setfattr -n explainer.vtt -v "subtitles.vtt" explainer.glb
+
+ | NOTE: Linux's setfattr/getfattr is xattr on mac, and Set-Content/
+ | Get-content on Windows. See pxattr
+ | (https://www.lesbonscomptes.com/pxattr/index.html) for lowlevel
+ | access.
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 8]
+
+Internet-Draft XR Fragments September 2025
+
+
+6.4. JSON sidecar-file
For developers, sidecar-file can allow for defining *explicit* XR
- Fragments metadata, outside of the 3D file.
- This can be done via a JSON-pointers RFC6901 (https://www.rfc-
- editor.org/rfc/rfc6901) in a JSON sidecar-file
- (https://en.wikipedia.org/wiki/Sidecar_file):
+ Fragments links (>level1), outside of the 3D file.
+ This can be done via (objectname/metadata) key/value-pairs in a JSON
+ sidecar-file (https://en.wikipedia.org/wiki/Sidecar_file):
* experience.glb
- * experience.json
+ * experience.json <----
{
- "/":{
- "#": "#-penguin",
+ "/":
"aria-description": "description of scene",
},
- "/room/chair": {
- "href": "#penguin"
+ "button": {
+ "href": "#roomB"
}
}
- | This would mean: hide object(s) with name or tag-value 'penguin'
- | upon scene-load, and show it when the user clicks the chair
+ | This will make object button clickable, and teleport the user to
+ | object roomB.
So after loading experience.glb the existence of experience.json is
detected, to apply the explicit metadata.
@@ -600,541 +480,485 @@ Internet-Draft XR Fragments September 2025
| In THREE.js-code this would boil down to:
- scene.userData['#'] = "#chair&penguin"
scene.userData['aria-description'] = "description of scene"
- scene.getObjectByName("room").getObjectByName("chair").userData.href = "#penguin"
+ scene.getObjectByName("button").userData.href = "#roomB"
// now the XR Fragments parser can process the XR Fragments userData 'extras' in the scene
-10.2. Level2: Implicit URI Fragments
+7. Level1: URI
- | Warning: non-normative
+ | *XR Fragments allows deeplinking of 3D objects by mapping
+ | objectnames to URI fragments*
+
+ XR Fragments tries to seek to connect the world of text (semantical
+ web / RDF), and the world of pixels.
+ Instead of forcing authors to combine 3D/2D objects programmatically
+ (publishing thru a game-editor e.g.), XR Fragments *integrates all*
+ which allows a universal viewing experience.
-van Kammen Expires 5 March 2026 [Page 11]
+
+
+van Kammen Expires 23 March 2026 [Page 9]
Internet-Draft XR Fragments September 2025
- These fragments are derived from objectnames (or their extras) within
- a 3D scene, and trigger certain actions when evaluated by the
- browser:
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ 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 │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
- +================+======================================+=============+=====================+=======================+
- | |fragment |type |example |info |
- +================+======================================+=============+=====================+=======================+
- |*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* |xrf://# |string |#person |(and show) object(s) |
- | | | | |with tag: person or |
- | | | | |name person (XRWG |
- | | | | |lookup) |
- +----------------+--------------------------------------+-------------+---------------------+-----------------------+
- |*FILTERS* |#[!][-][*] |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*|#[*]=|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 |#= |string=string|#foo=bar |sets URI Template |
- |UPDATE* | | | |(https://www.rfc- |
- | | | | |editor.org/rfc/rfc6570)|
- | | | | |variable foo to the |
- | | | | |value #t=0 from |
- | | | | |*existing* object |
- | | | | |metadata (bar:#t=0 |
- | | | | |e.g.), This allows for |
- | | | | |reactive URI Template |
- | | | | |(https://www.rfc- |
+ Fact: our typical browser URL's are just *a possible implementation*
+ of URI's (for untapped humancentric potential of URI's see
+ interpeer.io (https://interpeer.io) or NextGraph
+ (https://nextgraph.org) )
+
+ | XR Fragments does not look at XR (or the web) thru the lens of
+ | HTML or URLs.
+ | But approaches things from a higherlevel local-first 3D hypermedia
+ | browser-perspective.
+
+ Below you can see how this translates back into good-old URLs:
-van Kammen Expires 5 March 2026 [Page 12]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 10]
Internet-Draft XR Fragments September 2025
- | | | | |editor.org/rfc/rfc6570)|
- | | | | |defined in object |
- | | | | |metadata elsewhere |
- | | | | |(src:://m.com/ |
- | | | | |cat.mp4#{foo} e.g., to |
- | | | | |play media using media |
- | | | | |fragment URI |
- | | | | |(https://www.w3.org/TR/|
- | | | | |media-frags/#valid- |
- | | | | |uri)). NOTE: metadata-|
- | | | | |key should not start |
- | | | | |with # |
- +----------------+--------------------------------------+-------------+---------------------+-----------------------+
- |*ANIMATION* |#= |string=string|#people=walk |assign a different |
- | | | |#people=noanim |animation to object(s) |
- +----------------+--------------------------------------+-------------+---------------------+-----------------------+
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+ │ │
+ │ 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 ──────────────>─────────────+ │
+ │ │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
- Table 5
+ | ?-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.
-10.3. media fragments and datatypes
+8. List of URI Fragments
- | Warning: *non-normative* (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 | t=x | 0 | play from 0 |
- | W3C media | | | seconds to |
- | fragment | | | end (and |
- | | | | stop) |
- +-----------+----------------------+---------------+----------------+
- | temporal | t=x,y | 0,2 | play from 0 |
- | W3C media | | | seconds till |
- | fragment | | | 2 seconds |
- | | | | (and stop) |
- +-----------+----------------------+---------------+----------------+
- | temporal | s=x | 1 | set playback |
- | W3C media | | | speed of |
- | fragment | | | audio/ |
- | * | | | video/3D anim |
+ +=======================+======================================+===========+=============+
+ |fragment |type |example |info |
+ +=======================+======================================+===========+=============+
+ |#...... |vector3 |#room1 |positions/ |
+ | | |#room2 |parents |
+ | | |#cam2 |camera(rig) |
+ | | | |(or XR floor)|
+ | | | |to xyz- |
+ | | | |coord/object/|
+ | | | |camera and |
+ | | | |upvector |
+ +-----------------------+--------------------------------------+-----------+-------------+
+ |Media Fragments |media fragment |#t=0,2&loop|play (and |
+ |(https://www.w3.org/TR/|(#media%20fragments%20and%20datatypes)| |loop) 3D |
+ |media-frags/) | | |animation |
+ | | | |from 0 |
+ | | | |seconds till |
+ | | | |2 seconds |
+ +-----------------------+--------------------------------------+-----------+-------------+
-van Kammen Expires 5 March 2026 [Page 13]
+
+van Kammen Expires 23 March 2026 [Page 11]
Internet-Draft XR Fragments September 2025
- +-----------+----------------------+---------------+----------------+
- | temporal | [-]loop | loop | enable looped |
- | W3C media | | | playback of |
- | fragment | | | 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 | u:=hashbus for more info.
- | * = this is extending the W3C media fragments
- | (https://www.w3.org/TR/media-frags/#mf-advanced) 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).
+11. Level3: Media Fragments
- Example URI's:
+ | these allow for XR Movies with a controllable timeline using href
+ | URI's with Media Fragments
- * https://images.org/credits.jpg#uv=0,0,0,+0.1 (infinite vertical
- texturescrolling)
- * https://video.org/organogram.mp4#t=0&loop&uv=0.1,0.1,0.3,0.3
- (animated tween towards region in looped video)
- * https://shaders.org/plasma.glsl#t=0&u:col2=0,1,0 (red-green shader
- plasma starts playing from time-offset 0)
+ Just like with 2D media-files, W3C mediafragments (#t=1,2) can be
+ used to control a timeline via the #t (##t) primitive. XR Fragments
+ Level3 makes the 3D timeline, as well as URL-referenced files
+ *controllable* via Media Fragments like:
+
+ * level2 hrefs (href: #t=4 e.g. to control 3D timeline)
+ * level4: xrf: URI scheme:
+ - href: xrf:foo.wav#t=0 to play a wav
+ - href: xrf:news.glb?clone#t=0 to instance and play another
+ experience
+
+11.1. Animation(s) timeline
+
+ controls the animation(s) of the scene (or src resource which
+ contains a timeline)
+
+ | fragment | type | functionality | | #t=start,stop |
+ [vector2] (default:`#t=0,0`) | start,stop (in seconds |
+
+ | Example Value | Explanation | | #t=1 | play (3D) animations from 1
+ seconds till end (and stop) | | #t=1,100 | play (3D) animations from
+ 1 till 100 seconds (and stop) | | #t=0,0 | stop (3D) animations at
+ frame 0 |
+
+ | Use [[#s 🌱]] to control playback speed
+
+11.2. Specify playback loopmode
+
+ This compensates a missing element from Media Fragments to enable/
+ disable temporal looping. .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 15]
+van Kammen Expires 23 March 2026 [Page 13]
Internet-Draft XR Fragments September 2025
- +──────────────────────────────────────────────────────────+
- │ │
- │ 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)
- │ │
- │ │
- +──────────────────────────────────────────────────────────+
+ | fragment | type | functionality | | #loop | string | enables
+ animation/video/audio loop | | #-loop | string | disables
+ animation/video/audio loop |
-> 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).
+11.3. Controlling embedded content
-11. Navigating 3D
+ use [[URI Templates]] to control embedded media, for example a simple
+ video-player:
- +================+========+=============================+
- | fragment | type | functionality |
- +================+========+=============================+
- | #=room1 | string | position camera to position |
- | | | and upvector of objectname |
- | | | room1 (+userheight in VR) |
- +----------------+--------+-----------------------------+
+ 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
- Table 7
+12. Level4: prefix operators
- » example implementation
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/pos.js)
- » discussion (https://github.com/coderofsalvation/xrfragment/
- issues/5)
+ Prefixing objectnames with the following simple operators allow for
+ *extremely powerful* XR interactions:
- Here's the basic *level1* flow (with optional level2 features):
+ * #!
+ * #*
+ * #+ or #-
+ * #|
+ * xrf: URI scheme
+
+ | *Examples:* #+menu to show a object, #-menu to hide a menu, #!menu
+ | to teleport a menu, #*block to clone a grabbable block, #|object
+ | to share an object
+
+12.1. Object teleports (!)
+
+ Prefixing an object with an exclamation-symbol, will teleport a
+ (local or remote) referenced object from/to its original/usercamera
+ location.
+
+ [img[objecteleport.png]]
-van Kammen Expires 5 March 2026 [Page 16]
+van Kammen Expires 23 March 2026 [Page 14]
Internet-Draft XR Fragments September 2025
- 1. the Y-coordinate of `room1 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), except in case of camera-switching.
- 2. set the position of the camera accordingly to the vector3 values
- of room1
- 3. set the upvector of the camera accordingly to the vector3 values
- of room1 (local gravity as pioneered by Patrick Lichty)
- 4. if the referenced #room1 object is animated, parent the current
- camera to that object (so it animates too)
- 5. in case a href does not mention any 3D object, the current
- position will be assumed
+ 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
- Here's an ascii representation of a 3D scene-graph which contains 3D
- objects ◻ and their metadata:
+ #!menu
- +────────────────────────────────────────────────────────+
- │ │
- │ index.gltf │
- │ │ │
- │ ├── ◻ buttonA │
- │ │ └ href: #room1&t=100,200 │
- │ │ │
- │ └── ◻ buttonB │
- │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc)
- │ │
- +────────────────────────────────────────────────────────+
+ Clicking the href (#via-href-metadata)-value above will:
- An XR Fragment-compatible browser viewing this scene, allows the end-
- user to interact with the buttonA and buttonB.
- In case of buttonA the end-user will be teleported to another
- location and time in the *current loaded scene*, but buttonB will
- *replace the current scene* with a new one, like other.fbx, and
- assume camera coordinate 0,0,0
+ 1. *reposition the referenced object* (menu) to the
+ usercamera's-coordinates.
+ 2. *zoom* in case of (non-empty) mesh-object: rescale to 1 m³, and
+ position 1m in front of the camera
+ 3. toggle behaviour: revert values if 1/2 were already applied
+ 4. #+ is always implied (objects are always made visible)
- *Non-normative*:
+ 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.).
- 5. rot sets the rotation of the camera (only for non-VR/AR headsets,
- however a camera-value overrules this)
- 6. *level2*: mediafragment t in the top-URL sets the playbackspeed
- and animation-range of the global scene animation
- 7. before scene load: the scene is cleared
- 8. *level2*: after scene load: in case the scene (rootnode) contains
- an # default view with a fragment value: execute non-positional
- fragments via the hashbus (no top-level URL change)
- 9. *level2*: after scene load: in case the scene (rootnode) contains
- an # default view with a fragment value: execute positional
- fragment via the hashbus + update top-level URL
+ * href: #whiteroom&!explainer&!exitmenu
+
+ | This will teleport the user to whiteroom and moves object
+ | explainer and exitmenu in front of the user.
+
+ * href: `https://my.org/foo.glb#! (https://my.org/foo.glb#!)
+
+ Clicking the href (#via-href-metadata)-value above will:
+
+ 1. import foo.glb from my.org's webserver
+ 2. show it in front of the user (because #! indicates object
+ teleport)
+
+ * href: https://foo.glb#roomB&!bar
+
+ Clicking the href (#via-href-metadata)-value above will:
+
+ 1. replace the current scene with foo.glb
+ 2. teleport the user to #roomB inside foo.glb
+ 3. *instance the referenced object* (bar inside foo.glb) in front of
+ the user.
+ 4. it will update the top-Level URL (because xrf: was not used)
+ 5. hide the *instanced object* when clicked again (toggle
+ visibility)
-van Kammen Expires 5 March 2026 [Page 17]
+
+
+
+van Kammen Expires 23 March 2026 [Page 15]
Internet-Draft XR Fragments September 2025
- 10. *level2*: in case of no default # view on the scene (rootnode),
- default player(rig) position 0,0,0 is assumed.
+ | *NOTE*: level2 teleportation links, as well as instancing
+ | mitigates the 'broken embedded image'-issue of HTML: *always*
+ | attaching the href-values to *a 3D (preview) object* (that way
+ | broken links will not break the design).
-12. Top-level URL processing
+ *Example:* clicking a 3D button with title 'menu' and href (#href)-
+ value xrf:menu.glb?instance#t=4,5 would instance a 3D menu (menu.glb)
+ in front of the user, and loop its animation between from 4-5 seconds
+ (t=4,5)
- | Example URL: ://foo/world.gltf#room1&t=10
+ | *NOTE*: combining instance-operators allows dynamic construction
+ | of 3D scenes (#london&!welcomeMenu&!fadeBox e.g.)
+
+12.2. Object multipliers (*)
+
+ The star-prefix will clone a (local or remote) referenced object to
+ the usercamera's location, and make it grabbable.
+ Usecases: * object-picker (build stuff with objects)
+
+ | *NOTE*: this is basically the #! operator (#%23%21) which
+ | infinitely *clones* the referenced object (instead of
+ | repositioning the object).
+
+12.3. De/selectors (+ and -)
+
+ * href: #-welcome (or #+welcome)
+
+ Clicking href-value above will do:
+
+ 1. show/hide the target object (and children)
+
+ * href: #https://my.org/foo.glb/#bar&-welcome
+
+ | *NOTE:* the latter shows that (de)selectors can also be with
+ | regular href (#href)-values
+
+12.4. Sharing object or file (#|)
+
+ The pipe-symbol (|) sends a (targeted) object to the OS. Clicking
+ the href-value below will:
+
+ 1. share the (targeted object in the) file to a another application
+
+ | This URL can be fed straight into Web Share API
+ | (https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API)
+ | or xdg-open (https://www.freedesktop.org/wiki/Software/xdg-utils/)
+
+ * href: xrf://#|bar
+
+
+
+van Kammen Expires 23 March 2026 [Page 16]
+
+Internet-Draft XR Fragments September 2025
+
+
+ | *NOTE*: sharing is limited to (internal objects) via xrf: scheme-
+ | only
+
+12.5. xrf:// URI scheme
+
+ Prefixing the xrf: to href (#href)-values *will prevent* level2
+ (#📜%20level2:%20explicit%20links) href (#href)-values from changing
+ the top-Level URL.
+
+ | *Usecase*: for non-shareable URLs like href: xrf:#t=4,5, to
+ | display a stateful msg e.g.).
+
+ *Reason:* XR Fragments is inspired by HTML's href-attribute
+ (https://en.wikipedia.org/wiki/Hyperlink), which does various things:
+
+ 1. it updates the browser-location
+ 2. it makes something clickable
+ 3. it jumps to another document / elsewhere in the same document
+ 4. and more
+
+ The xrf: scheme will just do 2 & 3 (so the URL-values will not leak
+ into the top-level URL).
+
+ | *compliance with RFC 3986*: unimplemented/unknown URI schemes
+ | (xrf:... e.g.) will not update the top-level URL
+
+13. Top-level URL processing
+
+ | Example URL: ://foo/world.gltf#room1&t=10&cam
The URL-processing-flow for hypermedia browsers goes like this:
- 1. IF a #room1 matches a custom property-key (of an object) in the
- 3D file/scene (#room1: #......) THEN execute that
- predefined_view.
- 2. IF scene operators and/or animation operator (t) are present in
+ 1. IF scene operators and/or animation operator (t) are present in
the URL then (re)position the camera (to room1) and/or animation-
range (10) accordingly.
- 3. IF no camera-position has been set in step 1 or 2 assume
+ 2. IF no camera-position has been set in step 1 or 2 assume
0,0,0 as camera coordinate (XR: add user-height) (example (https:
//github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
three/navigator.js#L31]]))
+ 3. IF a camera-object exists with name cam assume that user(camera)
+ position
- *Non-normative / Deprecated*:
+13.1. UX
- 4. IF a #cube 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).
- 5. IF a #cube matches anything else in the XR Word Graph (XRWG) draw
- wires to them (text or related objects).
+ End-users should always have read/write access to:
-13. Embedding XR content using src
-
- | NOTE: only adviced for local-first experiences (where resources
- | can be cached).
-
- src is the 3D version of the iframe.
- 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.
+ 1. the current (toplevel) URL (an URLbar etc)
+ 2. URL-history (a back/forward button e.g.)
-
-
-
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 18]
+van Kammen Expires 23 March 2026 [Page 17]
Internet-Draft XR Fragments September 2025
- +========+========+===================================================+
- |fragment|type |example value |
- +========+========+===================================================+
- |src |string |#cube |
- | |(uri, |#sometag |
- | |hashtag/|#cube&-ball_inside_cube
#-sky&-rain
#- |
- | |filter) |language&english
#price=>5
https://linux.org/|
- | | |penguin.png` (https://linux.org/penguin.png`) |
- | | |https://linux.world/distrowatch.gltf#t=1,100 |
- | | |linuxapp://conference/nixworkshop/apply.gltf#- |
- | | |cta&cta_apply |
- | | |androidapp://page1?tutorial#room1&t1,100 |
- | | |foo.mp3#0,0,0 |
- +--------+--------+---------------------------------------------------+
+ 3. Clicking/Touching an href navigates (and updates the URL) to
+ another scene/file (and coordinate e.g. in case the URL contains
+ XR Fragments).
- Table 8
-
- Here's an ascii representation of a 3D scene-graph with 3D objects ◻
- which embeds remote & local 3D objects ◻ with/out using filters:
-
- +────────────────────────────────────────────────────────+ +─────────────────────────+
- │ │ │ │
- │ 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 │
- │ │
- +────────────────────────────────────────────────────────+
-
- An XR Fragment-compatible browser viewing this scene, lazy-loads and
- projects painting.png onto the (plane) object called canvas (which is
- copy-instanced in the bed and livingroom).
- Also, after lazy-loading ocean.com/aquarium.gltf, only the queried
- objects fishbowl (and bass and tuna) will be instanced inside
- aquariumcube.
- Resizing will be happen accordingly to its placeholder object
- aquariumcube, see chapter Scaling.
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 19]
-
-Internet-Draft XR Fragments September 2025
-
-
- | Instead of cherrypicking a rootobject #fishbowl with src,
- | additional filters can be used to include/exclude certain objects.
- | See next chapter on filtering below.
-
- *Specification*:
-
- 1. local/remote content is instanced by the src (filter) value (and
- attaches it to the placeholder mesh containing the src property)
- 2. by default all objects are loaded into the instanced src (scene)
- object (but not shown yet)
- 3. local src values (#... e.g.) starting with a non-negating
- filter (#cube e.g.) will (deep)reparent that object (with name
- cube) as the new root of the scene at position 0,0,0
- 4. local src values should respect (negative) filters
- (#-foo&price=>3)
- 5. the instanced scene (from a src value) should be scaled
- accordingly to its placeholder object or scaled
- relatively based on the scale-property (of a geometry-less
- placeholder, an 'empty'-object in blender e.g.). For more info
- see Chapter Scaling.
- 6. external src 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:
- 7. src values should make its placeholder object invisible, and
- only flush its children when the resolved content can
- succesfully be retrieved (see broken links (#links))
- 8. external src values should respect the fallback link
- mechanism (see broken links (#broken-links)
- 9. 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.
- 10. src-values are non-recursive: when linking to an external object
- (src: foo.fbx#bar), then src-metadata on object bar should be
- ignored.
- 11. an external src-value should always allow a sourceportation icon
- within 3 meter: teleporting to the origin URI to which the
- object belongs.
- 12. when only one object was cherrypicked (#cube e.g.), set its
- position to 0,0,0
- 13. when the enduser clicks an href with #t=1,0,0 (play) will be
- applied to all src mediacontent with a timeline (mp4/mp3 e.g.)
- 14. a non-euclidian portal can be rendered for flat 3D objects
- (using stencil buffer e.g.) in case ofspatial src-values (an
- object #world3 or URL world3.fbx e.g.).
-
- * model/gltf-binary
- * model/gltf+json
- * image/png
-
-
-
-van Kammen Expires 5 March 2026 [Page 20]
-
-Internet-Draft XR Fragments September 2025
-
-
- * image/jpg
- * text/plain;charset=utf-8
-
- » example implementation
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/src.js)
- » example 3D asset
- (https://github.com/coderofsalvation/xrfragment/blob/main/example/
- assets/src.gltf#L192)
- » discussion (https://github.com/coderofsalvation/xrfragment/
- issues/4)
-
-14. Navigating content href portals
+14. Example: Navigating content href portals
navigation, portals & mutations
@@ -1142,15 +966,14 @@ Internet-Draft XR Fragments September 2025
| fragment | type | example value |
+==========+==================+========================+
| href | string (uri or | #room1 |
- | | predefined view) | #room1&rot=90,0,0 |
+ | | predefined view) | #room1 |
| | | ://somefile.gltf#room1 |
+----------+------------------+------------------------+
- Table 9
+ Table 5
1. clicking an outbound ''external''- or ''file URI'' fully replaces
- the current scene and assumes room2&rot=0,0,0 by default (unless
- specified)
+ the current scene and assumes room2 by default (unless specified)
2. relocation/reorientation should happen locally for local URI's
(#....)
@@ -1170,14 +993,6 @@ Internet-Draft XR Fragments September 2025
(https://github.com/coderofsalvation/xrfragment/blob/dev/example/
aframe/sandbox/index.html#L26-L29) for an example wearable)
-
-
-
-van Kammen Expires 5 March 2026 [Page 21]
-
-Internet-Draft XR Fragments September 2025
-
-
6. make sure that the ''back-button'' of the ''browser-history''
always refers to the previous position (see [here (https://github
.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/
@@ -1187,6 +1002,14 @@ Internet-Draft XR Fragments September 2025
using camera-portal collision (the back-button could cause a
teleport-loop if the previous position is too close)
+
+
+
+van Kammen Expires 23 March 2026 [Page 18]
+
+Internet-Draft XR Fragments September 2025
+
+
8. 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.
@@ -1206,627 +1029,50 @@ Internet-Draft XR Fragments September 2025
14.1. Walking surfaces
+ | By default position 0,0,0 of the 3D scene represents the walkable
+ | plane, however this is overridden when the following applies:
+
XR Fragment-compatible viewers can infer this data based scanning the
scene for:
- 1. materialless (nameless & textureless) mesh-objects (without src
- and href)
+ 1. materialless (nameless & textureless) mesh-objects (without href
+ and >0 faces)
| optionally the viewer can offer thumbstick, mouse or joystick
| teleport-tools for non-roomscale VR/AR setups.
-14.2. UX spec
+15. Virtual world rings
- End-users should always have read/write access to:
-
- 1. the current (toplevel) URL (an URLbar etc)
- 2. URL-history (a back/forward button e.g.)
- 3. Clicking/Touching an href navigates (and updates the URL) to
- another scene/file (and coordinate e.g. in case the URL contains
- XR Fragments).
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 22]
-
-Internet-Draft XR Fragments September 2025
-
-
-14.3. Scaling instanced content
-
- Sometimes embedded properties (like src) instance new objects.
- But what about their scale?
- How does the scale of the object (with the embedded properties)
- impact the scale of the referenced content?
-
- | 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.).
-
- 1. IF an embedded property (src e.g.) is set on an non-empty
- placeholder object (geometry of >2 vertices):
-
- * calculate the bounding box of the ''placeholder'' object
- (maxsize=1.4 e.g.)
- * hide the ''placeholder'' object (material e.g.)
- * instance the src scene as a child of the existing object
- * calculate the bounding box of the instanced scene, and
- scale it accordingly (to 1.4 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.)
-
- 2. ELSE multiply the scale-vector of the instanced scene with the
- scale-vector (a common property of a 3D node) of the
- placeholder object.
-
- | TODO: needs intermediate visuals to make things more obvious
-
-15. XR Fragment: pos
-
- [[» example implementation|https://github.com/coderofsalvation/xrfrag
- ment/blob/main/src/3rd/js/three/xrf/pos.js]
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/pos.js])]
-
-16. XR Fragment: rot
-
- [[» example implementation|https://github.com/coderofsalvation/xrfrag
- ment/blob/main/src/3rd/js/three/xrf/pos.js]
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/pos.js])]
-
-
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 23]
-
-Internet-Draft XR Fragments September 2025
-
-
-17. XR Fragment: t
-
- [[» example implementation|https://github.com/coderofsalvation/xrfrag
- ment/blob/main/src/3rd/js/three/xrf/t.js]
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/t.js])]
-
-18. XR audio/video integration
-
- To play global audio/video items:
-
- 1. add a src: foo.mp3 or src: bar.mp4 metadata to a 3D object (cube
- e.g.)
- 2. to enable auto-play and global timeline ([[#t=|t]]) control:
- hardcode a [[#t=|t]] XR Fragment: (src: bar.mp3#t=0&loop e.g.)
- 3. to play it, add href: #cube somewhere else
- 4. to enable enduser-triggered play, use a [[URI Template]] XR
- Fragment: (src: bar.mp3#{player} and play: t=0&loop and href:
- xrf://#player=play e.g.)
- 5. when the enduser clicks the href, #t=0&loop (play) will be
- applied to the src value
-
- | NOTE: hardcoded framestart/framestop uses sampleRate/fps of
- | embedded audio/video, otherwise the global fps applies. For more
- | info see [[#t|t]].
-
-19. XR Fragment filters
-
- Include, exclude, hide/shows objects using space-separated strings:
-
- +====================+===========================================+
- | 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 |
- | | (=*) |
- +--------------------+-------------------------------------------+
-
- Table 10
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 24]
-
-Internet-Draft XR Fragments September 2025
-
-
- It's simple but powerful syntax which allows filtering the scene
- using searchengine prompt-style feeling:
-
- 1. filters are a way to traverse a scene, and filter objects based
- on their name, tag- or property-values.
-
- * see an (outdated) example video here
- (https://coderofsalvation.github.io/xrfragment.media/queries.mp4)
- which used a dedicated q= variable (now deprecated and usable
- directly)
-
-19.1. including/excluding
-
- 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.
-
- +==========+==============================================+
- | 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 #) |
- +----------+----------------------------------------------+
-
- Table 11
-
- | 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).
-
- » example implementation
- (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
- three/xrf/q.js) » example 3D asset
-
-
-
-van Kammen Expires 5 March 2026 [Page 25]
-
-Internet-Draft XR Fragments September 2025
-
-
- (https://github.com/coderofsalvation/xrfragment/blob/main/example/
- assets/filter.gltf#L192) » discussion
- (https://github.com/coderofsalvation/xrfragment/issues/3)
-
-19.2. Filter Parser
-
- Here's how to write a filter parser:
-
- 1. create an associative array/object to store filter-arguments as
- objects
- 2. detect object id's & properties foo=1 and foo (reference regex=
- ~/^.*=[><=]?/ )
- 3. detect excluders like -foo,-foo=1,-.foo,-/foo (reference regex=
- /^-/ )
- 4. detect root selectors like /foo (reference regex= /^[-]?\// )
- 5. detect number values like foo=1 (reference regex= /^[0-9\.]+$/ )
- 6. detect operators so you can easily strip keys (reference regex=
- /(^-|\*$)/ )
- 7. detect exclude keys like -foo (reference regex= /^-/ )
- 8. for every filter token split string on =
- 9. and we set root to true or false (true=/ root selector is
- present)
- 10. therefore we we set show to true or false (false=excluder -)
-
- | An example filter-parser (which compiles to many languages) can be
- | found here
- | (https://github.com/coderofsalvation/xrfragment/blob/main/src/
- | xrfragment/Filter.hx)
-
-20. Visible links
-
- When predefined views, XRWG fragments and ID fragments (#cube or
- #mytag e.g.) are triggered by the enduser (via toplevel URL or
- clicking href):
-
- 1. draw a wire from the enduser (preferabbly a bit below the camera,
- heartposition) to object(s) matching that ID (objectname)
- 2. draw a wire from the enduser (preferabbly a bit below the camera,
- heartposition) to object(s) matching that tag value
- 3. draw a wire from the enduser (preferabbly a bit below the camera,
- heartposition) to object(s) containing that in their src or href
- value
-
- The obvious approach for this, is to consult the XRWG (example
- (https://github.com/coderofsalvation/xrfragment/blob/feat/macros/
- src/3rd/js/XRWG.js)), which basically has all these things already
- collected/organized for you during scene-load.
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 26]
-
-Internet-Draft XR Fragments September 2025
-
-
- *UX*
-
- 4. do not update the wires when the enduser moves, leave them as is
- 5. offer a control near the back/forward button which allows the
- user to (turn off) control the correlation-intensity of the XRWG
-
-21. Text in XR (tagging,linking to spatial objects)
-
- How does XR Fragments interlink text with objects?
-
- | The XR Fragments does this by collapsing space into a *Word Graph*
- | (the *XRWG* example
- | (https://github.com/coderofsalvation/xrfragment/blob/feat/macros/
- | src/3rd/js/XRWG.js)), augmented by Bib(s)Tex.
-
- Instead of just throwing together all kinds media types into one
- experience (games), what about their tagged/semantical relationships?
- Perhaps the following question is related: why is HTML adopted less
- in games outside the browser?
-
- Hence:
-
- 1. XR Fragments promotes (de)serializing a scene to a (lowercase)
- XRWG (example
- (https://github.com/coderofsalvation/xrfragment/blob/feat/macros/
- src/3rd/js/XRWG.js))
- 2. XR Fragments primes the XRWG, by collecting words from the tag
- and name-property of 3D objects.
- 3. XR Fragments primes the XRWG, by collecting words from *optional*
- metadata *at the end of content* of text (see default mimetype &
- Data URI)
- 4. XR Fragments primes the XRWG, by collecting tags/id's from linked
- hypermedia (URI fragments for HTML e.g.)
- 5. The XRWG should be recalculated when textvalues (in src) change
- 6. HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they
- fit better in the application-layer, or as embedded src content)
- 7. Applications don't have to be able to access the XRWG
- programmatically, as they can easily generate one themselves by
- traversing the scene-nodes.
- 8. 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)
- 9. Instead of exact lowercase word-matching, levensteihn-distance-
- based matching is preferred
-
- Example of generating XRWG out of the XRWG and textdata with
- hashtags:
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 27]
-
-Internet-Draft XR Fragments September 2025
-
-
- http://y.io/z.fbx | Derived XRWG (expressed as JSON)
- ----------------------------------------------------------------------------+--------------------------------------
- | Chapter: ['#mydoc']
- +-[src: data:.....]----------------------+ +-[3D mesh]-+ | one: ['#mydoc']
- | Chapter one | | / \ | | houses: ['#castle','#mydoc','#house']
- | | | / \ | | baroque: ['#mydoc','#castle']
- | John built houses in baroque style. | | / \ | | castle: ['#baroque','#house']
- | | | |_____| | | john: ['#john','#mydoc']
- | | +-----│-----+ | mydoc: ['#mydoc']
- | | │ |
- | | ├─ name: castle |
- | | └─ tag: house baroque |
- +----------------------------------------+ |
- └─ name: mydoc [3D mesh-+ |
- | O ├─ name: john |
- | /|\ | |
- | / \ | | ^ ^ ^
- +--------+ | | | |
- |
- [remotestorage.io]+ [ localstorage]-+ | <- the XR Fragment-compatible
- | XRWG (JSON) | | XRWG (JSON | | <- 3D hypermedia viewer should
- | | | | | <- be able to select the active XRWG
- +-----------------+ +---------------+ |
-
- This allows hasslefree authoring and copy-paste of associations *for
- and by humans*, but also makes these URLs possible:
-
- +==================+======================================+
- | URL example | Result |
- +==================+======================================+
- | https://my.com/ | draws lines between 3D mesh castle, |
- | foo.gltf#baroque | and mydoc's text baroque |
- +------------------+--------------------------------------+
- | https://my.com/ | draws lines between mesh john, and |
- | foo.gltf#john | the text John of mydoc |
- +------------------+--------------------------------------+
- | https://my.com/ | draws lines between mesh castle, and |
- | foo.gltf#house | other objects with tag house or todo |
- +------------------+--------------------------------------+
-
- Table 12
-
- | the URI fragment #john&mydoc&house would draw a connection between
- | these 3 meshes.
-
- The XRWG allows endusers to show/hide relationships in realtime in XR
- Browsers at various levels:
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 28]
-
-Internet-Draft XR Fragments September 2025
-
-
- * wordmatch *inside* src text
- * wordmatch *inside* href text
- * wordmatch object-names
- * wordmatch object-tagnames
-
- Spatial wires can be rendered between words/objects etc.
- Some pointers for good UX (but not necessary to be XR Fragment
- compatible):
-
- 9. 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)
- 10. 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.
- 11. respect multi-line BiBTeX metadata in text because of the core
- principle (#core-principle)
- 12. Default font (unless specified otherwise) is a modern monospace
- font, for maximized tabular expressiveness (see the core
- principle (#core-principle)).
- 13. anti-pattern: hardcoupling an XR Browser with a mandatory
- *markup/scripting-language* which departs from onubtrusive plain
- text (HTML/VRML/Javascript) (see the core principle (#core-
- principle))
- 14. anti-pattern: limiting human introspection, by abandoning plain
- text as first tag citizen.
-
-21.1. Default Data URI mimetype
-
- The src-values work as expected (respecting mime-types), however:
-
- The XR Fragment specification advices to bump the traditional default
- browser-mimetype
-
- text/plain;charset=US-ASCII
-
- to a hashtag-friendly one:
-
- text/plain;charset=utf-8;hashtag
-
- This indicates that:
-
- * utf-8 is supported by default
- * words beginning with # (hashtags) will prime the XRWG by adding
- the hashtag to the XRWG, linking to the current
- sentence/paragraph/alltext (depending on '.') to the XRWG
-
- Advantages:
-
-
-
-van Kammen Expires 5 March 2026 [Page 29]
-
-Internet-Draft XR Fragments September 2025
-
-
- * out-of-the-box (de)multiplex human text and metadata in one go
- (see the core principle (#core-principle))
- * no network-overhead for metadata (see the core principle (#core-
- principle))
- * ensuring high FPS: realtime HTML/RDF historically is too
- 'requesty'/'parsy' for game studios
- * rich send/receive/copy-paste everywhere by default, metadata being
- retained (see the core principle (#core-principle))
- * netto result: less webservices, therefore less servers, and
- overall better FPS in XR
-
- | 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.).
-
- For all other purposes, regular mimetypes can be used (but are not
- required by the spec).
-
-21.2. URL and Data URI
-
- +--------------------------------------------------------------+ +------------------------+
- | | | author.com/article.txt |
- | index.gltf | +------------------------+
- | │ | | |
- | ├── ◻ article_canvas | | Hello #friends |
- | │ └ src: ://author.com/article.txt | | |
- | │ | +------------------------+
- | └── ◻ note_canvas |
- | └ src:`data:welcome human\n@book{sunday...}` |
- | |
- | |
- +--------------------------------------------------------------+
-
- The enduser will only see welcome human and Hello friends 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.).
-
- | additional tagging using bibs
- | (https://github.com/coderofsalvation/hashtagbibs): to tag spatial
- | object note_canvas with 'todo', the enduser can type or speak
- | #note_canvas@todo
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 30]
-
-Internet-Draft XR Fragments September 2025
-
-
-22. Importing/exporting
-
- For usecases like importing/exporting/p2p casting a scene, the issue
- of external files comes into play.
-
- 1. export: if the 3D scene contains relative src/href values,
- rewrite them into absolute URL values.
-
-23. Reflection Mapping
-
- Environment mapping is crucial for creating realistic reflections and
- lighting effects on 3D objects. To apply environment mapping
- efficiently in a 3D scene, traverse the scene graph and assign each
- object's environment map based on the nearest ancestor's texture map.
- This ensures that objects inherit the correct environment mapping
- from their closest parent with a texture, enhancing the visual
- consistency and realism.
-
- +--------------------------------+
- | |
- | index.usdz |
- | │ |
- | └── ◻ sphere (texture:foo) |
- | └ ◻ cube (texture:bar) | envMap = foo
- | └ ◻ cylinder | envMap = bar
- +--------------------------------+
-
- Most 3D viewers apply one and the same environment map for various
- models, however this logic allows a more natural & automatic strategy
- for reflection mapping:
-
- 1. traverse the scene graph depth-first
- 2. remember the most recent parentnode (P) with a texture material
- 3. for every non-root node with a texture material 3.1 clone that
- material (as materials might be shared across objects) 3.2 set
- the environmentmap to the last known parent texture (P)
-
-24. Transclusion (broken link) resolution
-
- In spirit of Ted Nelson's 'transclusion resolution', there's a soft-
- mechanism to harden links & minimize broken links in various ways:
-
- 1. defining a different transport protocol (https vs ipfs or DAT) in
- src or href values can make a difference
- 2. mirroring files on another protocol using (HTTP) errorcode tags
- in src or href properties
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 31]
-
-Internet-Draft XR Fragments September 2025
-
-
- 3. in case of src: nesting a copy of the embedded object in the
- placeholder object (embeddedObject) will not be replaced when the
- request fails
-
- | 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.)
-
- For example:
-
- +────────────────────────────────────────────────────────+
- │ │
- │ 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.
- │ │
- +────────────────────────────────────────────────────────+
-
-25. Topic-based index-less Webrings
-
- As hashtags in URLs map to the XWRG, href-values can be used to
- promote topic-based index-less webrings.
- Consider 3D scenes linking to eachother using these href values:
+ Consider 3D scenes linking to eachother using these href values,
+ attached to 3D button-objects:
* href: schoolA.edu/projects.gltf#math
* href: schoolB.edu/projects.gltf#math
* href: university.edu/projects.gltf#math
- These links would all show visible links to math-tagged objects in
- the scene.
- To filter out non-related objects one could take it a step further
- using filters:
+ This would teleport users to the math-projects of those universities.
+ Now consider adding a 'webring index'-button to each file, with this
+ href-value:
- * href: schoolA.edu/projects.gltf#math&-topics math
- * href: schoolB.edu/projects.gltf#math&-courses math
- * href: university.edu/projects.gltf#math&-theme math
+ * href: workgroup.edu/webrings.glb#!webringmenu
+
+ This would allow displaying the (remote 3D file) webring menu with
+ various href-buttons inside, all centrally curated by the workgroup.
-
-van Kammen Expires 5 March 2026 [Page 32]
+van Kammen Expires 23 March 2026 [Page 19]
Internet-Draft XR Fragments September 2025
- | This would hide all object tagged with topic, courses or theme
- | (including math) so that later only objects tagged with math will
- | be visible
-
- 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.
-
-26. URI Templates (RFC6570)
+16. Level5: URI Templates (RFC6570)
XR Fragments adopts Level1 URI *Fragment* expansion to provide safe
interactivity.
- The following demonstrates a simple video player:
+ This is non-normative, and the draft spec is available on request.
- +─────────────────────────────────────────────+
- │ │
- │ 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} │
- │ │
- │ │
- +─────────────────────────────────────────────+
-
-27. Additional scene metadata
+17. Additional scene metadata
XR Fragments does not aim to redefine the metadata-space or
accessibility-space by introducing its own cataloging-metadata
@@ -1836,19 +1082,14 @@ Internet-Draft XR Fragments September 2025
* SPDX (https://spdx.dev/) license information
* ARIA (https://www.w3.org/WAI/standards-guidelines/aria/)
attributes (aria-*: .....)
+ * datapackage.json (https://datapackage.org) findability,
+ accessibility, interoperability, and reusability of data
- | SPDX and ARIA's aria-description are normative, as they promote
- | accessibility and scene transcripts: please start aria-description
- | with a verb to aid transcripts.
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 33]
-
-Internet-Draft XR Fragments September 2025
+ ARIA's aria-description-metadata is normative, to aid accessibility
+ and scene transcripts
+ | *NOTE*: please always start aria-description with a verb to aid
+ | transcripts.
The following metadata are non-normative but encouraged, since they
are popular and cheap to parse:
@@ -1873,6 +1114,14 @@ Internet-Draft XR Fragments September 2025
Individual nodes can be enriched with such metadata, but most
importantly the scene node:
+
+
+
+van Kammen Expires 23 March 2026 [Page 20]
+
+Internet-Draft XR Fragments September 2025
+
+
+================================+=========================+
| metadata key | example value |
+================================+=========================+
@@ -1896,15 +1145,7 @@ Internet-Draft XR Fragments September 2025
| journal (bibTeX) | {Future Of Text Vol 3}, |
+--------------------------------+-------------------------+
- Table 13
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 34]
-
-Internet-Draft XR Fragments September 2025
-
+ Table 6
| * = these are interchangable (only one needs to be defined)
@@ -1914,7 +1155,7 @@ Internet-Draft XR Fragments September 2025
| These attributes can be scanned and presented during an href or
| src eye/mouse-over.
-28. Accessibility interface
+18. Accessibility interface
The addressibility of XR Fragments allows for unique 3D-to-text
transcripts, as well as an textual interface to navigate 3D content.
@@ -1929,6 +1170,14 @@ Internet-Draft XR Fragments September 2025
to read (via screenreader, screen, or TTS e.g.)
4. the textlog contains aria-descriptions, and its narration
(Screenreader e.g.) can be skipped (via 2-button navigation)
+
+
+
+van Kammen Expires 23 March 2026 [Page 21]
+
+Internet-Draft XR Fragments September 2025
+
+
5. The back command should navigate back to the previous URL (alias
for browser-backbutton)
6. The forward command should navigate back to the next URL (alias
@@ -1952,21 +1201,11 @@ Internet-Draft XR Fragments September 2025
current #... (3D object) value (including its children)
16. The do command should list all possible href values which don't
contain an #... XR Fragment
-
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 35]
-
-Internet-Draft XR Fragments September 2025
-
-
17. The (dynamic) do abc command should navigate/execute
https://.../... in case a 3D node exist with name abc and href
value https://.../...
-28.1. Two-button navigation
+18.1. Two-button navigation
For specific user-profiles, gyroscope/mouse/keyboard/audio/visuals
will not be available.
@@ -1980,7 +1219,7 @@ Internet-Draft XR Fragments September 2025
3. the TTS reads the href-value (and/or aria-description if
available)
-28.2. Overlap with fileformat-specific extensions
+18.2. Overlap with fileformat-specific extensions
Some 3D scene-fileformats have support for extensions. What if the
functionality of those overlap? For example, GLTF has the OMI_LINK
@@ -1988,6 +1227,13 @@ Internet-Draft XR Fragments September 2025
| Priority Order and Precedence, otherwise fallback applies
+
+
+van Kammen Expires 23 March 2026 [Page 22]
+
+Internet-Draft XR Fragments September 2025
+
+
1.*Extensions Take Precedence*: 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
@@ -2009,21 +1255,12 @@ Internet-Draft XR Fragments September 2025
| teleport should be performed only (and other [overlapping]
| metadata should be ignored).
|
-
-
-
-
-van Kammen Expires 5 March 2026 [Page 36]
-
-Internet-Draft XR Fragments September 2025
-
-
| *Example 2* If an Extensions uses XR Fragments in URI's (href:
| #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.
-28.3. Vendor Prefixes
+18.3. Vendor Prefixes
Vendor-specific metadata in a 3D scenefiles, are similar to vendor-
specific CSS-prefixes (https://en.wikipedia.org/wiki/
@@ -2034,6 +1271,25 @@ Internet-Draft XR Fragments September 2025
Vendor Prefixes allows embedding 3D engines/framework-specific
features a 3D file via metadata:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 23]
+
+Internet-Draft XR Fragments September 2025
+
+
+===========+===================+==============================+
| what | XR metadata | Lowest common denominator |
+===========+===================+==============================+
@@ -2047,7 +1303,7 @@ Internet-Draft XR Fragments September 2025
| prefixs | | implementation |
+-----------+-------------------+------------------------------+
- Table 14
+ Table 7
| Why? Because not all XR interactions can/should be solved/
| standardized by embedding XR Fragments into any 3D file. The
@@ -2069,7 +1325,23 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 37]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+van Kammen Expires 23 March 2026 [Page 24]
Internet-Draft XR Fragments September 2025
@@ -2125,12 +1397,12 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 38]
+van Kammen Expires 23 March 2026 [Page 25]
Internet-Draft XR Fragments September 2025
-29. Security Considerations
+19. Security Considerations
The only dynamic parts are W3C Media Fragments
(https://www.w3.org/TR/media-frags/) and URI Templates (RFC6570)
@@ -2140,7 +1412,7 @@ Internet-Draft XR Fragments September 2025
n fact, it is much safer than relying on a scripting language
(javascript) which can change URN too.
-30. FAQ
+20. FAQ
*Q:* Why is everything HTTP GET-based, what about POST/PUT/DELETE
HATEOS
@@ -2173,7 +1445,7 @@ Internet-Draft XR Fragments September 2025
place, to 'extend' experiences, in contrast to code/javascript inside
hypermedia documents (this turned out as a hypermedia antipattern).
-31. authors
+21. authors
* Leon van Kammen (@lvk@mastodon.online)
* Jens Finkhäuser (@jens@social.finkhaeuser.de)
@@ -2181,16 +1453,16 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 39]
+van Kammen Expires 23 March 2026 [Page 26]
Internet-Draft XR Fragments September 2025
-32. IANA Considerations
+22. IANA Considerations
This document has no IANA actions.
-33. Acknowledgments
+23. Acknowledgments
* NLNET (https://nlnet.nl)
* Future of Text (https://futureoftext.org)
@@ -2205,7 +1477,7 @@ Internet-Draft XR Fragments September 2025
* Brandel Zackernuk
* Mark Anderson
-34. Appendix: Definitions
+24. Appendix: Definitions
+=================+=============================================+
| definition | explanation |
@@ -2237,7 +1509,7 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 40]
+van Kammen Expires 23 March 2026 [Page 27]
Internet-Draft XR Fragments September 2025
@@ -2293,7 +1565,7 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 41]
+van Kammen Expires 23 March 2026 [Page 28]
Internet-Draft XR Fragments September 2025
@@ -2319,7 +1591,7 @@ Internet-Draft XR Fragments September 2025
| | XML |
+-----------------+---------------------------------------------+
- Table 15
+ Table 8
@@ -2349,4 +1621,4 @@ Internet-Draft XR Fragments September 2025
-van Kammen Expires 5 March 2026 [Page 42]
+van Kammen Expires 23 March 2026 [Page 29]
diff --git a/doc/RFC_XR_Fragments.xml b/doc/RFC_XR_Fragments.xml
index 85325c9..9492de8 100644
--- a/doc/RFC_XR_Fragments.xml
+++ b/doc/RFC_XR_Fragments.xml
@@ -13,12 +13,12 @@
An open specification for hyperlinking & deeplinking 3D fileformats.
This draft is a specification for interactive URI-controllable 3D files, enabling hypermediatic navigation, to enable a spatial web for hypermedia browsers with- or without a network-connection.
-The specification uses W3C Media Fragments and URI Templates (RFC6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
-
XR Fragments allows us to better use implicit metadata inside 3D scene(files), by mapping it to proven technologies like URI Fragments .
-XR Fragments views XR experiences thru the lens of 3D object URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
-XR Fragments is a <b>heuristical 3D format</b> which leverages heuristic rules derived from any 3D scene or well-established 3D file formats, to extract meaningful features from scene hierarchies.
+XR Fragments views XR experiences thru the lens of 3D deeplinked URI's, rather than thru code(frameworks) or protocol-specific browsers (webbrowser e.g.).
+The standard comprises of various (optional) support levels, which also include W3C Media Fragments and URI Templates (RFC6570) to promote spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.
+
+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.
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.
Almost every idea in this document is demonstrated at https://xrfragment.org
@@ -36,7 +36,7 @@ Historically, there's many attempts to create the ultimate 3D fileformat.
The lowest common denominator is: designers describing/tagging/naming things using plain text.
XR Fragments exploits the fact that all 3D models already contain such metadata:
-XR Fragments allows controlling of metadata in 3D scene(files) using URI's
+XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments
It solves:
@@ -49,140 +49,28 @@ XR Fragments exploits the fact that all 3D models already contain such metadata:
NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
-Core principle
-XR Fragments allows controlling 3D models using URLs, based on (non)existing metadata via URI's
-XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
-
-Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments integrates all which allows a universal viewing experience.
-
-
-
-
-Fact: our typical browser URL's are just a possible implementation of URI's (for untapped humancentric potential of URI's see interpeer.io )
-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.
-
Below you can see how this translates back into good-old URLs:
-
- ?other.glb ─> #view ───> hashbus │
- │ │ #filter │ │
- │ │ #tag │ │
- │ │ (hypermediatic) #material │ │
- │ │ ( feedback ) #animation │ │
- │ │ ( loop ) #texture │ │
- │ │ #variable │ │
- │ │ │ │
- │ XRWG <─────────────────────<─────────────+ │
- │ │ │ │
- │ └─ objects ──────────────>─────────────+ │
- │ │
- │ │
- +───────────────────────────────────────────────────────────────────────────────────────────────+
-
-]]>
-
-?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
-
Traditional webbrowsers can become 4D document-ready by:
-
-
-The XR Fragments Trinity
+What is XR Fragments
XR Fragments utilizes URLs:
-- for 3D viewers/browser to manipulate the camera or objects (via URLbar)
-- as implicit metadata to reference (nested) objects inside 3D scene-file (local and remote)
-- via explicit metadata ('extras') inside 3D scene-files (interaction e.g.) or
-- [optionally for developers] via explicit metadata outside 3D scene-files (via
sidecarfile )
+- for 3D viewers/browser to manipulate the camera or objects (via URI fragments)
+- implicitly: by mapping 3D objectnames (of a 3D scene/file) to URI fragments (3D deeplinking)
+- explicitly: by scanning href metadata inside 3D scene-files to enable interactions
+- externally: progressively enhance a 3D (file) into an experience via
sidecarfiles
-List of URI Fragments
-
-
-
-fragment
-type
-example
-info
-
-
-
-
-
-#......
-vector3
-#room1 #room2 #cam2
-positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector
-
-
-
-Media Fragments
-media fragment
-#t=0,2&loop
-play (and loop) 3D animation from 0 seconds till 2 seconds
-
-
-
-
-List of *explicit metadata
-These are the possible 'extras' for 3D nodes and sidecar-files
-
-
-
-key
-type
-example (JSON)
-function
-existing compatibility
-
-
-
-
-
-href
-string
-"href": "b.gltf"
-XR teleport
-custom property in 3D fileformats
-
-
-
-
HFL (Hypermediatic Feedback Loop) for XR Browsers
-href metadata traditionally implies click AND navigate, however XR Fragments adds stateless click (xrf://#....) or navigate (xrf://#...)
- as well (which allows many extra interactions which otherwise need a scripting language). This is known as hashbus-only events (see image above).
-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.
+href metadata traditionally implies click AND navigate, however XR Fragments adds stateless click (xrf://....) via the xrf:// scheme, which does not change the top-level URL-adress (of the browser).
+This allows for many extra interactions via URLs, which otherwise needs a scripting language.
+These are called hashbus-only events/
+Being able to use the same URI Fragment DSL for navigation (href: #foo) as well as interactions (href: xrf://#foo) greatly simplifies implementation, increases HFL, and reduces need for scripting languages.
This opens up the following benefits for traditional & future webbrowsers:
hypermediatic loading/clicking 3D assets (gltf/fbx e.g.) natively (with or without using HTML).
-- allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the xrf:// hashbus (xrf://#person=walk to trigger walk-animation for object person)
-- collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
+- potentially allowing 3D assets/nodes to publish XR Fragments to themselves/eachother using the xrf:// hashbus (xrf://#person=walk to trigger walk-animation for object person)
+- potentially collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
- completely bypassing the security-trap of loading external scripts (by loading 3D model-files, not HTML-javascriptable resources)
XR Fragments itself are hypermediatic and HTML-agnostic, though pseudo-XR Fragment browsers can be implemented on top of HTML/Javascript.
@@ -190,7 +78,7 @@ But approaches things from a higherlevel feedbackloop/hypermedia browser-perspec
principle
-XR 4D URL
+3D URL
HTML 2D URL
@@ -286,7 +174,7 @@ sub-delims = "," / "="
-room1&rot=0,90,0&cam1
+room1&cam1
combinators
@@ -300,7 +188,9 @@ That way, if the link gets shared, the XR Fragments implementation at https:
Spatial Referencing 3D
-XR Fragments assume the following objectname-to-URIFragment mapping:
+3D files contain an hierarchy of objects.
+
+XR Fragments assumes the following objectname-to-URI-Fragment mapping, in order to deeplink 3D objects:
- href: https://scene.fbx
-- src: https://otherworld.gltf#mainobject
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.
-non-normative
-The following below is non-normative heuristics which are not part officially part of the spec.
+Level0: Files
+These are optional auto-loaded side-car files to enable hasslefree XR Movies .
+
+they can accomodate developers or applications who (for whatever reason) must not modify the 3D scene-file (a .glb e.g.).
+
+via href metadata
+
+
+
+heuristics:
+
+
+- if at least one href custom property/extra is found in a 3D scene
+- The viewer should poll for the above mentioned sidecar-file extensions (and present accordingly)
+
-additional explicit metadata
-| #rot | vector3 | #rot=0,90,0 | rotates camera to xyz-coord 0.5,0,0 |
-| 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.
-
-Sidecar-file
-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.).
-
For developers, sidecar-file can allow for defining explicit XR Fragments metadata, outside of the 3D file.
+via chained extension
-This can be done via a JSON-pointers RFC6901 in a JSON sidecar-file :
+
+
+A fallback-mechanism to turn 3D files into XR Movies without editing them.
+
heuristics:
+
+
+- the chained-extension heuristic .xrf. should be present in the filename (scene.xrf.glb e.g.)
+
+
+
+via subdocuments/xattr
+More secure protocols (Nextgraph e.g.) don't allow for simply polling files.
+In such case, subdocuments or extended attributes should be polled:
+NOTE: in the examples below we use the href-heuristic, but also the .xrf. chained-extension applies here.
+
+
+
+If only extended attributes (xattr) are available, the respective referenced file can be embedded:
+
+
+
+NOTE: Linux's setfattr/getfattr is xattr on mac, and Set-Content/Get-content on Windows. See pxattr for lowlevel access.
+
+
+JSON sidecar-file
+For developers, sidecar-file can allow for defining explicit XR Fragments links (>level1), outside of the 3D file.
+
+This can be done via (objectname/metadata) key/value-pairs in a JSON sidecar-file :
- experience.glb
-- experience.json
+- experience.json <----
-This would mean: hide object(s) with name or tag-value 'penguin' upon scene-load, and show it when the user clicks the chair
+This will make object button clickable, and teleport the user to object roomB.
So after loading experience.glb the existence of experience.json is detected, to apply the explicit metadata.
The sidecar will define (or override already existing) extras, which can be handy for multi-user platforms (offer 3D scene customization/personalization to users).
In THREE.js-code this would boil down to:
-
+
-Level2: Implicit URI Fragments
-Warning: non-normative
-
These fragments are derived from objectnames (or their extras) within a 3D scene, and trigger certain actions when evaluated by the browser:
+Level1: URI
+XR Fragments allows deeplinking of 3D objects by mapping objectnames to URI fragments
+
XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.
+
+Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments integrates all which allows a universal viewing experience.
+
+
+
+
+Fact: our typical browser URL's are just a possible implementation of URI's (for untapped humancentric potential of URI's see interpeer.io or NextGraph )
+XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
+But approaches things from a higherlevel local-first 3D hypermedia browser-perspective.
+
Below you can see how this translates back into good-old URLs:
+
+ ?other.glb ─> #object ─> hashbus │
+ │ │ #filter │ │
+ │ │ #tag │ │
+ │ │ (hypermediatic) #material │ │
+ │ │ ( feedback ) #animation │ │
+ │ │ ( loop ) #texture │ │
+ │ │ #variable │ │
+ │ │ │ │
+ │ XRWG <─────────────────────<─────────────+ │
+ │ │ │ │
+ │ └─ objects ──────────────>─────────────+ │
+ │ │
+ │ │
+ +───────────────────────────────────────────────────────────────────────────────────────────────+
+
+]]>
+
+?-linked and #-linked navigation are JUST one possible way to implement XR Fragments: the essential goal is to allow a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
+
+
+List of URI Fragments
-
fragment
type
example
@@ -396,376 +391,274 @@ The sidecar will define (or override already existing) extras,
-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 #
+#......
+vector3
+#room1 #room2 #cam2
+positions/parents camera(rig) (or XR floor) to xyz-coord/object/camera and upvector
-FOCUS
-xrf://#<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 URI Template variable foo to the value #t=0 from existing object metadata (bar:#t=0 e.g.), This allows for reactive URI Template defined in object metadata elsewhere (src:://m.com/cat.mp4#{foo} e.g., to play media using media fragment URI ). NOTE: metadata-key should not start with #
-
-
-
-ANIMATION
-#<tag_or_objectname>=<animationname>
-string=string
-#people=walk #people=noanim
-assign a different animation to object(s)
+Media Fragments
+media fragment
+#t=0,2&loop
+play (and loop) 3D animation from 0 seconds till 2 seconds
-media fragments and datatypes
-Warning: non-normative (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).
-
Example URI's:
-
-
-- https://images.org/credits.jpg#uv=0,0,0,+0.1 (infinite vertical texturescrolling)
-- https://video.org/organogram.mp4#t=0&loop&uv=0.1,0.1,0.3,0.3 (animated tween towards region in looped video)
-- https://shaders.org/plasma.glsl#t=0&u:col2=0,1,0 (red-green shader plasma starts playing from time-offset 0)
-
-
- 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).
-
-]]>
-
-
-
-
-Navigating 3D
+List of *explicit metadata
+These are the possible 'extras' for 3D nodes and sidecar-files
-fragment
+key
type
-functionality
+example (JSON)
+function
+existing compatibility
-<b>#</b>=room1
+href
string
-position camera to position and upvector of objectname room1 (+userheight in VR)
+"href": "b.gltf"
+XR teleport
+custom property in 3D fileformats
-
» example implementation
+
-» discussion
-
-Here's the basic level1 flow (with optional level2 features):
+Level2: href links
+Explicit href metadata ('extras') in a 3D object (of a 3D file), hint the viewer that the user ''can interact'' with that object :
+| fragment | type | example value |
+|href| string (uri or predefined view) | #pyramid
+#lastvisit
+xrf://#-someobject
+://somefile.gltf#foo
+ |
-
-- the Y-coordinate of `room1 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), except in case of camera-switching.
-- set the position of the camera accordingly to the vector3 values of room1
-- set the upvector of the camera accordingly to the vector3 values of room1 (local gravity as pioneered by Patrick Lichty)
-- if the referenced #room1 object is animated, parent the current camera to that object (so it animates too)
-- in case a href does not mention any 3D object, the current position will be assumed
-
-Here's an ascii representation of a 3D scene-graph which contains 3D objects ◻ and their metadata:
+Interaction behaviour
+When clicking an ''href''-value, the user(camera) is teleport to the referenced object.
+The imported/teleported destination can be another object in the same scene-file, or a different file.
+
-XR Viewer implementation
+| spec | action | feature |
+|-|-|-|
+| level0+1 | hover 3D file href | show the preview PNG thumbnail (if any). |
+| level0+1 | launch 3D file href | replace the current scene with a new 3D file (href: other.glb e.g.) |
+| level2 | click internal 3D file href (#roomB e.g.) | teleport the camera to the origin of object(name roomB). See [[teleport camera]].|
+| level2 | click external 3D file href (foo.glb e.g.) | replace the current scene with a new 3D file (href: other.glb e.g.) |
+| level2 | hover external 3D file href | show the preview PNG thumbnail (if any sidecar, see level0) |
+| level2 | click href | hashbus: execute without changing the toplevel URL location (href: xrf://#someObjectName e.g.) |
+| level3 | click href | set the global 3D animation timeline to its Media Fragment value (#t=2,3 e.g.) |
+NOTE: hashbus links (xrf://#foo&bar) don't change the toplevel URL, which makes it ideal for interactions (in contrast to typical #roomC navigation, which benefit back/forward browser-buttons), see <a href="#hashbus">hashbus</a> for more info.
+
+
+
+Level3: Media Fragments
+these allow for XR Movies with a controllable timeline using href URI's with Media Fragments
+
Just like with 2D media-files, W3C mediafragments (#t=1,2) can be used to control a timeline via the #t primitive.
+XR Fragments Level3 makes the 3D timeline, as well as URL-referenced files controllable via Media Fragments like:
+
+
+- level2 hrefs (href: #t=4 e.g. to control 3D timeline)
+level4: xrf: URI scheme:
+
+
+- href: xrf:foo.wav#t=0 to play a wav
+- href: xrf:news.glb?clone#t=0 to instance and play another experience
+
+
+
+Animation(s) timeline
+controls the animation(s) of the scene (or src resource which contains a timeline)
+| fragment | type | functionality |
+| <b>#t</b>=start,stop | [vector2] | start,stop (in seconds |
+| Example Value | Explanation |
+| #t=1 | play (3D) animations from 1 seconds till end (and stop) |
+| #t=1,100 | play (3D) animations from 1 till 100 seconds (and stop) |
+| #t=0,0 | stop (3D) animations at frame 0 |
+Use [[#s 🌱]] to control playback speed
+
+
+Specify playback loopmode
+This compensates a missing element from Media Fragments to enable/disable temporal looping. .
+| fragment | type | functionality |
+| <b>#loop</b> | string | enables animation/video/audio loop |
+| <b>#-loop</b> | string | disables animation/video/audio loop |
+
+
+Controlling embedded content
+use [[URI Templates]] to control embedded media, for example a simple video-player:
+
+
-An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the buttonA and buttonB.
+
+
-In case of buttonA the end-user will be teleported to another location and time in the current loaded scene, but buttonB will replace the current scene with a new one, like other.fbx, and assume camera coordinate 0,0,0
-Non-normative:
+Level4: prefix operators
+Prefixing objectnames with the following simple operators allow for extremely powerful XR interactions:
-
-- rot sets the rotation of the camera (only for non-VR/AR headsets, however a camera-value overrules this)
-- level2: mediafragment t in the top-URL sets the playbackspeed and animation-range of the global scene animation
-- before scene load: the scene is cleared
-- level2: after scene load: in case the scene (rootnode) contains an # default view with a fragment value: execute non-positional fragments via the hashbus (no top-level URL change)
-- level2: after scene load: in case the scene (rootnode) contains an # default view with a fragment value: execute positional fragment via the hashbus + update top-level URL
-- level2: in case of no default # view on the scene (rootnode), default player(rig) position 0,0,0 is assumed.
+
+- #!
+- #*
+- #+ or #-
+- #|
+- xrf: URI scheme
+
+Examples: #+menu to show a object, #-menu to hide a menu, #!menu to teleport a menu, #*block to clone a grabbable block, #|object to share an object
+
+Object teleports (!)
+Prefixing an object with an exclamation-symbol, will teleport a (local or remote) referenced object from/to its original/usercamera location.
+
+[img[objecteleport.png]]
+Usecases:
+* show/hide objects/buttons (menu e.g.) in front of user
+* embed remote (object within) 3D file via remote URL
+* instance an interactive object near the user regardless of location
+* instance HUD or semi-transparent-textured-sphere (LUT) around the user
+<div class="border padding" style="border:4px solid #888">
+ <span class="big hi1">#!menu</span>
+</div>
+
+
+Clicking the href -value above will:
+
+
+- reposition the referenced object (menu) to the usercamera's-coordinates.
+- zoom in case of (non-empty) mesh-object: rescale to 1 m³, and position 1m in front of the camera
+- toggle behaviour: revert values if 1/2 were already applied
+- #+ is always implied (objects are always made visible)
+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.).
+
+
+- href: #whiteroom&!explainer&!exitmenu
+
+This will teleport the user to whiteroom and moves object explainer and exitmenu in front of the user.
+
+
+- href: `
https://my.org/foo.glb#!
+
+Clicking the href -value above will:
+
+
+- import foo.glb from my.org's webserver
+- show it in front of the user (because #! indicates object teleport)
+
+
+
+- href: https://foo.glb#roomB&!bar
+
+Clicking the href -value above will:
+
+
+- replace the current scene with foo.glb
+- teleport the user to #roomB inside foo.glb
+- instance the referenced object (bar inside foo.glb) in front of the user.
+- it will update the top-Level URL (because xrf: was not used)
+- hide the instanced object when clicked again (toggle visibility)
+
+NOTE: level2 teleportation links, as well as instancing mitigates the 'broken embedded image'-issue of HTML: always attaching the href-values to a 3D (preview) object (that way broken links will not break the design).
+
Example: clicking a 3D button with title 'menu' and href -value xrf:menu.glb?instance#t=4,5 would instance a 3D menu (menu.glb) in front of the user, and loop its animation between from 4-5 seconds (t=4,5)
+NOTE: combining instance-operators allows dynamic construction of 3D scenes (#london&!welcomeMenu&!fadeBox e.g.)
+
+
+Object multipliers (*)
+The star-prefix will clone a (local or remote) referenced object to the usercamera's location, and make it grabbable.
+
+Usecases:
+* object-picker (build stuff with objects)
+NOTE: this is basically the #! operator which infinitely clones the referenced object (instead of repositioning the object).
+
+
+De/selectors (+ and -)
+
+
+- href: #-welcome (or #+welcome)
+
+Clicking href-value above will do:
+
+
+- show/hide the target object (and children)
+
+
+
+- href: #https://my.org/foo.glb/#bar&-welcome
+
+NOTE: the latter shows that (de)selectors can also be with regular href -values
+
+
+Sharing object or file (#|)
+The pipe-symbol (|) sends a (targeted) object to the OS.
+Clicking the href-value below will:
+
+
+- share the (targeted object in the) file to a another application
+
+This URL can be fed straight into Web Share API or xdg-open
+
+
+- href: xrf://#|bar
+
+NOTE: sharing is limited to (internal objects) via xrf: scheme-only
+
+
+xrf:// URI scheme
+Prefixing the xrf: to href -values will prevent level2 href -values from changing the top-Level URL.
+Usecase: for non-shareable URLs like href: xrf:#t=4,5, to display a stateful msg e.g.).
+
Reason: XR Fragments is inspired by HTML's href-attribute , which does various things:
+
+
+- it updates the browser-location
+- it makes something clickable
+- it jumps to another document / elsewhere in the same document
+- and more
+
+The xrf: scheme will just do 2 & 3 (so the URL-values will not leak into the top-level URL).
+compliance with RFC 3986: unimplemented/unknown URI schemes (xrf:... e.g.) will not update the top-level URL
+
Top-level URL processing
-Example URL: ://foo/world.gltf#room1&t=10
+Example URL: ://foo/world.gltf#room1&t=10&cam
The URL-processing-flow for hypermedia browsers goes like this:
-- IF a #room1 matches a custom property-key (of an object) in the 3D file/scene (#room1: #......) <b>THEN</b> execute that predefined_view.
- IF scene operators and/or animation operator (t) are present in the URL then (re)position the camera (to room1) and/or animation-range (10) accordingly.
- IF no camera-position has been set in <b>step 1 or 2</b> assume 0,0,0 as camera coordinate (XR: add user-height) (
example )
+- IF a camera-object exists with name cam assume that user(camera) position
-Non-normative / Deprecated:
-
-- IF a #cube 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).
-- IF a #cube matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects).
-
-
-
-Embedding XR content using src
-NOTE: only adviced for local-first experiences (where resources can be cached).
-
src is the 3D version of the <a target="_blank" href="https://www.w3.org/html/wiki/Elements/iframe">iframe</a>.
-
-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.
-
-
-
-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.org/penguin.png`
-https://linux.world/distrowatch.gltf#t=1,100
-linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply
-androidapp://page1?tutorial#room1&t1,100
-foo.mp3#0,0,0
-
-
-
Here's an ascii representation of a 3D scene-graph with 3D objects ◻ which embeds remote & local 3D objects ◻ with/out using filters:
-
-
-
-An XR Fragment-compatible browser viewing this scene, lazy-loads and projects painting.png onto the (plane) object called canvas (which is copy-instanced in the bed and livingroom).
-
-Also, after lazy-loading ocean.com/aquarium.gltf, only the queried objects fishbowl (and bass and tuna) will be instanced inside aquariumcube.
-
-Resizing will be happen accordingly to its placeholder object aquariumcube, see chapter Scaling.
-
-Instead of cherrypicking a rootobject #fishbowl with src, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
-
Specification:
+UX
+End-users should always have read/write access to:
-- local/remote content is instanced by the src (filter) value (and attaches it to the placeholder mesh containing the src property)
-- by default all objects are loaded into the instanced src (scene) object (but not shown yet)
-- <b>local</b> src values (#... e.g.) starting with a non-negating filter (#cube e.g.) will (deep)reparent that object (with name cube) as the new root of the scene at position 0,0,0
-- <b>local</b> src values should respect (negative) filters (#-foo&price=>3)
-- the instanced scene (from a src 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.
-- <b>external</b> src 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:
-- src values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see
broken links )
-- <b>external</b> src values should respect the fallback link mechanism (see
broken links
-- 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.
-- src-values are non-recursive: when linking to an external object (src: foo.fbx#bar), then src-metadata on object bar should be ignored.
-- an external src-value should always allow a sourceportation icon within 3 meter: teleporting to the origin URI to which the object belongs.
-- when only one object was cherrypicked (#cube e.g.), set its position to 0,0,0
-- when the enduser clicks an href with #t=1,0,0 (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.)
-- a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial src-values (an object #world3 or URL world3.fbx e.g.).
+- the current (toplevel) <b>URL</b> (an URLbar etc)
+- URL-history (a <b>back/forward</b> button e.g.)
+- Clicking/Touching an href navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-
-
-- model/gltf-binary
-- model/gltf+json
-- image/png
-- image/jpg
-- text/plain;charset=utf-8
-
-» example implementation
-
-» example 3D asset
-
-» discussion
-
+
-Navigating content href portals
+Example: Navigating content href portals
navigation, portals & mutations
@@ -781,14 +674,14 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
href
string (uri or predefined view)
#room1
-#room1&rot=90,0,0
+#room1
://somefile.gltf#room1
-clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes room2&rot=0,0,0 by default (unless specified)
+clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes room2 by default (unless specified)
relocation/reorientation should happen locally for local URI's (#....)
@@ -815,457 +708,38 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
Walking surfaces
-XR Fragment-compatible viewers can infer this data based scanning the scene for:
+By default position 0,0,0 of the 3D scene represents the walkable plane, however this is overridden when the following applies:
+
XR Fragment-compatible viewers can infer this data based scanning the scene for:
-- materialless (nameless & textureless) mesh-objects (without src and href)
+- materialless (nameless & textureless) mesh-objects (without href and >0 faces)
optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.
-
-UX spec
-End-users should always have read/write access to:
-
-
-- the current (toplevel) <b>URL</b> (an URLbar etc)
-- URL-history (a <b>back/forward</b> button e.g.)
-- Clicking/Touching an href navigates (and updates the URL) to another scene/file (and coordinate e.g. in case the URL contains XR Fragments).
-
-Scaling instanced content
-Sometimes embedded properties (like src) instance new objects.
-
-But what about their scale?
-
-How does the scale of the object (with the embedded properties) impact the scale of the referenced content?
-
-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.).
-
-
-- <b>IF</b> an embedded property (src e.g.) is set on an non-empty placeholder object (geometry of >2 vertices):
-
-
-
-- calculate the <b>bounding box</b> of the ''placeholder'' object (maxsize=1.4 e.g.)
-- hide the ''placeholder'' object (material e.g.)
-- instance the src scene as a child of the existing object
-- calculate the <b>bounding box</b> of the instanced scene, and scale it accordingly (to 1.4 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.)
-
-
-- 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.
-
-TODO: needs intermediate visuals to make things more obvious
-
-
-
-XR Fragment: pos
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js] ]
-
-
-
-XR Fragment: rot
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js] ]
-
-
-
-XR Fragment: t
-[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js] ]
-
-
-
-XR audio/video integration
-To play global audio/video items:
-
-
-- add a src: foo.mp3 or src: bar.mp4 metadata to a 3D object (cube e.g.)
-- to enable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (src: bar.mp3#t=0&loop e.g.)
-- to play it, add href: #cube somewhere else
-- to enable enduser-triggered play, use a [[URI Template]] XR Fragment: (src: bar.mp3#{player} and play: t=0&loop and href: xrf://#player=play e.g.)
-- when the enduser clicks the href, #t=0&loop (play) will be applied to the src value
-
-NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].
-
-
-XR Fragment filters
-Include, exclude, hide/shows objects using space-separated strings:
-
-
-
-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 (=*)
-
-
-
It's simple but powerful syntax which allows filtering the scene using searchengine prompt-style feeling:
-
-
-- filters are a way to traverse a scene, and filter objects based on their name, tag- or property-values.
-
-
-
-- see
an (outdated) example video here which used a dedicated q= variable (now deprecated and usable directly)
-
-
-including/excluding
-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.
-
-
-
-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).
-
» example implementation
-» example 3D asset
-» discussion
-
-
-Filter Parser
-Here's how to write a filter parser:
-
-
-- create an associative array/object to store filter-arguments as objects
-- detect object id's & properties foo=1 and foo (reference regex= ~/^.*=[><=]?/ )
-- detect excluders like -foo,-foo=1,-.foo,-/foo (reference regex= /^-/ )
-- detect root selectors like /foo (reference regex= /^[-]?\// )
-- detect number values like foo=1 (reference regex= /^[0-9\.]+$/ )
-- detect operators so you can easily strip keys (reference regex= /(^-|\*$)/ )
-- detect exclude keys like -foo (reference regex= /^-/ )
-- for every filter token split string on =
-- and we set root to true or false (true=/ root selector is present)
-- therefore we we set show to true or false (false=excluder -)
-
-An example filter-parser (which compiles to many languages) can be found here
-
-
-
-Visible links
-When predefined views, XRWG fragments and ID fragments (#cube or #mytag e.g.) are triggered by the enduser (via toplevel URL or clicking href):
-
-
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname)
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that tag value
-- draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) containing that in their src or href value
-
-The obvious approach for this, is to consult the XRWG (example ), which basically has all these things already collected/organized for you during scene-load.
-UX
-
-
-- do not update the wires when the enduser moves, leave them as is
-- offer a control near the back/forward button which allows the user to (turn off) control the correlation-intensity of the XRWG
-
-
-
-Text in XR (tagging,linking to spatial objects)
-How does XR Fragments interlink text with objects?
-The XR Fragments does this by collapsing space into a Word Graph (the XRWG example ), augmented by Bib(s)Tex.
-
Instead of just throwing together all kinds media types into one experience (games), what about their tagged/semantical relationships?
-
-Perhaps the following question is related: why is HTML adopted less in games outside the browser?
-Hence:
-
-
-- XR Fragments promotes (de)serializing a scene to a (lowercase) XRWG (
example )
-- XR Fragments primes the XRWG, by collecting words from the tag and name-property of 3D objects.
-- XR Fragments primes the XRWG, by collecting words from optional metadata at the end of content of text (see default mimetype & Data URI)
-- XR Fragments primes the XRWG, by collecting tags/id's from linked hypermedia (URI fragments for HTML e.g.)
-- The XRWG should be recalculated when textvalues (in src) change
-- HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they fit better in the application-layer, or as embedded src content)
-- Applications don't have to be able to access the XRWG programmatically, as they can easily generate one themselves by traversing the scene-nodes.
-- 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)
-- Instead of exact lowercase word-matching, levensteihn-distance-based matching is preferred
-
-Example of generating XRWG out of the XRWG and textdata with hashtags:
-
-
-
-This allows hasslefree authoring and copy-paste of associations for and by humans, but also makes these URLs possible:
-
-
-
-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.
-
The XRWG allows endusers to show/hide relationships in realtime in XR Browsers at various levels:
-
-
-- wordmatch inside src text
-- wordmatch inside href text
-- wordmatch object-names
-- wordmatch object-tagnames
-
-Spatial wires can be rendered between words/objects etc.
-
-Some pointers for good UX (but not necessary to be XR Fragment compatible):
-
-
-- 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)
-- 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.
-- respect multi-line BiBTeX metadata in text because of
the core principle
-- Default font (unless specified otherwise) is a modern monospace font, for maximized tabular expressiveness (see
the core principle ).
-- anti-pattern: hardcoupling an XR Browser with a mandatory markup/scripting-language which departs from onubtrusive plain text (HTML/VRML/Javascript) (see
the core principle )
-- anti-pattern: limiting human introspection, by abandoning plain text as first tag citizen.
-
-
-Default Data URI mimetype
-The src-values work as expected (respecting mime-types), however:
-The XR Fragment specification advices to bump the traditional default browser-mimetype
-text/plain;charset=US-ASCII
-to a hashtag-friendly one:
-text/plain;charset=utf-8;hashtag
-This indicates that:
-
-
-- utf-8 is supported by default
-- words beginning with # (hashtags) will prime the XRWG by adding the hashtag to the XRWG, linking to the current sentence/paragraph/alltext (depending on '.') to the XRWG
-
-Advantages:
-
-
-- out-of-the-box (de)multiplex human text and metadata in one go (see
the core principle )
-- no network-overhead for metadata (see
the core principle )
-- ensuring high FPS: realtime HTML/RDF historically is too 'requesty'/'parsy' for game studios
-- rich send/receive/copy-paste everywhere by default, metadata being retained (see
the core principle )
-- netto result: less webservices, therefore less servers, and overall better FPS in XR
-
-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.).
-
For all other purposes, regular mimetypes can be used (but are not required by the spec).
-
-
-
-URL and Data URI
-
-
-
-The enduser will only see welcome human and Hello friends 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.).
-additional tagging using bibs : to tag spatial object note_canvas with 'todo', the enduser can type or speak #note_canvas@todo
-
-
-
-Importing/exporting
-For usecases like importing/exporting/p2p casting a scene, the issue of external files comes into play.
-
-
-- export: if the 3D scene contains relative src/href values, rewrite them into absolute URL values.
-
-
-
-Reflection Mapping
-Environment mapping is crucial for creating realistic reflections and lighting effects on 3D objects.
-To apply environment mapping efficiently in a 3D scene, traverse the scene graph and assign each object's environment map based on the nearest ancestor's texture map. This ensures that objects inherit the correct environment mapping from their closest parent with a texture, enhancing the visual consistency and realism.
-
-
-
-Most 3D viewers apply one and the same environment map for various models, however this logic
-allows a more natural & automatic strategy for reflection mapping:
-
-
-- traverse the scene graph depth-first
-- remember the most recent parentnode (P) with a texture material
-- for every non-root node with a texture material
-3.1 clone that material (as materials might be shared across objects)
-3.2 set the environmentmap to the last known parent texture (P)
-
-
-
-Transclusion (broken link) resolution
-In spirit of Ted Nelson's 'transclusion resolution', there's a soft-mechanism to harden links & minimize broken links in various ways:
-
-
-- defining a different transport protocol (https vs ipfs or DAT) in src or href values can make a difference
-- mirroring files on another protocol using (HTTP) errorcode tags in src or href properties
-- in case of src: nesting a copy of the embedded object in the placeholder object (embeddedObject) will not be replaced when the request fails
-
-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.)
-
For example:
-
-
-
-
-
-Topic-based index-less Webrings
-As hashtags in URLs map to the XWRG, href-values can be used to promote topic-based index-less webrings.
-
-Consider 3D scenes linking to eachother using these href values:
+Virtual world rings
+Consider 3D scenes linking to eachother using these href values, attached to 3D button-objects:
- href: schoolA.edu/projects.gltf#math
- href: schoolB.edu/projects.gltf#math
- href: university.edu/projects.gltf#math
-These links would all show visible links to math-tagged objects in the scene.
+This would teleport users to the math-projects of those universities.
-To filter out non-related objects one could take it a step further using filters:
+Now consider adding a 'webring index'-button to each file, with this href-value:
-- href: schoolA.edu/projects.gltf#math&-topics math
-- href: schoolB.edu/projects.gltf#math&-courses math
-- href: university.edu/projects.gltf#math&-theme math
+- href: workgroup.edu/webrings.glb#!webringmenu
-This would hide all object tagged with topic, courses or theme (including math) so that later only objects tagged with math will be visible
-
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.
+This would allow displaying the (remote 3D file) webring menu with various href-buttons inside, all centrally curated by the workgroup.
-URI Templates (RFC6570)
+Level5: URI Templates (RFC6570)
XR Fragments adopts Level1 URI Fragment expansion to provide safe interactivity.
-The following demonstrates a simple video player:
-
-
-
+This is non-normative, and the draft spec is available on request.
Additional scene metadata
@@ -1275,8 +749,10 @@ Instead, it encourages browsers to scan nodes for the following custom propertie
SPDX license information
ARIA attributes (aria-*: .....)
+datapackage.json findability, accessibility, interoperability, and reusability of data
-SPDX and ARIA's aria-description are normative, as they promote accessibility and scene transcripts: please start aria-description with a verb to aid transcripts.
+ARIA's aria-description-metadata is normative, to aid accessibility and scene transcripts
+NOTE: please always start aria-description with a verb to aid transcripts.
The following metadata are non-normative but encouraged, since they are popular and cheap to parse:
diff --git a/index.html b/index.html
index d59916b..8d8f262 100644
--- a/index.html
+++ b/index.html
@@ -48,7 +48,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." />
XR Fragments —
-A tiny specification for controlling any 3D model using URLs
+A cute standard for (deep)linking 3D files via URI's.
@@ -832,7 +832,7 @@ button.sidebar-toggle{
- Edit a 3D scene file
-- embed a 3D object (subtree)
+- embed a 3D object
- EU keeps/stops funding FOSS?
@@ -1005,7 +1005,7 @@ button.sidebar-toggle{