<?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/"
	>

<channel>
	<title>Quasipartikel</title>
	<atom:link href="http://quasipartikel.at/feed/" rel="self" type="application/rss+xml" />
	<link>http://quasipartikel.at</link>
	<description>Just another WordPress weblog</description>
	<pubDate>Mon, 07 May 2012 17:19:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Dancing with Data</title>
		<link>http://quasipartikel.at/2012/04/25/dancing-with-data/</link>
		<comments>http://quasipartikel.at/2012/04/25/dancing-with-data/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 03:25:38 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[Webscience]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=686</guid>
		<description><![CDATA[Last Sunday I gave a small workshop at the <a href="http://mapbox.com">MapBox</a> office, where I showed new findings I've discovered while working on my last visualization project. We turned a collection of countries into a dance of dots, each dot referring to a country in the collection. In other words: We created a simple animated Scatterplot.]]></description>
			<content:encoded><![CDATA[<p>The goal was to implement a data-driven visualization where the output image is determined by the data and visualization state, such as filters and selected variables. Once users modify either the state or the data, the visualization gets updated accordingly using smooth transitions between states.</p>
<p><img src="http://substance-assets.s3.amazonaws.com/3d/8b1c49f1dff4e7cfe8c1938f4e103f/datadriven-vis-01.png" alt="image"></p>
<p>We applied fundamental concepts such as Data Joins (a technique introduced by <a href="http://mbostock.github.com/d3/">D3.js</a>), Scales and Animation. For our example we were using <a href="http://github.com/michael/dance">Dance.js</a>, a minimal visualization framework I&#8217;ve built (which is essentially just a flavor of Backbone.js) as well as <a href="http://github.com/michael/data">Data.js</a> for representing and accessing domain data.</p>
<h2>Representing domain data</h2>
<p>We are describing our domain data using a Data.js <code>Data.Collection</code>, which is very easy to use.</p>
<pre><code>var countries_data = {
  "type": {
    "_id": "/type/country",
    "name": "Country",
    "properties": {
      "name": {"name": "Country Name", "type": "string" },
      "languages": {"name": "Languages spoken", "type": "string" },
      "population": { "name": "Population", "type": "number" },
      "gdp": { "name": "GDP per capita", "type": "number" }
    }
  },
  "objects": [
    {
      "_id": "at",
      "name": "Austria",
      "languages": ["German", "Austrian"],
      "population": 8.3,
      "gdp": 41.805
    },
    {
      "_id": "de",
      "name": "Germany",
      "languages": ["German"],
      "population": 82,
      "gdp": 46.860
    },
    ...
  ]
}
</code></pre>
<h2>The Interface</h2>
<p>We wanted our visualization to be easily embeddable into web-applications. So here&#8217;s how creating a scatterplot instance, using an arbitrary dataset looks like:</p>
<pre><code>var countries = new Data.Collection(countries_data);
var scatterplot = new Scatterplot();

// Display the scatterplot by showing GDP (x-Axis) and Population (y-Axis)
scatterplot.update(countries, ["gdp", "population"]);

// Switch axes and refresh the scatterplot
scatterplot.update(countries, ["population", "gdp"]);
</code></pre>
<h2>Layout and Refresh</h2>
<p>Most visualizations can be implemented efficiently by separating them into two separate phases. In the first phase positions of the visual marks are calculated while in the refresh phase the actual drawing takes place. Here&#8217;s the implementation of our update function, which accomodates that pattern. It gets called every time the visualization needs to be updated.</p>
<pre><code>function update(items, properties) {
  this.data["items"] = items;
  this.layout(properties);
  this.refresh();
}
</code></pre>
<h2>Layout</h2>
<p>In order to turn domain objects into dots we need to apply a scatterplot layout algorithm. The first part of the function sets up scale functions for the x and y-Axis, since we want to map our domain values (which can be very big numbers) to limited pixel space. The second part just iterates through all items we have in our collection in order to set the x and y positions by passing the values to the corresponding scale function.</p>
<pre><code>function layout(properties) {
  var that = this;

  // Prepare scales
  function aggregate(p, fn) {
    var values = _.map(that.data["items"].objects, function(i) { return i.get(p); });
    return fn.apply(this, values);
  }

  var minX = aggregate(properties[0], Math.min);
  var maxX = aggregate(properties[0], Math.max);

  var minY = aggregate(properties[1], Math.min);
  var maxY = aggregate(properties[1], Math.max);

  function x(val) {
    return (((val-minX) * $('#canvas').width()) / (maxX-minX));
  }

  function y(val) {
    return (((val-minY) * $('#canvas').height()) / (maxY-minY));
  }

  // Apply layout
  this.data["items"].each(function(item, key, index) {
    item.pos = {
      x: x(item.get(properties[0])),
      y: y(item.get(properties[1]))
    };
  });
}
</code></pre>
<h2>Refresh</h2>
<p>During the refresh phase, elements are actually drawn on the screen. We need an individual strategy for placing new marks, update the positions of existing marks and remove marks that no longer exist in the dataset.</p>
<h2>Enter / Update / Exit</h2>
<p>Much like in the spirit of D3.js, we specified transformations, based on data-changes to update our visualization. There are three different cases we need to take care of: The updating nodes to modify, the entering nodes to add, and the exiting nodes to remove. The process where new, existing and exiting nodes are determined is called a <a href="http://bost.ocks.org/mike/join/">Data Join</a>.</p>
<p><img src="http://substance-assets.s3.amazonaws.com/15/10d431a6a07a189801674bfd627485/Screen-Shot-2012-04-22-at-1.26.05-AM.png" alt="image"></p>
<p>With Dance.js we are able to specify transformations for each case separately:</p>
<pre><code>var collections = {
  "items": {
    enter: function(items) {
      items.each(function(item) {
        var dot = $('&lt;div class="dot" id="'+htmlId(item)+'"&gt;&lt;/div&gt;')
                     .css('left', Math.random()*$('#canvas').width())
                     .css('bottom', Math.random()*$('#canvas').height())
                     .css('width', 1)
                     .css('height', 1);
        $('#canvas').append(dot);
      });

      // Delegate to update (motion tweening fun)
      _.delay(this.collections["items"].update, 200, items);
    },

    update: function(items) {
      items.each(function(item) {
        var cell = $('#'+htmlId(item))
                     .css('left', item.pos.x)
                     .css('bottom', item.pos.y)
                     .css('width', 10)
                     .css('height', 10);
      });
    },

    exit: function(items) {
      items.each(function(i) { $('#'+htmlId(i)).remove() });
    }
  }
};
</code></pre>
<h2>Results</h2>
<p>Finally this is how our result looks like. It&#8217;s kept very minimal intentionally, as this example should just serve as a starting point.</p>
<div style="background: #eee">
<iframe width='680' height='500' frameBorder='0' src='http://bl.ocks.org/d/2458819/'> </iframe>
</div>
</p>
<p>There&#8217;s another first time dance you might want to look at, the Barchart Dance.</p>
<div style="background: #eee">
<iframe width='680' height='500' frameBorder='0' src='http://bl.ocks.org/d/2172216/'> </iframe>
</div>
<h2>Dance.js and Data.js</h2>
<p>You could use other tools or even no framework to apply the same techniques. I just chose this lightweight toolset as I&#8217;m using it in my projects and it suffices for many tasks. There are more major tools around, such as the D3.js visualization framework. Actually Dance.js works well in conjunction with D3. It gives you the joy of both Backbone and D3. Instead of <code>Backbone.Model</code> it uses Data.js for representing your domain models. Just ping me on <a href="http://twitter.com/_mql">twitter</a> if you have any questions.</p>
<h2>Start experimenting</h2>
<p>Feel free to create your own variations and further improve the code. Let me know if you&#8217;d like to share your work. You can access the<br />
full source code at Github. Probably the easiest way to get started is to check out Dance.js and look at the examples.</p>
<pre><code>git clone git://github.com/michael/dance.git
cd dance
git submodule init
git submodule update
</code></pre>
<h2>References:</h2>
<ul>
<li>
<p><a href="http://github.com/michael/dance">Dance.js</a></p>
</li>
<li>
<p><a href="http://github.com/michael/data">Data.js</a></p>
</li>
<li>
<p><a href="http://bl.ocks.org/2172216">The Barchart Dance</a></p>
</li>
<li>
<p><a href="http://bl.ocks.org/2458819">The Scatterplot Dance</a></p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2012/04/25/dancing-with-data/feed/</wfw:commentRss>
		</item>
		<item>
		<title>VVVV.js</title>
		<link>http://quasipartikel.at/2011/09/01/vvvvjs/</link>
		<comments>http://quasipartikel.at/2011/09/01/vvvvjs/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 08:45:27 +0000</pubDate>
		<dc:creator>Matthias</dc:creator>
		
		<category><![CDATA[Arty]]></category>

		<category><![CDATA[Code]]></category>

		<category><![CDATA[canvas]]></category>

		<category><![CDATA[javascript]]></category>

		<category><![CDATA[vvvv]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=668</guid>
		<description><![CDATA[The VVVV.js project has launched, and joins the game of porting great stuff to JavaScript. Read about what it is, what it is not and what to do to make it become, what it might be some day, in this quasi-artikel.]]></description>
			<content:encoded><![CDATA[<p>VVVV.js is an open project, which aims to bring the visual programming language VVVV to your web browser, by porting its &#8220;runtime parts&#8221; to JavaScript. This enables your web browser to run VVVV files (or VVVV XML code) on the client side.</p>
<p>Get the full idea at the project website <a href="http://vvvvjs.quasipartikel.at">vvvvjs.quasipartikel.at</a></p>
<p>While this sounds too good to be true, here comes the bummer: besides porting parts of VVVV&#8217;s internals, all the nodes you want to use have to be ported to JavaScript as well. Having in mind, that there are hundeds of nodes for the original VVVV, this is just absurd &#8230; right? But let&#8217;s just give it a try anyway.</p>
<h2>Why?</h2>
<ul>
<li>Because once you&#8217;re into patching VVVV, textual programming just makes you feel fat and sluggish. There should be a way to develope client side web applications the VVVV way.</li>
<li>Because HTML5 with Canvas and WebGL, combined with powerful Javascript interpreters make it possible.</li>
<li>Because of a tiny flavour of cross-platform compatibility: VVVV patches on mobile devices, anyone?</li>
</ul>
<p>The project is far from being ready to use in real life, in terms of functionality as well as in terms of performance. Its further development totally depends on your help. Checkout the Github repository at</p>
<p><a href="https://github.com/zauner/vvvv.js">github.com/zauner/vvvv.js</a></p>
<p>and help porting your favourite nodes, it&#8217;s not that hard.</p>
<p>Also visit us in the dedicated ##vvvvjs channel on irc.freenode.net!</p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2011/09/01/vvvvjs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>U+223D</title>
		<link>http://quasipartikel.at/2011/02/18/u223d/</link>
		<comments>http://quasipartikel.at/2011/02/18/u223d/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 15:23:49 +0000</pubDate>
		<dc:creator>Matthias</dc:creator>
		
		<category><![CDATA[Arty]]></category>

		<category><![CDATA[multi projection]]></category>

		<category><![CDATA[projection mapping]]></category>

		<category><![CDATA[visuals]]></category>

		<category><![CDATA[vvvv]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=642</guid>
		<description><![CDATA[U+223D (Reversed Tilde) is a multi-projector club visual setup featuring a non-planar sculpture, which consists of four separated canvases. Have a look inside the article, to watch a video of its first application in the Eiskeller Hagenberg.]]></description>
			<content:encoded><![CDATA[<p>The canvas layout was designed together with Michael Holzer, who also was responsible for actually constructing the blueprinted sculpture. He came up with a light-weight and light-budget connector system for realizing the canvas frames. This was crucial, to be able to hang the sculpture on silk wires from the ceiling, and keeping the whole thing as portable as possible. For the first application the canvas itself was made of common fabric.</p>
<div id="attachment_653" class="wp-caption aligncenter" style="width: 610px"><img src="http://quasipartikel.at/wp-content/uploads/2011/02/u223d_blogpic2.png" alt="From design and simulation to the first installation in the Eiskeller." title="u223d_blogpic2" width="600" height="180" class="size-full wp-image-653" /><p class="wp-caption-text">From design and simulation to the first installation in the Eiskeller.</p></div>
<p>Two projectors are used to bring content to the sculpture. Projection mapping and audio reactive real time fancyness is done using <a href="http://www.vvvv.org">VVVV</a>. We patched a framework which allows to do both: wrap rectangular visuals from back in the days around the canvases, as well as create material especially fitting the canvas&#8217; shape. The framework provides tools to transform geometry and points from orthogonal 2D space into the distorted canvas space, which lets us somehow <i>squeeze</i> animations into the shape of the sculpture.</p>
<p>The video below shows the setup in action during the basement bash in the Eiskeller Hagenberg, thrown by the guys from Deliciouz.</p>
<div id="attachment_544" class="wp-caption aligncenter" style="width: 613px"><br />
<iframe src="http://player.vimeo.com/video/20199000?portrait=0" width="400" height="300" frameborder="0"></iframe><p class="wp-caption-text">The setup installed at the Eiskeller Hagenberg. The left projector shifted upwards during the night, but still, you can get the idea, don't you?.</p></div>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2011/02/18/u223d/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Music artist similarities from co-occurrences in playlists</title>
		<link>http://quasipartikel.at/2010/07/28/music-artist-similarities/</link>
		<comments>http://quasipartikel.at/2010/07/28/music-artist-similarities/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 21:30:04 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=584</guid>
		<description><![CDATA[As an exercise for the university I had to calculate music artist similarities based on co-occurrences in user generated playlists. Such similarity measures play a vital role in many application scenarios of Music Information Retrieval (MIR), e.g., in music recommendation and playlist generation applications.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cp.jku.at/people/schedl/Research/Publications/pdf/phd_schedl_2008.pdf">Schedl,  2008</a> describes music information retrieval (MIR) as the extraction, analysis, and usage of information about any kind of music entity (for example, a song or a music artist) on any representation level (for example, audio signal, symbolic MIDI representation of a piece of music, or name of a music artist).</p>
<p>It&#8217;s a quite challenging and repetitive job to calculate and analyze artist similarities as well as make the results visible using data visualization techniques.</p>
<p>Since I&#8217;m working on a web-based visualization toolkit, which is dedicated to data analysis and visualization, I just decided to use this specific task of calculating artist similarities as a real-world use-case for the toolkit I&#8217;m working on.</p>
<p>The approach described in this post tries to generalize the problem domain and aims to make the calculation, analyzation and visualization of artist similarities a uniform and repeatable process.</p>
<h3>Unveil.js</h3>
<p>Before I start explaining my approach on the exercise, I want to give you a short introduction on Unveil.js, a data-driven visualization toolkit. It basically provides a simple abstraction layer for visualizations to ease the process of creating re-usable charts. To accomplish this, a data-driven methodology is used.</p>
<p>Data-driven means, that the appearance of the result is determined by the underlying data rather than by user defined plotting options. Visualizations directly access data trough a well defined data interface, a Collection, so there&#8217;s no longer a gap between domain data and data used by the visualization engine.</p>
<p>Such visualization can be re-used in terms of putting in arbitrary data in, as long as the data is a valid Collection and satisfies the visualization specification (some visualizations exclusively use numbers as their input, others use dates (e.g. Timeline plots), and so on&#8230;).</p>
<p>You can track the project&#8217;s progress at <a href="http://github.com/michael/unveil">Github</a>.</p>
<p>The toolkit&#8217;s data layer also provides means to implement arbitrary transformations that operate on raw data. So the challenge was to take input data, a set of user generated playlists, and perform similarity-measurement algorithms on it. The result is a new collection of artists (that occurred in the original data-set) that feature a set of similar artists. This set is based on a similarity score, which is determined by the algorithm.</p>
<h3>Data Retrieval</h3>
<p>In the first place you are faced with the problem of extracting data from different sources where various methods of information retrieval (MIR) need to be applied. So this task needs to be done mostly by hand and depends on how the data source is organized. The result of this task is usually an intermediate proprietary data format, which is used to perform processing and analysis on the data.</p>
<p>If you would agree on a uniform data exchange format you would be able to generically apply common operations like co-occurrence analysis on it.</p>
<p>Therefore, here&#8217;s a proposal of a lightweight Collection format represented as a JSON string that holds the raw data as well as some meta information about the data&#8217;s structure. </p>
<p>For my task (analyzation of playlists) I&#8217;ve built a simple data aggregation service that pulls user generated playlists from Last.fm and translates them into a uniform collection exchange format.</p>
<p>I&#8217;ve used the following strategy to get some suitable playlists:</p>
<ol>
<li>Load a set of seed Artists (those relationships you&#8217;re finally interested in)</li>
<li>Collect top fans (users) for all seed artists</li>
<li>For every user pull its playlists</li>
<li>The resulting playlists contain only those artists and songs that are listed in the set of seed artists</li>
</ol>
<p>Using this approach I&#8217;m most likely getting playlists that contain artists of the set of seed artists and eliminate the buzz. So once you have this format of data it&#8217;s quite easy to operate on it.</p>
<p>Here&#8217;s how a resulting collection of playlists looks like:</p>
<pre><code class="codesnippet">
{
  "properties": {
    "name": {
      "name": "Playlist Name",
      "type": "string",
      "unique": true
    },
    "artists": {
      "name": "Artists",
      "type": "string",
      "unique": false
    },
    "songs": {
      "name": "Songs",
      "type": "string",
      "unique": false
    },
    "song_count": {
      "name": "Song count",
      "type": "number",
      "unique": false
    }
  }
  "items": {
    "4976660": {
      "name": "JD_Turk's.Vol.2",
      "artists": [
        "Beck",
        "Michael Jackson",
        "Green Day",
        "Madonna"
      ],
      "songs": [
        "Beck - Think I'm In Love",
        "Michael Jackson - Remember the Time",
        "Green Day - Last Night On Earth",
        "Madonna - Forbidden Love"
      ],
      "song_count": 8
    },
    "1380177": {
      "name": "Random!!!",
      "artists": [
        "Daft Punk",
        "Depeche Mode",
        "Moloko",
        "Radiohead"
      ],
      "songs": [
        "Daft Punk - Something About Us",
        "Depeche Mode - Precious",
        "Moloko - Cannot Contain This",
        "Radiohead - Nude"
      ],
      "song_count": 4
    },
  }
}
</code></pre>
<p>See the full collection <a href="http://quasipartikel.at/unveil/fixtures/playlists.js">here</a>.</p>
<p>You can read more about Collections at the <a href="http://docs.quasipartikel.at/#/unveil">Unveil.js documentation page</a>.</p>
<h3>Gaining Similarity Measures</h3>
<p>In order to perform similarity measurement on that data, I&#8217;ve implemented two different algorithms that calculate a similarity score based on co-occurrences. Those algorithms have been described in detail by <a href="http://www.cp.jku.at/people/schedl/Research/Publications/pdf/websim_lsas_2009.pdf">Schedl, Knees, 2009</a>.</p>
<p>Below you can see the essential parts of the transformation functions I&#8217;ve implemented.</p>
<h4>Normalized Co-Occurrences described by Pachet et. al, 2001:</h4>
<p>This approach just counts co-occurrences and normalize the result by using a symmetric function.</p>
<pre><code class="codesnippet">
function coOccurrences(v1, v2) {
  var items1 = v1.list('items'),
      items2 = v2.list('items');
  return items1.intersect(items2).length;
};

function similarity(v1, v2) {
  return 0.5* (coOccurrences(v1, v2) / coOccurrences(v1, v1)
        + coOccurrences(v2, v1) / coOccurrences(v2, v2));
};
</code></pre>
<p>See the full implementation <a href="http://github.com/michael/unveil/blob/master/src/collection/transformers/co_occurrences.js">here</a>.</p>
<h4>Weighted co-occurrences on different distances, described by Baccigalupo et. al.:</h4>
<pre><code class="codesnippet">
function coOccurencesAtDistance(v1, v2, d) {
  var items1 = v1.list('items'),
      items2 = v2.list('items'),
      playlists = items1.intersect(items2);
  return playlists.select(function(p) {
    return checkDistance(p, v1, v2, d);
  }).length;
};

function similarity(v1, v2) {
  return 1*coOccurencesAtDistance(v1, v2, 0) +
         0.8* coOccurencesAtDistance(v1, v2, 1) +
         0.64* coOccurencesAtDistance(v1, v2, 2);
};
</code></pre>
<p>See the full implementation <a href="http://github.com/michael/unveil/blob/master/src/collection/transformers/co_occurrences_baccigalupo.js">here</a></p>
<h4>Visualization of the results</h4>
<p>In order to visualize the result I decided to implement an interactive visualization that uses a number of small barcharts (showing similar artists for a certain artist).</p>
<div id="attachment_431" class="wp-caption aligncenter" style="width: 690px"><br />
<img src="http://quasipartikel.at/wp-content/uploads/2010/07/artist_similarities.png" alt="Artist Similarities" title="Artist Similarities" width="680" height="439" class="aligncenter size-full wp-image-596" /><p class="wp-caption-text">Visual representation of the result</p></div>
<p><a href="http://quasipartikel.at/unveil/examples/artist_similarities.html">See the result in action</a></p>
<h4>Conclusio</h4>
<p>The algorithms implemented do not claim to be state-of-the art similarity measurement methods. However, the fact, that you can just swap-in any other implementation makes similarity analysis a repeatable process. In case you&#8217;re considering using this framework for your own data analysis tasks, just let me know. I&#8217;d be glad to get you started.</p>
<p>References:</p>
<ul>
<li><a href="http://www.cp.jku.at/people/schedl/Research/Publications/pdf/phd_schedl_2008.pdf">Automatically Extracting, Analyzing, and Visualizing Information on Music Artists</a> (M. Schedl, 2008)</li>
<li><a href="http://www.cp.jku.at/people/schedl/Research/Publications/pdf/websim_lsas_2009.pdf">Context-based Music Similarity Estimation</a> (M. Schedl, P. Knees, 2009)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2010/07/28/music-artist-similarities/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Skinning with VVVV&#8217;s character animation nodes</title>
		<link>http://quasipartikel.at/2010/05/12/skinning-with-vvvvs-character-animation-nodes/</link>
		<comments>http://quasipartikel.at/2010/05/12/skinning-with-vvvvs-character-animation-nodes/#comments</comments>
		<pubDate>Wed, 12 May 2010 11:44:15 +0000</pubDate>
		<dc:creator>Matthias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[character animation]]></category>

		<category><![CDATA[skinning]]></category>

		<category><![CDATA[vvvv]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=533</guid>
		<description><![CDATA[After having explained how to create skeletons for 3D characters and animating them in VVVV, this quasi-article shows how to use VVVV's character animation nodes in combination with software and hardware skinning methods.]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://quasipartikel.at/2010/05/12/character-animation-in-vvvv/">prevous quasi-article</a> introduces some nodes which were designed to create skeletal animation in VVVV. However, the article didn&#8217;t describe how those nodes can actually deform 3D geometry. So <strong>this</strong> article shows an example of how to build and skin a kind of abstract character model based on a skeleton dynamically.</p>
<p><strong>UPDATE:</strong> I uploaded an extended version of the patch described below, which also shows some parts from the previous article. You can download it here: <a href="http://sagishi.zive.at/vvvvwiki/walkingboxes.rar">walkingboxes.rar</a>.</p>
<p><img src="http://quasipartikel.at/wp-content/uploads/2010/05/walking_cubes.png" alt="walking_cubes" title="walking_cubes" width="354" height="354" class="aligncenter size-full wp-image-577" /></p>
<h4>Some skinning theory</h4>
<p>Skinning describes the process of binding a 3D geometry to a skeleton. The skeleton acts as some kind of abstraction layer over the 3D geometry: instead of moving single vertices, the animator can move joints - the 3D vertices are moved accordingly.
<p>Besides X,Y,Z coordinates, every 3D vertex can have further data assigned, e.g. <em>bind indices</em> and <em>skin weights</em>. Those measures describe, to which extent a vertex is influenced by a certain joint. The <em>bind index</em> is the index of the influencing joint, and the <em>skin weight</em> is the amount of influence, the joint has on a vertex.</p>
<p>If each vertex of a model is influenced by only one joint to full extent, we call this <em>rigid skinning</em>. If multiple joints influence one vertex, we speak of <em>soft skinning</em> or <em>smooth skinning</em>. As you might have guessed, the results here are softer. And smoother, as well. If you are working with vertex buffers and hardware skinning, the number of influencing joints per vertex is limited to 4.<br />
<h4>Building some character</h4>
<p>We already talked about <a href="http://quasipartikel.at/2010/05/12/character-animation-in-vvvv/">creating skeletons</a>, so for this, we take a humanoid skeleton as granted. The image below shows the skeletal structure, and the global joint positions represented by quads in the renderer.</p>
<div id="attachment_537" class="wp-caption aligncenter" style="width: 627px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/skinning_example11.png" alt="A humanoid skeleton created inside a subpatch. The joint positions in world space are computed by the &lt;code&gt;GetJointTransform (Skeleton)&lt;/code&gt; node." title="skinning_example11" width="617" height="442" class="size-full wp-image-537" /><p class="wp-caption-text">A humanoid skeleton created inside a subpatch. The joint positions in world space are computed by the <code>GetJointTransform (Skeleton)</code> node.</p></div>
<p>We can use the joint positions to create some fancy 3D geometry. For this example, I&#8217;m going to build one from some boxes. I&#8217;m not going into detail on how I did this, because it&#8217;s not looking that awesome anyway, so we will take this as granted as well <img src='http://quasipartikel.at/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div id="attachment_539" class="wp-caption aligncenter" style="width: 628px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/skinning_example21.png" alt="Some fancy 3D geometry dynamically built based on that given skeleton. The computed vertices are passed into a VertexBuffer, which flows into a Phong shader effect." title="skinning_example21" width="618" height="662" class="size-full wp-image-539" /><p class="wp-caption-text">Some fancy 3D geometry dynamically built based on that given skeleton. The computed vertices are passed into a VertexBuffer, which flows into a Phong shader effect.</p></div>
<h4>Skin it</h4>
<p>The only way to create perfect skin weights still is manually doing it in a modelling package. This would be the way to go, if we created a model e.g. in Maya and imported it into VVVV using the COLLADA format. Since we built our geometry in VVVV, we need a way to create skin weights in VVVV as well. There are algorithms which automatically calculate skin weights. The most trivial of all is fully assigning a vertex to its nearest joint, which of course results in a rigid skinned mesh. Exaclty this is done by the node <code>AutoSkinWeights (Skeleton)</code>. It takes vertex coordinates and a skeleton, and computes simple skin weights. Of course, there are smarter algorithms, like <a href="http://www.mit.edu/~ibaran/autorig/">using heat maps</a>, which aren&#8217;t implemented yet.</p>
<div id="attachment_541" class="wp-caption aligncenter" style="width: 637px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/skinning_example31.png" alt="Using the &lt;code&gt;AutoSkinWeights&lt;/code&gt; node to automatically determine skin weights for the created geometry. It simply assignes every vertex to its nearest joint, which results in a &lt;em&gt;rigid skinned&lt;/em&gt; mesh. Skin weights and bind indices computed by the &lt;code&gt;AutoSkinWeights&lt;/code&gt; node flow into the &lt;code&gt;VertexBuffer&lt;/code&gt; node (you have to enable those pins in the inspector!)" title="skinning_example31" width="627" height="658" class="size-full wp-image-541" /><p class="wp-caption-text">Using the <code>AutoSkinWeights</code> node to automatically determine skin weights for the created geometry. It simply assignes every vertex to its nearest joint, which results in a <em>rigid skinned</em> mesh. Skin weights and bind indices computed by the <code>AutoSkinWeights</code> node flow into the <code>VertexBuffer</code> node (you have to enable those pins in the inspector!)</p></div>
<h4>Deform it</h4>
<p>Since our mesh is now officially skinned, we can go on and actually deform it. The image above already contains the Skinning.fx shader effect. This effect does the calculation of the deformed vertices based on the joint transformations of the skeleton. All we have to do, is using <code>GetJointTransform (Skeleton)</code> on a <em>posing</em> skeleton, to get all the joints&#8217; compiled transformations, and pass it on to the Skinning effect. The image below shows, how this would look like.</p>
<div id="attachment_544" class="wp-caption aligncenter" style="width: 613px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/skinning_example41.png" alt="The &lt;code&gt;SetJoint (Skeleton)&lt;/code&gt; nodes rotate the character&#039;s hip and knee. The resulting, possing &lt;code&gt;Skeleton&lt;/code&gt; object flows into the &lt;code&gt;GetJointTransform (Skeleton)&lt;/code&gt; node, which calculates the combined joint transformations. The Skinning shader effect deforms the geometry based on those joint transformations." title="skinning_example41" width="603" height="761" class="size-full wp-image-544" /><p class="wp-caption-text">The <code>SetJoint (Skeleton)</code> nodes rotate the character's hip and knee. The resulting, possing <code>Skeleton</code> object flows into the <code>GetJointTransform (Skeleton)</code> node, which calculates the combined joint transformations. The Skinning shader effect deforms the geometry based on those joint transformations.</p></div>
<h4>The inverse bind pose transformation</h4>
<p>There&#8217;s still one thing in the image above, that has to be clarified: the 2nd input of <code>GetJointTransform (Skeleton)</code>, which gets the <em>inverse</em> of the initial, <em>unanimated</em> joint transformations. This is, what in literature is referred to as the <em>Inverse Bind Pose Transformation (IBP)</em>. The IBP holds information about the <em>bind pose</em> - the skeleton&#8217;s pose in the moment, the skin weights of a geometry are defined.</p>
<p>In our example, the skeleton&#8217;s initial pose, and the model&#8217;s initial pose match up, so the IPB is just the inverse of the &#8220;still standing&#8221; skeleton. Sometimes, this is not the case, e.g. if you use the same skeleton for different meshes. If you are using a mesh you imported from an external source, the IBP should be delivered by the importer.</p>
<p><center><br />
<object width="640" height="480"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=11739587&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=11739587&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="480"></embed></object></center></p>
<h4>A word on software skinning</h4>
<p>Although using a shader effect for deforming geometry is definitly the common way to go, in certain cases you have to calculate the vertex positions on the CPU. This is, e.g. if your character rig exceeds the current hardware limits of 60 joints or 4 influences, or if you need the transformed vertex positions for further processing. In that case you can use the <code>SkinDeformer (Skeleton)</code>, which basically does the same calculation as the Skinning vertex shader effect. However, instead of GPU calculation, <code>SkinDeformer (Skeleton)</code> works on the CPU, and returns the deformed vertices as vector spread, which then can run into a vertex buffer, or can be used however you want.</p>
<h4>What to do in the future</h4>
<p>Besides being very slow, <code>AutoSkinWeights (Skeleton)</code> only performs rigid skinning, which results in un-smooth deformation in joint regions. This might be ok for prototyping and in the cases, the result should look noisy anyway. But for more advanced projects, <code>AutoSkinWeights (Skeleton)</code> should also provide a soft skinning algorithm. Using <em>heat maps</em> as proposed in section 4 of <a href="http://www.mit.edu/~ibaran/autorig/">Automatic Rigging and Animation of 3D characters</a> looks promising.</p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2010/05/12/skinning-with-vvvvs-character-animation-nodes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Character animation in VVVV</title>
		<link>http://quasipartikel.at/2010/05/12/character-animation-in-vvvv/</link>
		<comments>http://quasipartikel.at/2010/05/12/character-animation-in-vvvv/#comments</comments>
		<pubDate>Wed, 12 May 2010 11:41:09 +0000</pubDate>
		<dc:creator>Matthias</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[character animation]]></category>

		<category><![CDATA[vvvv]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=462</guid>
		<description><![CDATA[As my weapon of choice, the visual programming environment <a href="http://www.vvvv.org">VVVV</a> provides a huge amount of functionality in the area of multimedia and 3D computer graphics - all accessible in a nice non-textual programming environment. While there exist several ways of manipulation 3D geometry in VVVV, right now there are no explicit methods for doing character animation.
So, this project (which was topic of my diploma thesis) aims to create an API, which introduces the terms of character animation to the world of VVVV. In this article I'm giving a little introduction of the developed nodes, and how to use them.]]></description>
			<content:encoded><![CDATA[<h4>Installation</h4>
<p>The nodes have been developed using VVVV version 40beta23, and are therefore only tested with that version. First, download the nodes here: <a href="http://sagishi.zive.at/vvvvwiki/Skeleton.zip">Skeleton.zip</a>. Just place the files contained in the zip into the plugins-directory of you VVVV folder. Note, that you need Microsoft .NET Framework 2.0 and SlimDX installed, to use the nodes.</p>
<p>Alternatively, you can checkout the latest version of the sourcecode from the VVVV plugin repository on Sourceforge:</p>
<p><code>http://vvvv.svn.sourceforge.net/svnroot/vvvv/plugins/c#/Skeleton/SkeletonNodes/trunk</code><br />
and<br />
<code>http://vvvv.svn.sourceforge.net/svnroot/vvvv/plugins/c#/Skeleton/SkeletonInterfaces/trunk</code></p>
<p>That should be it, let&#8217;s go, create some skeletons.</p>
<h4>But before we start &#8230;</h4>
<p>&#8230; let&#8217;s talk about some terms we will use from now on, quickly. For character animation in computer graphics, the most commonly used metaphor is binding <em>skeletons</em> to a geometry. A skeleton consists of <em>joints</em>, which can be animated. Animating joints ultimatly leads to animating the bound geometry accordingly.</p>
<p><em>Joints</em> are arranged in a tree structure, beginning with the root joint (which might be somewhere around a characters belly, for example). Every joint can have child joints (e.g. fingers are children of the wrist), and most of the joints have one parent joint (e.g. the elbow&#8217;s parent is the shoulder). The position of a specific joint relative to its parent joint in &#8220;unanimated&#8221; pose is defined by the <em>Base Transformation</em>. The transformation, which describes the movement of a joint (e.g. raising the arm) is refered to as <em>Animation Transformation</em>. Both terms, &#8220;Base Transformation&#8221; and &#8220;Animation Transformation&#8221; are not commonly used in computer graphics, but only have been introduced here, to distinguish between a) describing a skeleton&#8217;s shape and b) defining a skeleton&#8217;s animation, respectivly. There may be other, more suitable terms for those two transformations.</p>
<h4>One last thing &#8230;</h4>
<p>In the screenshots below, a certain window is used to display skeletons and visualize how the nodes work. Don&#8217;t get confused, if you haven&#8217;t seen it yet in VVVV, because it comes from the <code>SelectJoint</code> node, which is described below. It just comes very handy for debugging and viewing skeletons.</p>
<h4>Oh, i forgot: the <code>Skeleton</code> type</h4>
<p>To be able to pass skeletal information from one VVVV node to another, the &#8220;type&#8221; <code>Skeleton</code> has been introduced. Most of the nodes described below will have such a <code>Skeleton</code> pin as in- or output.</p>
<h4>I guess we can start: creating skeletons</h4>
<p>One way of using character rigs in VVVV of course is importing them from an external 3D modelling package like Maya. This can be done easily by using the <a href="http://www.vvvv.org/tiki-index.php?page=COLLADA&#038;highlight=collada">Collada Importer</a> provided by VVVV. Another approach is creating the skeleton data inside VVVV. There are two ways of doing that: a <em>spread-based</em> and a <em>graph-based</em> way, both having advantages and disadvantages.</p>
<p>Using the node <code>CreateJoint (Skeleton)</code> is the way to go, if you wish to create skeletons based on spreads - for example if you want a dynamic skeleton, with an arbitrary number of joints (which you actually might not even know), and arbitrary topology. It takes spreads of data, one slice for each joint, and outputs a <code>Skeleton</code>-object based on this. This is an example of how you would use <code>CreateJoint (Skeleton)</joint>:</p>
<div id="attachment_431" class="wp-caption aligncenter" style="width: 690px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/createjoint.png" alt="Barchart Original Terminology" title="Barchart Original Terminology" class="size-full wp-image-431" /><p class="wp-caption-text">The use of CreateJoint to dynamically create a straight skeleton. Joints are defined by its joint names, which have to be unique. The topology of the skeleton is defined by every joint's parent joint. The parent of 'joint1' is 'joint0', the parent of 'joint2' is 'joint1', and so on. Every joint is translated 2 units and rotated slightly to its parent joint.</p></div>
<p>If you&#8217;d like to create some skeleton, which is more specific and static in terms of its underlying structure, e.g. a human skeleton, you might prefer the graph-based approach using the node <code>Joint (Skeleton Join)</code>. In contrast to its spread-based brother, this node doesn&#8217;t take spreads as input, but only one value per input. In the most simple case, the output of <code>Joint (Skeleton Join)</code> is a <code>Skeleton</code>-object, which contains one single joint. Because this alone isn&#8217;t any fun at all, such a <code>Skeleton</code>-object can flow into another <code>Joint (Skeleton Join)</code>-node, which makes it the child of another joint. This way, the skeleton&#8217;s topology is defined by the vvvv graph. Take a look at this example to finally understand, what I&#8217;m trying to say:</p>
<div id="attachment_517" class="wp-caption aligncenter" style="width: 541px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/joint2.png" alt="Creating a skeleton using the &lt;code&gt;Joint (Skeleton Join)&lt;/code&gt; node. Every node creates a sub-skeleton, which again is assigned to other ones. The bottom most &lt;code&gt;Joint&lt;/code&gt; node outputs the complete skeleton of the hand. Here, the skeleton&#039;s topology is defined by the VVVV graph topology." title="joint2" width="531" height="531" class="size-full wp-image-517" /><p class="wp-caption-text">Creating a skeleton using the <code>Joint (Skeleton Join)</code> node. Every node creates a sub-skeleton, which again is assigned to other ones. The bottom most <code>Joint</code> node outputs the complete skeleton of the hand. Here, the skeleton's topology is defined by the VVVV graph topology.</p></div>
<h4>Moving single joints</h4>
<p>Alright, now that we have created our skeleton, animating it would make sense. This is simply done by passing our brandnew <code>Skeleton</code>-object through a <code>SetJoint (Skeleton)</code> node. Although typical setter-nodes in VVVV usually manipulate single slices of a spread, <code>SetJoint (Skeleton)</code> works in a similar way. It manipulates single joints of a skeleton, selected through a selector pin.</p>
<p>Using this node, you can set most of a joint&#8217;s properties - you can even change its parent joint (Which is not tested very well yet, by the way). But the most common way of using <code>SetJoint (Skeleton)</code> is setting the <em>Animation Transform</em> pin, which ultimatly leads to a movement of a specific joint.</p>
<div id="attachment_519" class="wp-caption aligncenter" style="width: 526px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/setjoint.png" alt="Animating joints using the &lt;code&gt;SetJoint (Skeleton)&lt;/code&gt; node. The &#039;elbow&#039; joint is selected through the selector pin. The joint is rotated by setting its &lt;em&gt;animation transformation&lt;/em&gt; property. Note, how there come up multiple different &quot;poses&quot; inside the patch." title="setjoint" width="516" height="561" class="size-full wp-image-519" /><p class="wp-caption-text">Animating joints using the <code>SetJoint (Skeleton)</code> node. The 'elbow' joint is selected through the selector pin. The joint is rotated by setting its <em>animation transformation</em> property. Note, how there come up multiple different 'poses' inside the patch.</p></div>
<h4>Selecting joints</h4>
<p>As you can see in the previous image, you need to know a joint&#8217;s name to be able to edit it with the <code>SetJoint (Skeleton)</code> node. This might be ok, if you get the joint name from somewhere programatically anyway. If you want to explicitly select a specific joint, e.g. your character&#8217;s shoulder, you don&#8217;t want to mess with the correct spelling, and prefer a visual way of selecting instead. This is, where the <code>SelectJoint (Skeleton)</code> node comes into play. It provides a window, which displays a skeleton in its current pose, and enables you to select specific joints by clicking them. <code>SelectJoint (Skeleton)</code> outputs the names of the selected joints. Besides selecting, this node is also very useful for debugging, and viewing animations - just as in the screenshots above.</p>
<div id="attachment_524" class="wp-caption aligncenter" style="width: 405px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/selectjoint.png" alt="Selecting Joints using the &lt;code&gt;SelectJoint (Skeleton)&lt;/code&gt; node. The names of the joints, which are selected by clicking them inside the editor window, are returned by the node." title="selectjoint" width="395" height="282" class="size-full wp-image-524" /><p class="wp-caption-text">Selecting Joints using the <code>SelectJoint (Skeleton)</code> node. The names of the joints, which are selected by clicking them inside the editor window, are returned by the node.</p></div>
<h4>Animating on a higher level</h4>
<p>Ok, moving single joints might be enough for waving a character&#8217;s arm or make it nod. But for more complex animations, or in your overall program logic, you don&#8217;t want to deal with single joints all the time. Instead, you want to talk about &#8220;poses&#8221; and &#8220;animations&#8221;, which should be triggerd in certain situations. To be able to work in such kind of way, the nodes <code>InputMorph (Skeleton)</code> and <code>MixPose (Skeleton)</code> are very useful.
<p><code>InputMorph (Skeleton)</code> works similar to the <code>InputMorph (Value)</code> node. It is used to interpolate through a series of poses by modulating an input value. This is very useful to morph from one pose to another - and therefore can be used to work in a way oftenr refered to as &#8220;pose-to-pose animation&#8221;.</p>
<div id="attachment_530" class="wp-caption aligncenter" style="width: 610px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/inputmorph.png" alt="Interpolating through a series of poses. The &lt;code&gt;SetJoint (Skeleton)&lt;/code&gt; nodes define four key poses of a simple walk cycle. The &lt;code&gt;InputMorph (Skeleton)&lt;/code&gt; nodes create intermediate poses, based on the input value on the left most side." title="inputmorph" width="600" height="650" class="size-full wp-image-530" /><p class="wp-caption-text">Interpolating through a series of poses. The <code>SetJoint (Skeleton)</code> nodes define four key poses of a simple walk cycle. The <code>InputMorph (Skeleton)</code> nodes create intermediate poses, based on the input value on the left most side.</p></div>
<p><code>MixPose (Skeleton)</code> like <code>InputMorph (Skeleton)</code> interpolates multiple poses and returns a result pose. In contrast to <code>InputMorph (Skeleton)</code> it doesn&#8217;t have one modulating value, but one for each incoming pose. This modulating value defines, to which extend the according input pose is expressed in the final result pose.</p>
<div id="attachment_527" class="wp-caption aligncenter" style="width: 591px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/mixpose.png" alt="Combining two poses or animations using the &lt;code&gt;MixPose (Skeleton)&lt;/code&gt; node. For each input pose, the amount of expression in the resulting pose can be defined." title="mixpose" width="581" height="751" class="size-full wp-image-527" /><p class="wp-caption-text">Combining two poses or animations using the <code>MixPose (Skeleton)</code> node. For each input pose, the amount of expression in the resulting pose can be defined.</p></div>
<p><code>InputMorph (Skeleton)</code> works like a <em>cross fader</em>, <code>MixPose (Skeleton)</code> like <em>line faders</em> between single poses, if you want to.</p>
<h4>Applying animations</h4>
<p>So far we only viewed the results of our animations via <code>SelectJoint (Skeleton)</code>&#8217;s editor window, but didn&#8217;t output anything in any kind of renderer. First thing you will need are the global, compiled transformations of each joint. All transformations we dealt with until now were local transformations inside the joint&#8217;s space. However, to get a joint&#8217;s <em>global</em> transformation in world space, we need something, that &#8220;sums up&#8221; all local transformations in a joint chain. This is done by the node <code>GetJointTransform (Skeleton)</code>. It takes an animated skeleton as an input, and outputs the compiled transformations of the joints, which are selected by the selector pin (leave the selector pin empty, to get all joints).</p>
<div id="attachment_537" class="wp-caption aligncenter" style="width: 627px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/skinning_example11.png" alt="A humanoid skeleton created inside a subpatch. The joint positions in world space are computed by the &lt;code&gt;GetJointTransform (Skeleton)&lt;/code&gt; node." title="skinning_example11" width="617" height="442" class="size-full wp-image-537" /><p class="wp-caption-text">A humanoid skeleton created inside a subpatch. The joint positions in world space are computed by the <code>GetJointTransform (Skeleton)</code> node.</p></div>
<p>Having the global transformations, you can use them e.g. to kind of &#8220;assign&#8221; objects to joints, say, if your character consists of boxes. Also, you can use the information of the joint&#8217;s world position to accomplish some kind of collision detection, and so on. Finally, the compiled transformations are necessary for skinning, which will be explained in the next article.</p>
<h4>Known Issues</h4>
<p>There are still a lot of issues with the nodes described above. I set up quick bug tracker at <a href="http://sagishi.zive.at/bugs">sagishi.zive.at/bugs</a>, where there are listed upcoming tasks to do. It&#8217;s public, so feel free to add issues, if you want to give feedback. However, some of the major issues are:</p>
<ul>
<li><strong>Constraints (or joint limits):</strong> In the initial implementation there has been a way of setting constraints for each joint, to define, how far, and aroun which axes a joint can move. However, this has been in combination with saving joint rotations as euler angles. In the meantime, those euler angles have been replaced with quaternions. I haven&#8217;t stumbled upon a simple way of defining limits for quaternion rotations - any hints very much appreciated.</li>
<li><strong>Performance:</strong> There&#8217;s definitly a lot of potential in improving performance. When several <code>InputMorph (Skeleton)</code> nodes are connected in serial, framerate drops. This is caused by the fact, that the whole chain of nodes has to recalculate complete skeletons, as soon es only one joint changes. There is need of a smarter way to handle this.</li>
<li><strong>Inverse kinematcis</strong> would be awesome.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2010/05/12/character-animation-in-vvvv/feed/</wfw:commentRss>
		</item>
		<item>
		<title>In search of a suitable object model for describing charts</title>
		<link>http://quasipartikel.at/2010/05/04/in-search-of-a-suitable-object-model-for-describing-charts/</link>
		<comments>http://quasipartikel.at/2010/05/04/in-search-of-a-suitable-object-model-for-describing-charts/#comments</comments>
		<pubDate>Tue, 04 May 2010 10:00:33 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[Webscience]]></category>

		<category><![CDATA[infovis]]></category>

		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=424</guid>
		<description><![CDATA[When looking at various charting libraries I usually see the developers using concepts like Series, Categories, Axis, etc.
For some reason I've always had troubles wrapping my head around those concepts in order to 'think' in those terms.]]></description>
			<content:encoded><![CDATA[<p>I suppose these notations were taken intuitively because most people have a visual picture in mind when they think of a chart.<br />
However, I&#8217;m tempted to find an alternative object model that describes arbitrary data in the first place and graphical representation afterwards. This would allow to just pass arbitrary data and let the chart implementation decide (or at least suggest) which plot type fits the data best.</p>
<h3>The old school</h3>
<p>Let&#8217;s take Highcharts as a prominent example using the described ordinary naming pattern:</p>
<pre><code>
  var chart1 = new Highcharts.Chart({
  	chart: {
  		defaultSeriesType: 'column'
  	},
  	title: {
  		text: 'Fruit Consumption By Fruit'
  	},
  	xAxis: {
  		categories: ['Apples', 'Oranges', 'Pears', 'Bananas', 'Plums']
  	},
  	series: [{
  		name: 'Jane',
  		data: [3, 2, 1, 3, 4]
  	}, {
  		name: 'John',
  		data: [2, 3, 5, 7, 6]
  	}, {
  		name: 'Joe',
  		data: [4, 3, 3, 9, 0]
  	}]
  });

</code></pre>
<p>That&#8217;s how the rendered result looks like:</p>
<div id="attachment_431" class="wp-caption aligncenter" style="width: 690px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/barchart_original.png" alt="Barchart Original Terminology" title="Barchart Original Terminology" width="680" height="335" class="size-full wp-image-431" /><p class="wp-caption-text">Barchart Original Terminology</p></div>
<p><br/></p>
<p>We can identify the following objects:</p>
<h4>Series</h4>
<p>Represents a series of data points usually having one (x value) or two dimensions (x, y values).</p>
<h4>Category</h4>
<p>A category specifies labels for all data points at a certain index. We can see five data points per series in the example, which are labeled with &#8216;Apples&#8217;, &#8216;Oranges&#8217;, etc.</p>
<h4>Axis</h4>
<p>Describes either an x-Axis or y-Axis of a plot. Sometimes there are even more than one x-Axes or y-Axes.<br />
That&#8217;s where things become complicated. Often the results become confusing because of different scales for one direction at the same time.</p>
<h3>The proposal</h3>
<p>Okay here&#8217;s a proposal of a more data-centric less graphic-centric object model.</p>
<h4>Group</h4>
<p>Groups like categories are used to distinguish different kinds of data points (Apples/Oranges/Pears or Male/Female). Nothing special. Each data point must be assigned to a group (if there are groups at all).</p>
<h4>Measure</h4>
<p>A measure describes an arbitrary numeric property that can be visualized in some way. It holds a list of data points</p>
<p>That&#8217;s all.</p>
<p>Of course there&#8217;s no information about the graphical representation. But I think this should be separated. It&#8217;s just another layer of abstraction. And I was told abstraction is always a good thing in computer science ;—)</p>
<p>A complete visualization workflow would look like as follows:</p>
<ul>
<li>Initialize the chart by passing some data (groups and measures)</li>
<li>Ask the chart (respectively the user) which plot types (bar, line, scatter, pie) are available for the data provided</li>
<li>Specify plotting options that are relevant for the currently selected plot type</li>
</ul>
<p>Let&#8217;s look at an example:</p>
<pre><code>
  $('#chart1').chart({
  	groups: ['Apples', 'Oranges', 'Pears', 'Bananas', 'Plums'],
  	group_assignments: [0, 1, 2, 3, 4],
  	measures: [{
  		name: 'Jane',
  		data: [3, 2, 1, 3, 4]
  	}, {
  		name: 'John',
  		data: [2, 6, 5, 5, 6]
  	}, {
  		name: 'Joe',
  		data: [4, 3, 3, 6, 9]
  	}],
  	plotOptions: {
  		defaultplotType: 'bar',
  		chartTitle: 'Fruit Consumption By Fruit'
  	}
  });

</code></pre>
<div id="attachment_433" class="wp-caption aligncenter" style="width: 690px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/barchart_new.png" alt="Barchart Proposed Terminology" title="Barchart Proposed Terminology" width="680" height="335" class="size-full wp-image-433" /><p class="wp-caption-text">Barchart Proposed Terminology</p></div>
<p><br/><br />
I just replaced the term Categories with Groups. This 1D data (is it really 1D?) example is a special case where each data point of a measure belongs to one group. So the <em>group_assignments</em> option is redundant in this case and can be left out.</p>
<p>However the benefit of this alternative object model becomes more obvious if we are looking at 2D data, which is represented as Points (x, y values) in the common old school format.</p>
<pre><code>
  var chart = new Highcharts.Chart({
     chart: {
        defaultSeriesType: 'scatter',
     },
     title: {
        text: 'Height Versus Weight of 507 Individuals by Gender'
     },
     xAxis: {
        title: {
           text: 'Height (cm)'
        },
     },
     yAxis: {
        title: {
           text: 'Weight (kg)'
        }
     },
     series: [{
        name: 'Female',
        color: 'rgba(223, 83, 83, .5)',
        data: [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6]]

     }, {
        name: 'Male',
        color: 'rgba(119, 152, 191, .5)',
        data: [[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8]]
     }]
  });

</code></pre>
<div id="attachment_434" class="wp-caption aligncenter" style="width: 690px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/scatterplot_original.png" alt="Scatterplot Original Terminology" title="Scatterplot Original Terminology" width="680" height="355" class="size-full wp-image-434" /><p class="wp-caption-text">Scatterplot Original Terminology</p></div>
<p><br/><br />
Again we can describe the data using Groups and Measures:</p>
<pre><code>
$('#chart1').chart({
   groups: ['Male', 'Female'],
   group_assignments: [0,0,0,0,0,1,1,1,1,1],
   measures: [{
     name: 'Height (cm)',
     data: [161.2, 167.5, 159.5, 157.0, 155.8, 174.0, 175.3, 193.5, 186.5, 187.2]
   }, {
     name: 'Weight (kg)',
     data: [51.6, 59.0, 49.2, 63.0, 53.6, 65.6, 71.8, 80.7, 72.6, 78.8]
   }],
   plotOptions: {
 		defaultplotType: 'scatter',
 		chartTitle: 'Height Versus Weight of 10 Individuals by Gender'
   }
});
</code></pre>
<p><div id="attachment_435" class="wp-caption aligncenter" style="width: 690px"><img src="http://quasipartikel.at/wp-content/uploads/2010/05/scatterplot_new.png" alt="Scatterplot Proposed Terminology" title="Scatterplot Proposed Terminology" width="680" height="355" class="size-full wp-image-435" /><p class="wp-caption-text">Scatterplot Proposed Terminology</p></div><br />
<br/><br />
As you see measures are always series of numbers (it&#8217;s just 1D). If you want to render a scatter plot you&#8217;d probably take the first measure, assign it to the x-Axis, and use the second measure for the y-Axis. 2D. Finally. Since you can pass arbitrary many measures you can specify infinitely many dimensions. It&#8217;s up to you how to visualize them ;—) You may use the dot size of each data point to visualize a 3rd dimension. The group assignments option assigns each data point to a group so we can outline them accordingly.</p>
<p>Using the proposed (generic) object model it&#8217;s easier to pass arbitrary data to the chart. After this has been done, the chart itself can tell its available plotting options (e.g. Barplot, Lineplot for one measure/group etc.).</p>
<p>I don&#8217;t have much theoretical background in statistics and data visualization. However this is just what came to my mind and feels natural to me. I&#8217;m going to change the API of the <a href="http://github.com/michael/chart">charting library</a> I&#8217;m working on to fit the proposed model.</p>
<p>What are your thoughts about this topic? Can this work out? Am I missing something? I&#8217;d really love to have some discussion. Even the naming needs to be discussed — I&#8217;m not sure about &#8216;Groups&#8217; and &#8216;Measures&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2010/05/04/in-search-of-a-suitable-object-model-for-describing-charts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Quadratic bezier curves for Processing.js</title>
		<link>http://quasipartikel.at/2010/01/07/quadratic-bezier-curves-for-processingjs/</link>
		<comments>http://quasipartikel.at/2010/01/07/quadratic-bezier-curves-for-processingjs/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 01:56:25 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[canvas]]></category>

		<category><![CDATA[processing.js]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=397</guid>
		<description><![CDATA[Since Processing and respectively Processing.js don't support quadratic curves, you are forced to construct them with a conventional cubic bezier curve. I've never used bezier curves before, so I took this as a lesson.]]></description>
			<content:encoded><![CDATA[<p>I came up at least with an implementation for quadraticBezierVertex(cpx, cpy, x, y), which you can use to create shapes.</p>
<p><script src="http://gist.github.com/270898.js?file=gistfile1.js"></script></p>
<p>You can put this code into a .lib file and import() it into your sketch to add support for quadratic curves to <a href="http://www.processingjs.org">Processing.js</a>.</p>
<p>The actual reason I created this was the need for flexible rounded rectangles, which don&#8217;t look smart unless you use quadratic curves for the corners. Because it&#8217;s a shape based on a path you can modify <em>fill</em> and <em>stroke</em> as usual.</p>
<p><script src="http://gist.github.com/270899.js?file=gistfile1.java"></script></p>
<p>Finally here&#8217;s the result. I&#8217;m using a stroke weight of 2 pixels and a 10 pixel radius for the rounded corners.</p>
<p><canvas id="quadraticcurve" class="wp-caption" datasrc="/js/quadraticcurve.pjs" width="400" height="150"></canvas></p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2010/01/07/quadratic-bezier-curves-for-processingjs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Etage 12900</title>
		<link>http://quasipartikel.at/2009/12/08/etage-12300/</link>
		<comments>http://quasipartikel.at/2009/12/08/etage-12300/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 17:29:11 +0000</pubDate>
		<dc:creator>Matthias</dc:creator>
		
		<category><![CDATA[Arty]]></category>

		<category><![CDATA[visuals]]></category>

		<category><![CDATA[vvvv]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=279</guid>
		<description><![CDATA[Last April I played a VJ-set at the closing event of vienna's <a href="http://www.soundframe.at/">sound:frame</a> festival at the Fluc Wanne. Now i finally managed to patch up some documentation about the content I built especially for this event.]]></description>
			<content:encoded><![CDATA[<p>I wanted to take a different approach to what I usually do: instead of combining various smaller <a href="http://vvvv.org">VVVV</a>-Effects, I created an entire new scenario featuring an endlessly high tower, providing various elements and sites, which appear during the time of the show. This approach is very much inspired by the audiovisual show <strong>Orbit</strong> by <strong>AV</strong>, which i saw on last year&#8217;s <a href="http://node08.vvvv.org/">Node08-Festival</a> in Frankfurt.</p>
<p>Evolving shapes and camera movement are controlled by audio events on the one hand, and my NintendoDS featuring the <a href="http://ndsvisuals.zive.at">NDSVisuals-Project</a> on the other hand.</p>
<p><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage186_web.png" alt="etage186_web" title="etage186_web" width="696" height="261" class="aligncenter size-full wp-image-347" /></p>
<p><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage116_web.png" alt="etage186_web" title="etage186_web" width="696" height="261" class="aligncenter size-full wp-image-347" /></p>
<p>The video below is a 2-min-overview of what potentially would happen &#8212; the actual colors usually depend on my current mood :). Watch it on the <a href="http://vimeo.com/8405276">Vimeo Site</a> for better quality. Additionally, there are some screenshots of the running VVVV-patch below.</p>
<p><center><br />
<object width="400" height="225"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=8405276&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=8405276&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="225"></embed></object><br />
</center></p>
<p><br/><br/><br />

<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage106_web/' title='etage106_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage106_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage186_web/' title='etage186_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage186_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage19_web/' title='etage19_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage19_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage26_web/' title='etage26_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage26_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage39_web/' title='etage39_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage39_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage76_web/' title='etage76_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage76_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage101_web/' title='etage101_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage101_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage107_web/' title='etage107_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage107_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage109_web/' title='etage109_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage109_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage110_web/' title='etage110_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage110_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage112_web/' title='etage112_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage112_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage116_web/' title='etage116_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage116_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage130_web/' title='etage130_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage130_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage150_web/' title='etage150_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage150_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage158_web/' title='etage158_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage158_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage165_web/' title='etage165_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage165_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage198_web/' title='etage198_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage198_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage255_web/' title='etage255_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage255_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage218_web/' title='etage218_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage218_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
<a href='http://quasipartikel.at/2009/12/08/etage-12300/etage238_web/' title='etage238_web'><img src="http://quasipartikel.at/wp-content/uploads/2009/12/etage238_web-150x150.png" width="150" height="150" class="attachment-thumbnail" alt="" /></a>
</p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2009/12/08/etage-12300/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Motion Tweening for Processing.js</title>
		<link>http://quasipartikel.at/2009/11/30/motion-tweening-for-processingjs/</link>
		<comments>http://quasipartikel.at/2009/11/30/motion-tweening-for-processingjs/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 19:00:42 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[Webscience]]></category>

		<category><![CDATA[infovis]]></category>

		<category><![CDATA[javascript]]></category>

		<category><![CDATA[processing.js]]></category>

		<guid isPermaLink="false">http://quasipartikel.at/?p=218</guid>
		<description><![CDATA[Creating animations in Processing.js can be a quite hard and repetitive job. Having a simple library for animating graphical objects probably makes the ambitious animator's life easier.]]></description>
			<content:encoded><![CDATA[<p>Due to usability improvements to <a href="http://askken.heroku.com">ASKKEN™</a> I had to add some animations. However creating animations by hand turned out to be a quite hard and repetitive job. I soon realized that I need some abstraction for managing animations in a smart way.</p>
<p>Since I don&#8217;t have much experience in the animation business, I did some research and found a really good introduction to <a href="http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf">Motion Tweening</a> by Robert Penner.<br />
I also found an existing library for Processing called <a href="http://www.megamu.com/processing/shapetween/">Shapetween</a>. However, I favoured the approach Robert Penner takes for his ActionScript Motion Tweening Library. Letting a Motion Tween directly manipulate properties on objects totally makes sense to me (at least for Processing.js). </p>
<p>Fortunately Philippe Maegerman has already put together a <a href="http://jstween.blogspot.com/#TweenEasing">Javascript version</a> of Robert Penner&#8217;s tweening library. So all I had to do is adapting the code for use with Processing.js.</p>
<p>Here&#8217;s what I came up with:</p>
<h4>Motion Tweening</h4>
<p><canvas id="tween" class="wp-caption" datasrc="/js/tween1.pjs" width="400" height="150"></canvas></p>
<p>This first example shows the application of two different Tweens for manipulating x and y coordinates of the graphical object. Please click on the canvas to start/restart the Tween. </p>
<p><script src="http://gist.github.com/245489.js?file=motiontween.js"></script></p>
<p>The code for this example is quite simple. Two Tween objects are created and bound to the object (most often &#8220;this&#8221;) and property that should be manipulated. You also specify start and end values, the desired easing function and the Tween&#8217;s duration (in seconds). </p>
<p>An easing function thereby  is a mathematical function used to transform data. Provided a number between 0 and 1, an easing function will return a number usually between 0 and 1 corresponding to the nature of that function.</p>
<p>There are a couple of easing functions to choose from:</p>
<ul>
<li>Tween.backEaseIn</li>
<li>Tween.backEaseOut</li>
<li>Tween.backEaseInOut</li>
<li>Tween.elasticEaseIn</li>
<li>Tween.elasticEaseOut</li>
<li>Tween.elasticEaseInOut</li>
<li>Tween.bounceEaseOut</li>
<li>Tween.bounceEaseIn</li>
<li>Tween.bounceEaseInOut</li>
<li>Tween.strongEaseInOut</li>
<li>Tween.regularEaseIn</li>
<li>Tween.regularEaseOut</li>
<li>Tween.regularEaseInOut</li>
<li>Tween.strongEaseIn</li>
<li>Tween.strongEaseOut</li>
<li>Tween.strongEaseInOut</li>
<li>&#8230; more to come</li>
</ul>
<h4>Color Tweening</h4>
<p>But Tweening is not restricted to motion. You can use the same approach to change a color over time.</p>
<p><canvas id="tween" class="wp-caption" datasrc="/js/tween2.pjs" width="400" height="150"></canvas></p>
<p>In this example the blue level of a colored object is tweened from 255 downto 0 within two seconds.</p>
<p><script src="http://gist.github.com/245490.js?file=colortween.js"></script></p>
<h4>In the wild</h4>
<p>Additionally here&#8217;s the result of my animated donut chart, which will be integrated in the next version of <a href="http://askken.heroku.com">ASKKEN™</a>. It makes heavy use of Tweens.</p>
<p><canvas id="tween" class="wp-caption" datasrc="/js/donut.pjs" width="400" height="400"></canvas></p>
<p>You can find a dedicated demo page at <a href="http://quasipartikel.at/donut">http://quasipartikel.at/donut</a> and get the source code from <a href="http://github.com/donut">Github</a>.</p>
<h4>Finally</h4>
<p>There&#8217;s a dedicated <a href="http://quasipartikel.at/tween/">demo</a> for the tweening library as well. And *surprise* you can get the source code at <a href="http://github.com/michael/tween">Github</a>. Well, I have to put some more documentation to the example page.</p>
<p>Please let me know what you think. There’s so much room for ideas and improvements.<br />
I’d be happy to get your feedback. If you’d like to contribute, I’d be even happier.</p>
]]></content:encoded>
			<wfw:commentRss>http://quasipartikel.at/2009/11/30/motion-tweening-for-processingjs/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

