<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4455594986753745785</id><updated>2011-11-20T07:07:02.695-08:00</updated><category term='scenejs'/><category term='roadmaps'/><title type='text'>Lindsay Stanley Kay</title><subtitle type='html'>ALERT: A Java developer has escaped the domed city and has been seen working with JavaScript</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-3549730956688443801</id><published>2010-03-02T02:53:00.000-08:00</published><updated>2010-03-02T11:48:21.385-08:00</updated><title type='text'>SceneJS boundingBox Nodes</title><content type='html'>SceneJS V0.7.0 now has &lt;b&gt;boundingBox&lt;/b&gt; nodes, which specify the spatial boundaries of scene graph subtrees so that the subtrees are only traversed when their enclosing boundingBoxes intersect the current view frustum. When configured with a projected size threshold for each child, they can also function as &lt;b&gt;level-of-detail&lt;/b&gt; (LOD) selectors.&lt;br /&gt;&lt;br /&gt;Before I show you how to define them, take a look at this demo in which an array of objects are wrapped in LOD boundingBoxes so that they are each represented as cubes at the lowest level, then as spheres at the next level, then as teapots at the highest level:&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/194YJ3AAO9M&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/194YJ3AAO9M&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;To define a boundingBox that functions as both a frustum-culler and a LOD selector, configure it with both an axis-aligned boundary and a &lt;b&gt;levels&lt;/b&gt; parameter like so:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/319409.js?file=scenejs-boundingbox-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;This boundingBox will select exactly one of its child nodes to traverse for its current projected size, where the levels parameter specifies for each child the size threshold above which the child becomes selected. No child is selected (nothing is drawn) when the projected size is below the lowest level.&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;No automatic generation of boundingBoxes (or boundingBox hierarchies) is provided in V0.7.0. &amp;nbsp;That's a tricky problem that will require some head-scratching. There's nothing stopping the scene-creation process (ie. exporter script or human) from creating hierarchies in the mean time, however.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Efficiency&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Best case&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;SceneJS's view frustum is calculated from the combined View and Projection matrices using the &lt;a href="http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf"&gt;technique by Grib and Hatmann&lt;/a&gt;, so the boundingBox's optimal case is when there are no modelling transform nodes (ie. rotate, scale, translate) above it, where its specified axis-aligned boundary can be tested directly against the frustum with no transformation.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next-best case&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If there is a model transform node, then the axis-aligned boundary is converted to an oriented bounding box (ie. of six 3D coordinates), which is transformed by the Model matrix, then converted back to an axis-aligned box for testing against the frustum.&lt;br /&gt;&lt;br /&gt;If the model transform is statically configured (by a parameter object and not by a function), then the boundingBox can just memoize and then subsequently re-test the axis-aligned box against the frustum.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Worst case&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When a higher model transform is dynamically configured, then the boundingBox must assume that the model matrix will change. In such case it will always recreate the oriented box coordinates, transform those, convert them to an axis-aligned box, then and test that against the frustum. &lt;br /&gt;&lt;br /&gt;The moral of the story is: &lt;b&gt;don't use boundingBoxes for large quantities of moving things&lt;/b&gt;. However, they are awesome for bounding static scene content and should be used liberally for the best case.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-3549730956688443801?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/3549730956688443801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/03/scenejs-boundingbox-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3549730956688443801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3549730956688443801'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/03/scenejs-boundingbox-nodes.html' title='SceneJS boundingBox Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-1736393289409875809</id><published>2010-02-23T15:31:00.000-08:00</published><updated>2010-03-15T04:34:21.278-07:00</updated><title type='text'>Custom SceneJS Shader Nodes</title><content type='html'>&lt;b&gt;Update March 16, 2010&lt;/b&gt;: This feature, the SceneJS.shading node, has been removed from SceneJS V0.7.0, which now automatically generates GLSL shaders internally, fitted to current scene state (number of lights, textures etc) as required by geometry elements. For efficiency, the shaders are cached for re-use among geometries that share scene state, each shader mapped against a hash code derived from the scene state. The benefit is that GLSL is now entirely encapsulated within SceneJS. Consequently, the SceneJS.shader node will be removed from the API.&lt;br /&gt;&lt;br /&gt;Therefore, I snuck back here and deleted this article. &lt;br /&gt;&lt;br /&gt;Thank you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-1736393289409875809?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/1736393289409875809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/custom-scenejs-shader-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/1736393289409875809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/1736393289409875809'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/custom-scenejs-shader-nodes.html' title='Custom SceneJS Shader Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-4952559197877398252</id><published>2010-02-23T14:23:00.000-08:00</published><updated>2010-02-23T15:16:04.077-08:00</updated><title type='text'>Extending SceneJS Nodes</title><content type='html'>&lt;b&gt;SceneJS  V0.7.0 gives you more control over extending SceneJS nodes.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The scene definition API is functional, so what we really do when we "extend a node" is wrap an invocation to its function with a new function. So far we've been able to do simple extensions, such as how people have been extending the geometry node:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/312763.js?file=scenejs-simple-node-extension.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Note that V0.7.0 renames SceneJs to SceneJS - sorry about that, I know the grief that kind of thing causes - check the release notes for any more of that.&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;Note that we are ignoring any arguments passed to our new node, which is fine when your new node expects no parameters or child nodes.&lt;br /&gt;&lt;br /&gt;If we wanted to pass arguments through to the wrapped node, we could do this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/312788.js?file=scenejs-extend-node-passthrough-arguments.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That doesn't accomplish much however - what we normally want to do is insert a few special parameters into the wrapped node.&lt;br /&gt;&lt;br /&gt;For that, V0.7.0 provides a new utility function, SceneJS._utils.extendNodeArgs, that can intercept the parameters argument and add new members as required. Here's how to extend the shader node to create your own shader:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/312780.js?file=scenejs-extend-node-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Oh no, not again! V0.7.0 renames some of the scene nodes for a more declarative feel - in this case "shader" became "shading".&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;Here are the general cases for how we might invoke our new node:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;myNewShading()&lt;/li&gt;&lt;li&gt;myNewShading(node, node..)&lt;/li&gt;&lt;li&gt;myNewShading({ vertexShaders: [ ... ] }, node, node..)&lt;/li&gt;&lt;li&gt;SceneJS.rotate(function(scope) { return { vertexShaders : [ ... ] }; }, node, node..)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;In Cases (1) and (2), extendNodeArgs is going to insert the new parameters into the front of the argument array (which is empty in Case 1). Case (3) has a parameters object, which extendNodeArgs is going to augment with the "type" and "fragmentShaders" members, without replacing the existing "vertexShaders". &lt;br /&gt;&lt;br /&gt;Case (4) has one of those nifty parameterisation functions that allows you to dynamically parameterise a node during scene-traversal. These functions pull parameters from a data scope that is being passed down through the graph (see the official examples for how that works). For this case, extendNodeArgs is going to augment the result returned by the parameterisation function.&lt;br /&gt;&lt;br /&gt;Confused? Well so was I for a bit when I wrote this and I don't expect you to be &lt;a href="http://en.wikipedia.org/wiki/Joe_90"&gt;Joe 90&lt;/a&gt;, so I'll be updating the examples with some templates for you to follow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-4952559197877398252?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/4952559197877398252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/extending-scenejs-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/4952559197877398252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/4952559197877398252'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/extending-scenejs-nodes.html' title='Extending SceneJS Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-2569990825635899108</id><published>2010-02-09T14:52:00.000-08:00</published><updated>2010-03-18T15:02:45.857-07:00</updated><title type='text'>SceneJS Logger Nodes</title><content type='html'>SceneJS V0.7.0 now lets you plug &lt;b&gt;logger&lt;/b&gt; nodes into your scene graphs to catch errors, warnings and debug information from nodes that have something to say (such as &lt;a href="http://lindsaystanleykay.blogspot.com/2010/02/scenejs-error-management-and-logging.html"&gt;complaints from assets and textures when they time out&lt;/a&gt;). Take a look at this example:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/299775.js?file=scenejs-logging-node-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;SceneJS always sets up a default logger that pops up alerts for errors and warnings, which you can replace for the whole scene graph by defining your own logger node close to the root of the scene graph. The default alerts are a little pushy, but at least they get your attention! &lt;br /&gt;&lt;br /&gt;In this example I'm just that logger it with the same functionality just to show how it's done.&lt;br /&gt;&lt;br /&gt;But here I'm also inserting a couple more loggers to show to to override logging for selected portions of the scene graph. In this hypothetical case, we have a couple of nodes that are being a real pain to debug, so we're making life easier by focusing some logging around those, with specially-prefixed messages.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Logging to Webpage&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;SceneJS V0.7.0 provides a specialised logger that logs to a DIV in the page. Use it like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/336910.js?file=scenejs-logging-to-page.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;If you omit the elementId, it will look for an element identified as "_scenejs-default-logging". That's so that when you show off your examples in the Playroom they will be able to find the logging element there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-2569990825635899108?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/2569990825635899108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-logger-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/2569990825635899108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/2569990825635899108'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-logger-nodes.html' title='SceneJS Logger Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-1414445116256697948</id><published>2010-02-09T14:21:00.000-08:00</published><updated>2010-02-09T14:21:37.326-08:00</updated><title type='text'>SceneJS Error Management and Logging</title><content type='html'>&lt;b&gt;Texture and asset nodes no longer fail silently!&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;For V0.7.0, scene processes are now managed with a timeout.&amp;nbsp;Timed-out processes are reaped after each scene traversal; each process thats been running too long is destroyed, a message is logged, and its timeout callback is called.&lt;br /&gt;&lt;br /&gt;This is super handy for asynchronously loading resources, such as assets and textures. Let's look at assets.&lt;br /&gt;&lt;br /&gt;When an &lt;b&gt;&lt;a href="http://lindsaystanleykay.blogspot.com/2010/01/collada-parser-for-scenejs.html"&gt;asset&lt;/a&gt;&lt;/b&gt; node is first visited during scene traversal, it fires off a request to a server for a fragment of scene graph (an "asset"). It uses JSONP, which as we know does not tell us much when things go wrong - JSONP inserts a script tag into the DOM that pulls in the remote script &amp;nbsp;- if the asset cannot be found then nothing much happens.&lt;br /&gt;&lt;br /&gt;The asset node starts an asynchronous process that will return the asset's scene fragment to it if and when it successfully arrives. Since the transaction is asynchronous and some other node of the scene graph is likely to be currently under traversal, the asset node will just saves a reference to the fragment at that point. Then, when it is next visited, it will connect the fragment as a child and directs traversal down into it. However if the asset hasn't loaded by the time it's next visited, it will just pass traversal on through to the next node.&lt;br /&gt;&lt;br /&gt;If the asset never loads, the user may never realise since the asset node will never do anything.&lt;br /&gt;&lt;br /&gt;This is where a timeout-managed process is handy. On starting an asset request, the asset node starts a new process,configured with a timeout of (maybe) 60 seconds and a callback to fire in the event of it timing out. Then the asset allows traversal to continue on to the next node. After each scene traversal, SceneJS reaps currently active processes that have timed out. For each of those it logs an error with the new logger backend and calls the timeout, which for our asset node cause it to flag itself as "errored"&amp;nbsp;so that it won't keep trying to load the asset.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-1414445116256697948?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/1414445116256697948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-error-management-and-logging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/1414445116256697948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/1414445116256697948'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-error-management-and-logging.html' title='SceneJS Error Management and Logging'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-2045971449194445601</id><published>2010-02-09T13:33:00.000-08:00</published><updated>2010-02-09T13:44:45.711-08:00</updated><title type='text'>SceneJS Memory Management Ninjitsu</title><content type='html'>My mission is to have SceneJS never run out of memory.&lt;br /&gt;&lt;br /&gt;SceneJS currently manages three kinds of resource in video RAM:&amp;nbsp;shaders,&amp;nbsp;geometry and&amp;nbsp;textures.&amp;nbsp;Each of these have a node type, along with a backend module that does things like create, activate, deactivate and destroy them. These backends I'll call "cachers".&lt;br /&gt;&lt;br /&gt;For V0.7.0 I created a "memory manager" backend, against which cacher backends register themselves.&lt;br /&gt;&lt;br /&gt;Whenever any backend wants to allocate some resource in video RAM, it will get the memory manager to mediate the allocation, passing in a callback that will attempt the actual allocation. The memory manager will then try the callback and if no exception is thrown by it, all is good and that's that.&lt;br /&gt;&lt;br /&gt;However, if the callback throws an out-of-memory exception, the memory manager will poll each registered cacher to evict something to free up some memory in order to satisfy the request. As soon as one of the cachers has successfully evicted something, the memory manager will have another go with the &amp;nbsp;callback. It will repeat this process, polling a different cacher each time, until the callback succeeds. For fairness, the memory manager remembers the last cacher it polled, to continue with the next cacher when it needs to evict something again.&lt;br /&gt;&lt;br /&gt;The sequence diagram below shows the general deal:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.websequencediagrams.com/cgi-bin/cdraw?lz=VGV4dHVyZUJhY2tlbmQtPk1lbW9yeQAIBzogUmVnaXN0ZXIgbWUKU2hhZGVyAAYkR2VvbWV0AD4JADkdCnQAfAYtPgB9DjogQ3JlYXRlIAAZBwoAgQsfYWxsb2NhdGUoY2FsbGJhY2spCmFjdGl2YXRlIACBSA0KCgCBVw0AgWMQADcIICAodGhyb3dzIE9VVF9PRl9NRU1PUlkpIAAvEACBKA90cnlFdmljdABWEACCBQ8AHgoAgR0JAIInDwCCJiBzdWNjZXNzCmRlACkZAIFDJyhubyBleGNlcHRpb25zIACBcgVuKSAAghgRAIMSDwBuEwCCWg8&amp;amp;s=qsd" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://www.websequencediagrams.com/cgi-bin/cdraw?lz=VGV4dHVyZUJhY2tlbmQtPk1lbW9yeQAIBzogUmVnaXN0ZXIgbWUKU2hhZGVyAAYkR2VvbWV0AD4JADkdCnQAfAYtPgB9DjogQ3JlYXRlIAAZBwoAgQsfYWxsb2NhdGUoY2FsbGJhY2spCmFjdGl2YXRlIACBSA0KCgCBVw0AgWMQADcIICAodGhyb3dzIE9VVF9PRl9NRU1PUlkpIAAvEACBKA90cnlFdmljdABWEACCBQ8AHgoAgR0JAIInDwCCJiBzdWNjZXNzCmRlACkZAIFDJyhubyBleGNlcHRpb25zIACBcgVuKSAAghgRAIMSDwBuEwCCWg8&amp;amp;s=qsd" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Each cacher backend is responsible for maintaining its own eviction policy. I'm starting with the Least-Recently-Used variety, where each texture, program of geometry buffer set gets a "last used" timestamp and the one with the oldest timestamp gets evicted. &amp;nbsp;Hopefully, with this strategy SceneJS wont run out of memory, and will at worst just slow down as backends find themselves&amp;nbsp;continually having to&amp;nbsp;reload resources.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hopefully an LRU policy will capatalise on spatial coherence of scene content, where as long as the viewer doesn't teleport wildly about the scene, there will be a smooth flow of resources in and out of a working set of spatially local elements.&lt;br /&gt;&lt;br /&gt;We'll see!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-2045971449194445601?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/2045971449194445601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-memory-management-ninjitsu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/2045971449194445601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/2045971449194445601'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/02/scenejs-memory-management-ninjitsu.html' title='SceneJS Memory Management Ninjitsu'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-5555023501305003518</id><published>2010-01-31T05:14:00.000-08:00</published><updated>2010-01-31T05:55:33.684-08:00</updated><title type='text'>SceneJS Parameterised Assets</title><content type='html'>Back in V0.3.0 I introduced asset nodes, which I &lt;a href="http://lindsaystanleykay.blogspot.com/2010/01/collada-parser-for-scenejs.html"&gt;blogged about back then&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;After adding textures to V0.6.0, I started fooling around with the spiral staircase asset and realised that assets can actually be fully parameterised - which could be a rather powerful feature enabling libraries of customisable assets.&lt;br /&gt;&lt;br /&gt;In the scene graph definition, we can import a staircase asset, feeding it some custom parameters through a scope node, which sets those on a local data scope for access by the nodes within the actual asset definition:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/291056.js?file=scenejs-example-asset-import-with-params.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The result is this marbled spiral of steps:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_lkvlvpyY4oM/S2WDqZbrW3I/AAAAAAAAACE/E2iCcTVxxkA/s1600-h/spiral-staircase.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="315" src="http://4.bp.blogspot.com/_lkvlvpyY4oM/S2WDqZbrW3I/AAAAAAAAACE/E2iCcTVxxkA/s320/spiral-staircase.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And here is the asset definition, which finds all those parameters on the data scope:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/291060.js?file=scenejs-example-parameterised-asset.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Note that all those scope reads could be greatly optimised - after all, a scope will hunt all the way up to the root scope for a variable that does not exist on it. &lt;br /&gt;&lt;br /&gt;We could wrap the asset definition in a closure containing variables for the parameters, then just initialise the variables from the scope in one hit, say within the config function of that texture node, them refer to those variables in all the assets subnodes instead of repeatedly reading the scope.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-5555023501305003518?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/5555023501305003518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-parameterised-assets.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/5555023501305003518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/5555023501305003518'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-parameterised-assets.html' title='SceneJS Parameterised Assets'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_lkvlvpyY4oM/S2WDqZbrW3I/AAAAAAAAACE/E2iCcTVxxkA/s72-c/spiral-staircase.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-8137897655412986492</id><published>2010-01-27T16:17:00.000-08:00</published><updated>2010-01-28T12:36:32.916-08:00</updated><title type='text'>SceneJS Selector Nodes</title><content type='html'>My last couple of posts on SceneJS bounding volumes and textures got me thinking about levels-of-detail in SceneJS scene graphs. It would be cool, for example, to select which textures are to be applied to child nodes depending on what level of detail we want to show. Or perhaps select an appropriate geometric representation to display.&lt;br /&gt;&lt;br /&gt;Level-of-detail (LOD) or "detail culling" is a classic technique whereby we attempt to avoid rendering more than is necessary to create a nice image. Typically, it's done by taking a bounding a volume around a portion of the scene and determining its projected size within the display area. We would configure size thresholds at which different scene representations, of different levels of detail, would be rendered. So when the volume is, say, larger than 300 pixels wide we render the full detail version, when smaller than 100 pixels render medium detail, smaller than 10 render minimal detail etc.&lt;br /&gt;&lt;br /&gt;A LOD scene node would then select a child for traversal to descend into for each detail level. &lt;br /&gt;&lt;br /&gt;Often, we would only want to select between parents for some child node. Check this idea out:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/288288.js?file=scenejs-parent-selector-node-idea.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That's what this node type would do. Recall that a node has a configuration object, followed by a variable list of child nodes. The last node in the child list is the child we'll select parents for, and the preceding two child nodes in the list are the available parents to splice. The configuration selects the second parent.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-8137897655412986492?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/8137897655412986492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-selector-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/8137897655412986492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/8137897655412986492'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-selector-nodes.html' title='SceneJS Selector Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-7733860275946892835</id><published>2010-01-26T12:44:00.000-08:00</published><updated>2010-03-15T04:40:00.218-07:00</updated><title type='text'>SceneJS Bounding Nodes</title><content type='html'>Pretty soon I'm going to add boundary nodes to scenejs. Here are my current plans for those, subject to me changing my mind and sneaking back here to edit this post to make it look like I knew what I was doing all along.&lt;br /&gt;&lt;br /&gt;There will be two ways in which you can use a boundary: 1) with manually-configured extents, or 2) as a hint that you'd like one, automatically created at the desired location in the graph, expanded to enclose geometry in its subtree.&lt;br /&gt;&lt;br /&gt;I'll implement support for the use case soon and put that in a release, then leave support for the next case for a day when I've had enough Red Bull.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;Update March 16, 2010&lt;/b&gt;: &lt;a href="http://lindsaystanleykay.blogspot.com/2010/03/scenejs-boundingbox-nodes.html"&gt;&lt;span class="Apple-style-span" style="color: black;"&gt;manually configured SceneJS.boundingBox node in SceneJs V0.7&lt;/span&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;b&gt;Manually-configured extents&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The first case is easy - a manually-created boundary is configured with extents like so:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/288134.js?file=scenejs-boundary-example-with-extends.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;When a COLLADA file is converted to a SceneJS JavaScript asset, it's a cinch for the converter to slap a bounding box around it, so there's plenty of mileage there.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Boundary hints&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The second case ain't so easy. A boundary &lt;b&gt;hint&lt;/b&gt; looks like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/287180.js?file=scenejs-boundary-example1.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;It has no extents, which is an invitation for SceneJS to automatically compute them, if it can.&lt;br /&gt;&lt;br /&gt;Lets imagine what will happen within the scene traversal for this example. On visiting the boundary, SceneJS begins creating a bounding volume, set to minimal size. It also creates a new child data scope for the subtree and attaches a listener to the scope to be notified whenever data is read from the scope. If the listener fires during traversal of the subtree then the boundary will know that the subtree is not a "closed universe" in terms of data dependencies on higher nodes and cannot be counted on to always have the same geometric extents. For example, a rotation node might be taking its angle from a data scope written by a node somewhere up the tree. As long as the listener is never called, however, each geometry node is instanced into the local modelling coordinate-space of the boundary and the boundary is expanded to encompass it. However, as soon as the listener fires, the boundary permanently short-circuits itself so that it does nothing at all when visited, other pass traversal on to its child nodes, as if it was never there.&lt;br /&gt;&lt;br /&gt;This strategy will require that the modelling matrix stack be sort of forked at the boundary node. It also requires the framework user to use ONLY the SceneJS data flow mechanism to configure scene nodes (ie. not using their own global vars).&lt;br /&gt;&lt;br /&gt;A boundary node could cause all transform nodes in its subtree to memoise their local matrices for availability to gemoetries to transform themselves by for the purpose of expanding the volume. &lt;br /&gt;&lt;br /&gt;Also, it adds a bit of extra (pre)processing to the scene graph, but I think it could be quite transparent. Making it a "hint" lets me off the hook somewhat. Implementation could approach that incrementally - a first cut will follow the hint only if the subtree is totally static, with no config functions and no generators.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-7733860275946892835?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/7733860275946892835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-bounding-volumes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/7733860275946892835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/7733860275946892835'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-bounding-volumes.html' title='SceneJS Bounding Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-7162442531390230376</id><published>2010-01-21T15:50:00.000-08:00</published><updated>2010-03-15T04:49:16.290-07:00</updated><title type='text'>SceneJS GL State Nodes</title><content type='html'>I just added "renderer" nodes to SceneJS. Basically, a renderer node sets WebGL state for the nodes in its subtree. &lt;br /&gt;&lt;br /&gt;Check this early example out: &lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/283336.js?file=scenejs-renderer-idea.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;See how you can nest them. The inner one temporarily overrides everything in the outer one for its sub-nodes. Their "clear" properties indicate that we want them to clear their drawing areas (in this case bounded by scissor boxes) when visited during traversal.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;canvas&lt;/b&gt; and &lt;b&gt;viewport&lt;/b&gt; nodes are gone - they are now merged into the renderer node.&lt;br /&gt;&lt;br /&gt;See the "cullFace" property on the inner environment. To process that, SceneJS calls the WebGL's cullFace function on the active context, mapping the "frontAndBack" argument to the WebGL FRONT_AND_BACK (GL_FRONT_AND_BACK) constant. I want to expose the &lt;b&gt;functionality&lt;/b&gt; of WebGL, but not directly expose the actual WebGL API. &lt;br /&gt;&lt;br /&gt;Of course, this feature invites the scene designer to create some horribly sub-optimal scene graphs, that will cause the GPU to thrash around between states. For example: continuously enabling and disabling textures might not be so cool for optimal GPU pipelining, I'm not sure.  I guess that's where a user manual might be handy. Or perhaps the scene graph could log warnings?&lt;br /&gt;&lt;br /&gt;Anyway, this will be going into Release V0.5.0, hopefully this weekend, depending how much skateboarding I want to so as well!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-7162442531390230376?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/7162442531390230376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-environment-nodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/7162442531390230376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/7162442531390230376'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-environment-nodes.html' title='SceneJS GL State Nodes'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-3767385277695068342</id><published>2010-01-19T20:36:00.000-08:00</published><updated>2010-01-27T19:27:37.029-08:00</updated><title type='text'>Asset Imports with Backends</title><content type='html'>I just had an idea on how to extend the SceneJS asset mechanism to also provide backend plugins to support new node types within the asset. &lt;br /&gt;&lt;br /&gt;Assets are SceneJS nodes that load fragments of scene graph, defined in JavaScript, from remote locations. The fragments just evaluate straight into the scene graph with a minimal hit on frame rate. And of course, they come from trusted locations that will provide nice JavaScript that won't mess with your browser.&lt;br /&gt;&lt;br /&gt;So,to refresh your memory, an asset node looks like this:&lt;br /&gt;&lt;script src="http://gist.github.com/276561.js?file=scenejs-proxied-dae-asset-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;When visited during scene travesal, they make a request of an asset server, which responds with something like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/281594.js?file=scene-asset-response-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That's a JSONP response with a callback that will glue the asset into the scene graph. The asset is then immediately executed.&lt;br /&gt;&lt;br /&gt;What if the asset contained nodes that are not supported by the version of the SceneJS library that is running in the client, where the library doesn't have the backend plugins to support them?&lt;br /&gt;&lt;br /&gt;One solution could be for the asset node to indicate the version of the library on the client. The server knows that the client does't have the support for the asset it is about to provide, so offers the backend plugins as part of the response:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/281608.js?file=scenejs-asset-response-withbackends.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The client then checks to see it has support for "foo" and "bar" node types (ie. does it have such backends and node functions). When it doesnt, it then loads and evaluates JavaScript from the offered URI to install the support. Then it evaluates the asset.&lt;br /&gt;&lt;br /&gt;Exciting! The client only needs a core library!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-3767385277695068342?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/3767385277695068342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/asset-imports-with-backends.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3767385277695068342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3767385277695068342'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/asset-imports-with-backends.html' title='Asset Imports with Backends'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-8786828141200095758</id><published>2010-01-13T12:18:00.000-08:00</published><updated>2010-01-13T12:40:22.924-08:00</updated><title type='text'>Asset Nodes - Boundaries and Proxies</title><content type='html'>One cool thing we could do with asset nodes would be to wrap them in a &lt;span style="font-weight: bold;"&gt;boundary&lt;/span&gt; node that would only allow traversal of its children when it intersects the current view volume:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/276543.js?file=scenejs-bounded-asset-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;On intersection, the asset is visited and begins its asynchronous load of its remote asset.&lt;br /&gt;&lt;br /&gt;Speaking of which, I realised how much overhead there would be in parsing other file formats like COLLADA in the browser. Pulling in a big chunk of COLLADA and parsing all those features in the XML is going to cause a fair bit of latency in a running scene graph.&lt;br /&gt;&lt;br /&gt;I also realised that the currently-supported JavaScript format for scene assets (like the example above) actually has a high power-to-weight ratio in terms of expressiveness, and evaluates into the scene way faster than any XML conversion would.&lt;br /&gt;&lt;br /&gt;I still plan to support COLLADA assets, with XML parsing in the client. However higher priority for me now is a server-side proxy that converts COLLADA assets into SceneJS JavaScript assets.&lt;br /&gt;&lt;br /&gt;Check out this asset node:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/276561.js?file=scenejs-proxied-dae-asset-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;It asks the proxy for a COLLADA asset, the proxy then finds that COLLADA, converts it to a JavaScript scene chunk and returns that. It could also cache the JavaScript for when the same request is made in future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-8786828141200095758?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/8786828141200095758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/asset-nodes-boundaries-and-proxies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/8786828141200095758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/8786828141200095758'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/asset-nodes-boundaries-and-proxies.html' title='Asset Nodes - Boundaries and Proxies'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-6300376594414204117</id><published>2010-01-06T18:52:00.000-08:00</published><updated>2010-01-09T01:05:00.437-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scenejs'/><title type='text'>Asset Import for SceneJS</title><content type='html'>I just added the ability to load remotely-stored "assets", cross-&lt;br /&gt;domain, into a scene graph at render time. Version 0.3.0 now has this new feature.&lt;br /&gt;&lt;br /&gt;You use an asset node like this:&lt;br /&gt;&lt;script src="http://gist.github.com/272814.js?file=scenejs-asset-node-example.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The uri is the location of the asset, in this case a JSON scene fragment, and a JSONP proxy to mediate the cross-domain request for it. This example is a real existing asset, at the time of the blog post.&lt;br /&gt;&lt;p&gt;At &lt;a href="http://www.scenejs.com/"&gt;scenejs.com&lt;/a&gt; there's now an example in the Playroom that shows this  in action, and the same example in the download.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Also, you'll find a new experimental asset catalogue over there, which I'll be hacking on over the next few weeks.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Assets can potentially be stored in any format, such as COLLADA, JSON, XML etc., and you can extend SceneJS with plugins to parse various formats.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When the scene is first rendered, an 'asset' node  will make a JSONP request of a repository, which will respond with  the  asset data. The asset node will then convert the data  into a subtree of scene graph content.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The asset node's  request will always be asynchronous. This means that when SceneJS  renders the asset node, it's not going to wait for the asset to  load before continuing to render the rest of the scene.&lt;br /&gt;&lt;/p&gt;&lt;p&gt; SceneJS  will just trigger the asset's request and move on.  So if you're  rendering one frame, you wont see the asset in the image. But if  you keep rendering the scene for a few frames like in this example, as you would when animating, the asset will magically appear once loaded.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The ultimate plan with assets is to somehow use them  to pre-load bits of scene just before they fall into view, then  rely on SceneJS to flush them when they haven't been rendered  recently.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;SceneJS currently caches assets with a  max-time-inactive eviction policy.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Next, I'll start on a backend plugin to help the asset node import COLLADA assets.&lt;br /&gt;&lt;/p&gt;Whew!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-6300376594414204117?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/6300376594414204117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/collada-parser-for-scenejs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/6300376594414204117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/6300376594414204117'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/collada-parser-for-scenejs.html' title='Asset Import for SceneJS'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-3824052863815362114</id><published>2010-01-06T12:57:00.000-08:00</published><updated>2010-01-06T15:27:25.026-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scenejs'/><title type='text'>SceneJS Coolness #1</title><content type='html'>&lt;a href="http://www.scenejs.com"&gt;SceneJS&lt;/a&gt; is a JavaScript framework I just kicked off that allows you to program scene graphs on &lt;a href="webgl.org"&gt;WebGL&lt;/a&gt;, which will soon enable our favourite browsers to hook into an underlying OpenGL library and render hardware-accelerated graphics. &lt;br /&gt;&lt;br /&gt;I'm making SceneJS in my spare time, which means that I'll spend at least a day on it per week, but it's going great there's some fun demos and downloads now over at &lt;a href="http://www.scenejs"&gt;scenejs.com&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;On this blog I'll do a regular braindump on how SceneJS is going and whatever ideas I have for it.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Compact Scene Definitions&lt;/h2&gt;&lt;br /&gt;One of SceneJS sweet spots is its  functional design, which gives it a tendency towards compact,  declarative scene definitions that are quick to define and easy to read. One of my aims is to make them as short as possible, so you can just stick them into your web pages and remember what they do when you come back to look at them months later.&lt;br /&gt;&lt;h2&gt;Memoisation for Speed&lt;/h2&gt;&lt;br /&gt;Another benefit of SceneJS's  functional design is that there are many opportunities to &lt;a href="http://en.wikipedia.org/wiki/Memoization" target="_blank"&gt;memoise&lt;/a&gt; state within closures to avoid the overheads of recomputation and memory  management. A scene node is actually a &lt;a href="http://en.wikipedia.org/wiki/Higher-order_function" target="_blank"&gt;higher  order function&lt;/a&gt; that returns the actual function that will be  called during scene traversal. The node computes various things from  it's parameters, such as transformation matrices, which are then  available via closure to its product function.&lt;br /&gt;&lt;br /&gt;To use SceneJS efficiently, it's worth  knowing something about what happens internally with node memoisation.&lt;br /&gt;&lt;br /&gt;Nodes only memoise when they know  for certain that their state will never change. In the examples you'll  see how a node may be either configured statically with an object, or  dynamically with a function that will return an object each time the  node is visited. In the latter case, a node knows that it had better not  memoise anything at all because it can't assume that the output of that  config function will be constant.&lt;br /&gt;&lt;br /&gt;Some nodes need to be a bit more  clever about memoisation because either their effect on the underlying  OpenGL state machine is potentially cumulative on the effects of higher  nodes, or their internal state might be derived from the effects of  higher nodes.&lt;br /&gt;&lt;br /&gt;This is a fascinating area of  ongoing research in SceneJS and a wellspring of optimisation  opportunites.&lt;br /&gt;&lt;h3&gt;Modelling transform nodes&lt;/h3&gt;&lt;br /&gt;Lets take a look at how modelling  transform nodes (such as rotate, scale and translate) decide whether or  not they will memoise. SceneJS maintains a modelling matrix as it  traverses a scene; on entry, each of these nodes post-multiplies a  transformation onto the matrix, later restoring it again on exit,  effectively maintaining a matrix stack on the function call stack. The  matrix has a "fixed" flag which is false whenever it is currently the  product of at least one dynamically-configured modelling transform node.  When a modelling transform node sees that flag is true, it knows that  all higher modelling transform nodes are statically-configured and that,  as far as it's concerned, the modelling matrix will always have the  same value. So the first time the node is visited, it memoises the  matrix after post-multiplication to avoid recalculating it each time.  All it has to do from then on is copy into the active shader on the way  in, then replace it with the previous matrix the way out - a big win!&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/270799.js?file=scenejs-rotate-node-snapshot.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;However - you guessed it - the most  inefficient modelling transform hierarchy is one in which the root  transform is dynamically configured. This is, by the way, the rationale  for SceneJS having seperate modelling and viewing matrices - to isolate  modelling transform nodes from viewing transform nodes, which are likely  to be dynamic. It's a small hit on the GPU to allow a big gain on the  JavaScript side through memoisation.&lt;br /&gt;&lt;h3&gt;Geometry Nodes&lt;/h3&gt;&lt;br /&gt;Geometry nodes are usually static - you can generate configurations for those  with functions, but that's rather inefficient since they they may have to  recompute so things such as normal vectors each time they are visited. When they are statically configured, they can buffer their geometry as VBOs, which is cool because then you can have a set of reusable geometry primitives in fast video RAM,  forming a kind of symbol table, then instance those with modeling  transforms. Early benchmark tests instancing hundreds of buffered OpenGL  teapots at high frame rates, which then revealed JavaScript to be the major bottleneck. I'm confident that can be offset significantly with clever and adaptive memoisation.&lt;br /&gt;&lt;h3&gt;Shader Nodes&lt;/h3&gt;&lt;br /&gt;When first visited during traversal, a shader node loads a GLSL shader program into video RAM, memoises a pointer to it, then makes it active. Then, when departed from, it deactivates it again, leaving the program loaded. Then whenever the shader is visited again, all it has to do is reactivate the program.&lt;br /&gt;&lt;br /&gt;Maybe SceneJS is a little memory-hungry - I may have to have some kind of eviction policy for VBOs and shaders, and maybe some kind of preloading trick to kick in when the load on the renderer is low. Those might not be a bad idea when I end up adding bounding volume  generation later on.&lt;br /&gt;&lt;br /&gt;Well that's enough for now, in the mean time I'll try think of a few more cool things, and maybe some things that ought to be cool.&lt;br /&gt;&lt;br /&gt;Lindsay&lt;br /&gt;&lt;div id="_mcePaste" style="position: absolute; left: -10000px; top: 0pt; width: 1px; height: 1px; overflow: hidden;"&gt;&lt;br /&gt;&lt;h2 style="font-family: Verdana;"&gt;Compact Scene Definition&lt;/h2&gt;&lt;br /&gt;&lt;span style="font-family: Verdana;"&gt;One of SceneJS sweet spots is its  functional design, which gives it a tendency towards compact,  declarative scene definitions that are quick to define and easy to read.&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt;&lt;br /&gt;&lt;h2&gt;&lt;span style="font-family: Verdana;"&gt;Memoisation for Speed&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;span style="font-family: Verdana;"&gt;Another benefit of SceneJS's  functional design is that there are many opportunities to &amp;lt;a  href="http://en.wikipedia.org/wiki/Memoization"&amp;gt;memoise&amp;lt;/a&amp;gt;  state within closures to avoid the overheads of recomputation and memory  management. A scene node is actually a &amp;lt;a  href="http://en.wikipedia.org/wiki/Higher-order_function"&amp;gt;higher  order function&amp;lt;/a&amp;gt; that returns the actual function that will be  called during scene traversal. The node computes various things from  it's parameters, such as transformation matrices, which are then  available via closure to its product function. &lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt; &lt;span style="font-family: Verdana;"&gt;To use SceneJS effiently, it's worth  knowing something about what happens internally with node memoisation.&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt; &lt;span style="font-family: Verdana;"&gt;Nodes only memoise when they know  for certain that their state will never change. In the examples you'll  see how a node may be either configured statically with an object, or  dynamically with a function that will return an object each time the  node is visited. In the latter case, a node knows that it had better not  memoise anything at all because it can't assume that the output of that  config function will be constant.&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt; &lt;span style="font-family: Verdana;"&gt;Some nodes need to be a bit more  clever about memoisation because either their effect on the underlying  OpenGL state machine is potentially cumulative on the effects of higher  nodes, or their internal state might be derived from the effects of  higher nodes.&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt; &lt;span style="font-family: Verdana;"&gt;This is a fascinating area of  ongoing research in SceneJS and a wellspring of optimisation  opportunites. &lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt;&lt;br /&gt;&lt;h3&gt;&lt;span style="font-family: Verdana;"&gt;Modelling transform nodes&lt;/span&gt;&lt;/h3&gt;&lt;br /&gt;&lt;span style="font-family: Verdana;"&gt;Lets take a look at how modelling  transform nodes (such as rotate, scale and translate) decide whether or  not they will memoise. SceneJS maintains a modelling matrix as it  traverses a scene; on entry, each of these nodes post-multiplies a  transformation onto the matrix, later restoring it again on exit,  effectively maintaining a matrix stack on the function call stack. The  matrix has a "fixed" flag which is false whenever it is currently the  product of at least one dynamically-configured modelling transform node.  When a modelling transform node sees that flag is true, it knows that  all higher modelling transform nodes are statically-configured and that,  as far as it's concerned, the modelling matrix will always have the  same value. So the first time the node is visited, it memoises the  matrix after post-multiplication to avoid recalculating it each time.  All it has to do from then on is copy into the active shader on the way  in, then replace it with the previous matrix the way out - a big win!&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt; &lt;span style="font-family: Verdana;"&gt;However - you guessed it - the most  inefficient modelling transform hierarchy is one in which the root  transform is dynamically configured. This is, by the way, the rationale  for SceneJS having seperate modelling and viewing matrices - to isolate  modelling transform nodes from viewing transform nodes, which are likely  to be dynamic. It's a small hit on the GPU to allow a big gain on the  JavaScript side through memoisation.&lt;/span&gt;&lt;br style="font-family: Verdana;" /&gt; &lt;br style="font-family: Verdana;" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-3824052863815362114?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/3824052863815362114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-coolness-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3824052863815362114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/3824052863815362114'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-coolness-1.html' title='SceneJS Coolness #1'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4455594986753745785.post-822728459459045734</id><published>2010-01-06T12:56:00.000-08:00</published><updated>2010-01-06T13:17:31.523-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scenejs'/><category scheme='http://www.blogger.com/atom/ns#' term='roadmaps'/><title type='text'>SceneJS Roadmap #1</title><content type='html'>&lt;h2 style="font-family: arial;"&gt;Roadmap #1&lt;/h2&gt;    &lt;small style="font-family: arial;"&gt;By Lindsay Kay&lt;/small&gt;          &lt;div style="font-family: arial;" class="snap_preview"&gt;&lt;h3&gt;The roadmap – what’s coming up.&lt;/h3&gt; &lt;p&gt;1. &lt;strong&gt;Replace the Sylvester matrix  library&lt;/strong&gt; with a  custom module optimised for SceneJS, using such tricks as  efficient  transform post-concatenation [CYCHOSZ].&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;2. Automatic  hierarchical bounding-volume generation.&lt;/strong&gt; There’s  enough information  already in the scene graph to determine which bits  of it are static  enough to warrant an efficiency boost from bounding  volumes.&lt;/p&gt; &lt;p&gt;Internally,  the nodes can tell whether their configurations are  fixed or were  generated by a function parameter. They can therefore  determine whether  they can safely memoise internal state.  Transformation nodes, for  example, will memoise their matrices  internally if they know that their  configs and those of higher  transforms are static; they can then memoise  their matrices, knowing  that wont have to recompute them.&lt;/p&gt; &lt;p&gt;Geometry  nodes are usually static – you can generate configs for  those with  functions, but that’s rather ineffient since they then have  to recompute  normals, reload VBOs etc. each time they are visited. It’s  nice to have  a set of reusable geometry primitives buffered as VBOs,  forming a kind  of symbol table, then instance those with modelling  transforms. Early  benchmark tests instancing hundreds of buffered  OpenGL teapots at high  frame rates, and actually revealed  JavaScript-side operations, such as  the matrix math module, as the  major bottleneck.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3. Textures  nodes&lt;/strong&gt;, of course! But one thing I’d  like to do is explore ways for them  to work optimally with pipelined  GPU architectures [VO]&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4.  Vector interpolation&lt;/strong&gt; – a vectorInterpolator node  using &lt;a href="http://en.wikipedia.org/wiki/Slerp" target="_blank"&gt;spherical  linear  interpolation&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;[CYCHOSZ] Cychosz, J. M. 1990. Efficient  post-concatenation of  transformation matrices. In Graphics Gems, A. S.  Glassner, Ed. Academic  Press Professional, San Diego, CA, 476-481.&lt;/p&gt; &lt;p&gt;[VO]  Vo, G. and Reiners, D. 2006. Towards a flexible back-end for   scenegraph-based rendering systems. In Proceedings of the 4th   international Conference on Computer Graphics and interactive Techniques   in Australasia and Southeast Asia (Kuala Lumpur, Malaysia, November 29  –  December 02, 2006). GRAPHITE ‘06. ACM, New York, NY, 303-309. DOI=   http://doi.acm.org/10.1145/1174429.1174481&lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4455594986753745785-822728459459045734?l=lindsaystanleykay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lindsaystanleykay.blogspot.com/feeds/822728459459045734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-roadmap-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/822728459459045734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4455594986753745785/posts/default/822728459459045734'/><link rel='alternate' type='text/html' href='http://lindsaystanleykay.blogspot.com/2010/01/scenejs-roadmap-1.html' title='SceneJS Roadmap #1'/><author><name>Lindsay Kay</name><uri>http://www.blogger.com/profile/15789881798223137425</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_lkvlvpyY4oM/S0T3fIXNX7I/AAAAAAAAABQ/rF5kjekgrUQ/S220/lindsayk.jpg'/></author><thr:total>0</thr:total></entry></feed>
