<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Syntopia &#187; Sunflow</title>
	<atom:link href="http://blog.hvidtfeldts.net/index.php/category/sunflow/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hvidtfeldts.net</link>
	<description>Generative Art, 3D Fractals, Creative Computing</description>
	<lastBuildDate>Fri, 27 Jan 2012 22:34:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Scripting in Structure Synth</title>
		<link>http://blog.hvidtfeldts.net/index.php/2010/11/scripting-in-structure-synth/</link>
		<comments>http://blog.hvidtfeldts.net/index.php/2010/11/scripting-in-structure-synth/#comments</comments>
		<pubDate>Fri, 12 Nov 2010 19:40:25 +0000</pubDate>
		<dc:creator>Mikael Hvidtfeldt Christensen</dc:creator>
				<category><![CDATA[Raytracing]]></category>
		<category><![CDATA[Structure Synth]]></category>
		<category><![CDATA[Sunflow]]></category>

		<guid isPermaLink="false">http://blog.hvidtfeldts.net/?p=775</guid>
		<description><![CDATA[I&#8217;ve added a JavaScript interface to Structure Synth. This makes it possible to automate and script animations from within Structure Synth. Here is an example: (Image links to YouTube video) The JavaScript interface will be part of the next version &#8230; <a href="http://blog.hvidtfeldts.net/index.php/2010/11/scripting-in-structure-synth/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve added a JavaScript interface to Structure Synth. This makes it possible to automate and script animations from within Structure Synth. Here is an example:<br />
<a href="http://www.youtube.com/watch?v=m1swzq1Dd9Q"><br />
<img src="http://blog.hvidtfeldts.net/media/youtube.jpg"/><br />
</a><br />
<i>(Image links to YouTube video)</i></p>
<p>The JavaScript interface will be part of the next version of Structure Synth (which is almost complete), but it is possible to try out the new features right now, by checking out the sources from the Subversion repository.</p>
<p>The rest of this post shows how to use the JavaScript interface.</p>
<p><span id="more-775"></span></p>
<h3>A very simple example</h3>
<p>This snippet shows how to raytrace an EisenScript system to an external file:<br />
<code><br />
#javascript<br />
Builder.load("NouveauMovie.es");<br />
Builder.setSize(0,100);<br />
Builder.define("myRotation",45);<br />
Builder.build();<br />
Builder.raytraceToFile("output.png",true);<br />
</code></p>
<p>The script above can be executed directly from within Structure Synth, the same way EisenScript code is run. Just paste it into a window and press the &#8216;play&#8217; button.</p>
<p>The first line (&#8220;#javascript&#8221;) tells Structure Synth that the code should be invoked using the internal JavaScript interpreter, instead of being parsed as EisenScript. This tag must appear as the first code line without any spaces.</p>
<p>The &#8216;load&#8217; command simply reads the given file into a buffer. Notice, that files are located relative to the path the current code is saved in (so save your script before running it). </p>
<p>The &#8216;setSize&#8217; determines the output size. In the example above the &#8216;width&#8217; argument is zero: this means the width will be calculated from the height using the aspect ratio from the OpenGL workspace window. It is of course possible to specify both dimensions, but be careful not to distort the aspect ratio. The setSize-command will not affect the OpenGL windows size &#8211; it only controls the internal raytracer and the template export dimensions.</p>
<p>Next, the &#8216;define&#8217; makes it possible to overwrite preprocessor variables in the EisenScript file. The example above assumes that there is a preprocessor variable defined such as:<br />
<code><br />
#define myRotation 180<br />
</code></p>
<p>Thus, by calling &#8216;Builder.define&#8217;, variables in the EisenScript code can be controlled, which as the next example shows, makes it possible to do scripted animations.</p>
<p>The &#8216;build&#8217; command executes the EisenScript system in the buffer. The results will be visible in the OpenGL window.</p>
<p>The final command &#8216;raytraceToFile&#8217; invokes the internal raytracer and renders an image to &#8220;output.png&#8221; (the &#8216;true&#8217; flag here just tells Structure Synth to overwrite files without warning).</p>
<p>But of course the real power of JavaScript is that you can write real programs, with functions and conditionals. Structure Synth uses QT&#8217;s QScriptEngine, which makes it possible to use standard JavaScript language constructs. The following example shows how this works.</p>
<h3>An animation example</h3>
<p>The example shows how to construct a 1000 frame animation using the internal raytracer.</p>
<div style="overflow: auto;"><code style="white-space:nowrap;"><br />
#javascript<br />
&nbsp;<br />
function pad(number) {<br />
&nbsp;&nbsp;&nbsp;number = number + ''; // convert to string<br />
&nbsp;&nbsp;&nbsp;while (number.length < 4) { number = "0" + number; }<br />
&nbsp;&nbsp;&nbsp;return number;<br />
}<br />
&nbsp;<br />
Builder.load("NouveauMovie.es");<br />
max = 1000;<br />
for (i = 0; i <=  max; i+=1) {<br />
&nbsp;&nbsp;&nbsp;c = i/max;<br />
&nbsp;&nbsp;&nbsp;Builder.reset();<br />
&nbsp;&nbsp;&nbsp;Builder.setSize(0,600);<br />
&nbsp;&nbsp;&nbsp;Builder.define("_rz",c*360);<br />
&nbsp;&nbsp;&nbsp;Builder.define("_md",parseInt(20+c*1000));<br />
&nbsp;&nbsp;&nbsp;Builder.define("_dofa",0.2+ 0.1*Math.sin(c*3.1415*2));<br />
&nbsp;&nbsp;&nbsp;Builder.build();<br />
&nbsp;&nbsp;&nbsp;Builder.raytraceToFile("Image" + pad(i) + ".png",true);<br />
}<br />
</code></div>
<p>&nbsp;<br />
The 'reset' command is necessary when building animations. This is because of the way 'define' variables are set: First, the Builder loads the EisenScript into a buffer, then it sets the 'define' variables by simply substituting text strings in the buffer with the actual values. Since this can only be done once, it is necessary to reset the buffer to the original state before each new frame - this is the done by calling the 'reset' command. </p>
<p>The JavaScript 'pad' function simply makes sure the files get properly named: Image0000.png, Image0001.png, Image0002.png, and so on. This makes it easier to encode them subsequently.</p>
<p>A few hints: fix the camera position and random seed in the EisenScript file. The camera settings can be included in the EisenScript by using the context menu on the OpenGL window, and choosing "Copy Camera Settings to EisenScript Window". Instead of changing the camera position, it is much easier to apply some zoom and rotational operations on the start rule in the EisenScript code.</p>
<h3>Converting images to a movie</h3>
<p>Video encoding can be extremely tricky, and there are many ways to do it. I used the <a href="http://en.wikipedia.org/wiki/MEncoder">mencoder</a> software (Windows binaries <a href="http://sourceforge.net/projects/mplayer-win32/">here</a>) to convert the series of images into a MPEG4-encoded avi file. This was done by the following command:</p>
<div style="overflow: auto;"><code style="white-space:nowrap;"><br />
c:\PathToMencoder\mencoder.exe "mf://*.png" -mf fps=25:type=png -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=2642822:mbd=2:keyint=132:vqblur=1.0:cmp=2:subcmp=2:dia=2:mv0:last_pred=3 -oac copy -o output.avi<br />
</code></div>
<p>&nbsp;<br />
Notice, that Mencoder can only recognize the correct image order, if they are alfabetically ordered (Image1.png, ..., Image10.png, ... will <i>not</i> work), which is why the example above used the 'pad' function.</p>
<p>Besides the <a href="http://www.youtube.com/watch?v=m1swzq1Dd9Q">YouTube version</a> shown at the top of this post, I tried a few other video sharing services as well: <a href="http://www.flickr.com/photos/syntopia/5139710187/">Flickr</a> and <a href="http://vimeo.com/16433638" rel="nofollow">Vimeo</a>. I was a bit disappointed by both - Vimeo has a large and interesting community, but the free 'basic' subscribtion seems a bit limited. For comparison the original version can be downloaded <a href="http://blog.hvidtfeldts.net/media/nouveau.avi" rel="nofollow">here</a> (15MB AVI).</p>
<h3>Calling external raytracers</h3>
<p>It is also possible to call external raytracers using the JavaScript interface.</p>
<p>The following code shows how the loop above can be modified to use Sunflow as external raytracer. </p>
<div style="overflow: auto;"><code style="white-space:nowrap;"><br />
/// ... load system ....<br />
for (i = 0; i <=  max; i+=1) {<br />
&nbsp;&nbsp;&nbsp;Builder.reset();<br />
&nbsp;&nbsp;&nbsp;/// ... set 'define' variables here<br />
&nbsp;&nbsp;&nbsp;Builder.build();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;// ---- Sunflow raytrace -----<br />
&nbsp;&nbsp;&nbsp;name = "f:/Test/out" + pad(i);<br />
&nbsp;&nbsp;&nbsp;Builder.templateRenderToFile("Sunflow-Colored.rendertemplate", name + ".sc",true);<br />
&nbsp;&nbsp;&nbsp;Builder.execute('"C:/Program Files/Java/jdk1.6.0_21/bin/java"', '-Xmx1G -server -jar  "%SUNFLOW%/sunflow.jar" ' +  name + ".sc -nogui -o " + name + ".png", true);<br />
}<br />
</code></div>
<p>&nbsp;<br />
The 'templateRenderToFile' takes three arguments: the first is the name of a rendertemplate (the default location is the 'Misc' folder), the second the desired output filename, and the third determines whether to overwrite without warnings.</p>
<p>The 'execute' command spawns an external process. The first parameter is the name of the executable, the second a string with command line arguments, and the third controls if the JavaScript interpreter should wait for the process to finish.</p>
<p>Getting the syntax right for executing external commands, can be tricky: for instance, normally Sunflow is invoked by calling a shell-script, but the 'Builder.execute' command cannot parse these. Instead it calls the Java spawner directly. </p>
<p>The 'Builder.execute' command is able to substitute environment commands (e.g. the '%SUNFLOW%' variable). </p>
<p>Also be careful with spaces: all command line arguments which contain spaces must be quoted. In JavaScript the easiest way to accomplish this, is by using <i>single quotes</i> for the arguments to 'Builder.execute', and use <i>double quotes</i> inside these strings for command line arguments which could contain spaces. (In the example above "%SUNFLOW%/sunflow.jar" is quoted even though it does not contain spaces - this is because %SUNFLOW% may be substituted for a path which contains spaces.)</p>
<p>Finally, it is also possible just to use 'Builder.renderToFile' to save the current OpenGL view as an image (without raytracing). This is useful for creating fast previews.</p>
<h3>Reference</h3>
<p>The Structure Synth JavaScript API only exposes a single, global object - the Builder. The following methods are available:</p>
<p>Builder.<u>load</u>(string fileName)<br />
Loads an EisenScript file into the working buffer.</p>
<p>Builder.<u>define</u>(string input, string value)<br />
Performs text substitutions on the buffer (but ignores preprocessor lines!)</p>
<p>Builder.<u>prepend</u>(string prescript);<br />
Prepends the buffer script with 'prescript'</p>
<p>Builder.<u>append</u>(string postscript);<br />
Appends the buffer script with 'postscript'</p>
<p>Builder.<u>build</u>();<br />
Builds the system. The output is visible in the OpenGL workspace window.</p>
<p>Builder.<u>renderToFile</u>(string fileName, bool overwrite);<br />
Saves the current OpenGL view to a file.<br />
'overwrite' toggles if it is okay to overwrite existing files without warning.</p>
<p>Builder.<u>raytraceToFile</u>(string fileName, bool overwrite);<br />
Raytrace image with internal raytracer to file.<br />
'overwrite' toggles if it is okay to overwrite existing files without warning.</p>
<p>Builder.<u>templateRenderToFile</u>(string templateName, string fileName, bool overwrite);<br />
Raytrace image with same dimensions as viewport to file.<br />
'overwrite' toggles if it is okay to overwrite existing files without warning.</p>
<p>Builder.<u>execute</u>(string fileName, string args, bool waitForFinish);<br />
Executes an external process. Meant to be used after having called 'templateRenderToFile'.<br />
If 'waitForFinish' is true, the JavaScript interpreter will block until the process has completed.</p>
<p>Builder.<u>reset</u>();<br />
Restores the original content of the buffer (useful if substitutions have been made.)</p>
<p>Builder.<u>setSize</u>(int width, int height);<br />
Sets the dimensions for the output (internal raytracer and templates).<br />
If both width and height is zero, the screen viewport size is used (default).<br />
If either width or height is zero, the other dimension is calculated using the aspect ratio of the viewport.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hvidtfeldts.net/index.php/2010/11/scripting-in-structure-synth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Are Boxes too Square for Sunflow?</title>
		<link>http://blog.hvidtfeldts.net/index.php/2008/02/are-boxes-to-square-for-sunflow/</link>
		<comments>http://blog.hvidtfeldts.net/index.php/2008/02/are-boxes-to-square-for-sunflow/#comments</comments>
		<pubDate>Tue, 05 Feb 2008 21:13:54 +0000</pubDate>
		<dc:creator>Mikael Hvidtfeldt Christensen</dc:creator>
				<category><![CDATA[Structure Synth]]></category>
		<category><![CDATA[Sunflow]]></category>

		<guid isPermaLink="false">http://blog.hvidtfeldts.net/index.php/2008/02/are-boxes-to-square-for-sunflow/</guid>
		<description><![CDATA[Structure Synth is now able to export boxes to Sunflow. That was actually a lot harder than spheres. Boxicity (Sunflow render). Sunflow has some amazing global illumination lightning, but why doesn&#8217;t it have a &#8216;box&#8217; primitive in its scene graph &#8230; <a href="http://blog.hvidtfeldts.net/index.php/2008/02/are-boxes-to-square-for-sunflow/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Structure Synth is now able to export <strong>boxes</strong> to Sunflow. That was actually a lot harder than spheres.</p>
<p></p><div class="photo"><p><a class="snap_noshots" href="/media/sunflow2.jpg" rel="gb_imageset[dds]" title="Boxicity (Sunflow render)"><img src="/media/sunflow2s.jpg" alt="Boxicity (Sunflow render)" /></a></p><div class="caption">Boxicity (Sunflow render).</div></div><p></p>
<p>Sunflow has some amazing global illumination lightning, but why doesn&#8217;t it have a &#8216;box&#8217; primitive in its scene graph language? I mean, it has Banchoff Surfaces, tori and teapots, but not a simple box?</p>
<p>By the way, for those who really dig boxes, check out the <a href="http://www.flickr.com/groups/boxclub/">Flickr Boxclub</a> (a few Structure Synth creations may also be spotted there).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hvidtfeldts.net/index.php/2008/02/are-boxes-to-square-for-sunflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Structure Synth Rendering Templates</title>
		<link>http://blog.hvidtfeldts.net/index.php/2008/02/structure-synth-rendering-templates/</link>
		<comments>http://blog.hvidtfeldts.net/index.php/2008/02/structure-synth-rendering-templates/#comments</comments>
		<pubDate>Sun, 03 Feb 2008 21:12:49 +0000</pubDate>
		<dc:creator>Mikael Hvidtfeldt Christensen</dc:creator>
				<category><![CDATA[POVRay]]></category>
		<category><![CDATA[Structure Synth]]></category>
		<category><![CDATA[Sunflow]]></category>

		<guid isPermaLink="false">http://blog.hvidtfeldts.net/index.php/2008/02/structure-synth-rendering-templates/</guid>
		<description><![CDATA[Creating a reasonable way of exporting Structure Synth objects to other renderers, like Sunflow and POV-Ray turned out to be more difficult than I expected. Not because they have complicated scene description languages &#8211; they don&#8217;t &#8211; but because there &#8230; <a href="http://blog.hvidtfeldts.net/index.php/2008/02/structure-synth-rendering-templates/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Creating a reasonable way of exporting Structure Synth objects to other renderers, like <a href="http://sunflow.sourceforge.net/">Sunflow</a> and <a href="http://www.povray.org/">POV-Ray</a> turned out to be more difficult than I expected. Not because they have complicated scene description languages &#8211; they don&#8217;t &#8211; but because there are a lot of settings and parameters, and I do not want to wrap and support every single one of them.</p>
<p></p><div class="photo"><p><a class="snap_noshots" href="/media/sunflow1.jpg" rel="gb_imageset[dds]" title="Sunflow export"><img src="/media/sunflow1s.jpg" alt="Sunflow export" /></a></p><div class="caption">Example Sunflow rendering with <a href="http://en.wikipedia.org/wiki/Global_illumination">Global Illuminated</a> <a href="http://en.wikipedia.org/wiki/Ambient_occlusion">Ambient Occlusion</a>.</div></div><p></p>
<p>The approach I came up with is quite simple &#8211; it is now possible to define a number of <i>rendering templates</i> which are XML-files containing a number of text fragments, one for each of the primitives (box, sphere, &#8230;) and a &#8216;start&#8217; and &#8216;end&#8217; fragment.</p>
<p>For instance, a fragment (for a Sunflow exporter) for the &#8216;sphere&#8217; primitive could look like this:</p>
<pre>
object {
  shader "s05"
  type sphere
  c {cx} {cy} {cz}
  r {rad}
}
</pre>
<p>where the center and radius parameters would be substituted for each instance of the primitive. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hvidtfeldts.net/index.php/2008/02/structure-synth-rendering-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

