refactor media fragments: extensions do not conflict with vanilla media fragments

This commit is contained in:
Leon van Kammen 2024-02-09 18:00:22 +01:00
parent e8308d738b
commit a4b05c752d
22 changed files with 376 additions and 370 deletions

View file

@ -435,7 +435,7 @@ That way, if the link gets shared, the XR Fragments implementation at <code>http
<tr>
<td></td>
<td>r</td>
<td></td>
<td></td>
<td><code>#soldout*=halfopacity</code></td>
<td>set material of objects tagged with <code>product</code> to material with name <code>metallic</code></td>
@ -496,20 +496,6 @@ That way, if the link gets shared, the XR Fragments implementation at <code>http
<td>play from 0 seconds till 2 seconds (and stop)</td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>t=[l:]x,y</td>
<td>l:0,1</td>
<td>play [as loop] between <code>x</code> and <code>y</code></td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>uv=u,v</td>
<td>uv:0,0,1,1</td>
<td>set uv offset (default <code>0,0</code>)</td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>s=x</td>
@ -519,9 +505,44 @@ That way, if the link gets shared, the XR Fragments implementation at <code>http
<tr>
<td>temporal W3C media fragment *</td>
<td>suv=[l:]uspeed,vspeed</td>
<td>uv:l:0.1,0.2</td>
<td>set uv scroll speed of (default <code>1,1</code> is instant) [<code>l:</code> means infinite texturescrolling] otherwise new <code>u,v</code> values will be lerped to</td>
<td>[-]loop</td>
<td>loop</td>
<td>enable looped playback of audio/video/3D anim</td>
</tr>
<tr>
<td></td>
<td></td>
<td>-loop</td>
<td>disable looped playback (does not affect playbackstate of media)</td>
</tr>
<tr>
<td>vector2</td>
<td>uv=uv,v,uspeed,vspeed</td>
<td>0,0</td>
<td>set uv offset instantly (default speed = <code>1,1</code>)</td>
</tr>
<tr>
<td></td>
<td></td>
<td>+0.5,+0.5</td>
<td>scroll instantly by adding 0.5 to the current uv coordinates</td>
</tr>
<tr>
<td></td>
<td></td>
<td>0.2,1,0.1,0.1</td>
<td>scroll (lerp) to uv coordinate <code>0,2,1</code> with <code>0.1</code> units per second</td>
</tr>
<tr>
<td></td>
<td></td>
<td>0,0,0,+0.1</td>
<td>scroll v coordinates with <code>0.1</code> units per second (infinitely)</td>
</tr>
<tr>
@ -534,49 +555,16 @@ That way, if the link gets shared, the XR Fragments implementation at <code>http
</table>
<blockquote>
<p>* = this is extending the <a href="https://www.w3.org/TR/media-frags/#mf-advanced">W3C media fragments</a> with finergrained playback/viewport-control:</p>
</blockquote>
<p>* = this is extending the <a href="https://www.w3.org/TR/media-frags/#mf-advanced">W3C media fragments</a> with (missing) playback/viewport-control. Normally <code>#t=0,2</code> implies setting start/stop-values AND starting playback, whereas <code>#s=0&amp;loop</code> allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping.</p>
<table>
<thead>
<tr>
<th>extension</th>
<th>info</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>l:</code> specifices loop</td>
<td><code>t=0,2</code> specifies oneshot-play (default) whereas <code>t=l:0,2</code> indicates looped-play</td>
</tr>
<tr>
<td><code>#uv=</code> specifies uv-coordinates</td>
<td>allows offsetting the uv-coordinates</td>
</tr>
<tr>
<td><code>#suv=</code> specifies scrollspeed of uv-coordinates</td>
<td>allows single/infinite uv-scrolling</td>
</tr>
<tr>
<td><code>#s</code> specifies playback speed</td>
<td>being able to specify loop(speed) of audio/video</td>
</tr>
</tbody>
</table>
<blockquote>
<p>The rationale not to extend the <code>xywh</code>-media fragment is that 3D geometries deal with triangular polygons (not rectangular).</p>
<p>The rationale for <code>uv</code> is that the <code>xywh</code> Media Fragment deals with rectangular media, which does not translate well to 3D models (which use triangular polygons, not rectangular) positioned by uv-coordinates.</p>
</blockquote>
<p>Example URI&rsquo;s:</p>
<ul>
<li><code>https://images.org/credits.jpg#t=0&amp;suv=l:0,0.1</code> (infinite vertical texturescrolling)</li>
<li><code>https://video.org/organogram.mp4#t=0&amp;suv:0.1,0.1&amp;uv=0.3,0.3</code> (animated zoom towards region in video)</li>
<li><code>https://images.org/credits.jpg#uv=0,0,0,+0.1</code> (infinite vertical texturescrolling)</li>
<li><code>https://video.org/organogram.mp4#t=0&amp;loop&amp;uv:0.1,0.1,0.3,0.3</code> (animated zoom towards region in looped video)</li>
<li><code>https://shaders.org/plasma.glsl#t=0&amp;u:col1=1,0,0&amp;u:col2=0,1,0</code> (red-green shader plasma starts playing from time-offset 0)</li>
</ul>

View file

@ -233,7 +233,7 @@ That way, if the link gets shared, the XR Fragments implementation at `https://m
|-------------------|------------|--------------------|----------------------------------------------------------------------|
| `#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 |
| [W3C Media Fragments](https://www.w3.org/TR/media-frags/) | [media fragment](#media%20fragments%20and%20datatypes) | `#t=0,2` `#xywh` | play/loop 3D animation from 0 seconds till 2 seconds|
| [W3C 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|
| | | | but can also crop, animate & configure uv-coordinates/shader uniforms |
## List of metadata for 3D nodes
@ -265,33 +265,28 @@ These are automatic fragment-to-metadata mappings, which only trigger if the 3D
> NOTE: below the word 'play' applies to 3D animations embedded in the 3D scene(file) **but also** media defined in `src`-metadata like audio/video-files (mp3/mp4 e.g.)
| type | syntax | example | info |
|-------------------------------|------------------------|-----------------|----------------------|
| vector2 | x,y | 2,3.0 | 2-dimensional vector |
| vector3 | x,y,z | 2,3.0,4 | 3-dimensional vector |
| temporal W3C media fragment | t=x | 0 | play from 0 seconds to end (and stop) |
| temporal W3C media fragment | t=x,y | 0,2 | play from 0 seconds till 2 seconds (and stop) |
| temporal W3C media fragment * | t=[l:]x,y | l:0,1 | play [as loop] between `x` and `y` |
| temporal W3C media fragment * | uv=u,v | uv:0,0,1,1 | set uv offset (default `0,0`) |
| temporal W3C media fragment * | s=x | 1 | set playback speed of audio/video/3D anim |
| temporal W3C media fragment * | suv=[l:]uspeed,vspeed | uv:l:0.1,0.2 | set uv scroll speed of (default `1,1` is instant) [`l:` means infinite texturescrolling] otherwise new `u,v` values will be lerped to |
|-------------------------------|-----------------------------------|-----------------|----------------------|
| 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=uv,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) |
| media parameter (shader uniform) | u:<uniform>=<string|float|vec2|vec3|vec4> | 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 finergrained playback/viewport-control:
> \* = 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.
| extension | info |
|------------------|---------|
| `l:` specifices loop | `t=0,2` specifies oneshot-play (default) whereas `t=l:0,2` indicates looped-play |
| `#uv=` specifies uv-coordinates | allows offsetting the uv-coordinates |
| `#suv=` specifies scrollspeed of uv-coordinates | allows single/infinite uv-scrolling |
| `#s` specifies playback speed | being able to specify loop(speed) of audio/video |
> The rationale not to extend the `xywh`-media fragment is that 3D geometries deal with triangular polygons (not rectangular).
> 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.
Example URI's:
* `https://images.org/credits.jpg#t=0&suv=l:0,0.1` (infinite vertical texturescrolling)
* `https://video.org/organogram.mp4#t=0&suv:0.1,0.1&uv=0.3,0.3` (animated zoom towards region in video)
* `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 zoom towards region in looped video)
* `https://shaders.org/plasma.glsl#t=0&u:col1=1,0,0&u:col2=0,1,0` (red-green shader plasma starts playing from time-offset 0)
```

View file

@ -3,7 +3,7 @@
Jens & Leon Internet Engineering Task Force L.R. van Kammen
Internet-Draft 8 February 2024
Internet-Draft 9 February 2024
Intended status: Informational
@ -43,7 +43,7 @@ Status of This Memo
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 11 August 2024.
This Internet-Draft will expire on 12 August 2024.
Copyright Notice
@ -53,7 +53,7 @@ Copyright Notice
van Kammen Expires 11 August 2024 [Page 1]
van Kammen Expires 12 August 2024 [Page 1]
Internet-Draft XR Fragments February 2024
@ -109,7 +109,7 @@ Table of Contents
van Kammen Expires 11 August 2024 [Page 2]
van Kammen Expires 12 August 2024 [Page 2]
Internet-Draft XR Fragments February 2024
@ -165,7 +165,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 3]
van Kammen Expires 12 August 2024 [Page 3]
Internet-Draft XR Fragments February 2024
@ -221,7 +221,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 4]
van Kammen Expires 12 August 2024 [Page 4]
Internet-Draft XR Fragments February 2024
@ -277,7 +277,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 5]
van Kammen Expires 12 August 2024 [Page 5]
Internet-Draft XR Fragments February 2024
@ -333,7 +333,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 6]
van Kammen Expires 12 August 2024 [Page 6]
Internet-Draft XR Fragments February 2024
@ -389,7 +389,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 7]
van Kammen Expires 12 August 2024 [Page 7]
Internet-Draft XR Fragments February 2024
@ -445,7 +445,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 8]
van Kammen Expires 12 August 2024 [Page 8]
Internet-Draft XR Fragments February 2024
@ -469,7 +469,7 @@ Internet-Draft XR Fragments February 2024
| | | | |metallic (*=including |
| | | | |children) |
+----------------+--------------------------------------+-------------+---------------------+-----------------------+
| |r | |#soldout*=halfopacity|set material of objects|
| | | |#soldout*=halfopacity|set material of objects|
| | | | |tagged with product to |
| | | | |material with name |
| | | | |metallic |
@ -501,7 +501,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 9]
van Kammen Expires 12 August 2024 [Page 9]
Internet-Draft XR Fragments February 2024
@ -514,97 +514,98 @@ Internet-Draft XR Fragments February 2024
| 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 end |
|fragment | | | (and stop) |
+---------+-----------------------+------------+--------------------+
|temporal | t=x,y |0,2 | play from 0 |
|W3C media| | | seconds till 2 |
|fragment | | | seconds (and |
| | | | stop) |
+---------+-----------------------+------------+--------------------+
|temporal | t=[l:]x,y |l:0,1 | play [as loop] |
|W3C media| | | between x and y |
|fragment | | | |
|* | | | |
+---------+-----------------------+------------+--------------------+
|temporal | uv=u,v |uv:0,0,1,1 | set uv offset |
|W3C media| | | (default 0,0) |
|fragment | | | |
|* | | | |
+---------+-----------------------+------------+--------------------+
|temporal | s=x |1 | set playback |
|W3C media| | | speed of audio/ |
|fragment | | | video/3D anim |
|* | | | |
+---------+-----------------------+------------+--------------------+
|temporal | suv=[l:]uspeed,vspeed |uv:l:0.1,0.2| set uv scroll |
|W3C media| | | speed of (default |
|fragment | | | 1,1 is instant) |
|* | | | [l: means |
| | | | infinite |
| | | | texturescrolling] |
| | | | otherwise new u,v |
+=========+=======================+===============+================+
|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 end |
|fragment | | | (and stop) |
+---------+-----------------------+---------------+----------------+
|temporal | t=x,y | 0,2 | play from 0 |
|W3C media| | | seconds till 2 |
|fragment | | | seconds (and |
| | | | stop) |
+---------+-----------------------+---------------+----------------+
|temporal | s=x | 1 | set playback |
|W3C media| | | speed of |
|fragment | | | audio/video/3D |
|* | | | anim |
+---------+-----------------------+---------------+----------------+
|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=uv,v,uspeed,vspeed | 0,0 | set uv offset |
| | | | instantly |
| | | | (default speed |
| | | | = 1,1) |
+---------+-----------------------+---------------+----------------+
| | | +0.5,+0.5 | scroll |
van Kammen Expires 11 August 2024 [Page 10]
van Kammen Expires 12 August 2024 [Page 10]
Internet-Draft XR Fragments February 2024
| | | | values will be |
| | | | lerped to |
+---------+-----------------------+------------+--------------------+
|media | u:<uniform>=<string |float | vec2 |
|parameter| | | |
|(shader | | | |
|uniform) | | | |
+---------+-----------------------+------------+--------------------+
| | | | 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) |
+---------+-----------------------+---------------+----------------+
|media | u:<uniform>=<string | float | vec2 |
|parameter| | | |
|(shader | | | |
|uniform) | | | |
+---------+-----------------------+---------------+----------------+
Table 6
Table 6
| * = this is extending the W3C media fragments
| (https://www.w3.org/TR/media-frags/#mf-advanced) with finergrained
| playback/viewport-control:
+=================+========================================+
| extension | info |
+=================+========================================+
| l: specifices | t=0,2 specifies oneshot-play (default) |
| loop | whereas t=l:0,2 indicates looped-play |
+-----------------+----------------------------------------+
| #uv= specifies | allows offsetting the uv-coordinates |
| uv-coordinates | |
+-----------------+----------------------------------------+
| #suv= specifies | allows single/infinite uv-scrolling |
| scrollspeed of | |
| uv-coordinates | |
+-----------------+----------------------------------------+
| #s specifies | being able to specify loop(speed) of |
| playback speed | audio/video |
+-----------------+----------------------------------------+
Table 7
| The rationale not to extend the xywh-media fragment is that 3D
| geometries deal with triangular polygons (not rectangular).
| (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.
Example URI's:
* https://images.org/credits.jpg#t=0&suv=l:0,0.1 (infinite vertical
* https://images.org/credits.jpg#uv=0,0,0,+0.1 (infinite vertical
texturescrolling)
* https://video.org/organogram.mp4#t=0&suv:0.1,0.1&uv=0.3,0.3
(animated zoom towards region in video)
* https://video.org/organogram.mp4#t=0&loop&uv:0.1,0.1,0.3,0.3
(animated zoom towards region in looped video)
* https://shaders.org/plasma.glsl#t=0&u:col1=1,0,0&u:col2=0,1,0
(red-green shader plasma starts playing from time-offset 0)
@ -612,8 +613,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 11]
van Kammen Expires 12 August 2024 [Page 11]
Internet-Draft XR Fragments February 2024
@ -669,7 +669,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 12]
van Kammen Expires 12 August 2024 [Page 12]
Internet-Draft XR Fragments February 2024
@ -701,7 +701,7 @@ Internet-Draft XR Fragments February 2024
| <b>#rot</b>=0,90,0 | vector3 | rotate camera |
+--------------------+---------+-----------------------------+
Table 8
Table 7
» example implementation
(https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/
@ -725,7 +725,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 13]
van Kammen Expires 12 August 2024 [Page 13]
Internet-Draft XR Fragments February 2024
@ -781,7 +781,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 14]
van Kammen Expires 12 August 2024 [Page 14]
Internet-Draft XR Fragments February 2024
@ -807,7 +807,7 @@ Internet-Draft XR Fragments February 2024
| | |foo.mp3#0,0,0 |
+--------+--------+---------------------------------------------------+
Table 9
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:
@ -837,7 +837,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 15]
van Kammen Expires 12 August 2024 [Page 15]
Internet-Draft XR Fragments February 2024
@ -893,7 +893,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 16]
van Kammen Expires 12 August 2024 [Page 16]
Internet-Draft XR Fragments February 2024
@ -929,7 +929,7 @@ Internet-Draft XR Fragments February 2024
| | | ://somefile.gltf#pos=1,1,0 |
+----------+------------------+----------------------------+
Table 10
Table 9
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
@ -949,7 +949,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 17]
van Kammen Expires 12 August 2024 [Page 17]
Internet-Draft XR Fragments February 2024
@ -1005,7 +1005,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 18]
van Kammen Expires 12 August 2024 [Page 18]
Internet-Draft XR Fragments February 2024
@ -1061,7 +1061,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 19]
van Kammen Expires 12 August 2024 [Page 19]
Internet-Draft XR Fragments February 2024
@ -1117,7 +1117,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 20]
van Kammen Expires 12 August 2024 [Page 20]
Internet-Draft XR Fragments February 2024
@ -1134,7 +1134,7 @@ Internet-Draft XR Fragments February 2024
| | then only show object with price above 10 |
+--------------------+-------------------------------------------+
Table 11
Table 10
It's simple but powerful syntax which allows filtering the scene
using searchengine prompt-style feeling:
@ -1169,11 +1169,11 @@ Internet-Draft XR Fragments February 2024
| | embedded objects (starting with #) |
+----------+----------------------------------------------+
Table 12
Table 11
van Kammen Expires 11 August 2024 [Page 21]
van Kammen Expires 12 August 2024 [Page 21]
Internet-Draft XR Fragments February 2024
@ -1229,7 +1229,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 22]
van Kammen Expires 12 August 2024 [Page 22]
Internet-Draft XR Fragments February 2024
@ -1285,7 +1285,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 23]
van Kammen Expires 12 August 2024 [Page 23]
Internet-Draft XR Fragments February 2024
@ -1341,7 +1341,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 24]
van Kammen Expires 12 August 2024 [Page 24]
Internet-Draft XR Fragments February 2024
@ -1390,14 +1390,14 @@ Internet-Draft XR Fragments February 2024
| foo.gltf#house | other objects with tag house or todo |
+------------------+--------------------------------------+
Table 13
Table 12
van Kammen Expires 11 August 2024 [Page 25]
van Kammen Expires 12 August 2024 [Page 25]
Internet-Draft XR Fragments February 2024
@ -1453,7 +1453,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 26]
van Kammen Expires 12 August 2024 [Page 26]
Internet-Draft XR Fragments February 2024
@ -1509,7 +1509,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 27]
van Kammen Expires 12 August 2024 [Page 27]
Internet-Draft XR Fragments February 2024
@ -1565,7 +1565,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 28]
van Kammen Expires 12 August 2024 [Page 28]
Internet-Draft XR Fragments February 2024
@ -1621,7 +1621,7 @@ xrtext = {
van Kammen Expires 11 August 2024 [Page 29]
van Kammen Expires 12 August 2024 [Page 29]
Internet-Draft XR Fragments February 2024
@ -1677,7 +1677,7 @@ console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back to
van Kammen Expires 11 August 2024 [Page 30]
van Kammen Expires 12 August 2024 [Page 30]
Internet-Draft XR Fragments February 2024
@ -1733,7 +1733,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 31]
van Kammen Expires 12 August 2024 [Page 31]
Internet-Draft XR Fragments February 2024
@ -1789,7 +1789,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 32]
van Kammen Expires 12 August 2024 [Page 32]
Internet-Draft XR Fragments February 2024
@ -1845,7 +1845,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 33]
van Kammen Expires 12 August 2024 [Page 33]
Internet-Draft XR Fragments February 2024
@ -1901,7 +1901,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 34]
van Kammen Expires 12 August 2024 [Page 34]
Internet-Draft XR Fragments February 2024
@ -1957,7 +1957,7 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 35]
van Kammen Expires 12 August 2024 [Page 35]
Internet-Draft XR Fragments February 2024
@ -2013,12 +2013,12 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 36]
van Kammen Expires 12 August 2024 [Page 36]
Internet-Draft XR Fragments February 2024
Table 14
Table 13
@ -2069,4 +2069,4 @@ Internet-Draft XR Fragments February 2024
van Kammen Expires 11 August 2024 [Page 37]
van Kammen Expires 12 August 2024 [Page 37]

View file

@ -345,7 +345,7 @@ That way, if the link gets shared, the XR Fragments implementation at <tt>https:
<tr>
<td></td>
<td>r</td>
<td></td>
<td></td>
<td><tt>#soldout*=halfopacity</tt></td>
<td>set material of objects tagged with <tt>product</tt> to material with name <tt>metallic</tt></td>
@ -402,20 +402,6 @@ That way, if the link gets shared, the XR Fragments implementation at <tt>https:
<td>play from 0 seconds till 2 seconds (and stop)</td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>t=[l:]x,y</td>
<td>l:0,1</td>
<td>play [as loop] between <tt>x</tt> and <tt>y</tt></td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>uv=u,v</td>
<td>uv:0,0,1,1</td>
<td>set uv offset (default <tt>0,0</tt>)</td>
</tr>
<tr>
<td>temporal W3C media fragment *</td>
<td>s=x</td>
@ -425,9 +411,44 @@ That way, if the link gets shared, the XR Fragments implementation at <tt>https:
<tr>
<td>temporal W3C media fragment *</td>
<td>suv=[l:]uspeed,vspeed</td>
<td>uv:l:0.1,0.2</td>
<td>set uv scroll speed of (default <tt>1,1</tt> is instant) [<tt>l:</tt> means infinite texturescrolling] otherwise new <tt>u,v</tt> values will be lerped to</td>
<td>[-]loop</td>
<td>loop</td>
<td>enable looped playback of audio/video/3D anim</td>
</tr>
<tr>
<td></td>
<td></td>
<td>-loop</td>
<td>disable looped playback (does not affect playbackstate of media)</td>
</tr>
<tr>
<td>vector2</td>
<td>uv=uv,v,uspeed,vspeed</td>
<td>0,0</td>
<td>set uv offset instantly (default speed = <tt>1,1</tt>)</td>
</tr>
<tr>
<td></td>
<td></td>
<td>+0.5,+0.5</td>
<td>scroll instantly by adding 0.5 to the current uv coordinates</td>
</tr>
<tr>
<td></td>
<td></td>
<td>0.2,1,0.1,0.1</td>
<td>scroll (lerp) to uv coordinate <tt>0,2,1</tt> with <tt>0.1</tt> units per second</td>
</tr>
<tr>
<td></td>
<td></td>
<td>0,0,0,+0.1</td>
<td>scroll v coordinates with <tt>0.1</tt> units per second (infinitely)</td>
</tr>
<tr>
@ -437,42 +458,13 @@ That way, if the link gets shared, the XR Fragments implementation at <tt>https:
<td>vec2</td>
</tr>
</tbody>
</table><blockquote><t>* = this is extending the <eref target="https://www.w3.org/TR/media-frags/#mf-advanced">W3C media fragments</eref> with finergrained playback/viewport-control:</t>
</blockquote><table>
<thead>
<tr>
<th>extension</th>
<th>info</th>
</tr>
</thead>
<tbody>
<tr>
<td><tt>l:</tt> specifices loop</td>
<td><tt>t=0,2</tt> specifies oneshot-play (default) whereas <tt>t=l:0,2</tt> indicates looped-play</td>
</tr>
<tr>
<td><tt>#uv=</tt> specifies uv-coordinates</td>
<td>allows offsetting the uv-coordinates</td>
</tr>
<tr>
<td><tt>#suv=</tt> specifies scrollspeed of uv-coordinates</td>
<td>allows single/infinite uv-scrolling</td>
</tr>
<tr>
<td><tt>#s</tt> specifies playback speed</td>
<td>being able to specify loop(speed) of audio/video</td>
</tr>
</tbody>
</table><blockquote><t>The rationale not to extend the <tt>xywh</tt>-media fragment is that 3D geometries deal with triangular polygons (not rectangular).</t>
</table><blockquote><t>* = this is extending the <eref target="https://www.w3.org/TR/media-frags/#mf-advanced">W3C media fragments</eref> with (missing) playback/viewport-control. Normally <tt>#t=0,2</tt> implies setting start/stop-values AND starting playback, whereas <tt>#s=0&amp;loop</tt> allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping.</t>
<t>The rationale for <tt>uv</tt> is that the <tt>xywh</tt> Media Fragment deals with rectangular media, which does not translate well to 3D models (which use triangular polygons, not rectangular) positioned by uv-coordinates.</t>
</blockquote><t>Example URI's:</t>
<ul spacing="compact">
<li><tt>https://images.org/credits.jpg#t=0&amp;suv=l:0,0.1</tt> (infinite vertical texturescrolling)</li>
<li><tt>https://video.org/organogram.mp4#t=0&amp;suv:0.1,0.1&amp;uv=0.3,0.3</tt> (animated zoom towards region in video)</li>
<li><tt>https://images.org/credits.jpg#uv=0,0,0,+0.1</tt> (infinite vertical texturescrolling)</li>
<li><tt>https://video.org/organogram.mp4#t=0&amp;loop&amp;uv:0.1,0.1,0.3,0.3</tt> (animated zoom towards region in looped video)</li>
<li><tt>https://shaders.org/plasma.glsl#t=0&amp;u:col1=1,0,0&amp;u:col2=0,1,0</tt> (red-green shader plasma starts playing from time-offset 0)</li>
</ul>

View file

@ -11,7 +11,7 @@
</head>
<body>
<a-scene xr-mode-ui="XRMode: xr" renderer="colorManagement: true; highRefreshRate:true; " light="defaultLightsEnabled: false">
<a-entity id="player" wasd-controls look-controls>
<a-entity id="player" wasd-controls="fly:true" look-controls>
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
<a-entity id="left-hand" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">

View file

@ -20,7 +20,7 @@ XRWG.match = (str,types,level) => {
return n
})
str = str.toLowerCase()
.replace(/[-\*]/,'') // remove excludes and wildcards
.replace(/[!-\*]/g,'') // remove excludes and wildcards
if( level <10 ) res = res.filter( (n) => n.key == str )
if( level >=10 ) res = res.filter( (n) => n.word == str || n.key == str )
if( level >30 ) res = res.filter( (n) => n.word.match(str) || n.key == str )
@ -39,11 +39,12 @@ XRWG.generate = (opts) => {
if( !key || key.match(/(^#$|name)/) ) return
let node = XRWG.get( XRWG.cleankey(key) )
if( node ){
node.types.push(type)
node.nodes.push(spatialNode)
}else{
node = { word: XRWG.cleankey(key), key, nodes:[spatialNode] }
node = { word: XRWG.cleankey(key), key, nodes:[spatialNode], types:[] }
if( spatialNode.userData[key] ) node.value = spatialNode.userData[key]
node[type] = true
node.types.push(type)
xrf.emit('XRWGnode',node)
XRWG.push( node )
}

View file

@ -17,10 +17,14 @@ xrf.frag.dynamic.material = function(v,opts){
xrf.frag.dynamic.material.setMatch = function(match,material,v){
match.map( (m) => {
m.nodes.map( (n) => {
n.material = setMaterial( n, material, v.reset )
if( v.filter.q.deep ) n.traverse( (c) => c.material && setMaterial( c, material, v.reset ) )
})
for( let i in m.types ){
let type = m.types[i]
let node = m.nodes[i]
if (type == 'name' || type == 'tag'){
setMaterial( node, material, v.reset )
if( v.filter.q.deep ) node.traverse( (c) => c.material && setMaterial( c, material, v.reset ) )
}
}
})
}

View file

@ -0,0 +1,17 @@
xrf.frag.loop = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
// handle object media players
if( mesh && mesh.media ){
for( let i in mesh.media ) mesh.media[i].pub(v)
return
}
// otherwise handle global 3D animations
xrf.mixers.map ( (mixer) => {
// update loop
mixer.loop.enabled = v.loop
})
}

View file

@ -1,11 +1,21 @@
xrf.frag.suv = function(v, opts){
xrf.frag.s = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
if( !mesh.geometry ) return // nothing to do here
// handle object media players
if( mesh && mesh.media ){
for( let i in mesh.media ) mesh.media[i].pub(v)
return
}
// otherwise handle global 3D animations
xrf.mixers.map ( (mixer) => {
mixer.s = v
// update speed
mixer.timeScale = v.x || 1.0
mixer.loop.speed = v.x || 1.0
mixer.loop.speedAbs = Math.abs( v.x )
})
xrf.frag.uv.init(mesh)
mesh.suv.x = v.x
mesh.suv.y = v.y !== undefined ? v.y : v.x
mesh.suv.loop = v.loop === true ? true : false
xrf.frag.uv.scroll(mesh)
}

View file

@ -39,32 +39,34 @@ let loadAudio = (mimetype) => function(url,opts){
mesh.add(sound)
sound.pub = (t) => {
sound.set = (mediafragment,v) => {
try{
sound.t = t
if( sound.isPlaying && t.y != undefined ) sound.stop()
if( sound.isPlaying && t.y == undefined ) sound.pause()
sound[mediafragment] = v
if( mediafragment == 't'){
sound.pause()
if( sound.isPlaying && v.y != undefined && v.x == v.y ) return
let hardcodedLoop = frag.t != undefined
t = hardcodedLoop ? { ...frag.t, x: t.x} : t // override with hardcoded metadata except playstate (x)
if( t && t.x != 0 ){
// *TODO* https://stackoverflow.com/questions/12484052/how-can-i-reverse-playback-in-web-audio-api-but-keep-a-forward-version-as-well
t.x = Math.abs(t.x)
sound.setPlaybackRate( t.x ) // WebAudio does not support negative playback
// setting loop
if( t.z ) sound.setLoop( true )
// apply embedded audio/video samplerate/fps or global mixer fps
let loopStart = hardcodedLoop ? t.y : t.y * buffer.sampleRate;
let loopEnd = hardcodedLoop ? t.z : t.z * buffer.sampleRate;
let timeStart = loopStart > 0 ? loopStart : (t.y == undefined ? xrf.model.mixer.time : t.y)
if( t.z > 0 ) sound.setLoopEnd( loopEnd )
if( t.y != undefined ){
sound.setLoopStart( loopStart )
sound.offset = loopStart
}
sound.setLoopStart(v.x * buffer.sampleRate );
sound.setLoopEnd(v.y * buffer.sampleRate );
sound.offset = v.x * buffer.sampleRate ;
sound.play()
}
if( mediafragment == 's'){
// *TODO* https://stackoverflow.com/questions/12484052/how-can-i-reverse-playback-in-web-audio-api-but-keep-a-forward-version-as-well
sound.pause()
sound.setPlaybackRate( Math.abs(v.x) ) // WebAudio does not support negative playback
sound.play()
}
if( mediafragment == 'loop'){
sound.pause()
sound.setLoop( v.loop )
sound.play()
}
debugger
}catch(e){ console.warn(e) }
}

View file

@ -28,15 +28,20 @@ let loadVideo = (mimetype) => function(url,opts){
video.src = url
video.speed = 1.0
video.looping = false
video.pub = (t) => {
video.t = t
video.pause()
if( t.x !== undefined && t.x == t.y ) return // stop paused
else{
video.currentTime = t.x
video.time = t.x
video.set = (mediafragment,v) => {
video[mediafragment] = v
if( mediafragment == 't'){
video.pause()
if( t.x !== undefined && t.x == t.y ) return // stop paused
else{
video.currentTime = t.x
video.time = t.x
video.play()
}
}
if( mediafragment == 's' ){
video.playbackRate = Math.abs( video.speed ) // html5 video does not support reverseplay :/
video.play()
}
}
}

View file

@ -1,11 +0,0 @@
xrf.frag.suv = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
if( !mesh.geometry ) return // nothing to do here
xrf.frag.uv.init(mesh)
mesh.suv.x = v.x
mesh.suv.y = v.y !== undefined ? v.y : v.x
mesh.suv.loop = v.loop === true ? true : false
mesh.onBeforeRender = xrf.frag.uv.scroll
}

View file

@ -5,7 +5,7 @@ xrf.frag.t = function(v, opts){
// handle object media players
if( mesh && mesh.media ){
for( let i in mesh.media ) mesh.media[i].pub(v)
for( let i in mesh.media ) mesh.media[i].set("t",v)
return
}
@ -21,7 +21,7 @@ xrf.frag.t = function(v, opts){
mixer.t = v
// update speed
mixer.timeScale = mixer.loop.speed || 1.0
mixer.timeScale = mixer.loop.speed
mixer.loop.speedAbs = Math.abs( mixer.timeScale )
mixer.updateLoop( v )
@ -81,15 +81,17 @@ xrf.addEventListener('parseModel', (opts) => {
}
mixer.updateLoop = (t) => {
mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart
mixer.loop.timeStop = t.y != undefined ? t.y : mixer.loop.timeStop
if( t ){
mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart
mixer.loop.timeStop = t.y != undefined ? t.y : mixer.duration
}
mixer.actions.map( (action) => {
if( mixer.loop.timeStart != undefined ){
action.time = mixer.loop.timeStart
action.setLoop( xrf.THREE.LoopOnce, )
action.timeScale = mixer.timeScale
action.enabled = true
if( t.x === 0 ) action.play()
if( t && t.x === 0 ) action.play()
}
})
mixer.setTime(mixer.loop.timeStart)
@ -98,16 +100,19 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.checkZombies( model.animations)
}
// update loop when needed
// monkeypatch: update loop when needed
if( !mixer.update.patched ){
let update = mixer.update
mixer.update = function(time){
mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time)
// loop jump
if( mixer.loop.speed > 0.0 && (mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop) ){
setTimeout( (time,anims) => mixer.updateLoop(time), 0, mixer.loop.timeStart ) // prevent recursion
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){
setTimeout( () => mixer.updateLoop(), 0 ) // prevent recursion
}else mixer.stop()
}
return update.call( this, time )
}
@ -142,7 +147,7 @@ xrf.addEventListener('render', (opts) => {
xrf.mixers.map( (m) => m.isPlaying && (m.update( time )) )
// update active camera in case selected by dynamicKey in URI
if( xrf.model.camera && model.mixer.isPlaying ){
if( xrf.model.camera && xrf.model.camera.length && model.mixer.isPlaying ){
let cam = xrf.camera.getCam()
// cam.fov = model.cameras[0].fov (why is blender not exporting radians?)

View file

@ -2,55 +2,69 @@ xrf.frag.uv = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
if( !mesh.geometry ) return // nothing to do here
if( v.floats.length != 4 ) return
xrf.frag.uv.init(mesh)
mesh.uv.x = v.x
mesh.uv.y = v.y !== undefined ? v.y : v.x
mesh.uv.u = v.floats[0]
mesh.uv.v = v.floats[1]
mesh.uv.uspeed = v.floats[2]
mesh.uv.vspeed = v.floats[3]
mesh.uv.uloop = v.shift[2]
mesh.uv.vloop = v.shift[3]
mesh.onBeforeRender = xrf.frag.uv.scroll
}
xrf.frag.uv.init = function(mesh){
if( !mesh.uv ) mesh.uv = {x:0, y:0, w:1, h:1, uv:false}
if( !mesh.suv ) mesh.suv = {x:1, y:1, loop:false }
if( !mesh.uv ) mesh.uv = {u:0, v:0, uspeed:1, vspeed:1, uloop:false, vloop:false, uv:false}
let uv = mesh.geometry.getAttribute("uv")
if( !uv.old ) uv.old = uv.clone()
if( !uv.old ) uv.old = mesh.geometry.getAttribute("uv").clone()
}
xrf.frag.uv.scroll = function(){
if( this.suv.x > 0.0 || this.suv.y > 0.0 ){
if( this.uv.uspeed > 0.0 || this.uv.vspeed > 0.0 ){
let diff = 0.0 // distance to end-state (non-looping mode)
let diffU = 0.0 // distance to end-state (non-looping mode)
let diffV = 0.0 // distance to end-state (non-looping mode)
let uv = this.geometry.getAttribute("uv")
// translate!
for( let i = 0; i < uv.count; i++ ){
let u = uv.getX(i)
let v = uv.getY(i)
let uTarget = uv.old.getX(i) + this.uv.x
let vTarget = uv.old.getY(i) + this.uv.y
let uTarget = uv.old.getX(i) + this.uv.u
let vTarget = uv.old.getY(i) + this.uv.v
if( this.suv.loop ){
u += this.suv.x * xrf.clock.delta
v += this.suv.y * xrf.clock.delta
// scroll U
if( this.uv.uloop ){
u += this.uv.uspeed * xrf.clock.delta
}else{
// recover from super-high uv-values due to looped scrolling
if( Math.abs(u-uTarget) > 1.0 ) u = uv.old.getX(i)
if( Math.abs(v-vTarget) > 1.0 ) v = uv.old.getY(i)
u = u > uTarget ? u + (this.uv.uspeed * -xrf.clock.delta)
: u + (this.uv.uspeed * xrf.clock.delta)
diffU += Math.abs( u - uTarget ) // are we done yet? (non-looping mode)
}
u = u > uTarget ? u + (this.suv.x * -xrf.clock.delta)
: u + (this.suv.x * xrf.clock.delta)
v = v > vTarget ? v + (this.suv.y * -xrf.clock.delta)
: v + (this.suv.y * xrf.clock.delta)
diff += Math.abs( u - uTarget ) // are we done yet? (non-looping mode)
diff += Math.abs( v - vTarget )
// scroll V
if( this.uv.vloop ){
v += this.uv.vspeed * xrf.clock.delta
}else{
// recover from super-high uv-values due to looped scrolling
if( Math.abs(v-vTarget) > 1.0 ) v = uv.old.getY(i)
v = v > vTarget ? v + (this.uv.vspeed * -xrf.clock.delta)
: v + (this.uv.vspeed * xrf.clock.delta)
diffV += Math.abs( v - vTarget )
}
uv.setXY(i,u,v)
}
uv.needsUpdate = true
if( !this.suv.loop && diff < 0.05 ){ // stop animating if done
if( (!this.uv.uloop && diffU < 0.05) &&
(!this.uv.vloop && diffV < 0.05)
){ // stop animating if done
this.onBeforeRender = function(){}
}
}

View file

@ -1,9 +0,0 @@
xrf.frag.xywh = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
xrf.mediafragment.init(mesh)
mesh.xywh.x = v.floats[0]
mesh.xywh.y = v.floats[1] !== undefined ? v.floats[1] : mesh.xywh.x
mesh.xywh.w = v.floats[2] !== undefined ? v.floats[2] : mesh.xywh.y
mesh.xywh.h = v.floats[3] !== undefined ? v.floats[3] : mesh.xywh.w
// TODO: nondestructive cropping of texture (not superimportant now)
}

View file

@ -18,10 +18,8 @@ class Test {
test( "url.json", Spec.load("src/spec/url.json") );
test( "pos.json", Spec.load("src/spec/pos.json") );
test( "t.json", Spec.load("src/spec/t.json") );
test( "xywh.json", Spec.load("src/spec/xywh.json") );
test( "s.json", Spec.load("src/spec/s.json") );
test( "suv.json", Spec.load("src/spec/suv.json") );
test( "suv.json", Spec.load("src/spec/uv.json") );
test( "uv.json", Spec.load("src/spec/uv.json") );
test( "filter.selectors.json", Spec.load("src/spec/filter.selectors.json") );
//test( Spec.load("src/spec/tmp.json") );
if( errors > 1 ) trace("\n-----\n[ ] "+errors+" errors :/");
@ -51,9 +49,8 @@ class Test {
if( item.expect.fn == "equal.xy" ) valid = equalXY(res,item);
if( item.expect.fn == "equal.xyz" ) valid = equalXYZ(res,item);
if( item.expect.fn == "equal.mediafragmentT" ) valid = equalMediaFragment(res,item,"t");
if( item.expect.fn == "equal.mediafragmentXYWH") valid = equalMediaFragment(res,item,"xywh");
if( item.expect.fn == "equal.mediafragmentUV") valid = equalMediaFragment(res,item,"uv");
if( item.expect.fn == "equal.mediafragmentS") valid = equalMediaFragment(res,item,"s");
if( item.expect.fn == "equal.mediafragmentSUV") valid = equalMediaFragment(res,item,"suv");
if( item.expect.fn == "testFilterRoot" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().root == item.expect.out;
if( item.expect.fn == "testFilterDeep" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().deep == item.expect.out;
var ok:String = valid ? "[ ] " : "[ ] ";

View file

@ -1,4 +0,0 @@
[
{"fn":"url","data":"http://foo.com?foo=1#suv=l:0,0.1", "expect":{ "fn":"equal.mediafragmentSUV", "input":"1","out":"0.1"},"label":"suv"},
{"fn":"url","data":"http://foo.com?foo=1#suv=0.2,0.1", "expect":{ "fn":"equal.mediafragmentSUV", "input":"0","out":"0.2"},"label":"suv looped"}
]

View file

@ -1,3 +1,4 @@
[
{"fn":"url","data":"http://foo.com?foo=1#uv=1.2,2.2", "expect":{ "fn":"equal.xy", "input":"uv","out":"1.2,2.2"},"label":"equal.string uv"}
{"fn":"url","data":"http://foo.com?foo=1#uv=1.2,2.2", "expect":{ "fn":"equal.xy", "input":"uv","out":"1.2,2.2"},"label":"equal.string uv"},
{"fn":"url","data":"http://foo.com?foo=1#uv=1.2,2.2,+1,+1", "expect":{ "fn":"equal.xyz", "input":"uv","out":"1.2,2.2,1"},"label":"equal.string uv"}
]

View file

@ -1,4 +0,0 @@
[
{"fn":"url","data":"http://foo.com?foo=1#xywh=0,0,1,1", "expect":{ "fn":"equal.mediafragmentXYWH", "input":"2","out":"1"},"label":"xywh"},
{"fn":"url","data":"http://foo.com?foo=1#xywh=1,100,400,500", "expect":{ "fn":"equal.mediafragmentXYWH", "input":"3","out":"500"},"label":"a equal.mediafragment"}
]

View file

@ -25,11 +25,10 @@ class Parser {
Frag.set("rot", XRF.QUERY_OPERATOR | XRF.PV_OVERRIDE | XRF.T_VECTOR3 | XRF.METADATA | XRF.NAVIGATOR );
// category: media fragments
Frag.set("t", XRF.PV_OVERRIDE | XRF.T_FLOAT | XRF.T_VECTOR2 | XRF.T_MEDIAFRAG | XRF.NAVIGATOR | XRF.METADATA);
Frag.set("xywh", XRF.T_FLOAT | XRF.T_VECTOR2 | XRF.T_MEDIAFRAG | XRF.NAVIGATOR | XRF.METADATA);
Frag.set("s", XRF.PV_OVERRIDE | XRF.T_MEDIAFRAG | XRF.T_FLOAT );
Frag.set("t", XRF.PV_OVERRIDE | XRF.T_FLOAT | XRF.T_VECTOR2 | XRF.NAVIGATOR | XRF.METADATA);
Frag.set("s", XRF.PV_OVERRIDE | XRF.T_MEDIAFRAG );
Frag.set("loop", XRF.PV_OVERRIDE );
Frag.set("uv", XRF.T_VECTOR2 | XRF.T_MEDIAFRAG );
Frag.set("suv", XRF.T_VECTOR2 | XRF.T_MEDIAFRAG );
// category: author / metadata
Frag.set("namespace", XRF.IMMUTABLE | XRF.T_STRING );

View file

@ -38,7 +38,8 @@ class URI {
var key:String = splitByEqual[0];
var value:String = "";
if (splitByEqual.length > 1) {
value = StringTools.urlDecode(regexPlus.split(splitByEqual[1]).join(" "));
if( XRF.isVector.match(splitByEqual[1]) ) value = splitByEqual[1];
else value = StringTools.urlDecode(regexPlus.split(splitByEqual[1]).join(" "));
}
var ok:Bool = Parser.parse(key,value,store,i); // 1. for every recognized fragment key/value-pair call [Parser.parse](#%E2%86%AA%20Parser.parse%28k%2Cv%2Cstore%29)
}

View file

@ -49,8 +49,9 @@ class XRF {
public static var isExclude:EReg = ~/^-/; // 1. detect excluders like `-foo`,`-foo=1`,`-.foo`,`-/foo` (reference regex= `/^-/` )
public static var isDeep:EReg = ~/\*/; // 1. detect deep selectors like `foo*` (reference regex= `/\*$/` )
public static var isNumber:EReg = ~/^[0-9\.]+$/; // 1. detect number values like `foo=1` (reference regex= `/^[0-9\.]+$/` )
public static var isMediaFrag:EReg = ~/^(l:)?([0-9\.,\*]+)$/; // 1. detect (extended) media fragment
public static var isMediaFrag:EReg = ~/^([0-9\.,\*+-]+)$/; // 1. detect (extended) media fragment
public static var isReset:EReg = ~/^!/; // 1. detect reset operation
public static var isShift:EReg = ~/[+-]/;
// value holder(s) // |------|------|--------|----------------------------------|
public var fragment:String;
@ -59,6 +60,7 @@ class XRF {
public var x:Float; // |vector| x,y,z| comma-separated | #pos=1,2,3 |
public var y:Float;
public var z:Float;
public var shift:Array<Bool> = new Array<Bool>();
public var floats:Array<Float> = new Array<Float>();
public var color:String; // |string| color| FFFFFF (hex) | #fog=5m,FFAACC |
public var string:String; // |string| | | #q=-sun |
@ -100,18 +102,18 @@ class XRF {
public function guessType(v:XRF, str:String):Void {
v.string = str;
if( isReset.match(v.fragment) ) v.reset = true;
if( v.fragment == 'loop' ) v.loop = true;
if( !Std.isOfType(str,String) ) return;
if( str.length > 0 ){
if( str.split("l:").length > 1 ){
str = str.split("l:")[1];
v.loop = true;
}
if( str.split(",").length > 1){ // 1. `,` assumes 1D/2D/3D vector-values like x[,y[,z]]
var xyzn:Array<String> = str.split(","); // 1. parseFloat(..) and parseInt(..) is applied to vector/float and int values
if( xyzn.length > 0 ) v.x = Std.parseFloat(xyzn[0]); // 1. anything else will be treated as string-value
if( xyzn.length > 1 ) v.y = Std.parseFloat(xyzn[1]); // 1. incompatible value-types will be dropped / not used
if( xyzn.length > 2 ) v.z = Std.parseFloat(xyzn[2]); //
for( i in 0...xyzn.length ){
v.shift.push( isShift.match(xyzn[i]) );
v.floats.push( Std.parseFloat(xyzn[i]) );
}
} // > the xrfragment specification should stay simple enough
@ -126,6 +128,7 @@ class XRF {
v.x = cast(v.int);
v.floats.push( cast(v.x) );
}
v.filter = new Filter(v.fragment+"="+v.string);
}else v.filter = new Filter(v.fragment);
}