xrfragment/doc/RFC_XR_Fragments.md

959 lines
59 KiB
Markdown
Raw Normal View History

2023-09-01 14:20:02 +02:00
%%%
Title = "XR Fragments"
area = "Internet"
workgroup = "Internet Engineering Task Force"
[seriesInfo]
name = "XR-Fragments"
value = "draft-XRFRAGMENTS-leonvankammen-00"
stream = "IETF"
status = "informational"
date = 2023-04-12T00:00:00Z
[[author]]
initials="L.R."
surname="van Kammen"
fullname="L.R. van Kammen"
%%%
<!-- for annotated version see: https://raw.githubusercontent.com/ietf-tools/rfcxml-templates-and-schemas/main/draft-rfcxml-general-template-annotated-00.xml -->
<!--{
<style type="text/css">
body{
font-family: monospace;
2023-09-04 21:20:59 +02:00
max-width: 1000px;
2023-09-01 14:20:02 +02:00
font-size: 15px;
2023-09-21 15:28:37 +02:00
padding: 0% 10%;
2023-09-01 14:20:02 +02:00
line-height: 30px;
color:#555;
2023-09-18 11:03:18 +02:00
background:#F7F7F7;
2023-09-01 14:20:02 +02:00
}
h1 { margin-top:40px; }
pre{ line-height:18px; }
2023-09-02 21:44:57 +02:00
a,a:visited,a:active{ color: #70f; }
code{
border: 1px solid #AAA;
border-radius: 3px;
padding: 0px 5px 2px 5px;
}
2023-09-04 21:20:59 +02:00
pre{
line-height: 18px;
overflow: auto;
padding: 12px;
}
pre + code {
background:#DDD;
}
2023-09-02 21:44:57 +02:00
pre>code{
border:none;
border-radius:0px;
padding:0;
}
blockquote{
padding-left: 30px;
margin: 0;
border-left: 5px solid #CCC;
}
2023-09-04 21:20:59 +02:00
th {
border-bottom: 1px solid #000;
text-align: left;
padding-right:45px;
padding-left:7px;
background: #DDD;
}
td {
border-bottom: 1px solid #CCC;
font-size:13px;
}
2023-09-01 14:20:02 +02:00
</style>
<br>
<h1>XR Fragments</h1>
<br>
<pre>
stream: IETF
area: Internet
status: informational
author: Leon van Kammen
date: 2023-04-12T00:00:00Z
workgroup: Internet Engineering Task Force
value: draft-XRFRAGMENTS-leonvankammen-00
</pre>
}-->
.# Abstract
This draft is a specification for 4D URLs & [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation, which links together space, time & text together, for hypermedia browsers with- or without a network-connection.<br>
The specification promotes spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.<br>
2023-10-30 07:49:41 +01:00
XR Fragments allows us to better use existing metadata inside 3D scene(files), by connecting it to proven technologies like [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment).
2023-09-05 19:14:10 +02:00
> Almost every idea in this document is demonstrated at [https://xrfragment.org](https://xrfragment.org)
2023-09-04 21:20:59 +02:00
{mainmatter}
2023-09-01 14:20:02 +02:00
# Introduction
2023-10-25 11:43:44 +02:00
How can we add more control to existing text & 3D scenes, without introducing new dataformats?<br>
2023-09-04 21:20:59 +02:00
Historically, there's many attempts to create the ultimate markuplanguage or 3D fileformat.<br>
2023-10-25 11:43:44 +02:00
The lowest common denominator is: designers describing/tagging/naming things using **plain text**.<br>
XR Fragments exploits the fact that all 3D models already contain such metadata:
**XR Fragments allows controlling of metadata in 3D scene(files) using URLs**
Or more detailed:
2023-09-01 14:20:02 +02:00
1. addressibility and [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation of 3D scenes/objects: [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment) + src/href spatial metadata
2023-10-25 11:43:44 +02:00
1. Interlinking (text)objects by collapsing space into a Word Graph (XRWG) to show [visible links](#visible-links)
2023-09-21 13:05:30 +02:00
1. unlocking spatial potential of the (originally 2D) hashtag (which jumps to a chapter) for navigating XR documents
2023-09-01 14:20:02 +02:00
2023-09-04 21:20:59 +02:00
> NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
2023-09-01 14:20:02 +02:00
2023-09-04 21:20:59 +02:00
# Core principle
2023-10-25 11:43:44 +02:00
**XR Fragments allows controlling of metadata in 3D scene(files) using URLs**
XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.<br>
2023-10-25 11:43:44 +02:00
Instead of combining them (in a game-editor e.g.), XR Fragments **integrates all**, by collecting metadata into an XRWG and control it via URL:
2023-09-04 21:20:59 +02:00
2023-09-21 13:05:30 +02:00
| principle | XR 4D URL | HTML 2D URL |
|----------------------|-------------------------------------------------|---------------------------------------|
| the XRWG | wordgraph (collapses 3D scene to tags) | Ctrl-F (find) |
2023-10-25 11:43:44 +02:00
| the hashbus | hashtags alter camera/scene/object-projections | hashtags alter document positions |
2023-09-21 13:05:30 +02:00
| src metadata | renders content and offers sourceportation | renders content |
2023-09-21 16:20:38 +02:00
| href metadata | teleports to other XR document | jumps to other HTML document |
2023-09-21 13:05:30 +02:00
| href metadata | triggers predefined view | Media fragments |
2023-10-25 11:43:44 +02:00
| href metadata | triggers camera/scene/object/projections | n/a |
| href metadata | draws visible connection(s) for XRWG 'tag' | n/a |
| href metadata | filters certain (in)visible objects | n/a |
2023-09-04 21:51:01 +02:00
2023-09-21 16:20:38 +02:00
> XR Fragments does not look at XR (or the web) thru the lens of HTML.<br>But approaches things from a higherlevel feedbackloop/hypermedia browser-perspective:
2023-09-04 21:51:01 +02:00
```
2023-09-21 13:05:30 +02:00
+──────────────────────────────────────────────────────────────────────────────────────────────+
│ │
│ the soul of any URL: ://macro /meso ?micro #nano
│ │
│ 2D URL: ://library.com /document ?search #chapter
│ │
│ 4D URL: ://park.com /4Dscene.fbx ──> ?misc ──> #view ───> hashbus │
│ │ #filter │ │
2023-09-21 13:05:30 +02:00
│ │ #tag │ │
2023-10-25 11:43:44 +02:00
│ │ #material │ │
│ │ #animation │ │
│ │ #texture │ │
│ │ #variable │ │
2023-09-21 13:05:30 +02:00
│ │ │ │
│ XRWG <─────────────────────<────────────+ │
│ │ │ │
2023-10-25 11:43:44 +02:00
│ └─ objects ──────────────>────────────+ │
2023-09-21 13:05:30 +02:00
│ │
│ │
+──────────────────────────────────────────────────────────────────────────────────────────────+
```
Traditional webbrowsers can become 4D document-ready by:
* [hypermediatic](https://github.com/coderofsalvation/hypermediatic) loading 3D assets (gltf/fbx e.g.) natively (with or without using HTML).
* allowing assets to publish hashtags to themselves (the scene) using the hashbus (like hashtags controlling the scrollbar).
* collapsing the 3D scene to an wordgraph (for essential navigation purposes) controllable thru a hash(tag)bus
2023-09-05 19:14:10 +02:00
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.
2023-09-07 15:53:32 +02:00
2023-09-04 21:51:01 +02:00
# Conventions and Definitions
2023-09-07 15:53:32 +02:00
See appendix below in case certain terms are not clear.
2023-09-01 14:20:02 +02:00
## XR Fragment URI Grammar
```
reserved = gen-delims / sub-delims
gen-delims = "#" / "&"
sub-delims = "," / "="
```
> Example: `://foo.com/my3d.gltf#pos=1,0,0&prio=-5&t=0,100`
| Demo | Explanation |
|-------------------------------|---------------------------------|
| `pos=1,2,3` | vector/coordinate argument e.g. |
| `pos=1,2,3&rot=0,90,0&foo` | combinators |
> this is already implemented in all browsers
2023-09-02 21:44:57 +02:00
# List of URI Fragments
2023-10-25 12:47:23 +02:00
| fragment | type | example | info |
2023-10-30 07:49:41 +01:00
|-------------------|------------|--------------------|----------------------------------------------------------------------|
| `#pos` | vector3 | `#pos=0.5,0,0` | positions camera (or XR floor) to xyz-coord 0.5,0,0, |
| `#rot` | vector3 | `#rot=0,90,0` | rotates camera to xyz-coord 0.5,0,0 |
| `#t` | timevector | `#t=2,2000,1` | play animation-loop range between frame 2 and 2000 at (normal) speed 1 |
2023-09-02 21:44:57 +02:00
2023-10-25 11:43:44 +02:00
## List of metadata for 3D nodes
2023-09-02 21:44:57 +02:00
2023-09-21 13:05:30 +02:00
| key | type | example (JSON) | function | existing compatibility |
|--------------|----------|------------------------|---------------------|----------------------------------------|
2023-09-29 09:05:24 +02:00
| `href` | string | `"href": "b.gltf"` | XR teleport | custom property in 3D fileformats |
2023-10-12 17:04:46 +02:00
| `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 |
2023-09-04 21:20:59 +02:00
2023-10-30 07:49:41 +01:00
> Supported popular compatible 3D fileformats: `.gltf`, `.obj`, `.fbx`, `.usdz`, `.json` (THREE.js), `.dae` and so on.
## vector datatypes
| type | syntax | example | info |
|------
| vector2 | x,y | 2,3.0 | 2-dimensional vector |
| vector3 | x,y,z | 2,3.0,4 | 3-dimensional vector |
| timevector | speed | 1 | 1D timeline: play |
| | | 0 | 1D timeline: stop |
| | x,speed | 1,2 | 1D timeline: play at offset `1` at (normal) speed `2` |
| | | 0,0 | 1D timeline: stop (stopoffset-startoffset == 0) |
2023-10-30 07:49:41 +01:00
| | | 0,1 | 1D timeline: unpause with (normal) speed `1` |
| | | 1..100,1 | 1D timeline: play (loop) between offset `1` and `100` at normal speed (`1`) |
2023-10-30 07:49:41 +01:00
| | x,y,xspeed,yspeed | 0,0.5,0,0 | 2D timeline: stop uv-coordinate at `0,0.5` |
| | | 0,0.5,0.2,0 | 2D timeline: play uv-coordinate at offset `0,0.5` and scroll `x` (=u) `0.2` within each second |
| | | 0,0..0.5,0.2,0 | 2D timeline: play uv-coordinate between offset `0,0` and `0,0.5` (loop) and scroll `x` (=u) `0.2` within each second |
2023-10-30 07:49:41 +01:00
| | x,y,z,xspeed,yspeed,zspeed | 0,0.5,1,0.2,0,2 | XD timeline: play uv-coordinate at `0,0.5` and scroll `x` (=u) `0.2` within each second and pass `1` and `2` as custom data to shader uniforms `za` and `zb` |
2023-09-04 21:20:59 +02:00
2023-10-12 17:04:46 +02:00
> NOTE: XR Fragments are optional but also file- and protocol-agnostic, which means that programmatic 3D scene(nodes) can also use the mechanism/metadata.
2023-09-02 21:44:57 +02:00
## Dynamic XR Fragments (+databindings)
2023-10-25 11:43:44 +02:00
These are automatic fragment-to-metadata mappings, which only trigger if the 3D scene metadata matches a specific identifier (`aliasname` e.g.)
2023-09-01 14:20:02 +02:00
2023-10-25 11:43:44 +02:00
| fragment | type | example | info |
|------------------------|----------|-------------------|-------------------------------------------------------------------------------|
| `#<aliasname>` | string | `#cubes` | evaluate predefined views (`#cubes: #foo&bar` e.g.) |
| `#<tag_or_objectname>` | string | `#person` | focus object(s) with `tag: person` or name `person` by looking up XRWG |
| `#<cameraname>` | string | `#cam01` | set camera as active camera |
2023-10-30 07:49:41 +01:00
| `#<objectname>=<material>` | string=string | `#car=metallic`| set material of car to material with name `metallic` |
| | string=string | `#product=metallic`| set material of objects tagged with `product` to material with name `metallic` |
| `#<objectname>=<mediafrag>` | string=[media frag](https://www.w3.org/TR/media-frags/#valid-uri) | `#foo=0,1`| play media `src` using [media fragment URI](https://www.w3.org/TR/media-frags/#valid-uri) |
| `#<objectname>=<timevector>` | string=timevector | `#sky=0,0.5,0.1,0`| sets 1D/2D/3D time(line) vectors (uv-position e.g.) to `0,0.5` (and autoscroll x with max `0.1` every second)|
2023-10-30 07:49:41 +01:00
| | | `#music=1,2`| play media of object (`src: podcast.mp3` e.g.) from beginning (`1`) at double speed (`2`) |
2023-10-25 11:43:44 +02:00
# Spatial Referencing 3D
2023-10-12 17:04:46 +02:00
XR Fragments assume the following objectname-to-URIFragment mapping:
2023-09-01 14:20:02 +02:00
```
2023-09-21 13:05:30 +02:00
my.io/scene.fbx
+─────────────────────────────+
│ sky │ src: http://my.io/scene.fbx#sky (includes building,mainobject,floor)
│ +─────────────────────────+ │
│ │ building │ │ src: http://my.io/scene.fbx#building (includes mainobject,floor)
│ │ +─────────────────────+ │ │
│ │ │ mainobject │ │ │ src: http://my.io/scene.fbx#mainobject (includes floor)
│ │ │ +─────────────────+ │ │ │
│ │ │ │ floor │ │ │ │ src: http://my.io/scene.fbx#floor (just floor object)
│ │ │ │ │ │ │ │
│ │ │ +─────────────────+ │ │ │
│ │ +─────────────────────+ │ │
│ +─────────────────────────+ │
+─────────────────────────────+
2023-09-01 14:20:02 +02:00
```
2023-10-12 17:04:46 +02:00
> Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).
2023-09-21 13:05:30 +02:00
Clever nested design of 3D scenes allow great ways for re-using content, and/or previewing scenes.<br>
For example, to render a portal with a preview-version of the scene, create an 3D object with:
2023-09-21 13:05:30 +02:00
* href: `https://scene.fbx`
* src: `https://otherworld.gltf#mainobject`
2023-09-07 14:06:50 +02:00
> 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.
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
# Navigating 3D
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
| fragment | type | functionality |
|----------|--------|------------------------------|
| <b>#pos</b>=0,0,0 | vector3 | (re)position camera |
2023-09-23 13:01:46 +02:00
| <b>#t</b>=0,100 | vector3 | set playback speed, and (re)position looprange of scene-animation or `src`-mediacontent |
2023-09-21 13:05:30 +02:00
| <b>#rot</b>=0,90,0 | vector3 | rotate camera |
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/pos.js)<br>
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/5)<br>
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
1. the Y-coordinate of `pos` 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).
1. set the position of the camera accordingly to the vector3 values of `#pos`
1. `rot` sets the rotation of the camera (only for non-VR/AR headsets)
2023-09-23 13:01:46 +02:00
1. `t` sets the playbackspeed and animation-range of the current scene animation(s) or `src`-mediacontent (video/audioframes e.g., use `t=0,7,7` to 'STOP' at frame 7 e.g.)
2023-09-21 13:05:30 +02:00
1. in case an `href` does not mention any `pos`-coordinate, `pos=0,0,0` will be assumed
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
Here's an ascii representation of a 3D scene-graph which contains 3D objects `◻` and their metadata:
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
```
+────────────────────────────────────────────────────────+
│ │
│ index.gltf │
│ │ │
│ ├── ◻ buttonA │
│ │ └ href: #pos=1,0,1&t=100,200 │
│ │ │
│ └── ◻ buttonB │
│ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc)
│ │
+────────────────────────────────────────────────────────+
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
```
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the `buttonA` and `buttonB`.<br>
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 `pos=0,0,0`.
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
# Top-level URL processing
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
> Example URL: `://foo/world.gltf#cube&pos=0,0,0`
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
The URL-processing-flow for hypermedia browsers goes like this:
2023-09-07 14:06:50 +02:00
2023-09-21 13:30:14 +02:00
1. IF a `#cube` matches a custom property-key (of an object) in the 3D file/scene (`#cube`: `#......`) <b>THEN</b> execute that predefined_view.
2. IF scene operators (`pos`) and/or animation operator (`t`) are present in the URL then (re)position the camera and/or animation-range accordingly.
3. IF no camera-position has been set in <b>step 1 or 2</b> update the top-level URL with `#pos=0,0,0` ([example](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/navigator.js#L31]]))
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).
2023-09-07 14:06:50 +02:00
# Embedding XR content using src
2023-09-07 14:06:50 +02:00
`src` is the 3D version of the <a target="_blank" href="https://www.w3.org/html/wiki/Elements/iframe">iframe</a>.<br>
It instances content (in objects) in the current scene/asset.
2023-09-07 14:06:50 +02:00
| fragment | type | example value |
|----------|------|---------------|
|`src`| string (uri, hashtag/filter) | `#cube`<br>`#sometag`<br>#cube&-ball_inside_cube`<br>`#-sky&-rain`<br>`#-language&english`<br>`#price=>5`<br>`https://linux.org/penguin.png`<br>`https://linux.world/distrowatch.gltf#t=1,100`<br>`linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply`<br>`androidapp://page1?tutorial#pos=0,0,1&t1,100`<br>`foo.mp3#0,0,0`|
2023-09-21 13:05:30 +02:00
Here's an ascii representation of a 3D scene-graph with 3D objects `◻` which embeds remote & local 3D objects `◻` with/out using filters:
2023-09-21 13:05:30 +02:00
```
+────────────────────────────────────────────────────────+ +─────────────────────────+
│ │ │ │
│ index.gltf │ │ ocean.com/aquarium.fbx │
│ │ │ │ ├ room │
2023-09-21 13:05:30 +02:00
│ ├── ◻ canvas │ │ └── ◻ fishbowl │
│ │ └ src: painting.png │ │ ├─ ◻ bass │
│ │ │ │ └─ ◻ tuna │
│ ├── ◻ aquariumcube │ │ │
│ │ └ src: ://rescue.com/fish.gltf#fishbowl │ +─────────────────────────+
2023-09-21 13:05:30 +02:00
│ │ │
│ ├── ◻ 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).<br>
Also, after lazy-loading `ocean.com/aquarium.gltf`, only the queried objects `fishbowl` (and `bass` and `tuna`) will be instanced inside `aquariumcube`.<br>
2023-09-21 13:05:30 +02:00
Resizing will be happen accordingly to its placeholder object `aquariumcube`, see chapter Scaling.<br>
> Instead of cherrypicking a rootobject `#fishbowl` with `src`, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
2023-09-21 13:05:30 +02:00
**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. <b>local</b> `src` values (`#...` e.g.) starting with a non-negating filter (`#cube` e.g.) will make that object (with name `cube`) the new root of the scene at position 0,0,0
3. <b>local</b> `src` values should respect (negative) filters (`#-foo&price=>3`)
4. 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.
5. <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:
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. <b>external</b> `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. clicking on external `src`-values always allow sourceportation: 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. equirectangular detection: when the width of an image is twice the height (aspect 2:1), an equirectangular projection is assumed.
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.)
* `model/gltf+json`
* `image/png`
* `image/jpg`
* `text/plain;charset=utf-8`
2023-09-18 11:03:18 +02:00
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js)<br>
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/src.gltf#L192)<br>
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/4)<br>
# Navigating content (internal/outbound href portals)
2023-09-18 11:03:18 +02:00
navigation, portals & mutations
| fragment | type | example value |
|----------|---------------------------------|---------------------------------------------------------------------------------------------------------------------------|
|`href` | string (uri or predefined view) | `#pos=1,1,0`<br>`#pos=1,1,0&rot=90,0,0`<br>`://somefile.gltf#pos=1,1,0`<br> |
1. clicking an outbound ''external''- or ''file URI'' fully replaces the current scene and assumes `pos=0,0,0&rot=0,0,0` by default (unless specified)
2023-09-18 11:03:18 +02:00
2. relocation/reorientation should happen locally for local URI's (`#pos=....`)
3. navigation should not happen ''immediately'' when user is more than 2 meter away from the portal/object containing the href (to prevent accidental navigation e.g.)
4. URL navigation should always be reflected in the client (in case of javascript: see [[here](https://github.com/coderofsalvation/xrfragment/blob/dev/src/3rd/js/three/navigator.js) for an example navigator).
5. In XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [[here](https://github.com/coderofsalvation/xrfragment/blob/dev/example/aframe/sandbox/index.html#L26-L29) for an example wearable)
6. in case of navigating to a new [[pos)ition, ''first'' navigate to the ''current position'' so 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/href.js#L97))
7. portal-rendering: a 2:1 ratio texture-material indicates an equirectangular projection
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js)<br>
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/href.gltf#L192)<br>
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/1)<br>
2023-09-21 13:05:30 +02:00
## UX spec
End-users should always have read/write access to:
1. the current (toplevel) <b>URL</b> (an URLbar etc)
2. URL-history (a <b>back/forward</b> 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
2023-09-07 14:06:50 +02:00
2023-09-21 13:05:30 +02:00
Sometimes embedded properties (like `src`) instance new objects.<br>
2023-09-18 11:03:18 +02:00
But what about their scale?<br>
How does the scale of the object (with the embedded properties) impact the scale of the referenced content?<br>
> 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. <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.)
2023-09-21 13:05:30 +02:00
2. 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.
2023-09-18 11:03:18 +02:00
> TODO: needs intermediate visuals to make things more obvious
2023-09-07 14:06:50 +02:00
2023-10-18 22:07:32 +02:00
# XR Fragment: pos
# XR Fragment: rot
# XR Fragment: t
controls the animation(s) of the scene (or `src` resource which contains a timeline)
| fragment | type | functionality |
| <b>#t</b>=1,1,100 | [[vector3|vector]] (default:`#t=1,0,0`) | speed,framestart,framestop |
* playposition is reset to framestart, when framestart or framestop is greater than 0 |
| Example Value | Explanation |
|-|-|
| `1,1,100` | play loop between frame 1 and 100 |
| `1,1,0` | play once from frame 1 (oneshot) |
| `1,0,0` | play (previously set looprange if any) |
| `0,0,0` | pause |
| `1,1,1` | play and auto-loop between begin and end of duration |
| `-1,0,0` | reverse playback speed |
| `2.3,0,0` | set (forward) playback speed to 2.3 (no restart) |
| `-2.3,0,0` | set (reverse) playback speed to -2.3 ( no restart)|
| `-2.3,100,0` | set (reverse) playback speed to -2.3 restarting from frame 100 |
[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]]<br>
[[» discussion|https://github.com/coderofsalvation/xrfragment/issues/10]]<br>
# XR audio/video integration
To play global audio/video items:
2023-10-25 11:43:44 +02:00
1. add a `src: foo.mp3` or `src: bar.mp4` metadata to a 3D object (`cube` e.g.)
1. to disable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (`src: bar.mp3#t=0,0,0` e.g.)
1. to play it, add `href: #cube` somewhere else
1. when the enduser clicks the `href`, `#t=1,0,0` (play) will be applied to the `src` value
1. to play a single animation, add href: #animationname=1,0,0 somewhere else
2023-10-18 22:07:32 +02:00
> 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
2023-09-21 13:05:30 +02:00
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 |
2023-09-21 13:05:30 +02:00
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.
2023-09-21 13:05:30 +02:00
* see [an (outdated) example video here](https://coderofsalvation.github.io/xrfragment.media/queries.mp4) which used a dedicated `q=` variable (now deprecated)
2023-09-21 13:05:30 +02:00
## including/excluding
| 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.) |
| `/` | reference to root-scene.<br>Useful in case of (preventing) showing/hiding objects in nested scenes (instanced by `src`) (*) |
2023-09-21 13:05:30 +02:00
> \* = `#q=-/cube` hides object `cube` only in the root-scene (not nested `cube` objects)<br> `#q=-cube` hides both object `cube` in the root-scene <b>AND</b> nested `skybox` objects |
[» 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)
2023-09-21 13:05:30 +02:00
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/3)
## Filter Parser
2023-09-21 13:05:30 +02:00
Here's how to write a filter parser:
2023-09-21 13:05:30 +02:00
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 `=`
2023-09-21 13:05:30 +02:00
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 `-`)
2023-09-21 13:05:30 +02:00
> An example filter-parser (which compiles to many languages) can be [found here](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Filter.hx)
2023-09-21 13:05:30 +02:00
# Visible links
2023-09-21 13:30:14 +02:00
When predefined views, XRWG fragments and ID fragments (`#cube` or `#mytag` e.g.) are triggered by the enduser (via toplevel URL or clicking `href`):
2023-09-21 13:05:30 +02:00
1. draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname)
2023-09-21 13:30:14 +02:00
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
2023-09-21 13:05:30 +02:00
2023-09-21 13:30:14 +02:00
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.
2023-09-21 13:05:30 +02:00
2023-09-21 13:30:14 +02:00
**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
2023-09-02 21:44:57 +02:00
2023-09-04 21:20:59 +02:00
# Text in XR (tagging,linking to spatial objects)
2023-09-01 14:20:02 +02:00
2023-09-11 15:20:43 +02:00
How does XR Fragments interlink text with objects?
2023-09-03 15:14:31 +02:00
2023-09-21 13:30:14 +02:00
> 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.
2023-09-11 11:43:02 +02:00
2023-09-21 13:05:30 +02:00
Instead of just throwing together all kinds media types into one experience (games), what about their tagged/semantical relationships?<br>
Perhaps the following question is related: why is HTML adopted less in games outside the browser?
Through the lens of constructive lazy game-developers, ideally metadata must come **with** text, but not **obfuscate** the text, or **spawning another request** to fetch it.<br>
XR Fragments does this by detecting Bib(s)Tex, without introducing a new language or fileformat<br>
2023-09-11 11:43:02 +02:00
> Why Bib(s)Tex? Because its seems to be the lowest common denominator for an human-curated XRWG (extendable by speech/scanner/writing/typing e.g, see [further motivation here](https://github.com/coderofsalvation/hashtagbibs#bibs--bibtex-combo-lowest-common-denominator-for-linking-data))
2023-09-11 11:43:02 +02:00
Hence:
2023-09-04 21:20:59 +02:00
2023-09-21 13:30:14 +02:00
1. XR Fragments promotes (de)serializing a scene to the 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.
2023-09-11 15:20:43 +02:00
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. [Bib's](https://github.com/coderofsalvation/hashtagbibs) and BibTex are first tag citizens for priming the XRWG with words (from XR text)
2023-09-11 15:20:43 +02:00
5. Like Bibs, XR Fragments generalizes the BibTex author/title-semantics (`author{title}`) into **this** points to **that** (`this{that}`)
6. The XRWG should be recalculated when textvalues (in `src`) change
7. HTML/RDF/JSON is still great, but is beyond the XRWG-scope (they fit better in the application-layer)
8. Applications don't have to be able to access the XRWG programmatically, as they can easily generate one themselves by traversing the scene-nodes.
9. 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)
2023-09-21 13:05:30 +02:00
10. Tags are the scope for now (supporting https://github.com/WICG/scroll-to-text-fragment will be considered)
2023-09-11 11:43:02 +02:00
2023-09-11 15:20:43 +02:00
Example:
2023-09-11 11:43:02 +02:00
```
2023-09-21 13:05:30 +02:00
http://y.io/z.fbx | Derived XRWG (expressed as BibTex)
2023-09-11 11:43:02 +02:00
----------------------------------------------------------------------------+--------------------------------------
| @house{castle,
+-[src: data:.....]----------------------+ +-[3D mesh]-+ | url = {https://y.io/z.fbx#castle}
| Chapter one | | / \ | | }
| | | / \ | | @baroque{castle,
| John built houses in baroque style. | | / \ | | url = {https://y.io/z.fbx#castle}
| | | |_____| | | }
| #john@baroque | +-----│-----+ | @baroque{john}
| | │ |
| | ├─ name: castle |
| | └─ tag: house baroque |
2023-09-11 11:43:02 +02:00
+----------------------------------------+ |
[3D mesh ] |
2023-09-11 15:20:43 +02:00
| O ├─ name: john |
| /|\ | |
| / \ | |
+--------+ |
2023-09-11 11:43:02 +02:00
```
2023-09-04 21:20:59 +02:00
> the `#john@baroque`-bib associates both text `John` and objectname `john`, with tag `baroque`
2023-09-04 21:20:59 +02:00
2023-09-11 15:20:43 +02:00
Another example:
```
2023-09-21 13:05:30 +02:00
http://y.io/z.fbx | Derived XRWG (expressed as BibTex)
2023-09-11 11:43:02 +02:00
----------------------------------------------------------------------------+--------------------------------------
2023-09-11 15:20:43 +02:00
|
2023-09-11 12:15:34 +02:00
+-[src: data:.....]----------------------+ +-[3D mesh]-+ | @house{castle,
| Chapter one | | / \ | | url = {https://y.io/z.fbx#castle}
| | | / \ | | }
| John built houses in baroque style. | | / \ | | @baroque{castle,
| | | |_____| | | url = {https://y.io/z.fbx#castle}
| #john@baroque | +-----│-----+ | }
2023-09-11 15:20:43 +02:00
| @baroque{john} | │ | @baroque{john}
| | ├─ name: castle |
| | └─ tag: house baroque |
2023-09-11 15:20:43 +02:00
+----------------------------------------+ | @house{baroque}
[3D mesh ] | @todo{baroque}
2023-09-11 12:15:34 +02:00
+-[remotestorage.io / localstorage]------+ | O + name: john |
2023-09-11 15:20:43 +02:00
| #baroque@todo@house | | /|\ | |
2023-09-11 12:15:34 +02:00
| ... | | / \ | |
2023-09-11 11:43:02 +02:00
+----------------------------------------+ +--------+ |
2023-09-09 11:30:03 +02:00
```
> both `#john@baroque`-bib and BibTex `@baroque{john}` result in the same XRWG, however on top of that 2 tages (`house` and `todo`) are now associated with text/objectname/tag 'baroque'.
2023-09-11 15:20:43 +02:00
As seen above, the XRWG can expand [bibs](https://github.com/coderofsalvation/hashtagbibs) (and the whole scene) to BibTeX.<br>
This allows hasslefree authoring and copy-paste of associations **for and by humans**, but also makes these URLs possible:
2023-09-09 11:30:03 +02:00
2023-09-11 15:20:43 +02:00
| URL example | Result |
|---------------------------------------|---------------------------------------------------------------------------|
2023-09-21 13:05:30 +02:00
| `https://my.com/foo.gltf#baroque` | draws lines between mesh `john`, 3D mesh `castle`, text `John built(..)` |
| `https://my.com/foo.gltf#john` | draws lines between mesh `john`, and the text `John built (..)` |
| `https://my.com/foo.gltf#house` | draws lines between mesh `castle`, and other objects with tag `house` or `todo` |
2023-09-09 11:30:03 +02:00
2023-09-11 15:20:43 +02:00
> [hashtagbibs](https://github.com/coderofsalvation/hashtagbibs) potentially allow the enduser to annotate text/objects by **speaking/typing/scanning associations**, which the XR Browser saves to remotestorage (or localStorage per toplevel URL). As well as, referencing BibTags per URI later on: `https://y.io/z.fbx#@baroque@todo` e.g.
2023-09-05 19:14:10 +02:00
2023-09-11 15:20:43 +02:00
The XRWG allows XR Browsers to show/hide relationships in realtime at various levels:
2023-09-03 15:14:31 +02:00
2023-09-11 15:20:43 +02:00
* wordmatch **inside** `src` text
* wordmatch **inside** `href` text
* wordmatch object-names
* wordmatch object-tagnames
2023-09-04 21:20:59 +02:00
2023-09-21 13:05:30 +02:00
Spatial wires can be rendered between words/objects etc.<br>
2023-09-11 15:20:43 +02:00
Some pointers for good UX (but not necessary to be XR Fragment compatible):
2023-09-04 21:20:59 +02:00
2023-09-11 12:15:34 +02:00
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.
2023-09-11 15:20:43 +02:00
12. respect multi-line BiBTeX metadata in text because of [the core principle](#core-principle)
2023-09-11 12:15:34 +02:00
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.
2023-09-09 11:30:03 +02:00
2023-09-11 11:43:02 +02:00
> The simplicity of appending metadata (and leveling the metadata-playfield between humans and machines) is also demonstrated by [visual-meta](https://visual-meta.info) in greater detail.
2023-09-02 21:44:57 +02:00
Fictional chat:
```
<John> Hey what about this: https://my.com/station.gltf#pos=0,0,1&rot=90,2,0&t=500,1000
<Sarah> I'm checking it right now
<Sarah> I don't see everything..where's our text from yesterday?
<John> Ah wait, that's tagged with tag 'draft' (and hidden)..hold on, try this:
<John> https://my.com/station.gltf#.draft&pos=0,0,1&rot=90,2,0&t=500,1000
<Sarah> how about we link the draft to the upcoming YELLO-event?
<John> ok I'm adding #draft@YELLO
<Sarah> Yesterday I also came up with other usefull assocations between other texts in the scene:
#event#YELLO
#2025@YELLO
<John> thanks, added.
<Sarah> Btw. I stumbled upon this spatial book which references station.gltf in some chapters:
<Sarah> https://thecommunity.org/forum/foo/mytrainstory.txt
<John> interesting, I'm importing mytrainstory.txt into station.gltf
<John> ah yes, chapter three points to trainterminal_2A in the scene, cool
```
2023-09-02 21:44:57 +02:00
## Default Data URI mimetype
2023-09-04 21:20:59 +02:00
The `src`-values work as expected (respecting mime-types), however:
2023-09-02 21:44:57 +02:00
The XR Fragment specification bumps the traditional default browser-mimetype
`text/plain;charset=US-ASCII`
2023-09-08 16:57:49 +02:00
to a hashtagbib(tex)-friendly one:
2023-09-04 21:20:59 +02:00
2023-09-11 12:07:06 +02:00
`text/plain;charset=utf-8;bib=^@`
2023-09-04 21:20:59 +02:00
2023-09-08 16:57:49 +02:00
This indicates that:
* utf-8 is supported by default
2023-09-11 15:20:43 +02:00
* lines beginning with `@` will not be rendered verbatim by default ([read more](https://github.com/coderofsalvation/hashtagbibs#hashtagbib-mimetypes))
* the XRWG should expand bibs to BibTex occurring in text (`#contactjohn@todo@important` e.g.)
2023-09-11 11:43:02 +02:00
By doing so, the XR Browser (applications-layer) can interpret microformats ([visual-meta](https://visual-meta.info)
to connect text further with its environment ( setup links between textual/spatial objects automatically e.g.).
2023-09-02 21:44:57 +02:00
2023-09-08 16:57:49 +02:00
> for more info on this mimetype see [bibs](https://github.com/coderofsalvation/hashtagbibs)
2023-09-03 15:14:31 +02:00
2023-09-08 16:57:49 +02:00
Advantages:
2023-09-03 15:14:31 +02:00
2023-09-11 11:43:02 +02:00
* auto-expanding of [hashtagbibs](https://github.com/coderofsalvation/hashtagbibs) associations
2023-09-08 16:57:49 +02:00
* out-of-the-box (de)multiplex human text and metadata in one go (see [the core principle](#core-principle))
2023-09-06 15:13:36 +02:00
* no network-overhead for metadata (see [the core principle](#core-principle))
* ensuring high FPS: HTML/RDF historically is too 'requesty'/'parsy' for game studios
2023-09-04 21:20:59 +02:00
* rich send/receive/copy-paste everywhere by default, metadata being retained (see [the core principle](#core-principle))
2023-09-06 15:13:36 +02:00
* netto result: less webservices, therefore less servers, and overall better FPS in XR
2023-09-03 15:14:31 +02:00
2023-09-06 15:13:36 +02:00
> 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.).
2023-09-02 21:44:57 +02:00
2023-09-04 21:20:59 +02:00
For all other purposes, regular mimetypes can be used (but are not required by the spec).<br>
## URL and Data URI
2023-09-02 21:44:57 +02:00
```
+--------------------------------------------------------------+ +------------------------+
| | | author.com/article.txt |
| index.gltf | +------------------------+
| │ | | |
| ├── ◻ article_canvas | | Hello friends. |
| │ └ src: ://author.com/article.txt | | |
2023-09-11 15:20:43 +02:00
| │ | | @book{greatgatsby |
2023-09-04 21:20:59 +02:00
| └── ◻ note_canvas | | ... |
2023-09-11 15:20:43 +02:00
| └ src:`data:welcome human\n@book{sunday...}` | | } |
2023-09-04 21:20:59 +02:00
| | +------------------------+
2023-09-02 21:44:57 +02:00
| |
+--------------------------------------------------------------+
```
2023-09-11 15:20:43 +02:00
The enduser will only see `welcome human` and `Hello friends` rendered verbatim (see mimetype).
2023-09-09 11:30:03 +02:00
The beauty is that text in Data URI automatically promotes rich copy-paste (retaining metadata).
2023-09-04 21:20:59 +02:00
In both cases, the text gets rendered immediately (onto a plane geometry, hence the name '_canvas').
2023-09-02 21:44:57 +02:00
The XR Fragment-compatible browser can let the enduser access visual-meta(data)-fields after interacting with the object (contextmenu e.g.).
2023-09-11 15:20:43 +02:00
> 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`
2023-09-07 14:06:50 +02:00
## XR Text example parser
2023-09-04 21:20:59 +02:00
To prime the XRWG with text from plain text `src`-values, here's an example XR Text (de)multiplexer in javascript (which supports inline bibs & bibtex):
2023-09-03 15:14:31 +02:00
```
2023-09-04 21:20:59 +02:00
xrtext = {
2023-09-08 16:57:49 +02:00
expandBibs: (text) => {
let bibs = { regex: /(#[a-zA-Z0-9_+@\-]+(#)?)/g, tags: {}}
text.replace( bibs.regex , (m,k,v) => {
tok = m.substr(1).split("@")
match = tok.shift()
if( tok.length ) tok.map( (t) => bibs.tags[t] = `@${t}{${match},\n}` )
else if( match.substr(-1) == '#' )
bibs.tags[match] = `@{${match.replace(/#/,'')}}`
else bibs.tags[match] = `@${match}{${match},\n}`
})
return text.replace( bibs.regex, '') + Object.values(bibs.tags).join('\n')
},
2023-09-03 15:14:31 +02:00
2023-09-05 19:14:10 +02:00
decode: (str) => {
2023-09-08 16:57:49 +02:00
// bibtex: ↓@ ↓<tag|tag{phrase,|{ruler}> ↓property ↓end
let pat = [ /@/, /^\S+[,{}]/, /},/, /}/ ]
let tags = [], text='', i=0, prop=''
let lines = xrtext.expandBibs(str).replace(/\r?\n/g,'\n').split(/\n/)
for( let i = 0; i < lines.length && !String(lines[i]).match( /^@/ ); i++ )
text += lines[i]+'\n'
bibtex = lines.join('\n').substr( text.length )
bibtex.split( pat[0] ).map( (t) => {
try{
let v = {}
if( !(t = t.trim()) ) return
if( tag = t.match( pat[1] ) ) tag = tag[0]
if( tag.match( /^{.*}$/ ) ) return tags.push({ruler:tag})
2023-09-11 11:43:02 +02:00
if( tag.match( /}$/ ) ) return tags.push({k: tag.replace(/}$/,''), v: {}})
2023-09-08 16:57:49 +02:00
t = t.substr( tag.length )
t.split( pat[2] )
.map( kv => {
if( !(kv = kv.trim()) || kv == "}" ) return
v[ kv.match(/\s?(\S+)\s?=/)[1] ] = kv.substr( kv.indexOf("{")+1 )
})
tags.push( { k:tag, v } )
}catch(e){ console.error(e) }
})
return {text, tags}
2023-09-04 21:20:59 +02:00
},
2023-09-08 16:57:49 +02:00
2023-09-06 15:13:36 +02:00
encode: (text,tags) => {
let str = text+"\n"
for( let i in tags ){
let item = tags[i]
2023-09-08 16:57:49 +02:00
if( item.ruler ){
2023-09-06 15:13:36 +02:00
str += `@${item.ruler}\n`
continue;
}
str += `@${item.k}\n`
for( let j in item.v ) str += ` ${j} = {${item.v[j]}}\n`
2023-09-05 19:14:10 +02:00
str += `}\n`
}
2023-09-08 16:57:49 +02:00
return str
2023-09-03 15:14:31 +02:00
}
}
2023-09-04 21:20:59 +02:00
```
2023-09-03 15:14:31 +02:00
The above functions (de)multiplexe text/metadata, expands bibs, (de)serialize bibtex and vice versa
2023-09-06 15:13:36 +02:00
2023-09-05 19:14:10 +02:00
> above can be used as a startingpoint for LLVM's to translate/steelman to a more formal form/language.
2023-09-06 15:13:36 +02:00
```
str = `
hello world
2023-09-08 16:57:49 +02:00
here are some hashtagbibs followed by bibtex:
#world
#hello@greeting
#another-section#
2023-09-06 15:13:36 +02:00
@{some-section}
@flap{
asdf = {23423}
}`
var {tags,text} = xrtext.decode(str) // demultiplex text & bibtex
tags.find( (t) => t.k == 'flap{' ).v.asdf = 1 // edit tag
tags.push({ k:'bar{', v:{abc:123} }) // add tag
console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back together
```
2023-09-08 16:57:49 +02:00
This expands to the following (hidden by default) BibTex appendix:
2023-09-05 19:14:10 +02:00
```
2023-09-07 14:06:50 +02:00
hello world
2023-09-08 16:57:49 +02:00
here are some hashtagbibs followed by bibtex:
2023-09-05 19:14:10 +02:00
2023-09-07 14:06:50 +02:00
@{some-section}
@flap{
asdf = {1}
2023-09-05 19:14:10 +02:00
}
2023-09-08 16:57:49 +02:00
@world{world,
}
@greeting{hello,
}
@{another-section}
2023-09-07 14:06:50 +02:00
@bar{
abc = {123}
2023-09-05 19:14:10 +02:00
}
```
2023-09-03 15:14:31 +02:00
2023-09-07 18:48:40 +02:00
> when an XR browser updates the human text, a quick scan for nonmatching tags (`@book{nonmatchingbook` e.g.) should be performed and prompt the enduser for deleting them.
2023-09-24 11:12:52 +02:00
# Transclusion (broken link) resolution
2023-09-22 10:08:28 +02:00
2023-09-29 09:05:24 +02:00
In spirit of Ted Nelson's 'transclusion resolution', there's a soft-mechanism to harden links & minimize broken links in various ways:
2023-09-22 10:08:28 +02:00
1. defining a different transport protocol (https vs ipfs or DAT) in `src` or `href` values can make a difference
2023-09-29 09:05:24 +02:00
2. mirroring files on another protocol using (HTTP) errorcode tags in `src` or `href` properties
2023-09-22 10:08:28 +02:00
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
2023-09-29 09:05:24 +02:00
> 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.)
2023-09-22 10:08:28 +02:00
For example:
```
+────────────────────────────────────────────────────────+
│ │
│ index.gltf │
│ │ │
│ │ #: #q=-offlinetext │
│ │ │
│ ├── ◻ buttonA │
│ │ └ href: http://foo.io/campagne.fbx │
2023-09-29 09:05:24 +02:00
│ │ └ href@404: ipfs://foo.io/campagne.fbx │
│ │ └ href@400: #q=clienterrortext │
2023-09-22 10:08:28 +02:00
│ │ └ ◻ offlinetext │
│ │ │
│ └── ◻ embeddedObject <--------- the meshdata inside embeddedObject will (not)
│ └ src: https://foo.io/bar.gltf │ be flushed when the request (does not) succeed.
2023-09-29 09:05:24 +02:00
│ └ 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.
2023-09-22 10:08:28 +02:00
│ │
+────────────────────────────────────────────────────────+
```
2023-09-29 09:05:24 +02:00
# 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.<br>
Consider 3D scenes linking to eachother using these `href` values:
* `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.<br>
To filter out non-related objects one could take it a step further using filters:
2023-09-29 09:05:24 +02:00
* `href: schoolA.edu/projects.gltf#math&q=-topics math`
* `href: schoolB.edu/projects.gltf#math&q=-courses math`
* `href: university.edu/projects.gltf#math&q=-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
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.
2023-09-01 14:20:02 +02:00
# Security Considerations
2023-09-04 21:20:59 +02:00
Since XR Text contains metadata too, the user should be able to set up tagging-rules, so the copy-paste feature can :
* filter out sensitive data when copy/pasting (XR text with `tag:secret` e.g.)
2023-09-01 14:20:02 +02:00
2023-09-21 13:05:30 +02:00
# FAQ
**Q:** Why is everything HTTP GET-based, what about POST/PUT/DELETE HATEOS<br>
**A:** Because it's out of scope: XR Fragment specifies a read-only way to surf XR documents. These things belong in the application layer (for example, an XR Hypermedia browser can decide to support POST/PUT/DELETE requests for embedded HTML thru `src` values)
---
2023-09-29 09:05:24 +02:00
**Q:** Why isn't there support for scripting, while we have things like WASM
**A:** This is out of scope as it unhyperifies hypermedia, and this is up to XR hypermedia browser-extensions.<br> Historically scripting/Javascript seems to been able to turn webpages from hypermedia documents into its opposite (hyperscripted nonhypermedia documents).<br>In order to prevent this backward-movement (hypermedia tends to liberate people from finnicky scripting) XR Fragments should never unhyperify itself by hardcoupling to a particular markup or scripting language. [XR Macro's](https://xrfragment.org/doc/RFC_XR_Macros.html) are an example of something which is probably smarter and safer for hypermedia browsers to implement, instead of going full-in with a turing-complete scripting language (and suffer the security consequences later).<br>
XR Fragments supports filtering objects in a scene only, because in the history of the javascript-powered web, showing/hiding document-entities seems to be one of the most popular basic usecases.<br>
Doing advanced scripting & networkrequests under the hood are obviously interesting endavours, but this is something which should not be hardcoupled with hypermedia.<br>This belongs to browser extensions.<br>
Non-HTML Hypermedia browsers should make browser extensions the right place, to 'extend' experiences, in contrast to code/javascript inside hypermedia documents (this turned out as a hypermedia antipattern).
2023-09-21 13:05:30 +02:00
2023-09-01 14:20:02 +02:00
# IANA Considerations
This document has no IANA actions.
# Acknowledgments
2023-09-07 15:53:32 +02:00
* [NLNET](https://nlnet.nl)
* [Future of Text](https://futureoftext.org)
* [visual-meta.info](https://visual-meta.info)
# Appendix: Definitions
2023-09-11 12:08:04 +02:00
|definition | explanation |
|----------------------|--------------------------------------------------------------------------------------------------------------------------------------|
|human | a sentient being who thinks fuzzy, absorbs, and shares thought (by plain text, not markuplanguage) |
|scene | a (local/remote) 3D scene or 3D file (index.gltf e.g.) |
|3D object | an object inside a scene characterized by vertex-, face- and customproperty data. |
|metadata | custom properties of text, 3D Scene or Object(nodes), relevant to machines and a human minority (academics/developers) |
|XR fragment | URI Fragment with spatial hints like `#pos=0,0,0&t=1,100` e.g. |
|the XRWG | wordgraph (collapses 3D scene to tags) |
|the hashbus | hashtags map to camera/scene-projections |
|spacetime hashtags | positions camera, triggers scene-preset/time |
2023-09-21 13:05:30 +02:00
|teleportation | repositioning the enduser to a different position (or 3D scene/file) |
|sourceportation | teleporting the enduser to the original XR Document of an `src` embedded object. |
2023-09-18 11:03:18 +02:00
|placeholder object | a 3D object which with src-metadata (which will be replaced by the src-data.) |
2023-09-11 12:08:04 +02:00
|src | (HTML-piggybacked) metadata of a 3D object which instances content |
|href | (HTML-piggybacked) metadata of a 3D object which links to content |
|filter | URI Fragment(s) which show/hide object(s) in a scene based on name/tag/property (`#q=cube&-price=>3`) |
2023-09-11 12:08:04 +02:00
|visual-meta | [visual-meta](https://visual.meta.info) data appended to text/books/papers which is indirectly visible/editable in XR. |
|requestless metadata | metadata which never spawns new requests (unlike RDF/HTML, which can cause framerate-dropping, hence not used a lot in games) |
|FPS | frames per second in spatial experiences (games,VR,AR e.g.), should be as high as possible |
|introspective | inward sensemaking ("I feel this belongs to that") |
|extrospective | outward sensemaking ("I'm fairly sure John is a person who lives in oklahoma") |
|`◻` | ascii representation of an 3D object/mesh |
|(un)obtrusive | obtrusive: wrapping human text/thought in XML/HTML/JSON obfuscates human text into a salad of machine-symbols and words |
|BibTeX | simple tagging/citing/referencing standard for plaintext |
|BibTag | a BibTeX tag |
|(hashtag)bibs | an easy to speak/type/scan tagging SDL ([see here](https://github.com/coderofsalvation/hashtagbibs) which expands to BibTex/JSON/XML |
2023-09-07 15:53:32 +02:00