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

<channel>
	<title>OOgtech.org</title>
	<atom:link href="http://www.oogtech.org/content/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.oogtech.org/content</link>
	<description>Tea&#039;s blog</description>
	<lastBuildDate>Sat, 13 Apr 2013 14:28:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>An anonymous crash</title>
		<link>http://www.oogtech.org/content/2013/04/12/an-anonymous-crash/</link>
		<comments>http://www.oogtech.org/content/2013/04/12/an-anonymous-crash/#comments</comments>
		<pubDate>Fri, 12 Apr 2013 15:50:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[iOS/Cocoa]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4879</guid>
		<description><![CDATA[I&#8217;ve been itching to write about something interesting (it&#8217;s been a while) but today all I&#8217;ve got is a sticky crash that bubbles up fairly anonymously in the organizer. I&#8217;m suspecting this has to do with graphic memory allocations. Found a great article about VM tracker here: http://liam.flookes.com/wp/2012/05/03/finding-ios-memory/ And a no-less-informative article from Ray Wenderlich, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been itching to write about something interesting (it&#8217;s been a while) but today all I&#8217;ve got is a sticky crash that bubbles up fairly anonymously in the organizer.</p>
<p>I&#8217;m suspecting this has to do with graphic memory allocations.</p>
<p>Found a great article about VM tracker here:</p>
<ul>
<li><a href="http://liam.flookes.com/wp/2012/05/03/finding-ios-memory/">http://liam.flookes.com/wp/2012/05/03/finding-ios-memory/</a></li>
</ul>
<p>And a no-less-informative article from Ray Wenderlich, here:</p>
<ul>
<li><a href="http://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs">http://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs</a></li>
</ul>
<p>As in the Ray Wenderlich article I see process/type as <em>unknown/unknown</em> (how elegant). However I don&#8217;t get <em>jettisoned. </em></p>
<p><em></em>Instead I get <strong>[vm]</strong> under &#8216;reason&#8217; and the statuses of my app are:</p>
<p><em>(audio) (frontmost) (resume)</em></p>
<p>So, given that texture allocations are a likely reason for memory shortage, I think I&#8217;m on the right track. Reading a stack overflow item, I also find that the number of pages used by my app at the time of crash looks dangerously similar to what I get, so if you feel worried you may be gobbling too much memory, have a look here for comparison: <a href="http://stackoverflow.com/questions/13152502/my-app-crashes-and-closes-down-and-there-is-very-little-information-as-to-why">http://stackoverflow.com/questions/13152502/my-app-crashes-and-closes-down-and-there-is-very-little-information-as-to-why</a></p>
<p>Yea that&#8217;s it for me so much for the exciting stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2013/04/12/an-anonymous-crash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ShadowCasting: 2.1 &#8211; Segment/Plane intersections</title>
		<link>http://www.oogtech.org/content/2012/11/27/shadowcasting-2-triangletriangle-shadows-a/</link>
		<comments>http://www.oogtech.org/content/2012/11/27/shadowcasting-2-triangletriangle-shadows-a/#comments</comments>
		<pubDate>Tue, 27 Nov 2012 12:37:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[geometry]]></category>
		<category><![CDATA[intersect]]></category>
		<category><![CDATA[intersection]]></category>
		<category><![CDATA[plane]]></category>
		<category><![CDATA[segment]]></category>
		<category><![CDATA[triangle]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4771</guid>
		<description><![CDATA[One simple way to evaluate the shadow cast by a triangle onto another consists in generating a &#8216;shadow volume&#8217;, using one triangle as &#8216;caster&#8217; and the other triangle as &#8216;target&#8217;. The shadow volume generated by the casting triangle consists in four planes. The first plane contains the casting triangle. The remaining planes include one edge [...]]]></description>
			<content:encoded><![CDATA[<p>One simple way to evaluate the shadow cast by a triangle onto another consists in generating a &#8216;shadow volume&#8217;, using one triangle as &#8216;caster&#8217; and the other triangle as &#8216;target&#8217;.</p>
<p>The shadow volume generated by the casting triangle consists in four planes. The first plane contains the casting triangle. The remaining planes include one edge each, and are parallel to light rays.</p>
<p>So, a method to determine which part of the target is shadowed consists in performing a CSG operation between the target and the four planes.</p>
<p>So the problem can be reduced to plane / segment intersections.</p>
<p><span style="text-decoration: underline;">Intersecting a segment and a plane</span>:</p>
<p>Intersecting a segment A,B with a plane P,n, where n is the plane&#8217;s normal and P is any point on the plane</p>
<p style="padding-left: 30px;"><em>def xSegmentPlane(A,B,P,n):</em></p>
<p style="padding-left: 60px;"><em>AB = vector(A,B)<br />
</em><em>AP = vector(A,P)</em></p>
<p style="padding-left: 60px;"><em>k = dot(n,AP) / dot(n,AB)</em></p>
<p style="padding-left: 60px;"><em>if k &lt; 0 or k &gt; 1: </em><em>return None</em></p>
<p style="padding-left: 60px;"><em>u = mul(AB,k)</em><br />
<em>X = add(A,u)</em></p>
<p style="padding-left: 60px;"><em>return X</em></p>
<p>Of course, &#8216;vector&#8217; evaluates the corresponding vector given two points, &#8216;dot&#8217; is the dot product, &#8216;add&#8217; is the sum of two vectors, &#8216;mul&#8217; multiplies a vector by a number.</p>
<p>So, the intersection test per se isn&#8217;t difficult. Annoyances will arise, however:</p>
<ul>
<li>If dot(n,AB) is zero, an error will be generated. Additionally, imprecision may arise when dot(n,AB) is near-zero. At first it appears that such imprecisions are not important, but later we will see that these imprecisions can result in &#8216;holes&#8217; in the generated geometry.</li>
<li>Likewise, imprecisions may arise when k is almost zero or one.</li>
<li>We&#8217;d like to know which side of the plane A and B are. This is given by the sign of dot(n,AP) and dot(n,BP). Theoretically, if A and B are both on the same side of the plane there will be no intersection. However, we can verify that, given the above imprecisions, the method may return an intersection with A and B (evaluating to being) on the same side, or may return no intersection even though A and B evaluate to being each on either side of the plane.</li>
</ul>
<p>So, if you read somewhere that performing CSGs is difficult, that would be one of the reasons: while the above test looks neat and simple, it does not take into account numerical inaccuracies, nor does it provide all the information we need. A better intersection test should return the following:</p>
<ul>
<li>Nothing. If the plane does not intersect the segment.</li>
<li>An intersection. If there is one. Plus, it will tell us whether the intersection is &#8216;special&#8217; (the plane touches A or B) or &#8216;ordinary&#8217; (a point along AB, different from A and B )</li>
<li>The segment itself, if the plane contains it.</li>
</ul>
<p>If we don&#8217;t take these into account, a trivial triangle/plane intersection test will result in missing or degenerate triangles.</p>
<p><em>[to be continued...]</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/11/27/shadowcasting-2-triangletriangle-shadows-a/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shadowcasting: 1 &#8211; A random introduction</title>
		<link>http://www.oogtech.org/content/2012/11/26/shadow-casting-1-in-the-middle-of-everything/</link>
		<comments>http://www.oogtech.org/content/2012/11/26/shadow-casting-1-in-the-middle-of-everything/#comments</comments>
		<pubDate>Mon, 26 Nov 2012 10:03:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[geometry]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4765</guid>
		<description><![CDATA[Designing shadow-casting methods.  A common problem between all these is the overhead involved in processing triangle/triangle (t/t) pairs. For example, to perform self shadowing over 1,000 triangles, you might process 1 million pairs. Let&#8217;s not process 1 million pairs. In context: using python; the balance is towards clarity and concision since we are not aiming [...]]]></description>
			<content:encoded><![CDATA[<p><em>Designing shadow-casting methods. </em></p>
<p><em></em><em>A common problem between all these is the overhead involved in processing triangle/triangle (t/t) pairs. For example, to perform self shadowing over 1,000 triangles, you might process 1 million pairs. </em></p>
<p><em>Let&#8217;s not process 1 million pairs.</em></p>
<p><em>In context: using python; the balance is towards clarity and concision since we are not aiming at realtime (yet).</em></p>
<p><em>There isn&#8217;t a super-abundance of zero-nonsense explanations about how to do geometry on the computer so I&#8217;ll probably open an A to Z with useful recipes.</em></p>
<p><em>The original shadow casting spike should be a pre-requisite to this article, maybe I&#8217;ll find a moment to introduce this later.</em></p>
<p>Previously I was working on a &#8216;shadow gun&#8217; casting shadow particles. I used a grid (in light view) to optimise processing. It works quite well. To cast a shadow particle, identify the grid slot you&#8217;re casting to, recover the list of candidate triangles. Before shooting rays, move the triangles to light view then, for each grid slot, list all triangles intersecting the slot (I have not verified whether using triangle bounds or actual geometry to intersect the slots would be faster).</p>
<p>Now writing a &#8216;shadow cutter&#8217;. Compared to shadow particles there may be less work (no more shooting rays) but a grid may not perform well. What bothers us here? With the grid based method each triangle may cover several slots. But, rather than asking &#8220;would a ray intersect triangles T0, T1, &#8230; &#8221; we are now asking, &#8220;would T0 intersect T1, T2, &#8230;&#8221;.</p>
<p><strong>Choosing an optimisation strategy</strong></p>
<p><span style="text-decoration: underline;">Quadtree</span></p>
<p>I tried using a quadtree to sort the input. The advantage compared to a grid would be that, we can retrieve candidates without having to search for duplicates. Each node is instantiated as follows:</p>
<ul>
<li>If MAX_DEPTH is reached, add all triangles as <em>leaves</em>.</li>
<li>Otherwise, consider the bottom-left, bottom-right, top-left, top-right quadrants implied by the current node and sort triangles accordingly to get the <em>branches</em>.</li>
<li>Triangles that do not fit into any quadrant are added to <em>leaves</em>. This disposition may be imperfect in some ways; the advantage, however, is that each triangle is represented once in the tree (no duplicates)</li>
</ul>
<div>So, what is the candidate list in this case?</div>
<div>
<ul>
<li>Start from the branch containing the input (the triangle to cast over)</li>
<li>Add all triangles under this branch.</li>
<li>Add all triangles in &#8216;ascent&#8217; (ancestors). In other words, for each ancestor, add the &#8216;leaves&#8217; that didn&#8217;t move &#8216;down the tree&#8217; (as above &#8216;triangles that do not fit&#8230;&#8217;)</li>
</ul>
<div>With a small input set, the benefit of this strategy is low. Still, it helps understanding two criteria used to evaluate optimisation strategies.</div>
</div>
<div></div>
<div>
<ul>
<li>The number of candidates per target. With a brute force approach, if we&#8217;re processing N triangles, the number of candidates per target is N/N = 1. With a somewhat representative input set, the quadtree returned ~ 1/2, ridding us of about half of the input.</li>
<li>The (average) number of &#8216;false positives&#8217; returned; if we submitted K candidates (in total) and the number of hits is H, then this is (1-H)/K.</li>
</ul>
<div>The first criterion can be used to determine whether a strategy is better than another. The second criterion is more powerful: it indicates how close we are to a &#8216;perfect&#8217; strategy.</div>
</div>
<div></div>
<div>I could determine experimentally that performance increased as the average size of triangles in the input decreased. Statistically this limits &#8216;collisions&#8217; with the grid. So, I guess the optimal input set for a quadtree (or octree etc&#8230;) would be a&#8230; point cloud.</div>
<div>Think of the quadtree as a fish net, or maybe nested fish nets: big fishes are easier to catch &#8211; unfortunately we&#8217;re trying to catch as few triangles as we can.</div>
<div></div>
<div>Extrapolating, I guess that, if the average (or mean) radius of an object (triangle, mesh&#8230;) in the input set is S &lt; K<em>small</em>, (e.g K = 0.1 or lower), then a quadtree may become somewhat effective.</div>
<div></div>
<div><strong>A work in progress</strong></div>
<div></div>
<div>That&#8217;s all for now. I&#8217;ll discuss other optimisation strategies as I investigate.</div>
<div></div>
<div><strong>Notes:</strong></div>
<div>I removed a (somewhat pedantic) discussion about integrating optimisation strategies. I&#8217;ll come back to this later, or maybe I&#8217;ll just post some code</div>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/11/26/shadow-casting-1-in-the-middle-of-everything/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blender Scripting A to Z (2.63)</title>
		<link>http://www.oogtech.org/content/2012/11/09/blender-scripting-a-to-z-2-63/</link>
		<comments>http://www.oogtech.org/content/2012/11/09/blender-scripting-a-to-z-2-63/#comments</comments>
		<pubDate>Fri, 09 Nov 2012 12:56:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blender Scripting]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4708</guid>
		<description><![CDATA[This A-Z list is a work in progress; just started :) Add a new material scene.objects.active = myObject bpy.ops.object.material_slot_add() # add a material slot to active object material = bpy.data.materials.new(&#8220;gold&#8221;) # assuming the object previously had no material slots, otherwise search for empty slot myObject.materials[0] = silver Create an object foo = bpy.data.objects.new(name=&#8221;foo&#8221;, object_data = [...]]]></description>
			<content:encoded><![CDATA[<p><em>This A-Z list is a work in progress; just started</em> :)</p>
<p><strong>Add a new material</strong></p>
<p>scene.objects.active = myObject<br />
bpy.ops.object.material_slot_add() # add a material slot to active object<br />
material = bpy.data.materials.new(&#8220;gold&#8221;)<br />
# assuming the object previously had no material slots, otherwise search for empty slot<br />
myObject.materials[0] = silver</p>
<p><strong>Create an object</strong></p>
<p><em>foo = bpy.data.objects.new(name=&#8221;foo&#8221;, object_data = data)</em><br />
<em>scene.objects.link( foo)</em></p>
<p><strong>Create a mesh</strong></p>
<p><em>mesh = bpy.data.meshes.new(&#8220;mesh&#8221;)</em></p>
<p>Populate using <em>from_pydata(vertices,edges,faces)</em>. For example:</p>
<p><em>verts = [ ( 0,0,0), (1,0,0), (1,1,0), (0,1,0) ] # a square</em><br />
<em>edges = [] # usually not needed, but, e.g. [ (0,1), (1,2), (2,3), (3,0) ]</em><br />
<em>faces = [ (0,1,2,3) ] # connecting the square corners; can use 3, 4 points or more!<br />
</em><em>mesh.from_pydata(verts, edges, faces)</em></p>
<p><strong>Duplicate an object</strong></p>
<p><span style="text-decoration: underline;">Method 1: bpy.ops.object.duplicate()</span></p>
<ul>
<li><em>bpy.ops.object.duplicate()</em> &#8211; duplicate currently selected objects (deep copy)</li>
<li><em>bpy.ops.object.duplicate( linked = True )</em> &#8211; duplicate currently selected objects (shallow copy &#8211; mesh and other properties should be shared).</li>
</ul>
<p>@see make an object the only active, selected object</p>
<p><span style="text-decoration: underline;">Method 2: create a new object and duplicate properties</span></p>
<p>The disadvantage of this is that duplicating all properties can be hard.</p>
<p>@see <em>create an object</em></p>
<p><strong>Get the current scene</strong></p>
<p style="padding-left: 30px;"><em>bpy.context.scene</em></p>
<p><strong>Get the scale (&#8216;unit&#8217;) of the current scene</strong></p>
<p style="padding-left: 30px;"><em>scene.unit_settings.scale_length</em></p>
<p><strong>Make an object the active, selected object</strong></p>
<p>Assume an object named X</p>
<p><em>for k in bpy.data.objects:</em><br />
<em>    k.select = False</em><br />
<em>X.select = True</em><br />
<em>scene.objects.active =  X</em></p>
<p><strong>Set an object&#8217;s location</strong></p>
<p><em>object.location = (x ,y ,z )</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/11/09/blender-scripting-a-to-z-2-63/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blender &#8211; Quick and dirty script integration (2.63)</title>
		<link>http://www.oogtech.org/content/2012/10/24/blender-quick-and-dirty-script-integration-2-63/</link>
		<comments>http://www.oogtech.org/content/2012/10/24/blender-quick-and-dirty-script-integration-2-63/#comments</comments>
		<pubDate>Wed, 24 Oct 2012 13:00:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blender Scripting]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[Script]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4711</guid>
		<description><![CDATA[This article is useful you want to get productive quickly with blender scripting. There are much better ways to integrate scripts. I feel *almost* embarrassed to post this. Initially, however, script integration may feel intimidating.  You&#8217;ve been toying around with the python console and/or adding quick scripts as text nodes in blender files, you wish [...]]]></description>
			<content:encoded><![CDATA[<p><em>This article is useful you want to get productive quickly with blender scripting. There are much better ways to integrate scripts. I feel *almost* embarrassed to post this. Initially, however, script integration may feel intimidating. </em></p>
<p><em>You&#8217;ve been toying around with the python console and/or adding quick scripts as text nodes in blender files, you wish to reuse your scripts, but add-on creation feels intricate? Read on.</em></p>
<p><em>However, if you&#8217;ve created a great script that you&#8217;d like to share with the community, you need to create an add-on instead (checking existing add-ons in the blender scripts folder is the way to go).</em></p>
<p><strong>Move your script to py files</strong></p>
<p>The idea here is to bypass time consuming integration steps, while retaining basic flexibility:</p>
<ul>
<li>Don&#8217;t create an add-on.</li>
<li>Don&#8217;t create a button oriented UI</li>
<li>Keep scripts in *.py files (not in a *.blend file)</li>
</ul>
<p>So, let&#8217;s say we have a script under /Users/Dick/foo.py, how can we call this from blender? The (quick and dirty) solution is to create a text node in the blender file, and add the following code:</p>
<p style="padding-left: 30px;"><em># import sys and foo modules; append our script dir to the python path</em><br />
<em>import sys, imp</em><br />
<em>sys.path.append(&#8220;/Users/Dick&#8221;)</em></p>
<p style="padding-left: 30px;"><em># import our py file as a module; reload to make sure recent changes</em><br />
<em># to the script are considered</em><br />
<em>import foo</em><br />
<em>imp.reload(foo)</em></p>
<p style="padding-left: 30px;"><em># call a function in the script file</em><br />
<em>foo.myFunction()</em></p>
<p><em></em>Then, we can invoke our script by hitting &#8216;run script&#8217; in the text window.</p>
<p>We don&#8217;t want to type these lines over and over again. So we can add them as part of the default startup file. Just do <strong>File &gt; Save User Settings</strong>.</p>
<p>Keep in mind that this will overwrite the startup file with whatever&#8217;s in your workspace (so, adding the quick and dirty &#8216;script runner&#8217; right after opening blender is a good idea).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/10/24/blender-quick-and-dirty-script-integration-2-63/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Art, Design &amp; the GPU</title>
		<link>http://www.oogtech.org/content/2012/09/26/art-design-the-gpu/</link>
		<comments>http://www.oogtech.org/content/2012/09/26/art-design-the-gpu/#comments</comments>
		<pubDate>Tue, 25 Sep 2012 19:28:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Game Design]]></category>
		<category><![CDATA[game art]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4668</guid>
		<description><![CDATA[A quick article investigating artistic constraints developing at the interface between game design and technology. One of the most basic choices in game design is camera management. Choosing to create a game in first, third person view, deciding wether cameras will be fixed or not, these are choices directly impacting processing cost (GPU time, if [...]]]></description>
			<content:encoded><![CDATA[<p><em>A quick article investigating artistic constraints developing at the interface between game design and technology.</em></p>
<p>One of the most basic choices in game design is camera management. Choosing to create a game in first, third person view, deciding wether cameras will be fixed or not, these are choices directly impacting processing cost (GPU time, if you want).</p>
<p>Put bluntly:</p>
<p style="text-align: center;"><strong><em>*** It takes very powerful hardware driving well optimised rendering engines to correctly display large amounts of painstakingly detailed artwork with a great depth of field. ***</em></strong></p>
<p>In a typical scenario not all these are available;  I orient my review towards &#8220;optimisation strategies&#8221; which directly encompass artwork and level design. The key idea is that good game art is a lot easier when designers, artists and programmers are willing to designate an area of interest. And as we&#8217;ll see, focus needn&#8217;t be constant throughout the gaming experience. So we can have everything (detailed characters, pretty environments, atmospheric scenes etc&#8230;) and do everything <em>just right</em>, but in most cases<em> we can&#8217;t have everything at the same time</em>.</p>
<p><strong>First person games</strong></p>
<p>The problem with first person cameras is that they easily develop perspectives which are deep and wide at the same time. Typically this drives savvy designers in either of two directions:</p>
<ul>
<li>Dungeons and Corridors. It is no coincidence that the first FPS games had so many dank corridors. In a best case scenario all that&#8217;s left two draw is walls, ceiling and a few NPCs.<img src="http://cache.g4tv.com/ImageDb3/295038_S/doom.jpg" alt="" width="320" height="240" /><br />
<em>(</em>Doom<em>, image found on gt4v.com)<br />
.<br />
</em>What&#8217;s more, dungeons and corridors can be mapped on a grid, so you don&#8217;t really need a level editor. Heck, you could map your levels in notepad using a fixed size font.</li>
</ul>
<ul>
<li>Foggy settings. Using fog to limit depth of field is a trick that never grows old (honest). While serious 3D programmers will look down on it, fog rarely makes a scene look bad and efficiently limits depth of field; within limits, it also produces visuals that scale down well over less hardware.<br />
This time honoured trick predates graphic cards.<br />
<img src="http://www.mobygames.com/images/shots/l/542894-ishar-legend-of-the-fortress-atari-st-screenshot-someone-is.png" alt="" /><br />
<em>(Ishar: legend of the Fortress on Atari ST &#8211; image found @ mobygames.com)</em></li>
</ul>
<p><strong>Isometric views, with or without perspective</strong></p>
<p>With first person games, we start with a problem to which we need to find solutions. In contrast, isometric views<em> </em>(forcing the camera to look 30 to 60 degrees down), are less demanding:</p>
<p><img src="http://rampantgames.com/blog/images/diablo1-320.jpg" alt="" /><br />
<em>Diablo &#8211; image found on rampantgames.com</em></p>
<p>The obvious reasons being:<br />
(1) the distance from the camera to each object is constant (or mostly constant if perspective is added).<br />
(2) here we don&#8217;t need walls everywhere (!) since the camera angle naturally restricts the view to a very small part of the map.</p>
<p>So, this is inherently a savvy approach and there is hardly an excuse for messing up (displaying low definition artwork) &#8211; since isometric views are nowhere near as lively, dynamic and complex as first person views.</p>
<p><strong>Platforms versus continuous terrain</strong></p>
<p>Platforms are an awesome device, both for game artists and level designers. In short, platforms are a game convention allowing a very idiosyncratic (meaning, specific to games) form of ellipsis: using platforms relieves everybody from the need to consider &#8216;intermediate space&#8217; that is either non playable or non interactive.</p>
<ul>
<li>Less load on the GPU</li>
<li>Easier design. Often the junior artists I work with (and myself) find it difficult to design models which aren&#8217;t self-contained. It seems that there is an implicit requirement to (mentally) break down continuous environments into separate elements, then later reverse the process and design continuities. Good platforms need visual framing yes, but that is, apparently, more straightforward.</li>
</ul>
<p>Walls may also be used to delimit playable areas. But walls increase fill (more GPU time) and create design issues &#8211; with a fixed camera for instance, the player can&#8217;t see behind walls which creates (tractable yet time consuming) problems with either first or third person views.</p>
<p>Platforms seem to work with any kind of view &#8211; isometric, first person, third person &#8211; the effect is the same. All you need (if anything) is a nice background to act as filler.</p>
<p><img src="http://blog.hartwork.org/__images/super_mario_war.png" alt="" /></p>
<p><em> Super Mario War &#8211; image found on h</em><em>artwork.org</em></p>
<p>Platforms are no worse than fog. They are a device which at times may seem cheap. In the meantime, <strong><em>platforms create wonderlands.</em></strong> Floating islands and castles (lost in the fog).</p>
<p><strong>Freeze!</strong></p>
<p>The <strong>obvious</strong> (lame) solution to warrant awesome game art is to freeze the camera. Two advantages:</p>
<ul>
<li>Everything is under control. You get the best shots and you can pre-render artwork for *hours*.</li>
<li>Your GPU programmer will resign so you can hire another artist instead (yay!)</li>
</ul>
<p>Okay, this is extreme. Still, many games take significant steps in this direction:</p>
<ul>
<li><strong>Fixed angles</strong>. Even with an isometric view, using fixed cameras (instead of a turntable style approach) will yield a significant increase in performance (and/or art quality). Also (and although some players readily dislike it) using fixed cameras affords increased usability (at the cost of additional design).</li>
<li><strong>Games on rails</strong>. They&#8217;ve been doing it since game arcades, and they&#8217;re still doing it. Putting players on a rail pushes the idea of linearity to the extreme.<br />
Non linear gameplay is a deep concept, but when it comes to media production, it is a thorny road as you&#8217;re practically scattering resources and incurring the risk of producing a lot of artwork that no single player will fully experience.<br />
Providing a linear story line and defining artwork along a clear path, to the contrary, ensures that all resources converge towards a designed gaming experience. That rail games (however shallow) still encounter concrete success is no surprise ( not convinced? lookup <em>Rage</em> &#8211; ID software! &#8211; or <em>Temple Run</em>).</li>
</ul>
<p><strong>Arenas </strong></p>
<p><strong></strong>Arenas offer a choice that is (in appearance) even more limiting than putting games on rails &#8211; with an arena based approach, the camera needn&#8217;t be fixed; since gameplay is confined to very little space, it is no longer a problem.</p>
<p>Unreal&#8217;s mobile flagship, <em>Infinity Blade,</em> is a well disguised arena game: between fights &#8216;gameplay&#8217; is on a rail &#8211; actually there&#8217;s no interaction but since the scenes aren&#8217;t pre-rendered the transition is seamless (&#8216;we&#8217;re still playing but we&#8217;re not!&#8217;). During fights the opponents do not move (oh wait, the second half of every fight takes place 3 meters forward, right?).</p>
<p>I attended a post-mortem which leaves very little doubt as to how they fit the pretty artwork into a mobile format:</p>
<ul>
<li>Use cards (somewhat-elaborate-yet-to-cut-a-long-story-short-pre-rendered-backgrounds).</li>
<li>No more than 2 characters on-screen.</li>
<li>2048 x 2048 textures, one for each character, including the complete UV unwrap (body, head, armour and weapons).</li>
</ul>
<div>Using short sequences between fights also reinforces the narrative element. It doesn&#8217;t quite add up to a great story, but it makes a world of a difference &#8211; who think of this game as a pretty Virtua Fighter?</div>
<p><strong> Multimodal interaction</strong></p>
<p>If we look at the approaches I described so far, all but arena oriented games share a common problem: how can we express characterisation when we don&#8217;t get a chance to display detailed characters in closeup?</p>
<p>So, one answer may be &#8216;using cut-scenes&#8217;; but (maybe my own bias), this tends to frame dramatisation &#8216;outside gameplay&#8217;. There is an approach, typical of JRPGs, which can give you the best of both worlds.</p>
<p><img src="http://epicagames.com/wp-content/uploads/2011/05/final-fantasy-7-translations.jpg" alt="" /></p>
<p>Yes! Regular navigation (isometric, FPS style or other) affords developing scope &#8211; the sense of being immersed in a large world &#8211; while arena based interaction (combat or conversation) allows maxing poly count and texture detail (isn&#8217;t it obvious? :D ) to reinforce characterisation.</p>
<p><img src="http://epicagames.com/wp-content/uploads/2011/05/final-fantasy-vii-gameplay1.jpg" alt="" /></p>
<p><em>(images found on epicagames.com)</em></p>
<p><strong>Conclusion</strong></p>
<p>From a technical point of view, methods are definitely available to help display (and fit into memory) beautiful vistas with a great depth of field:</p>
<ul>
<li>Mip-mapped textures</li>
<li>LoD (level of detail) nodes</li>
<li>JIT (just in time) pre-rendered backgrounds</li>
<li><em>(and more&#8230;)</em></li>
</ul>
<div>(Note, I only have generic notions about how they do <em>this </em>in realtime).</div>
<p><img src="http://s1.hubimg.com/u/5765624_f1024.jpg" alt="" width="640" height="480" /></p>
<p>The Elder Scrolls: Skyrim<em> &#8211; personal screenshot found on j-u-i-c-e.hubpages.com</em></p>
<p>Technical optimisations can be applied regardless of target hardware. What&#8217;s happening is that you keep more GPU time for drawing the foreground and I think it&#8217;s obvious even in the pretty screenshot above.</p>
<p>In the meantime, I think the approaches I described above are here to stay. Only the most ambitious projects running the latest hardware can deploy the production muscle needed to <em>do</em> <em>everything perfectly at the same time</em>. So I guess the main idea behind my article is that any project can achieve a balance between production cost, visual quality and rendering complexity.</p>
<p><em>Copyright notice: none of the images in this article were produced by me. These images belong to their respective owners.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/09/26/art-design-the-gpu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blender/Python &#8211; Bones and Curves (Blender 2.63)</title>
		<link>http://www.oogtech.org/content/2012/09/12/blenderpython-bones-and-curves-blender-2-63/</link>
		<comments>http://www.oogtech.org/content/2012/09/12/blenderpython-bones-and-curves-blender-2-63/#comments</comments>
		<pubDate>Wed, 12 Sep 2012 08:58:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blender Scripting]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Armature]]></category>
		<category><![CDATA[Bone]]></category>
		<category><![CDATA[Bones]]></category>
		<category><![CDATA[Pose]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4656</guid>
		<description><![CDATA[Bones For games, exporting bone transforms is often more efficient than exporting animation curves. Most animation data is modeled using Actions; however, data related to the current pose (for an Object using an Armature) is exposed via Object : x = D.objects['armature'] bone = x.pose.bones['root'] bone.matrix # transform bone.location # just the location. (&#8216;D&#8217; is a shortcut for bpy.data). [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Bones</strong></p>
<p>For games, exporting bone transforms is often more efficient than exporting animation curves.</p>
<p>Most animation data is modeled using <em>Action</em>s; however, data related to the current pose (for an <em>Object </em>using an <em>Armature</em>) is exposed via <em>Object </em>:</p>
<p style="padding-left: 30px;"><em>x = D.objects['armature']</em></p>
<p style="padding-left: 30px;"><em>bone = x.pose.bones['root']</em></p>
<p style="padding-left: 30px;"><em>bone.matrix # transform</em><br />
<em>bone.location # just the location.</em></p>
<p>(&#8216;D&#8217; is a shortcut for <em>bpy.data</em>).</p>
<p><strong>Actions</strong></p>
<p>In Blender 2.63, retrieve actions using:</p>
<p style="padding-left: 30px;"><em>anAction = D.actions[name]</em></p>
<p><em>Action.fcurves </em>contains animation data per channel. The grouping of fcurves (in the blender UI) is cosmetic.</p>
<ul>
<li><em>FCurve.data_path </em>refers the data being animated using a given animation curve. This could be something like &#8216;pose.bones["neck"].scale&#8217;. Several curves may use the same name (e.g. scale has 3 components so there may be 3 curves with the same data-path)</li>
<li><em>FCurve.keyframe_points</em> refers keyframes for a given curve. The main property of a Keyframe is co, which includes the time offset <em>co.x</em> (the frame) and property value <em>co.y</em></li>
</ul>
<div><em>data_path</em> does not fully identify which property of the object is being animated (e.g. for location, X, Y or Z?). for vector properties, it appears that <em>FCurve.array_index </em>identifies the component ( x &lt;=&gt; 0, y &lt;=&gt; 1, z &lt;=&gt; 2)</div>
<p><strong>References (Blender API docs)</strong></p>
<ul>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.Armature.html#bpy.types.Armature">bpy.types.O</a>bject</li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.Pose.html#bpy.types.Pose">bpy.types.Pose</a></li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.PoseBone.html#bpy.types.PoseBone">bpy.types.PoseBone</a></li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.Action.html#bpy.types.Action">bpy.types.Action</a></li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.FCurve.html#bpy.types.FCurve">bpy.types.FCurve</a></li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.Keyframe.html#bpy.types.Keyframe">bpy.types.Keyframe</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/09/12/blenderpython-bones-and-curves-blender-2-63/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Annotating animations (Blender2.6x/Python)</title>
		<link>http://www.oogtech.org/content/2012/09/03/annotating-animations-blender2-6xpython/</link>
		<comments>http://www.oogtech.org/content/2012/09/03/annotating-animations-blender2-6xpython/#comments</comments>
		<pubDate>Sun, 02 Sep 2012 22:57:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blender]]></category>
		<category><![CDATA[Blender Scripting]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Game Logic]]></category>
		<category><![CDATA[marker]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4653</guid>
		<description><![CDATA[Blender allows associating markers to a given action. This is useful to add logic to animations, for example: Label an &#8216;effect frame&#8217; for a hit animation Label a &#8216;takeoff frame&#8217; for a jump Markers can be added from the action editor in the dope sheet: M to create a marker CTRL+M to rename a marker [...]]]></description>
			<content:encoded><![CDATA[<div>Blender allows associating markers to a given action. This is useful to add logic to animations, for example:</div>
<div>
<ul>
<li>Label an &#8216;effect frame&#8217; for a hit animation</li>
<li>Label a &#8216;takeoff frame&#8217; for a jump</li>
</ul>
<div>Markers can be added from the action editor in the dope sheet:</div>
<div>
<ul>
<li>M to create a marker</li>
<li>CTRL+M to rename a marker</li>
</ul>
<div>After creating markers select &#8216;Make markers local&#8217; from the Marker menu in the dope sheet; otherwise markers are associated with the timeline instead of the current action.</div>
</div>
</div>
<p><span style="text-decoration: underline;">Python</span></p>
<p><em># get a reference to the 1st marker in action 0<br />
m = bpy.data.actions[0].pose_markers[0]</em><br />
<em>m.name # marker name</em><br />
<em>m.frame # frame for this marker </em></p>
<p><strong>References</strong></p>
<ul>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.Action.html">Action</a></li>
<li><a href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.TimelineMarker.html">TimeLineMarker</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/09/03/annotating-animations-blender2-6xpython/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blender 2.6x + XCode</title>
		<link>http://www.oogtech.org/content/2012/08/22/blender-2-6x-xcode/</link>
		<comments>http://www.oogtech.org/content/2012/08/22/blender-2-6x-xcode/#comments</comments>
		<pubDate>Wed, 22 Aug 2012 09:38:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Game Programming]]></category>
		<category><![CDATA[2.62]]></category>
		<category><![CDATA[2.63]]></category>
		<category><![CDATA[2.6x]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[Build rules]]></category>
		<category><![CDATA[Command Line]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4648</guid>
		<description><![CDATA[Earlier, I described how to integrate Blender 2.4x assets with XCode build rules. Let&#8217;s jump into the present and do the same with Blender 2.6x. Fundamentally, the solution is the same (see here). I added a new build rule with the described parameters: Matching rule *2.5x/assets/*.blend So, all 2.5x / 2.6x files go under a [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier, I described how to integrate Blender 2.4x assets with XCode build rules. Let&#8217;s jump into the present and do the same with Blender 2.6x.</p>
<p>Fundamentally, the solution is the same (see <strong><a href="http://www.oogtech.org/content/2012/03/20/4000/">here</a></strong>). I added a new build rule with the described parameters:</p>
<p><span style="text-decoration: underline;">Matching rule</span></p>
<p style="padding-left: 30px;"><em>*2.5x/assets/*.blend</em></p>
<p>So, all 2.5x / 2.6x files go under a ###/2.5x/### folder (depending on the file version, I run either Blender 2.49b or Blender 2.6x ). This rule matches a fragment of the path, so it will still work with multiple projects, e.g. :</p>
<ul>
<li>&#8230;/foobar/2.5x/assets/foo.blend,</li>
<li>&#8230;/superfungame/2.5x/assets/funasset.blend</li>
<li>(&#8230;)</li>
</ul>
<p><span style="text-decoration: underline;">Script invocation</span></p>
<p style="padding-left: 30px;"><em>/Applications/blender-2.6x/blender.app/Contents/MacOS/blender -b &#8220;${INPUT_FILE_PATH}&#8221; -P /Users/xxx/svn/blender-scripts/ox3ich/ox3ich_main.py &#8212; &#8220;$INPUT_FILE_DIR/../../build/$INPUT_FILE_BASE.blz&#8221;</em></p>
<p><em>ox3ich_main.py</em> is the script used to export assets, so maybe you&#8217;ll invoke a COLLADA export script or such.</p>
<p><span style="text-decoration: underline;">Output:</span></p>
<p style="padding-left: 30px;"><em>${INPUT_FILE_DIR}/../../build/${INPUT_FILE_BASE}.blz</em></p>
<p>This just matches the output (in script invocation, specified after &#8220;&#8211;&#8221;, note this is a custom script rule, Blender lets you pass custom parameters after &#8220;&#8211;&#8221; )</p>
<p><span style="text-decoration: underline;">Caveats</span></p>
<p>While testing remember XCode may not re-run the script unless the input file has changed (even if the previous invocation failed).</p>
<p>Blender 2.5x/2.6x has a somewhat complex script registration mechanism. When integrating with XCode, however, what tends to happen is&#8230; &#8230;nothing. So typically you have a script FOO.py, which is designed to run as a registered blender script; then you should pass a bootstrap script BAR.py to drive FOO when running Blender from cd. This is more or less what I did.</p>
<p>One more thought on this is that, all considered, if the main use of your script is exporting via cd, you don&#8217;t need to learn about script registration, you just write your export script and feed it to Blender via the command line.</p>
<p>Note: With a little trickery you can write scripts that will run on both blender 2.5x and 2.63 and later; I&#8217;ll cover the changes later. Or you can read the <a href="http://www.blender.org/documentation/blender_python_api_2_63_17/info_gotcha.html#info-gotcha-mesh-faces">NGons and tesselated faces gotcha</a> (from blender.org).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/08/22/blender-2-6x-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python &#8211; Fooling with files (part 1?)</title>
		<link>http://www.oogtech.org/content/2012/07/31/python-fooling-with-files-part-1/</link>
		<comments>http://www.oogtech.org/content/2012/07/31/python-fooling-with-files-part-1/#comments</comments>
		<pubDate>Tue, 31 Jul 2012 13:32:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.oogtech.org/content/?p=4611</guid>
		<description><![CDATA[Opiates Maybe it&#8217;s the weather; or maybe I&#8217;m bored. I was just thinking &#8211; why am I still doing all my Objective C coding with XCode? Is it that good? Meeehh. Seriously, I used to type less code. In fact I was annoyed enough with your average off the shelf IDE that I used to [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Opiates</strong></p>
<p>Maybe it&#8217;s the weather; or maybe I&#8217;m bored. I was just thinking &#8211; why am I still doing all my Objective C coding with XCode? Is it that good?<em> Meeehh.</em></p>
<p><em>Seriously, I used to type less code. In fact I was annoyed enough with your average off the shelf IDE that I used to write all my code using my own tools. While it&#8217;s gonna take more than a rain check for me to pick up ee-ide and integrate with ObjC,</em> there&#8217;s something left from this bygone era &#8211; the urge to meta-program.</p>
<p><strong>Sidekick wanted</strong></p>
<p>So putting aside the more interesting question (what do I want to analyze? What would I use meta-programming for?) I found myself wondering once again: if not java, what am I supposed to write my utilities <em>in</em>?</p>
<p>I&#8217;m pretty used to Objective C by now, but it&#8217;s not the kind of language that I want to use to write rough and ready utilities. Python comes to mind. I have this unqualified connection with Python: using it to write our blender scripts, suffering from the lack of straight OO semantics, irked by the lack of typing and compile time checking, amused by the syntactic sugar (e.g. sequences), encouraged by the no-nonsense, generous approach to standard libraries.</p>
<p>I prepared a bunch of references to skim through. I think I&#8217;ll be going old school, approaching utilities with the command line before (hopefully) integrating with XCode.</p>
<p>Yea that&#8217;s it for today. My refs are below. Just basic stuff.</p>
<p><strong>References</strong></p>
<p>Varied tutorials for working with files</p>
<ul>
<li><a href="http://www.dreamincode.net/forums/topic/81428-working-with-files-in-python/">Working with files in Python</a> (dream.in.code)</li>
<li><a href="http://www.diveintopython.net/file_handling/file_objects.html">Working with file objects</a> (diveintopython.net)</li>
<li><a href="http://python.about.com/od/simplerscripts/tp/WorkWithFiles.htm">Top 4 ways to work with files in python</a> (python.about.com)</li>
<li><a href="http://marakana.com/bookshelf/python_fundamentals_tutorial/working_with_files.html">Working with files</a> (marakana.com)</li>
<li><a href="http://www.voidspace.org.uk/python/pathutils.html">The pathutils module </a> (voidspace.org.uk)</li>
</ul>
<p>And some n00b references to run our py scripts:</p>
<ul>
<li><a href="http://beckism.com/2008/05/run_python_mac_os_x/">Run a python script in Mac OS X terminal</a> (beckism.com)</li>
<li><a href="http://www.theatreofnoise.com/2010/03/running-python-scripts-on-mac-os-x.html">Running python scripts on Mac OS X</a> (theatre of noise)</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.oogtech.org/content/2012/07/31/python-fooling-with-files-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
