Process SMIL directives in XML data: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Wren)
m (→‎{{header|Phix}}: syntax coloured)
Line 383: Line 383:


=={{header|Phix}}==
=={{header|Phix}}==
<lang Phix>include builtins\xml.e
<!--<lang Phix>(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>

<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">xml</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
constant xml = """
<?xml version="1.0" ?>
<span style="color: #008080;">constant</span> <span style="color: #000000;">xml</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
<smil>
&lt;?xml version="1.0" ?&gt;
<X3D>
&lt;smil&gt;
<Scene>
&lt;X3D&gt;
<Viewpoint position="0 0 8" orientation="0 0 1 0"/>
&lt;Scene&gt;
<PointLight color='1 1 1' location='0 2 0'/>
&lt;Viewpoint position="0 0 8" orientation="0 0 1 0"/&gt;
<Shape>
<Box size='2 1 2'>
&lt;PointLight color='1 1 1' location='0 2 0'/&gt;
&lt;Shape&gt;
<animate attributeName="size" from="2 1 2"
&lt;Box size='2 1 2'&gt;
to="1 2 1" begin="0s" dur="10s"/>
&lt;animate attributeName="size" from="2 1 2"
</Box>
to="1 2 1" begin="0s" dur="10s"/&gt;
<Appearance>
&lt;/Box&gt;
<Material diffuseColor='0.0 0.6 1.0'>
&lt;Appearance&gt;
<animate attributeName="diffuseColor" from="0.0 0.6 1.0"
&lt;Material diffuseColor='0.0 0.6 1.0'&gt;
to="1.0 0.4 0.0" begin="0s" dur="10s"/>
&lt;animate attributeName="diffuseColor" from="0.0 0.6 1.0"
</Material>
to="1.0 0.4 0.0" begin="0s" dur="10s"/&gt;
</Appearance>
&lt;/Material&gt;
</Shape>
&lt;/Appearance&gt;
</Scene>
&lt;/Shape&gt;
</X3D>
&lt;/Scene&gt;
</smil>
&lt;/X3D&gt;
"""
&lt;/smil&gt;

"""</span>
function scan_all(sequence s, fmt)
for i=1 to length(s) do
<span style="color: #008080;">function</span> <span style="color: #000000;">animate_contents</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
{{s[i]}} = scanf(s[i],fmt)
<span style="color: #000000;">doc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_nodes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"animate"</span><span style="color: #0000FF;">)</span>
return s
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span>
end function
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>

<span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">animate_contents</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
function animate_contents(sequence doc, atom t)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
sequence a = xml_get_nodes(doc,"animate")
<span style="color: #008080;">else</span>
if a={} then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
for i=1 to length(doc[XML_CONTENTS]) do
<span style="color: #008080;">if</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_TAGNAME</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"animate"</span> <span style="color: #008080;">then</span>
doc[XML_CONTENTS][i] = animate_contents(doc[XML_CONTENTS][i],t)
<span style="color: #004080;">string</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"attributeName"</span><span style="color: #0000FF;">),</span>
end for
<span style="color: #000000;">vfrm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"from"</span><span style="color: #0000FF;">),</span>
else
<span style="color: #000000;">v_to</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"to"</span><span style="color: #0000FF;">),</span>
for i=1 to length(doc[XML_CONTENTS]) do
<span style="color: #000000;">sbeg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"begin"</span><span style="color: #0000FF;">),</span>
if doc[XML_CONTENTS][i][XML_TAGNAME]="animate" then
<span style="color: #000000;">sdur</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_get_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"dur"</span><span style="color: #0000FF;">)</span>
string name = xml_get_attribute(doc[XML_CONTENTS][i],"attributeName"),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">from</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">apply</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vfrm</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">),</span>
vfrm = xml_get_attribute(doc[XML_CONTENTS][i],"from"),
<span style="color: #000000;">to_s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">apply</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v_to</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">)</span>
v_to = xml_get_attribute(doc[XML_CONTENTS][i],"to"),
<span style="color: #004080;">atom</span> <span style="color: #000000;">begin</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sbeg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">)),</span>
sbeg = xml_get_attribute(doc[XML_CONTENTS][i],"begin"),
<span style="color: #000000;">durat</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sdur</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">)),</span>
sdur = xml_get_attribute(doc[XML_CONTENTS][i],"dur")
<span style="color: #000000;">fj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">begin</span><span style="color: #0000FF;">+</span><span style="color: #000000;">durat</span><span style="color: #0000FF;">-</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span>
sequence from = scan_all(split(vfrm),"%f"),
<span style="color: #000000;">tj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">-</span><span style="color: #000000;">begin</span>
to_s = scan_all(split(v_to),"%f")
<span style="color: #000080;font-style:italic;">-- plenty more error handling possible here...</span>
atom {{begin}} = scanf(sbeg,"%fs"),
<span style="color: #008080;">if</span> <span style="color: #000000;">tj</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">fj</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">from</span><span style="color: #0000FF;">)!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">to_s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
{{durat}} = scanf(sdur,"%fs"),
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">from</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
fj = begin+durat-t,
<span style="color: #000000;">from</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%.2f"</span><span style="color: #0000FF;">,(</span><span style="color: #000000;">from</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">fj</span><span style="color: #0000FF;">+</span><span style="color: #000000;">to_s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">tj</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">durat</span><span style="color: #0000FF;">)</span>
tj = t-begin
-- plenty more error handling possible here...
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">doc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xml_set_attribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">from</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
if tj<0 or fj<0 or length(from)!=length(to_s) then ?9/0 end if
<span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- remove 'animate'</span>
for j=1 to length(from) do
from[j] = sprintf("%.2f",(from[j]*fj+to_s[j]*tj)/durat)
<span style="color: #008080;">exit</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
doc = xml_set_attribute(doc,name,join(from," "))
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
doc[XML_CONTENTS][i..i] = "" -- remove 'animate'
<span style="color: #008080;">return</span> <span style="color: #000000;">doc</span>
exit
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end if
end for
<span style="color: #008080;">function</span> <span style="color: #000000;">animate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">doc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">)</span>
return doc
<span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- remove smil</span>
end function
<span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">animate_contents</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">],</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">doc</span>
function animate(sequence doc, atom t)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
doc[XML_CONTENTS] = doc[XML_CONTENTS][XML_CONTENTS][1] -- remove smil
doc[XML_CONTENTS] = animate_contents(doc[XML_CONTENTS],t)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">doc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xml_parse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xml</span><span style="color: #0000FF;">)</span>
return doc
<span style="color: #008080;">if</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_DOCUMENT</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"document"</span>
end function
<span style="color: #008080;">or</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_TAGNAME</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"smil"</span>

<span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">1</span>
sequence doc = xml_parse(xml)
<span style="color: #008080;">or</span> <span style="color: #000000;">doc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_CONTENTS</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">XML_TAGNAME</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"X3D"</span> <span style="color: #008080;">then</span>
if doc[XML_DOCUMENT]!="document"
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span>
or doc[XML_CONTENTS][XML_TAGNAME]!="smil"
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
or length(doc[XML_CONTENTS][XML_CONTENTS])!=1
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"At time = 0:\n\n"</span><span style="color: #0000FF;">)</span>
or doc[XML_CONTENTS][XML_CONTENTS][1][XML_TAGNAME]!="X3D" then
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">xml_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">animate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)))</span>
?9/0
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nAt time = 2:\n\n"</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">xml_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">animate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">doc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)))</span>
printf(1,"At time = 0:\n\n")
<!--</lang>-->
puts(1,xml_sprint(animate(doc,0)))
printf(1,"\nAt time = 2:\n\n")
puts(1,xml_sprint(animate(doc,2)))</lang>
{{out}}
{{out}}
<pre>
<pre>

Revision as of 20:04, 24 March 2022

Process SMIL directives in XML data is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

In order to represent evolutions of contents over time, the SMIL standard provides a solution to record the animation of data. Smil animations can be added to any kind of contents formated in XML.

The task is to create an utility that given the first Smiled XML file, would return the following ones:

<lang xml><?xml version="1.0" ?> <smil> <X3D>

 <Scene>
   <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
   <PointLight color='1 1 1' location='0 2 0'/>
   <Shape>
     <Box size='2 1 2'>
       <animate attributeName="size" from="2 1 2"
                                       to="1 2 1" begin="0s" dur="10s"/>
     </Box>
     <Appearance>
       <Material diffuseColor='0.0 0.6 1.0'>
         <animate attributeName="diffuseColor" from="0.0 0.6 1.0"
                                                 to="1.0 0.4 0.0" begin="0s" dur="10s"/>
       </Material>
     </Appearance>
   </Shape>
 </Scene>

</X3D> </smil></lang>

At t = 0 second here is the expected output:

<lang xml><?xml version="1.0" ?> <X3D>

 <Scene>
   <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
   <PointLight color='1 1 1' location='0 2 0'/>
   <Shape>
     <Box size='2 1 2'/>
     <Appearance>
       <Material diffuseColor='0.0 0.6 1.0'/>
     </Appearance>
   </Shape>
 </Scene>

</X3D></lang>

At t = 2 second here is the expected output:

<lang xml><?xml version="1.0" ?> <X3D>

 <Scene>
   <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
   <PointLight color='1 1 1' location='0 2 0'/>
   <Shape>
     <Box size='1.8 1.2 1.8'/>
     <Appearance>
       <Material diffuseColor='0.2 0.56 0.8'/>
     </Appearance>
   </Shape>
 </Scene>

</X3D></lang>

Go

Library: etree

<lang go>package main

import (

   "fmt"
   "github.com/beevik/etree"
   "log"
   "os"
   "strconv"
   "strings"

)

type animData struct {

   element *etree.Element
   attrib  string
   from    string
   to      string
   begin   float64
   dur     float64

}

func check(err error) {

   if err != nil {
       log.Fatal(err)
   }

}

func (ad *animData) AtTime(t float64) string {

   beg := ad.begin
   end := beg + ad.dur
   if t < beg || t > end {
       log.Fatalf("time must be in interval [%g, %g]", beg, end)
   }
   fromSplit := strings.Fields(ad.from)
   toSplit := strings.Fields(ad.to)
   le := len(fromSplit)
   interSplit := make([]string, le)
   for i := 0; i < le; i++ {
       fromF, err := strconv.ParseFloat(fromSplit[i], 64)
       check(err)
       toF, err := strconv.ParseFloat(toSplit[i], 64)
       check(err)
       interF := (fromF*(end-t) + toF*(t-beg)) / ad.dur
       interSplit[i] = fmt.Sprintf("%.2f", interF)
   }
   return strings.Join(interSplit, " ")

}

func main() {

   doc := etree.NewDocument()
   check(doc.ReadFromFile("smil.xml"))
   smil := doc.SelectElement("smil")
   if smil == nil {
       log.Fatal("'smil' element not found")
   }
   x3d := smil.SelectElement("X3D")
   if x3d == nil {
       log.Fatal("'X3D' element not found")
   }
   doc.SetRoot(x3d) // remove 'smil' element
   var ads []*animData
   for _, a := range doc.FindElements("//animate") {
       attrib := a.SelectAttrValue("attributeName", "?")
       from := a.SelectAttrValue("from", "?")
       to := a.SelectAttrValue("to", "?")
       beginS := a.SelectAttrValue("begin", "?")
       durS := a.SelectAttrValue("dur", "?")
       if attrib == "?" || from == "?" || to == "?" ||
           beginS == "?" || durS == "?" {
           log.Fatal("an animate element has missing attribute(s)")
       }
       begin, err := strconv.ParseFloat(beginS[:len(beginS)-1], 64)
       check(err)
       dur, err := strconv.ParseFloat(durS[:len(durS)-1], 64)
       check(err)
       p := a.Parent()
       if p == nil {
           log.Fatal("an animate element has no parent")
       }
       pattrib := p.SelectAttrValue(attrib, "?")
       if pattrib == "?" {
           log.Fatal("an animate element's parent has missing attribute")
       }
       ads = append(ads, &animData{p, attrib, from, to, begin, dur})
       p.RemoveChild(a) // remove 'animate' element
   }
   ts := []float64{0, 2}
   for _, t := range ts {
       for _, ad := range ads {
           s := ad.AtTime(t)
           ad.element.CreateAttr(ad.attrib, s)
       }
       doc.Indent(2)
       fmt.Printf("At time = %g seconds:\n\n", t)
       doc.WriteTo(os.Stdout)
       fmt.Println()
   }

}</lang>

Output:
At time = 0 seconds:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color="1 1 1" location="0 2 0"/>
    <Shape>
      <Box size="2.00 1.00 2.00"/>
      <Appearance>
        <Material diffuseColor="0.00 0.60 1.00"/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>

At time = 2 seconds:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color="1 1 1" location="0 2 0"/>
    <Shape>
      <Box size="1.80 1.20 1.80"/>
      <Appearance>
        <Material diffuseColor="0.20 0.56 0.80"/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>

Nim

<lang Nim>import sequtils, strformat, strtabs, strutils, xmlparser, xmltree

type

 Animation = object
   attrName: string          # Attribute to animate.
   fromValues: seq[float]    # List of "from" values.
   toValues: seq[float]      # List of "to" values.
   begin: float              # Animation starting time.
   duration: float           # Animation duration.


func getAnim(node: XmlNode): Animation =

 ## Build an animation object from an XML node.
 result.attrName = node.attr("attributeName")
 if result.attrName.len == 0:
   raise newException(ValueError, "missing 'attributeName' attribute")
 var str = node.attr("from")
 if str.len == 0:
   raise newException(ValueError, "missing 'from' attribute")
 result.fromValues = str.splitWhitespace().map(parseFloat)
 str = node.attr("to")
 if str.len == 0:
   raise newException(ValueError, "missing 'to' attribute")
 result.toValues = str.splitWhitespace().map(parseFloat)
 if result.fromValues.len != result.toValues.len:
   raise newException(ValueError, "inconsistent number of values")
 str = node.attr("begin")
 if str.len == 0:
   raise newException(ValueError, "missing 'begin' attribute")
 if str[^1] != 's':
   raise newException(ValueError, "missing unit")
 result.begin = parseFloat(str[0..^2])
 str = node.attr("dur")
 if str.len == 0:
   raise newException(ValueError, "missing 'dur' attribute")
 if str[^1] != 's':
   raise newException(ValueError, "missing unit")
 result.duration = parseFloat(str[0..^2])


func buildXml(node: XmlNode; t: float): XmlNode =

 ## Build the XML tree of a SMIL animation at time "t".
 if node.len > 0 and node[0].tag == "animate":
   # Child is an animate node.
   let anim = node[0].getAnim()
   # Check attribute name.
   if node.attr(anim.attrName).len == 0:
     raise newException(ValueError, &"unable to find attribute '{anim.attrName}'")
   # Check time.
   if t notin anim.begin..(anim.begin + anim.duration):
     raise newException(ValueError, "time value out of range")
   # Build attribute value.
   var aVal = newSeq[float](anim.fromValues.len)
   for i in 0..aVal.high:
     aVal[i] = (anim.fromValues[i] * (anim.begin + anim.duration - t) +
                anim.toValues[i] * (t - anim.begin)) / anim.duration
   # Set attributes.
   let a = node.attrs
   a[anim.attrName] = aVal.mapIt(it.formatFloat(ffDefault, 2)).join(" ")
   result = newElement(node.tag)
   result.attrs = a
 else:
   # Node child (if any) is not an animate node: copy the node and process children.
   result = newElement(node.tag)
   result.attrs = node.attrs
   for child in node:
     result.add child.buildXml(t)


when isMainModule:

 let smil = loadXml("smil.xml")
 if smil.tag != "smil":
   raise newException(ValueError, "not a SMIL file")
 let newRoot = smil[0]
 echo "At time 0 second:\n"
 echo xmlHeader, newRoot.buildXml(0)
 echo "\nAt time 2 seconds:\n"
 echo xmlHeader, newRoot.buildXml(2)</lang>
Output:
At time 0 second:

<?xml version="1.0" encoding="UTF-8" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0" />
    <PointLight color="1 1 1" location="0 2 0" />
    <Shape>
      <Box size="2.0 1.0 2.0" />
      <Appearance>
        <Material diffuseColor="0.0 0.60 1.0" />
      </Appearance>
    </Shape>
  </Scene>
</X3D>

At time 2 seconds:

<?xml version="1.0" encoding="UTF-8" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0" />
    <PointLight color="1 1 1" location="0 2 0" />
    <Shape>
      <Box size="1.8 1.2 1.8" />
      <Appearance>
        <Material diffuseColor="0.20 0.56 0.80" />
      </Appearance>
    </Shape>
  </Scene>
</X3D>

Perl

Translation of: Raku

<lang Perl># 20201101 added Perl programming solution

use 5.014; # for s///r; use strict; use warnings;

BEGIN {

  package Animatee;
  use Moo;
  has [qw(todo begin dur from to)] => ( is => 'rw');
  $INC{"Animatee.pm"} = 1;

}

use Animatee; use XML::Twig; use List::AllUtils 'pairwise';

my $smil = <<'DATA'; <?xml version="1.0" ?> <smil><X3D><Scene><Viewpoint position="0 0 8" orientation="0 0 1 0" /><PointLight color="1 1 1" location="0 2 0" /><Shape><Box size="2 1 2"><animate attributeName="size" from="2 1 2" to="1 2 1" begin="0s" dur="10s" /></Box><Appearance><Material diffuseColor="0.0 0.6 1.0"><animate attributeName="diffuseColor" from="0.0 0.6 1.0" to="1.0 0.4 0.0" begin="0s" dur="10s" /></Material></Appearance></Shape></Scene></X3D></smil> DATA

my %Parents;

my $x = XML::Twig->new->parse($smil);

for my $node ($x->findnodes("//animate")) {

  my $y = $node->parent;
  exists($Parents{$y}) ? (die) : ($Parents{my $k = $y->getName} = Animatee->new);
  for my $animatee ($y->getChildNodes)  {
     my %h = %{$animatee->atts};
     $Parents{$k}->todo($h{attributeName});
     $Parents{$k}->from([ split(/\s+/,$h{from}) ]);
     $Parents{$k}->to([ split(/\s+/,$h{to}) ]);
     $Parents{$k}->begin( $h{begin} =~ m/\d+/g);
     $Parents{$k}->dur  ( $h{dur}   =~ m/\d+/g);
  }

}

my $z = XML::Twig->new->parse($smil =~ s/\<\/?smil\>//gr) or die;

for my $t ( 0, 2, 4 ) {

  my $clone = $z;
  while ( my( $k,$v ) = each %Parents) {
     my @incre = pairwise { ($a-$b)/$v->dur } @{$v->to}, @{$v->from};
     for my $f ($clone->findnodes("//$k")) {
        my $c = join (' ', pairwise { $a+$b*$t } @{$v->from}, @incre);
        $f->set_att($v->todo,$c);
     }
     for my $f ($clone->findnodes("//animate")) {
        $f->delete
     }
  }
  print "when t = $t\n";
  print $clone->sprint,"\n";

}</lang>

Output:
when t = 0
<?xml version="1.0"?>
<X3D><Scene><Viewpoint orientation="0 0 1 0" position="0 0 8"/><PointLight color="1 1 1" location="0 2 0"/><Shape><Box size="2 1 2"></Box><Appearance><Material diffuseColor="0 0.6 1"></Material></Appearance></Shape></Scene></X3D>
when t = 2
<?xml version="1.0"?>
<X3D><Scene><Viewpoint orientation="0 0 1 0" position="0 0 8"/><PointLight color="1 1 1" location="0 2 0"/><Shape><Box size="1.8 1.2 1.8"></Box><Appearance><Material diffuseColor="0.2 0.56 0.8"></Material></Appearance></Shape></Scene></X3D>
when t = 4
<?xml version="1.0"?>
<X3D><Scene><Viewpoint orientation="0 0 1 0" position="0 0 8"/><PointLight color="1 1 1" location="0 2 0"/><Shape><Box size="1.6 1.4 1.6"></Box><Appearance><Material diffuseColor="0.4 0.52 0.6"></Material></Appearance></Shape></Scene></X3D>

Phix

with javascript_semantics
include builtins\xml.e
 
constant xml = """
<?xml version="1.0" ?>
<smil>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color='1 1 1' location='0 2 0'/>
    <Shape>
      <Box size='2 1 2'>
        <animate attributeName="size" from="2 1 2"
                                        to="1 2 1" begin="0s" dur="10s"/>
      </Box>
      <Appearance>
        <Material diffuseColor='0.0 0.6 1.0'>
          <animate attributeName="diffuseColor" from="0.0 0.6 1.0"
                                                  to="1.0 0.4 0.0" begin="0s" dur="10s"/>
        </Material>
      </Appearance>
    </Shape>
  </Scene>
</X3D>
</smil>
"""
 
function animate_contents(sequence doc, atom t)
    doc = deep_copy(doc)
    sequence a = xml_get_nodes(doc,"animate")
    if a={} then
        for i=1 to length(doc[XML_CONTENTS]) do
            doc[XML_CONTENTS][i] = animate_contents(doc[XML_CONTENTS][i],t)
        end for
    else
        for i=1 to length(doc[XML_CONTENTS]) do
            if doc[XML_CONTENTS][i][XML_TAGNAME]="animate" then
                string name = xml_get_attribute(doc[XML_CONTENTS][i],"attributeName"),
                       vfrm = xml_get_attribute(doc[XML_CONTENTS][i],"from"),
                       v_to = xml_get_attribute(doc[XML_CONTENTS][i],"to"),
                       sbeg = xml_get_attribute(doc[XML_CONTENTS][i],"begin"),
                       sdur = xml_get_attribute(doc[XML_CONTENTS][i],"dur")
                sequence from = apply(split(vfrm),to_number),
                         to_s = apply(split(v_to),to_number)
                atom begin = to_number(trim_tail(sbeg,"s")),
                     durat = to_number(trim_tail(sdur,"s")),
                     fj = begin+durat-t,
                     tj = t-begin
                -- plenty more error handling possible here...
                if tj<0 or fj<0 or length(from)!=length(to_s) then ?9/0 end if
                for j=1 to length(from) do
                    from[j] = sprintf("%.2f",(from[j]*fj+to_s[j]*tj)/durat)
                end for
                doc = xml_set_attribute(doc,name,join(from," "))
                doc[XML_CONTENTS][i..i] = "" -- remove 'animate'
                exit
            end if
        end for
    end if
    return doc
end function
 
function animate(sequence doc, atom t)
    doc = deep_copy(doc)
    doc[XML_CONTENTS] = doc[XML_CONTENTS][XML_CONTENTS][1]  -- remove smil
    doc[XML_CONTENTS] = animate_contents(doc[XML_CONTENTS],t)
    return doc
end function
 
sequence doc = xml_parse(xml)
if doc[XML_DOCUMENT]!="document"
or doc[XML_CONTENTS][XML_TAGNAME]!="smil"
or length(doc[XML_CONTENTS][XML_CONTENTS])!=1
or doc[XML_CONTENTS][XML_CONTENTS][1][XML_TAGNAME]!="X3D" then
    ?9/0
end if
printf(1,"At time = 0:\n\n")
puts(1,xml_sprint(animate(doc,0)))
printf(1,"\nAt time = 2:\n\n")
puts(1,xml_sprint(animate(doc,2)))
Output:
At time = 0:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0" />
    <PointLight color="1 1 1" location="0 2 0" />
    <Shape>
      <Box size="2.00 1.00 2.00" />
      <Appearance>
        <Material diffuseColor="0.00 0.60 1.00" />
      </Appearance>
    </Shape>
  </Scene>
</X3D>

At time = 2:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0" />
    <PointLight color="1 1 1" location="0 2 0" />
    <Shape>
      <Box size="1.80 1.20 1.80" />
      <Appearance>
        <Material diffuseColor="0.20 0.56 0.80" />
      </Appearance>
    </Shape>
  </Scene>
</X3D>

Raku

(formerly Perl 6) A crude attempt that only works with task data. <lang perl6>use XML::XPath;

my $smil = q:to; # cramped verison, modified from task data <?xml version="1.0" ?> <smil><X3D><Scene><Viewpoint position="0 0 8" orientation="0 0 1 0" /><PointLight color="1 1 1" location="0 2 0" /><Shape><Box size="2 1 2"><animate attributeName="size" from="2 1 2" to="1 2 1" begin="0s" dur="10s" /></Box><Appearance><Material diffuseColor="0.0 0.6 1.0"><animate attributeName="diffuseColor" from="0.0 0.6 1.0" to="1.0 0.4 0.0" begin="0s" dur="10s" /></Material></Appearance></Shape></Scene></X3D></smil> DATA

class Animatee { has ($.todo, @.from, @.to, $.begin, $.dur) is rw };

my %Parents; # keys store the parent tags that got <animate> child

my $x = XML::XPath.new(xml => $smil) or die;

for @($x.find("//animate")) { # strangely need .List or @ coercion to work

  my $y = .parent.name;
  %Parents{$y}:exists ?? die() !! %Parents{$y} = Animatee.new; # unique only
  for .parent.elements {
     %Parents{$y}.todo  = .attribs<attributeName>;
     %Parents{$y}.from  = .attribs<from>.split(/\s+/);
     %Parents{$y}.to    = .attribs<to>.split(/\s+/);
     %Parents{$y}.begin = .attribs<begin>.match(/\d+/);
     %Parents{$y}.dur   = .attribs<dur>.match(/\d+/);
  }

}

  1. use regex to strip SMIL tag and create a master template; sub-optimal approach

my $z = XML::XPath.new(xml => $smil.subst(/\<\/?smil\>/,,:g:ii:ss)) or die;

for 0, 2, 4 -> $t { # task requires 0 & 2 only

  my $clone = $z.clone; # work on a copy
  for %Parents.kv -> $k,$v {
     my @incre = ($v.to »-« $v.from) »/» $v.dur; # increment list
     with $clone.find("//$k") { # moving attribute = @from + @increment*$t
        .attribs{%Parents{$_.name}.todo} = $v.from »+« @incre »*» $t;
        .removeChild($_); #  ditch <animate> and friends
     }
  }
  say "when t = ", $t;
  say $clone.find("/");

}</lang>

Output:
when t = 0
<?xml version="1.0"?><X3D><Scene><Viewpoint position="0 0 8" orientation="0 0 1 0"/><PointLight location="0 2 0" color="1 1 1"/><Shape><Box size="2 1 2"/><Appearance><Material diffuseColor="0 0.6 1"/></Appearance></Shape></Scene></X3D>
when t = 2
<?xml version="1.0"?><X3D><Scene><Viewpoint position="0 0 8" orientation="0 0 1 0"/><PointLight location="0 2 0" color="1 1 1"/><Shape><Box size="1.8 1.2 1.8"/><Appearance><Material diffuseColor="0.2 0.56 0.8"/></Appearance></Shape></Scene></X3D>
when t = 4
<?xml version="1.0"?><X3D><Scene><Viewpoint position="0 0 8" orientation="0 0 1 0"/><PointLight location="0 2 0" color="1 1 1"/><Shape><Box size="1.6 1.4 1.6"/><Appearance><Material diffuseColor="0.4 0.52 0.6"/></Appearance></Shape></Scene></X3D>

Tcl

Works with: Tcl version 8.6
Library: tDOM

<lang tcl>package require Tcl 8.6 package require tdom

  1. Applies a time-based interpolation to generate a space-separated list

proc interpolate {time info} {

   dict with info {

scan $begin "%fs" begin scan $dur "%fs" dur

   }
   if {$time < $begin} {

return $from

   } elseif {$time > $begin+$dur} {

return $to

   }
   set delta [expr {($time - $begin) / $dur}]
   return [lmap f $from t $to {expr {$f + ($t-$f)*$delta}}]

}

  1. Applies SMIL <transform> elements to their container

proc applySMILtransform {sourceDocument time} {

   set doc [dom parse [$sourceDocument asXML]]
   foreach smil [$doc selectNodes //smil] {

foreach context [$smil selectNodes {//*[animate]}] { set animator [$context selectNodes animate] set animated [$context selectNodes @[$animator @attributeName]] $context removeChild $animator $context setAttribute [$animator @attributeName] \ [interpolate $time [lindex [$animator asList] 1]] } if {[$smil parentNode] eq ""} { set reparent 1 } else { [$smil parentNode] replaceChild $smil [$smil firstChild] }

   }
   if {[info exist reparent]} {

set doc [dom parse [[$smil firstChild] asXML]]

   }
   return $doc

}

set t [expr {[lindex $argv 0] + 0.0}] set result [applySMILtransform [dom parse [read stdin]] $t] puts {<?xml version="1.0" ?>} puts -nonewline [$result asXML -indent 2]</lang>

Demonstration:

Note that input.smil contains the source document from the task description.

$ tclsh8.6 applySmil.tcl 0 < input.smil
<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color="1 1 1" location="0 2 0"/>
    <Shape>
      <Box size="2.0 1.0 2.0"/>
      <Appearance>
        <Material diffuseColor="0.0 0.6 1.0"/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>
$ tclsh8.6 applySmil.tcl 2 < input.smil
<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color="1 1 1" location="0 2 0"/>
    <Shape>
      <Box size="1.8 1.2 1.8"/>
      <Appearance>
        <Material diffuseColor="0.2 0.5599999999999999 0.8"/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>

Wren

Library: Wren-pattern

As Wren lacks any kind of XML support (let alone SMIL), I've had to resort to string parsing to complete this task. <lang ecmascript>import "/pattern" for Pattern

var xml = """ <?xml version="1.0" ?> <smil> <X3D>

 <Scene>
   <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
   <PointLight color='1 1 1' location='0 2 0'/>
   <Shape>
     <Box size='2 1 2'>
       <animate attributeName="size" from="2 1 2"
                                       to="1 2 1" begin="0s" dur="10s"/>
     </Box>
     <Appearance>
       <Material diffuseColor='0.0 0.6 1.0'>
         <animate attributeName="diffuseColor" from="0.0 0.6 1.0"
                                                 to="1.0 0.4 0.0" begin="0s" dur="10s"/>
       </Material>
     </Appearance>
   </Shape>
 </Scene>

</X3D> </smil> """

var extractValue = Fn.new { |s| s.replace("\"", "").split("=")[1] }

var interpolate = Fn.new { |from, to, begin, dur, t|

   if (begin >= t) return from
   if (begin + t >= dur) return to
   var mid = List.filled(3, 0)
   for (i in 0..2) {
       mid[i] = (from[i] * (dur - t) + to[i] * (t - begin)) / (dur - begin)
   }
   return mid

}

var smil = xml.indexOf("smil") > -1 if (!smil) {

   System.print(xml)
   return

} xml = xml.replace("<smil>\n", "").replace("\n</smil>", "") var animate = Pattern.new("<animate +1^///>") var matches = animate.findAll(xml) var mcount = matches.count if (mcount == 0) {

   System.print(xml)
   return

}

var elem = List.filled(mcount, null) var attr = List.filled(mcount, null) var from = List.filled(mcount, null) var to = List.filled(mcount, null) var begin = List.filled(mcount, 0) var dur = List.filled(mcount, 0) for (i in 0...mcount) {

   var match = matches[i]
   xml = xml.replace(match.text + "\n", "")
   var p = Pattern.new("+1/s")
   var items = p.splitAll(match.text[1..-3])
   attr[i] = extractValue.call(items[1])
   from[i] = [0] * 3
   from[i][0] = Num.fromString(items[2].replace("from=\"", ""))
   from[i][1] = Num.fromString(items[3])
   from[i][2] = Num.fromString(items[4].replace("\"", ""))
   to[i] = [0] * 3
   to[i][0] = Num.fromString(items[5].replace("to=\"", ""))
   to[i][1] = Num.fromString(items[6])
   to[i][2] = Num.fromString(items[7].replace("\"", ""))
   begin[i] = Num.fromString(extractValue.call(items[8]).replace("s", ""))
   dur[i]   = Num.fromString(extractValue.call(items[9]).replace("s", ""))
   p = Pattern.new("<[+1/w] %(attr[i])/='[+1^']'>")
   var matches2 = p.find(xml)
   elem[i] = matches2.capsText[0]
   p = Pattern.new(">\n+1/s<//%(elem[i])>")
   xml = p.replaceAll(xml, "/>")

}

for (t in [0, 2]) {

   var xml2 = xml
   for (i in 0...mcount) {
       var p = Pattern.new("<%(elem[i]) %(attr[i])/='[+1^']'//>")
       var sfrom = p.find(xml2).capsText[0]
       var mid = interpolate.call(from[i], to[i], begin[i], dur[i], t)
       var smid = mid.map { |n| n.toString }.join(" ")
       xml2 = xml2.replace("<%(elem[i]) %(attr[i])='%(sfrom)'/>", "<%(elem[i]) %(attr[i])='%(smid)'/>")
   }
   System.print("At t = %(t) seconds:\n")
   System.print(xml2)
   System.print()

}</lang>

Output:
At t = 0 seconds:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color='1 1 1' location='0 2 0'/>
    <Shape>
      <Box size='2 1 2'/>
      <Appearance>
        <Material diffuseColor='0 0.6 1'/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>

At t = 2 seconds:

<?xml version="1.0" ?>
<X3D>
  <Scene>
    <Viewpoint position="0 0 8" orientation="0 0 1 0"/>
    <PointLight color='1 1 1' location='0 2 0'/>
    <Shape>
      <Box size='1.8 1.2 1.8'/>
      <Appearance>
        <Material diffuseColor='0.2 0.56 0.8'/>
      </Appearance>
    </Shape>
  </Scene>
</X3D>