diff options
author | Jedidiah Barber <contact@jedbarber.id.au> | 2022-11-27 01:21:53 +1300 |
---|---|---|
committer | Jedidiah Barber <contact@jedbarber.id.au> | 2022-11-27 01:21:53 +1300 |
commit | 8e36b81714320657b7d06973daa4e769bb17de46 (patch) | |
tree | 6a9289d4e458ebcd8c4e7b9c42de0a90da1e701c | |
parent | e75f04ce0747169b0f77aa55518982409cf9a876 (diff) |
Added ASCII fluid simulator article
18 files changed, 707 insertions, 0 deletions
diff --git a/project/assets/img/marching_squares.png b/project/assets/img/marching_squares.png Binary files differnew file mode 100644 index 0000000..6ca2d66 --- /dev/null +++ b/project/assets/img/marching_squares.png diff --git a/project/assets/robots.txt b/project/assets/robots.txt new file mode 100644 index 0000000..5d00a8e --- /dev/null +++ b/project/assets/robots.txt @@ -0,0 +1,4 @@ + +User-agent: * +Disallow: /vidframe/ + diff --git a/project/assets/vid/endoh1_column.jpg b/project/assets/vid/endoh1_column.jpg Binary files differnew file mode 100644 index 0000000..4d90d97 --- /dev/null +++ b/project/assets/vid/endoh1_column.jpg diff --git a/project/assets/vid/endoh1_column.mp4 b/project/assets/vid/endoh1_column.mp4 Binary files differnew file mode 100644 index 0000000..75c684f --- /dev/null +++ b/project/assets/vid/endoh1_column.mp4 diff --git a/project/assets/vid/fluid_tanada.jpg b/project/assets/vid/fluid_tanada.jpg Binary files differnew file mode 100644 index 0000000..ad9a586 --- /dev/null +++ b/project/assets/vid/fluid_tanada.jpg diff --git a/project/assets/vid/fluid_tanada.mp4 b/project/assets/vid/fluid_tanada.mp4 Binary files differnew file mode 100644 index 0000000..5cc0db0 --- /dev/null +++ b/project/assets/vid/fluid_tanada.mp4 diff --git a/project/complexity.yml b/project/complexity.yml index 7efaa87..64eeb99 100644 --- a/project/complexity.yml +++ b/project/complexity.yml @@ -15,6 +15,7 @@ unexpanded_templates: - "contributions.xhtml" - "deckconv.xhtml" - "fltkada.xhtml" + - "fluidsim.xhtml" - "grasp.xhtml" - "index.xhtml" - "integral.xhtml" @@ -38,9 +39,14 @@ unexpanded_templates: - "tags/library.xhtml" - "tags/maps.xhtml" - "tags/mathematics.xhtml" + - "tags/physics.xhtml" - "tags/politics.xhtml" - "tags/programming.xhtml" - "tags/transport.xhtml" - "tags/utility.xhtml" - "tags/videogames.xhtml" + - "vidframe/endoh1_column_preview.xhtml" + - "vidframe/endoh1_column_video.xhtml" + - "vidframe/fluid_tanada_preview.xhtml" + - "vidframe/fluid_tanada_video.xhtml" diff --git a/project/context/articles.json b/project/context/articles.json index e08c95c..e1a0c45 100644 --- a/project/context/articles.json +++ b/project/context/articles.json @@ -1,6 +1,12 @@ [ { + "title": "ASCII Fluid Simulator", + "anchor": "/fluidsim.xhtml", + "taglist": ["application", "physics", "programming"], + "postdate": "26/11/2022" + }, + { "title": "Number Wall Visualiser", "anchor": "/numberwall.xhtml", "taglist": ["application", "mathematics", "programming"], diff --git a/project/context/tags.json b/project/context/tags.json index 8910e07..323b09f 100644 --- a/project/context/tags.json +++ b/project/context/tags.json @@ -9,6 +9,7 @@ "library", "maps", "mathematics", + "physics", "politics", "programming", "transport", diff --git a/project/templates/fluidsim.xhtml b/project/templates/fluidsim.xhtml new file mode 100644 index 0000000..5537712 --- /dev/null +++ b/project/templates/fluidsim.xhtml @@ -0,0 +1,537 @@ + +{%- extends "base_math.xhtml" -%} + + + +{%- block title -%}ASCII Fluid Simulator{%- endblock -%} + + + +{%- block footer -%}{{ math_footer ("fluidsim.xhtml") }}{%- endblock -%} + + + +{%- block content %} +<h4>ASCII Fluid Simulator</h4> + +<p>Git repository: <a href="/cgi-bin/cgit.cgi/fluid-sim">Link</a><br /> +Yusuke Endoh's original: +<a href="https://web.archive.org/web/20190127192827/http://www.ioccc.org/2012/endoh1/hint.html" +class="external">IOCCC</a> <a href="https://invidious.namazso.eu/watch?v=QMYfkOtYYlg" class="external"> +Invidious</a> <a href="https://www.youtube.com/watch?v=QMYfkOtYYlg" class="external">Youtube</a></p> + +<h5>26/11/2022</h5> + + +<h5>Overview</h5> + +<p>One of the submissions for the 2012 International Obfuscated C Code Contest was +a 23, 30, or 31 line piece of seeming +<a href="https://web.archive.org/web/20201111232320/http://ioccc.org/2012/endoh1/endoh1.c" +class="external">nonsense code</a> that did... something. When fed appropriately sized text as +input, all characters except for instances of '#' would melt and flow as if liquid. It was a fluid +simulator that worked with ASCII text in the terminal.</p> + +<p>While it didn't win, it did receive an honorable mention and has also attracted the occasional +<a href="https://hackaday.com/2015/03/07/animated-ascii-fluid-dynamics-simulator-is-retro-cool/" +class="external">article</a> over the years since then. Often with commenters in awe of how it +does what it does. Because it is damned cool.</p> + +<div class="figure"> + <!-- In an ideal world this object would be 806x490, but... --> + <object type="application/xhtml+xml" data="/vidframe/endoh1_column_preview.xhtml" + width="806" height="500"> + </object> + <div class="figcaption">Endoh's fluid simulator with input column.txt, monochrome version</div> +</div> + +<p>So it's doing some sort of black magic to accomplish this, right? Well, yes, but also no. +Condensing and obfuscating the code to fit in 23 lines as in the original monochrome version is +definitely some impressive magic. But actually simulating a fluid in textual form is surprisingly +easy. What's going on is it's running a simplified version of +<a href="https://en.wikipedia.org/wiki/Smoothed-particle_hydrodynamics" class="external"> +smoothed-particle hydrodynamics</a> which involves nothing more complicated than addition, +subtraction, multiplication, division, exponentiation, and square roots. And technically also +complex numbers, because they tend to be the most accessible way to deal with two dimensional +values. Nothing too difficult.</p> + +<p>To prove how easy it is, the rest of this article is going to detail what you need to know so +that you too can write your very own comprehensible knockoff version.</p> + + +<h5>Reading Input</h5> + +<p>First thing to note is what we are dealing with. Every particle is stored as a structure +containing five values:</p> + +<ul> + <li><i>Position</i>, a two dimensional quantity, typically a complex number.</li> + <li><i>Is_Wall</i>, a flag denoting whether or not that particle is a solid wall or not.</li> + <li><i>Density</i>, a one dimensional real valued quantity.</li> + <li><i>Acceleration</i>, another complex number.</li> + <li><i>Velocity</i>, yet another complex number.</li> +</ul> + +<p>These particles can be stored in whatever convenient data structure you like. The most natural is +probably a vector since the program isn't sure how much input it is going to be given, but an array +can also be made to work.</p> + +<p>Reading in the input is just done with standard text I/O functions. But here is a very important +detail to note: Each character of ASCII input actually denotes two particles, one just above the +other in position. That is, while the input is usually a textfile with no more than 25 rows, once it +is read into the program you will have double the number of particles spread across an 80x50 field. +The display algorithm will scale it back to 25 later on.</p> + +<p>If you do not double up the input like this, your simulator will still work, but it won't look +quite right. Details like how high particles bounce will be off.</p> + +<p>Also note that by typical terminal conventions, coordinates (1,1) are at the top left corner and +numbers increase as you go down and right. Following this convention will make reading in input +easier, but will have some implications for gravity.</p> + + +<h5>Various Constants</h5> + +<p>Before going into the physics calculations, there are a handful of useful constants that are +going to be needed:</p> + +<ul> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>R</mi></math>, a radius distance from a + given particle, set here to be 2</li> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math>, the mass of a given + particle, set as 1</li> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"> + <msub> + <mi>ρ<!-- ρ --></mi> + <mn>0</mn> + </msub> + </math>, a density constant used in calculating interaction forces, set as 1.5</li> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>G</mi></math>, the gravitational + constant, which will be set to a magnitude of 1</li> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>P</mi></math>, the pressure parameter, + which will be set to 4</li> + <li><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>μ<!-- μ --></mi></math>, the + viscosity parameter, which will be set to 8</li> +</ul> + +<p>Note that while the gravitational constant magnitude is set to 1, care still has to be taken to +make sure the value is oriented in the correct direction. If terminal conventions are being followed +for axis orientation then the value will actually be the complex number +<math xmlns="http://www.w3.org/1998/Math/MathML"> + <mrow> + <mn>0</mn> + <mo>+</mo> + <mi>i</mi> + </mrow> +</math>. Endoh avoids this issue by switching the axes.</p> + +<p>Also note that while the documentation for Endoh's simulator claims the gravitational, pressure, +and viscosity parameters are set to 1, 4, 8 as they are here, there is actually an error in his +makefile. As a result the viscosity constant is set equal to the pressure constant, causing them +to take on values of 1, 4, 4 by default instead.</p> + + +<h5>Calculating Density</h5> + +<p>The density of each particle can be calculated by:</p> + +<div class="precontain"><div class="mathblock"> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <msub> + <mi>ρ<!-- ρ --></mi> + <mi>i</mi> + </msub> + <mo>=</mo> + <mrow> + <munder> + <mo>∑<!-- ∑ --></mo> + <mrow> + <mi>j</mi> + <mo>∈<!-- ∈ --></mo> + <msub> + <mi>Ω<!-- Ω --></mi> + <msub> + <mi>r</mi> + <mi>i</mi> + </msub> + </msub> + </mrow> + </munder> + <msub> + <mi>m</mi> + <mi>j</mi> + </msub> + <mi>W</mi> + <mo stretchy="false">(</mo> + <mo fence="false" stretchy="false">|<!-- | --></mo> + <msub> + <mi>r</mi> + <mi>i</mi> + </msub> + <mo>−<!-- − --></mo> + <msub> + <mi>r</mi> + <mi>j</mi> + </msub> + <mo fence="false" stretchy="false">|<!-- | --></mo> + <mo stretchy="false">)</mo> + </mrow> + </math><br /><br /> + where<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>ρ<!-- ρ --></mi> + </math> + is particle density<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>r</mi> + </math> + is particle position<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <msub> + <mi>Ω<!-- Ω --></mi> + <mi>r</mi> + </msub> + </math> + is the circular area around the position + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>r</mi> + </math> + with a radius equal to + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>R</mi> + </math><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>W</mi> + </math> + is the kernel function defined here as<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mrow> + <mi>W</mi> + <mo stretchy="false">(</mo> + <mi>d</mi> + <mo stretchy="false">)</mo> + </mrow> + <mo>=</mo> + <msup> + <mrow> + <mo stretchy="false">(</mo> + <mfrac> + <mi>d</mi> + <mi>R</mi> + </mfrac> + <mo>−<!-- − --></mo> + <mn>1</mn> + <mo stretchy="false">)</mo> + </mrow> + <mn>2</mn> + </msup> + </math><br /><br /> + and<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>m</mi> + <mo>,</mo> + <mi>R</mi> + </math> + are the constants defined earlier +</div></div> + +<p>Or in other words, for each particle, find all the other particles within a radius of 2, weight +the distance between the two by the <math xmlns="http://www.w3.org/1998/Math/MathML"><mi>W</mi> +</math> function, multiply by the particle mass of 1, and sum up all these intermediate results. +That's the particle's density.</p> + +<p>Particles that are part of a solid wall get an additional density of 9, so don't forget to add +that too.</p> + +<p>It is recommended that you do this step before you render any output results since you may want +to use density values to color the output. Endoh's simulator doesn't bother, however.</p> + + +<h5>Calculating Acceleration</h5> + +<p>The acceleration of each non-wall particle is the sum of two components, gravity and interaction +forces. Gravity is very simple as it is just the gravitational constant already defined earlier. The +interaction forces acting on each particle can be calculated by:</p> + +<div class="precontain"><div class="mathblock"> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <msubsup> + <mi>a</mi> + <mi>i</mi> + <mrow> + <mi>i</mi> + <mi>n</mi> + <mi>t</mi> + <mi>e</mi> + <mi>r</mi> + <mi>a</mi> + <mi>c</mi> + <mi>t</mi> + </mrow> + </msubsup> + <mo>=</mo> + <mrow> + <munder> + <mo>∑<!-- ∑ --></mo> + <mrow> + <mi>j</mi> + <mo>∈<!-- ∈ --></mo> + <msub> + <mi>Ω<!-- Ω --></mi> + <msub> + <mi>r</mi> + <mi>i</mi> + </msub> + </msub> + </mrow> + </munder> + <mfrac> + <mrow> + <mn>1</mn> + <mo>−<!-- − --></mo> + <mi>q</mi> + <mo stretchy="false">(</mo> + <mi>i</mi> + <mo>,</mo> + <mi>j</mi> + <mo stretchy="false">)</mo> + </mrow> + <msub> + <mi>ρ<!-- ρ --></mi> + <mi>j</mi> + </msub> + </mfrac> + <mo>⁢</mo> + <mo stretchy="false">[</mo> + <mi>P</mi> + <mo>⁢</mo> + <mo stretchy="false">(</mo> + <msub> + <mi>ρ<!-- ρ --></mi> + <mi>i</mi> + </msub> + <mo>+</mo> + <msub> + <mi>ρ<!-- ρ --></mi> + <mi>j</mi> + </msub> + <mo>−<!-- − --></mo> + <mn>2</mn> + <mo>⁢</mo> + <msub> + <mi>ρ<!-- ρ --></mi> + <mn>0</mn> + </msub> + <mo stretchy="false">)</mo> + <mo>⁢</mo> + <mo stretchy="false">(</mo> + <msub> + <mi>r</mi> + <mi>i</mi> + </msub> + <mo>−<!-- − --></mo> + <msub> + <mi>r</mi> + <mi>j</mi> + </msub> + <mo stretchy="false">)</mo> + <mo>−<!-- − --></mo> + <mi>μ<!-- μ --></mi> + <mo>⁢</mo> + <mo stretchy="false">(</mo> + <msub> + <mi>v</mi> + <mi>i</mi> + </msub> + <mo>−<!-- − --></mo> + <msub> + <mi>v</mi> + <mi>j</mi> + </msub> + <mo stretchy="false">)</mo> + <mo stretchy="false">]</mo> + </mrow> + </math><br /><br /> + where<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <msup> + <mi>a</mi> + <mrow> + <mi>i</mi> + <mi>n</mi> + <mi>t</mi> + <mi>e</mi> + <mi>r</mi> + <mi>a</mi> + <mi>c</mi> + <mi>t</mi> + </mrow> + </msup> + </math> + is the interaction force acting on a particle<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>ρ<!-- ρ --></mi> + </math> + is particle density<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>r</mi> + </math> + is particle position<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <msub> + <mi>Ω<!-- Ω --></mi> + <mi>r</mi> + </msub> + </math> + is the circular area around the position + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>r</mi> + </math> + with a radius equal to + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>R</mi> + </math><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>v</mi> + </math> + is particle velocity<br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>q</mi> + </math> + is a function defined for convenience as<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mrow> + <mi>q</mi> + <mo stretchy="false">(</mo> + <mi>x</mi> + <mo>,</mo> + <mi>y</mi> + <mo stretchy="false">)</mo> + </mrow> + <mo>=</mo> + <mfrac> + <mrow> + <mo stretchy="false">|<!-- | --></mo> + <msub> + <mi>r</mi> + <mi>x</mi> + </msub> + <mo>−<!-- − --></mo> + <msub> + <mi>r</mi> + <mi>y</mi> + </msub> + <mo stretchy="false">|<!-- | --></mo> + </mrow> + <mi>R</mi> + </mfrac> + </math><br /><br /> + and<br /><br /> + <math xmlns="http://www.w3.org/1998/Math/MathML"> + <mi>P</mi> + <mo>,</mo> + <msub> + <mi>ρ<!-- ρ --></mi> + <mn>0</mn> + </msub> + <mo>,</mo> + <mi>μ<!-- μ --></mi> + <mo>,</mo> + <mi>R</mi> + </math> + are the constants defined earlier +</div></div> + +<p>A lot to take in, I know. A bit too much to rephrase in plain english this time, even though it +is a simplified form compared to the usual smoothed-particle hydrodynamics formula. But as promised, +once you get past all the variables there is still only elementary math involved.</p> + +<p>So, the gravity plus the interaction force. That's the particle's acceleration.</p> + +<p>Acceleration of non-wall particles can be ignored since they will never move and the value won't +have any affect on other calculations.</p> + + +<h5>Updating Particle Positions</h5> + +<p>As implemented in Endoh's simulator this is by far the easiest step. For each non-wall particle, +merely divide the acceleration value by 10 then add that to the velocity value. Then add the +velocity to the particle's position. The division by 10 is an arbitrary scaling factor to make +things work in the space a standard 80x25 size terminal gives us.</p> + +<p>If you want to go the extra mile and add collision detection between moving particles and wall +particles, this would be the step to implement it. I haven't bothered. Partially because collision +detection is tricky, but also because doing so would result in visibly different behaviour.</p> + + +<h5>Display Rendering</h5> + +<p>Believe it or not, this is actually the most complicated part of this whole thing. It might be +fairly easy to explain in concept, but the actual implementation is more finnicky than any of the +previous steps.</p> + +<p>The algorithm in use here is called <a href="https://en.wikipedia.org/wiki/Marching_squares" +class="external">Marching Squares</a>. You calculate whether there are any particles present at the +corners of each character cell on an 80x25 terminal, then use those results to look up which +character should go in that cell from a predetermined mapping of cases to output characters. Some +experimentation may be required to find characters that look close enough, as the ASCII character +set was not made with this in mind.</p> + +<p>Be sure to scale the vertical axis back down by a factor of 2 before you perform these +calculations in order to take the input doubling into account.</p> + +<div class="figure"> + <img src="/img/marching_squares.png" + alt="Marching squares algorithm cell cases" + height="525" + width="525" /> + <div class="figcaption">The 16 possibilities for rendering cells, with blue for empty space and + purple for filled areas</div> +</div> + +<p>Various small tricks with bitwise-or operations can be used to make this process more efficient, +but going into those is beyond the scope of this article.</p> + +<p>To clear the screen and reset the cursor between output renders, +<a href="https://en.wikipedia.org/wiki/ANSI_escape_code" class="external">ANSI escape codes</a> are +used. They are also used if you want to add color to the output, with an escape code inserted before +each character to change the color according to the average density of the particles contributing to +that cell. Since the escape codes to do this are quite long, the resulting string will get decently +large. It won't affect the size when displayed to the terminal, however.</p> + +<p>In my experience, the average density in a given cell usually remains in the range 0-20 unless in +the middle of a thick solid wall. Scaling the colors used to that range tends to work well.</p> + + +<h5>Putting It All Together</h5> + +<p>The entire program consists of reading in the input, then looping through calculating density, +rendering output, calculating acceleration, and updating the particle positions. That's really it. +The only other thing you will probably want to do is have some step to get rid of particles should +their position go too far off-screen. Both to avoid unnecessary computation and the potential for +values to overflow and cause an error.</p> + +<p>The calculation and update steps are all embarrassingly parallel, so if you're looking for places +to improve things beyond adding color then there would be a good place to start. Neither Endoh's +implementation nor mine do anything with that, but that is more due to lack of need to put in the +effort.</p> + +<div class="figure"> + <!-- In an idea world this object would be 806x490, but... --> + <object type="application/xhtml+xml" data="/vidframe/fluid_tanada_preview.xhtml" + width="806" height="500"> + </object> + <div class="figcaption">My fluid simulator with input tanada.txt</div> +</div> + +<p>Now, was this entire exercise ultimately pointless, since it is concerned with ASCII rendering +done by intentionally obfuscated code? Yes. Was it nonetheless interesting and fun? Also yes.</p> + +<p>Thank you Daniele Venier for your informative, if incomplete, +<a href="http://asymptoticbits.com/posts/ascii-liquid/" class="external">article</a> on this same +topic which let me avoid having to analyse the IOCCC entry from scratch myself. Although really, it +probably would have still been easier to construct something from first principles anyway.</p> + +{% endblock -%} + + diff --git a/project/templates/tags/physics.xhtml b/project/templates/tags/physics.xhtml new file mode 100644 index 0000000..c88b7e5 --- /dev/null +++ b/project/templates/tags/physics.xhtml @@ -0,0 +1,10 @@ + +{%- extends "tags/base_tag.xhtml" -%} + + + +{%- block title -%}{{ tag_title ("Physics") }}{%- endblock -%} +{%- block content %}{{ tag_content ("Physics") }}{% endblock -%} +{%- block footer -%}{{ tag_footer ("physics.xhtml") }}{%- endblock -%} + + diff --git a/project/templates/vidframe/base_preview.xhtml b/project/templates/vidframe/base_preview.xhtml new file mode 100644 index 0000000..eaf0bea --- /dev/null +++ b/project/templates/vidframe/base_preview.xhtml @@ -0,0 +1,60 @@ + +{%- extends "vidframe/base_vidframe.xhtml" -%} + + + +{%- block style %} + body { + background-color: black; + } + a { + position: absolute; + top: 0; + left: 0; + } + img.thumb { + opacity: 0.5; + } + div.playbutton { + opacity: 1.0; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + } + svg { + position: absolute; + fill: #fff; + width: 100px; + height: 100px; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + } + div.playbutton:hover svg, + div.playbutton:focus svg { + fill: #17e617; + } +{% endblock -%} + + + +{%- block video %} +<div class="playbutton"> + <a href="{%- block vidlink -%}{%- endblock -%}"> + <img class="thumb" src="{%- block thumbnail -%}{%- endblock -%}" + alt="Click to load video" + width="100%" + height="100%" /> + <svg:svg version="1.1" xmlns:svg="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 311.69 311.69"> + <svg:path d="M155.84,0A155.85,155.85,0,1,0,311.69,155.84,155.84,155.84,0,0,0,155.84, + 0Zm0,296.42A140.58,140.58,0,1,1,296.42,155.84,140.58,140.58,0,0,1,155.84,296.42Z"/> + <svg:polygon points="218.79 155.84 119.22 94.34 119.22 217.34 218.79 155.84"/> + </svg:svg> + </a> +</div> +{% endblock -%} + + diff --git a/project/templates/vidframe/base_video.xhtml b/project/templates/vidframe/base_video.xhtml new file mode 100644 index 0000000..f298705 --- /dev/null +++ b/project/templates/vidframe/base_video.xhtml @@ -0,0 +1,26 @@ + +{%- extends "vidframe/base_vidframe.xhtml" -%} + + + +{%- block style %} + body { + margin: 0; + padding: 0; + } +{% endblock -%} + + + +{%- block video %} +<div> + <object type="video/mp4" + data="{%- block vidfile -%}{%- endblock -%}" + width="{%- block vidwidth -%}{%- endblock -%}" + height="{%- block vidheight -%}{%- endblock -%}"> + <a href="{%- block backup -%}{%- endblock -%}">Download video</a> + </object> +</div> +{% endblock -%} + + diff --git a/project/templates/vidframe/base_vidframe.xhtml b/project/templates/vidframe/base_vidframe.xhtml new file mode 100644 index 0000000..4f2e00e --- /dev/null +++ b/project/templates/vidframe/base_vidframe.xhtml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" + "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title></title> + <style type="text/css"> +{% block style -%}{%- endblock %} + </style> +</head> +<body> +{% block video -%} +{%- endblock %} +</body> +</html> diff --git a/project/templates/vidframe/endoh1_column_preview.xhtml b/project/templates/vidframe/endoh1_column_preview.xhtml new file mode 100644 index 0000000..9a444e6 --- /dev/null +++ b/project/templates/vidframe/endoh1_column_preview.xhtml @@ -0,0 +1,9 @@ + +{%- extends "vidframe/base_preview.xhtml" -%} + + + +{%- block vidlink -%}/vidframe/endoh1_column_video.xhtml{%- endblock -%} +{%- block thumbnail -%}/vid/endoh1_column.jpg{%- endblock -%} + + diff --git a/project/templates/vidframe/endoh1_column_video.xhtml b/project/templates/vidframe/endoh1_column_video.xhtml new file mode 100644 index 0000000..3cebb18 --- /dev/null +++ b/project/templates/vidframe/endoh1_column_video.xhtml @@ -0,0 +1,11 @@ + +{%- extends "vidframe/base_video.xhtml" -%} + + + +{%- block vidfile -%}/vid/endoh1_column.mp4{%- endblock -%} +{%- block vidwidth -%}806{%- endblock -%} +{%- block vidheight -%}490{%- endblock -%} +{%- block backup -%}/vid/endoh1_column.mp4{%- endblock -%} + + diff --git a/project/templates/vidframe/fluid_tanada_preview.xhtml b/project/templates/vidframe/fluid_tanada_preview.xhtml new file mode 100644 index 0000000..9e27878 --- /dev/null +++ b/project/templates/vidframe/fluid_tanada_preview.xhtml @@ -0,0 +1,9 @@ + +{%- extends "vidframe/base_preview.xhtml" -%} + + + +{%- block vidlink -%}/vidframe/fluid_tanada_video.xhtml{%- endblock -%} +{%- block thumbnail -%}/vid/fluid_tanada.jpg{%- endblock -%} + + diff --git a/project/templates/vidframe/fluid_tanada_video.xhtml b/project/templates/vidframe/fluid_tanada_video.xhtml new file mode 100644 index 0000000..4328290 --- /dev/null +++ b/project/templates/vidframe/fluid_tanada_video.xhtml @@ -0,0 +1,11 @@ + +{%- extends "vidframe/base_video.xhtml" -%} + + + +{%- block vidfile -%}/vid/fluid_tanada.mp4{%- endblock -%} +{%- block vidwidth -%}806{%- endblock -%} +{%- block vidheight -%}490{%- endblock -%} +{%- block backup -%}/vid/fluid_tanada.mp4{%- endblock -%} + + |