refactor media fragments: extensions do not conflict with vanilla media fragments
This commit is contained in:
parent
e8308d738b
commit
a4b05c752d
22 changed files with 376 additions and 370 deletions
|
|
@ -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&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’s:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>https://images.org/credits.jpg#t=0&suv=l:0,0.1</code> (infinite vertical texturescrolling)</li>
|
||||
<li><code>https://video.org/organogram.mp4#t=0&suv:0.1,0.1&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&loop&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&u:col1=1,0,0&u:col2=0,1,0</code> (red-green shader plasma starts playing from time-offset 0)</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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&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&suv=l:0,0.1</tt> (infinite vertical texturescrolling)</li>
|
||||
<li><tt>https://video.org/organogram.mp4#t=0&suv:0.1,0.1&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&loop&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&u:col1=1,0,0&u:col2=0,1,0</tt> (red-green shader plasma starts playing from time-offset 0)</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ) )
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
17
src/3rd/js/three/xrf/loop.js
Normal file
17
src/3rd/js/three/xrf/loop.js
Normal 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
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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?)
|
||||
|
|
|
|||
|
|
@ -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(){}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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 ? "[ ✔ ] " : "[ ❌] ";
|
||||
|
|
|
|||
|
|
@ -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"}
|
||||
]
|
||||
|
|
@ -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"}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"}
|
||||
]
|
||||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue