<?xml version="1.0" encoding="iso-8859-1"?> <rss version="2.0"      xmlns:dc="http://purl.org/dc/elements/1.1/"     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"     xmlns:admin="http://webns.net/mvcb/"     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"     xmlns:content="http://purl.org/rss/1.0/modules/content/">  

  <channel>
     <title>PhotoRant+ is a Botzilla Blog</title>
     <link>http://www.botzilla.com/blog/</link>
     <description>Optimistically world-weary since 1994.</description>
     <dc:language>en-us</dc:language>
     <dc:creator>bjorke@botzilla.com</dc:creator>
     <dc:rights>Copyright 2013</dc:rights>
     <dc:date>2012-12-26T12:46:38-08:00</dc:date>
     <admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=2.661" />
     <admin:errorReportsTo rdf:resource="mailto:bjorke@botzilla.com"/>
     <sy:updatePeriod>hourly</sy:updatePeriod>
     <sy:updateFrequency>1</sy:updateFrequency>
     <sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>




     <item>
       <title>A Missing Holiday</title>
       <link>http://www.botzilla.com/blog/archives/000752.html</link>
       <description> For random fun, here&apos;s a little one-day-only (Halloween) splash screen that I had made for a Rift internal build back in 2009 -- before it was called Rift. Ironically, it ended up that there was no build that day!...</description>
       <guid isPermaLink="false">752@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<center><iframe width="560" height="315" src="http://www.youtube.com/embed/bESCj_E0gf4" frameborder="0" allowfullscreen></iframe></center>

<p>For random fun, here's a little one-day-only (Halloween) splash screen that I had made for a <i>Rift</i> internal build back in 2009 -- before it was called <i>Rift.</i> Ironically, it ended up that there was no build that day! So it was never used.</p><a href="http://www.botzilla.com/blog/archives/000752.html#comments" title="Comment on: A Missing Holiday">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-12-26T12:46:38-08:00</dc:date>
     </item>
      <item>
       <title>Shading</title>
       <link>http://www.botzilla.com/blog/archives/000751.html</link>
       <description> As &quot; Senior Technical Artist&quot; on Rift, my tasks often involved the creation of specialized tool software; helping non-technical people within the art dept (usually) solve specific problems; interfacing between the art, management, and engineering groups... But the part...</description>
       <guid isPermaLink="false">751@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><img alt="turner_snow_storm _hannibal_and_his_army_crossing_the_alps.jpg" src="http://www.botzilla.com/blog/archives/pix2012/turner_snow_storm _hannibal_and_his_army_crossing_the_alps.jpg" width="807" height="503" border="0" title="JMW Turner, Hannibal and his Army Crossing the Alps. Feel free to knock this out in ZBrush some time -- yet without those figures at the base, it would be so much smearing" /></p>

<p>As " Senior Technical Artist" on <a href="http://www.riftgame.com" target="new"><i>Rift,</i></a> my tasks often involved the creation of specialized tool software; helping non-technical people within the art dept (usually) solve specific problems; interfacing between the art, management, and engineering groups... But the part of my job that’s been most-visible to game players is <i>shading.</i></p>

<p>The funny thing is that while shading is visible everywhere -- <i>every</i> pixel you see is a shaded one -- shading is a hidden art, like photographic lighting. It rarely has much of a narrative representational thrust of its own. You <i>can</i> make a drawing without shading, just as you can make a photo without any effort or thought about lighting. Yet you'll be hard pressed to find an un-shaded painting (or drawing) in a gallery or museum, just as you'll rarely see photos without very deliberate lighting in those venues, or in portrait or advertising studios; or especially in films, where the creators of those media have long learned and understood the value of careful control over tone, grading, and color. Not just on one costume or in one shot, but across the whole of their dramatic/artistic enterprise.</p>

<p>In computer image creation, shading -- the assignment of colors to pixels at all levels of detail -- is usually accomplished by the use of micro-programs called "shaders." In the case of <i>Rift,</i> I wrote nearly every shader, re-wrote those I didn't initially create, or created the shader-writing software that generated the shaders.</p>

<p>The exact meaning of "shader" can be a bit squirrelly for some. Engineers may prefer to call them "streaming processor functions" because they may not be "shading" visible images at all (see <a href="http://www.gpgpu.org" target="new">Mark Harris's excellent GPGPU.org</a> for some counter-examples). Most of the time, artists use the term "shader" and "material" interchangeably. The difference between a identically-colored materials that look like chalk, or ice, or plastic, or metal, or glowing ooze? The shader.</p>

<p>Shaders and interactions between shaders are also used to create lighting effects, glows, glints, shadows, depth buffers, and more. We'll talk about them as they come along in <a href="http://www.botzilla.com/blog/archives/000750.html" target="new">this series.</a></p>

<p>In the case of <i>Rift,</i> shaders for materials (and other purposes) not only had to look great for the best, high-end computers, they also had to be "heterofunctional": they needed to work on a wide variety of different PC's and in different environments. Some players had top-drawer computers with high-dollar GPU cards, while others had rather modest hand-me-down laptops. It was important to provide the best experience possible -- both pictorially and in terms of playable frame rate -- for all of these many thousands of players, across literally hundreds of material variations.</p>

<p>To complicate matters further, nearly all material shaders needed to have working analogues that run not only in the game as shipped, but also in our art-creation tools. This meant that each material needed its own OpenGL <a href="http://developer.download.nvidia.com/shaderlibrary/webpages/cgfx_shaders.html" target="new">CgFX</a> versions for use in <a href="http://usa.autodesk.com/maya/" target="new">Maya,</a> custom preview modes for model building and animation, special DirectX versions for use in our modified <a href="http://www.gamebryo.com/" target="new">Gamebryo 2.6</a> toolchain, some experiments with <a href="http://www.chromeexperiments.com/webgl/" target="new">WebGL</a> and <a href="http://unity3d.com/" target="new">Unity,</a> and of course the various editions for player consumption at varying degrees of performance (at least two, sometimes up to five different versions).</p>

<p>As usual, the way to manage vast complexity is to bite off a little at a time and revise/polish as you go. I used to say (to steal a bit of a metaphor from.. <a href="http://www.paulgraham.com/hp.html" target="new">Paul Graham?</a> Not sure at this point, but we all steal from the best)  that we started by jumping off a cliff and I built an airplane on the way down.</p>

<p><img alt="rift-storm-legion-expansion_4_ss_l_120925153932.jpg" src="http://www.botzilla.com/blog/archives/pix2012/rift-storm-legion-expansion_4_ss_l_120925153932.jpg" width="807" height="504" border="0" title="Rift Storm Legion Promotional Image" /></p><a href="http://www.botzilla.com/blog/archives/000751.html#comments" title="Comment on: Shading">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-12-19T21:12:40-08:00</dc:date>
     </item>
      <item>
       <title>Rift&apos;s End: The Beginning</title>
       <link>http://www.botzilla.com/blog/archives/000750.html</link>
       <description><![CDATA[ Four years ago I departed a good job at NVIDIA to join a start-up games company called Trion World Network -- Trion&rsquo;s plan was to revolutionize online gaming in the US, and their stated goals were ones that I...]]></description>
       <guid isPermaLink="false">750@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<img alt="rift-bear3a.jpg" src="http://www.botzilla.com/blog/archives/pix2012/rift-bear3a.jpg" width="807" height="388" border="0" />


<p>Four years ago I departed a good job at <a
    href="http://developer.nvidia.com" target="new">NVIDIA</a> to join a start-up
games company called <a href="http://www.trionworld.com" target="new">Trion World
    Network</a> -- Trion&rsquo;s plan was to revolutionize online
gaming in the US, and their stated goals were ones that I also shared:
to create a new, innovative, more-immersive and immediate online-gaming
experience.</p>

<p>I really believe that graphics matter. That great art is
more than just simulating realism, and that it goes right to
your emotions without waiting for rational analysis. That
it&rsquo;s those emotions that bring you back again and again
to entertaining experiences, more than DPS and EXP and
leveling-up to get the next BFG. Those are just background. Beautiful, vivid imagery -- even a beautiful image of an ugly subject
-- goes right to the heart of an audience&rsquo;s mind.</p>

<p>Among
games, online ones had to that point been rather poor cousins
in the graphics and art departments, with titles like
<i>Farmville</i> and <i>World of Warcraft.</i> I&rsquo;d had
conversations with developers of other online games who
declared &ldquo;we don&rsquo;t want to do anything more than
Blizzard is doing&rdquo; -- instead of seeing a future of
ubiquitously-cheaper and more powerful machines for
entertainment, they could only see that <i>WoW</i> had
millions of subscribers &amp; thought the only way to proceed
was via a zero-sum &nbsp;&ldquo;WWWD?&rdquo; -- &ldquo;What
Would <i>WoW</i> Do?&rdquo; -- mindset.</p>

<p>Given the fact that game development cycles are now often longer
than hardware-deployment cycles (a next generation of hardware may
appear every year or so, while games to use that hardware take much
longer), this vision gap was increasingly obvious. The future was
being held back by a desire to simply repeat the successes of the
past.</p>

<p>From my evangelist/consulting role at NVIDIA, it seemed like the
shortest route to really show people what a <a
    href="http://www.nvidia.com/object/nvision08-bwotf.html" target="new">beautiful
    online game experience</a> might be like was not to advise the
established developers, but to lead by doing: to simply go and create the
future myself. And so I jumped, just hours before the stock market crash of
2008 got fully underway.</p>

<p>Two and a half years later, <a
    href="http://www.riftgame.com/" target="new"><i>Rift: Planes of Telara</i></a> opened to <a href="http://www.gamerankings.com/pc/995594-rift/index.html" target="new">rave reviews;</a> reviews that nearly always began with accolades about how great the game looked (<a href="http://www.tentonhammer.com/rift/features/review" target="new">Ten Ton Hammer:</a> Graphics 95, &ldquo;outstanding&rdquo;; <a href="http://www.escapistmagazine.com/articles/view/editorials/reviews/8795-Rift-Review" target="new">The Escapist:</a> &ldquo;One area where Rift&nbsp;definitely delivers is the graphics&rdquo;; <a href="http://www.ign.com/articles/2010/12/02/why-you-should-care-about-rift-planes-of-telara" target="new">IGN:</a> &ldquo;an undeniably gorgeous game&rdquo;; etc).</p>

<p>We continued to ramp it up for future revisions: so much so that
previewers of &nbsp;the first expansion set, <i>Rift: Storm Legion,</i>
expressed their excitement about the &ldquo;new renderer&rdquo; (there
was no new renderer, but I&rsquo;d upgraded nearly all of the lighting
and atmospherics code). When the expansion was released it received
similar critical praise, such as this <a
    href="http://gamingtrend.com/game_reviews/rift-storm-legion-review-everything-you-want-in-an-expansion/" target="new">review
    from <i>Gaming Trend:</i></a> &ldquo;[<i>Storm Legion</i> has]
<i>the best looking things in gaming, period, right now.</i>&rdquo;</p>

<p><b><i>Quest Completed! You are dead.</i></b></p>

<p>However, the executives at Trion had a very different view. In
December 2012, just a very few weeks after the release of <i>Storm
    Legion,</i> despite the superlative reception, they laid off a big chunk (most?)
of the remaining <i>Rift</i>-focused art team: forty people including
myself. If I were to speculate, the company seems to be backing away
from &ldquo;Triple-A&rdquo; content focus and moving toward licensing
deals with other production companies along with a focus on smaller,
faster-iterating projects. Less &ldquo;vision of the future of
entertainment&rdquo; and more same-ol&rsquo; game publishing.
That&rsquo;s just speculation on my part, but they&rsquo;ve certainly
reduced their ability to create top-shelf experiences like <i>Rift</i> in the
short term future. Speculation.</p>

<p>While I&rsquo;m not happy with the choices of management, I hope
<i>Rift</i> continues to find an audience -- the whole point was to
make something worth showing and sharing, a better gaming experience
than what had been offered by anyone before. The effort means nothing
if no one gets to experience the world we&rsquo;ve created.</p>

<p>I&rsquo;ve also decided to write a series here on some of the
challenges and solutions in my process of collaboratively creating and
tweaking the artwork and graphics for the game. While most of the art
department has already been publicizing their work, as in this <a
    href="http://www.polycount.com/forum/showthread.php?t=112686" target="new">Polycount
    Art Dump,</a> we were specifically forbidden from revealing
&ldquo;technical details.&rdquo; Which means that if your work is
nearly <i>all</i> technical details, well... you&rsquo;re not allowed to talk
about your work! Now I can. Watch this space.</p></body></html><a href="http://www.botzilla.com/blog/archives/000750.html#comments" title="Comment on: Rift's End: The Beginning">Comments (1)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-12-15T20:58:33-08:00</dc:date>
     </item>
      <item>
       <title>JavaScript: The Bad Parts</title>
       <link>http://www.botzilla.com/blog/archives/000749.html</link>
       <description>Web Geek Warning Last night I headed over to the Paypal/EBay offices to see a presentation by Douglas Crockford, titled Programming Styles and Your Brain I&apos;ll admit that I was a little bit skeptical about coming away with much useful...</description>
       <guid isPermaLink="false">749@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<H3>Web Geek Warning</H3>
<P>Last night I headed over to the Paypal/EBay offices to see a presentation by <a HREF="http://crockford.com/">Douglas Crockford,</A> titled <a href="http://www.meetup.com/TechXploration/events/65087252/">Programming Styles and Your Brain</a></P>


<P>I'll admit that I was a little bit skeptical about coming away with much useful information (a general rule: be cautious around tech companies that have had near-zero evolution since, oh, 1995), but in fact the debugging bits were pretty illuminating. Here are some sketchy notes:</P>

<H3>Your Brain</H3>

<P>Crockford’s lecture had about five introductory minutes of broad speculation (he's earned the right!) mixed with notes cribbed from <a href="http://www.nobelprize.org/nobel_prizes/economics/laureates/2002/kahneman-autobio.html" TARGET="new">Daniel Kahneman</A>…</P>

<UL>
<LI>Computer programs are the most complicated things humans make</LI>
<LI>Humans suck at making such things</LI>
<LI>They make mistakes</LI>
<LI>They confuse “hardly ever happens” with “never happens”</LI>
<LI>They confuse reading two threads on a  jquery forum with an education</LI>
<LI>They write in C++ when the language is not C++ (or Java, HLSL, python, Mel, Fortran…)</LI>
<LI>They mistake complex obscurantist  “cool” with professional “clear” coding</LI>
<LI>The human is almost always the limiting factor in software</LI>
<LI>Being consistent in style is the easiest way to avoid common errors (especially forms that are difficult to distinguish rom errors, which in JS are many)</LI>
<LI>Anyone can program, few can debug</LI>
</UL>

<H3>JavaScript</H3>
<P>This was the expected real bulk of the presentation, a longer not-veiled pitch for <A HREF="http://www.jslint.com/" TARGET="new">JSLint</A> and his book <A HREF="http://www.amazon.com/exec/obidos/ASIN/0596517742/wrrrldwideweb" TARGET="new">“Javascript: the Good Parts”</a> -- especially about how to avoid the bad parts:</P>

<UL>
<LI><I>Auto-semicolon closure.</I> This burns people so, so, much, and is one reason where it really does make a difference (for polyglot programmers) to get in the habit of putting the curly open-brace to the right of the if() clause on the same line, rather than on the line below – just like K&R intended.</LI>
<LI>Stupid multi-line strings that use “\” at line breaks because the parsers don’t recognize trailing spaces and the editors don’t show them.</LI>
<LI>Mistaking the scope of “var” to be block scope (like C, python, etc) – it’s function scope, so avoid declaration-inside-the-block constructions like <TT>for (var i=0;…) { … }</TT> because it won’t get declared where you think it is. I know I make this error a fair bit.</LI>
<LI>Make global variables <TT>REALLY_OBVIOUS</TT>. Since there are no macros in JS, <TT>THIS_IN_ONE_WAY</TT> (clearer than, say, Hungarian). In general avoid globals, except that you can’t because that’s how modules link (no linker). </LI>
<LI>If using immediate-invocation functions, put the final () inside the encapsulating () parens – e.g. <TT>(function() {…}());</TT> not <TT>(function() { })();</TT> – the latter wrong construction he called “dangling dog balls style.”</LI>
<LI>Avoid “==” because it does type conversion and different interpreters convert differently! Is (‘’==0) true or false? Use “===” instead, for a direct comparison.</LI>
<LI>Avoid the “switch” statement or at least be obsessively diligent about having break statement in every clause -- and having a default case.</LI>
<LI>Avoid the “with” construct. Consider: <TT>with (o) { foo=koda; }</TT><br /> does it mean:<UL><LI><TT>foo=koda;</TT></LI><LI><TT>o.foo = koda;</TT></LI><LI><TT>foo = o.koda;</TT></LI><LI><TT>o.foo = o.koda;</TT></LI></UL>??? Different interpreters DO give different results!</LI>
<LI><TT>var a = b = 0;</TT> in JS is the same as <TT>/*global */ b = 0; /*local */ var a = b;</TT> -- NOT like C.</LI>
<LI>Not only are “var” declarations hoisted to the top of the function scope, so are function declarations. So beware dependencies that are not resolved! NO ERROR WILL PRINT. Better to just put the var and function declarations at the top of the enclosing function</LI>
<LI>Avoid the “new” pseudo-class construct, not because it doesn’t work but because people often forget to write “new” and then they may accidentally trash that global class-like definition and you are hosed. Just use simple {objects}</LI>
<LI>If you have constructor functions indicate them “LikeThis()” to distinguish them from “all_other_functions()”</LI>
<LI>Avoid “++” which is a leftover from pointer arithmetic days. Just use “+=1” it’s just one more character to type, using “++” doesn’t make you more efficient, it makes you sloppy (especially when few people remember that <TT>i+=1;</TT> is not <TT>i++</TT>  -- it’s <TT>++i;</TT>)</LI>
</UL>

<H3>The Bad Parts?</H3>

<P>So how does the Javascript on Botzilla stack up? Let's just say, it's an ongoing learning process!</P>

<P>In scanning the scripts here (and at <A HREF="http://www.trionworlds.com" TARGET="new">Trion</A>), there appear to really only be a couple of idoms that I need to stamp out from my code to make the analyzer happy. What's yet to be determined is if Javascript's scoping rules will ever really make sense...</p><a href="http://www.botzilla.com/blog/archives/000749.html#comments" title="Comment on: JavaScript: The Bad Parts">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Wire Service</dc:subject>
       <dc:date>2012-06-22T14:57:51-08:00</dc:date>
     </item>
      <item>
       <title>My Portable Office</title>
       <link>http://www.botzilla.com/blog/archives/000748.html</link>
       <description> Bike Friday Pocket Rocket + Burley Travoy + Samsonite...</description>
       <guid isPermaLink="false">748@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><img alt="bjorke_travoy.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_travoy.jpg" width="807" height="405" border="0" /></p>

<p>Bike Friday Pocket Rocket + Burley Travoy + Samsonite</p>

<p><img src="http://www.botzilla.com/blog/archives/pix2012/bjorke_travoy_thumb.jpg" STYLE="display: none;"  /></p><a href="http://www.botzilla.com/blog/archives/000748.html#comments" title="Comment on: My Portable Office">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>GearHead</dc:subject>
       <dc:date>2012-06-12T08:29:19-08:00</dc:date>
     </item>
      <item>
       <title>Pescadero Phone Panoramas</title>
       <link>http://www.botzilla.com/blog/archives/000747.html</link>
       <description></description>
       <guid isPermaLink="false">747@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><img alt="bjorke_pescadero.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_pescadero.jpg" width="807"  border="0" /></p>

<p><img alt="bjorke_pesca2.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_pesca2.jpg" width="807" border="0" /></p>

<p><img alt="bjorke_pesca3.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_pesca3.jpg" width="807" border="0" /></p>

<p><img alt="bjorke_pesca4.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_pesca4.jpg" width="807" border="0" /></p><a href="http://www.botzilla.com/blog/archives/000747.html#comments" title="Comment on: Pescadero Phone Panoramas">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>fStop</dc:subject>
       <dc:date>2012-06-10T11:17:41-08:00</dc:date>
     </item>
      <item>
       <title>Black</title>
       <link>http://www.botzilla.com/blog/archives/000746.html</link>
       <description>Fluid is the new Black goes the saying of the day, but for Botzilla the main message is: get over it. By that, I mean that if the site needs to work on all possible screen sizes, for future-friendly leanings,...</description>
       <guid isPermaLink="false">746@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><a href="http://unstoppablerobotninja.com/demos/resize/fix/">Fluid is the new Black</a> goes the saying of the day, but for Botzilla the main message is: <i>get over it.</i></p>

<p>By that, I mean that if the site needs to work on all possible screen sizes, for future-friendly leanings, then: the pictures are just going to have to be small. And there's the rub for a photo site -- when the pictures are reduced to being upgraded versions of the thumbnails, not the other way 'round. This is tough, and frankly I won't give up without a fight for getting the best possible photographic presentation into place.</p>

<p>At the moment, I'm getting cozy with this little bit of CSS:</p>

<pre>img { max-width: 100%; }</pre>

<p>Which is a trick to ensure that images are resized downwards as their containers shrink.</p>

<p>The obstacle on a site like Botzilla is that most photo &lt;IMG&gt; tags have both WIDTH <i>and</i> HEIGHT properties specified, so that when displayed on a small screen, "max-width" alone doesn't get you very far -- the images don't scale uniformly down, but instead simply compress horizontally, untill they're long tall sticks.</p>

<p>JQuery to the Rescue!</p>

<p>Including this as the first line in my <tt>ready()</tt> function does the trick:</p>

<pre>$("img").removeAttr("height");</pre><a href="http://www.botzilla.com/blog/archives/000746.html#comments" title="Comment on: Black">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Wire Service</dc:subject>
       <dc:date>2012-06-06T22:52:16-08:00</dc:date>
     </item>
      <item>
       <title>Merely Coincidence</title>
       <link>http://www.botzilla.com/blog/archives/000745.html</link>
       <description> That Isaac&apos;s choice of university is also near one of the best skate parks....</description>
       <guid isPermaLink="false">745@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><img alt="bjorke_P1050806.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_P1050806.jpg" width="807" height="454" border="0" /></p>

<p>That Isaac's <a href="http://www.econ.ucsb.edu/">choice of university</a> is also near one of the best skate parks.</p><a href="http://www.botzilla.com/blog/archives/000745.html#comments" title="Comment on: Merely Coincidence">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>GrayScale</dc:subject>
       <dc:date>2012-05-31T09:31:47-08:00</dc:date>
     </item>
      <item>
       <title>Silver Efex Pro</title>
       <link>http://www.botzilla.com/blog/archives/000744.html</link>
       <description><![CDATA[ Hard to look at B&amp;W photos these days without suspecting the hand of Nik Software behind the curtain....]]></description>
       <guid isPermaLink="false">744@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><img alt="bjorke_P1060066.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_P1060066.jpg" width="807" height="454" border="0" /></p>

<p>Hard to look at B&amp;W photos these days without suspecting the hand of Nik Software behind the curtain.</p>

<p><img src="http://www.botzilla.com/blog/archives/pix2012/bjorke_P1060066_thm.jpg" STYLE="display: none;"  /></p><a href="http://www.botzilla.com/blog/archives/000744.html#comments" title="Comment on: Silver Efex Pro">Comments (0)</a></p>]]></content:encoded>
       <dc:subject></dc:subject>
       <dc:date>2012-05-30T13:27:52-08:00</dc:date>
     </item>
      <item>
       <title>All Minds Think Alike</title>
       <link>http://www.botzilla.com/blog/archives/000743.html</link>
       <description>I&apos;m a bit annoyed at the realization that my most-recent post on fiddling with HTML5 canvas in Moveable Type looks and behaves in a way that&apos;s terribly similar to the page header on the official Google blog. I must have...</description>
       <guid isPermaLink="false">743@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p>I'm a bit annoyed at the realization that my most-recent <a href="http://www.botzilla.com/blog/archives/000741.html">post on fiddling with HTML5 canvas in Moveable Type</a> looks and behaves in a way that's terribly similar to the page header on <a href="http://googleblog.blogspot.com/">the official Google blog.</a> I <i>must</i> have seen that before... we rarely know where our ideas and parts of ideas come from! Or is it merely "parallel evolution"? Still, it's not as if I'm launching a product, and hardly expect Google's IP lawyers to appear on Botzilla any time soon (hi guys).</p>

<p>And I like their "version" of the interactivity -- ONLY let the mouse have an effect when moving. Will have to check that out on a tablet.... of course, when they're creating a brand presence for a company with.. what, 30,000 employees? you would only expect that they'd take a little more time on polishing than my slice-of-a-Saturday attempt. Pat on the back, lads.</p>

<p>While not posting for a few days, I've been scraping at Botzilla's underlying CSS structure, so that I can rebuild it once more with CSS that will allow a fairly seamless multi-screen experience -- PC web or mobile phone/tablet. This has meant I've already had to update (internally) my use of jquery to use jquery-mobile, have started playing with Modernizr for those stodgy users who insist on running IE, and trying to make peace with myself over the idea that photos that I felt barely look okay 800+ pixels across will just have to be acceptable at mobile-phone sizes.</p>

<p>More to come as this gels.</p><a href="http://www.botzilla.com/blog/archives/000743.html#comments" title="Comment on: All Minds Think Alike">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Wire Service</dc:subject>
       <dc:date>2012-05-21T08:02:42-08:00</dc:date>
     </item>
      <item>
       <title>At Work</title>
       <link>http://www.botzilla.com/blog/archives/000742.html</link>
       <description></description>
       <guid isPermaLink="false">742@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<img alt="bjorke_P1060056.jpg" src="http://www.botzilla.com/blog/archives/pix2012/bjorke_P1060056.jpg" width="807" height="454" border="0" />
<a href="http://www.botzilla.com/blog/archives/000742.html#comments" title="Comment on: At Work">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>fStop</dc:subject>
       <dc:date>2012-05-17T16:11:14-08:00</dc:date>
     </item>
      <item>
       <title>791</title>
       <link>http://www.botzilla.com/blog/archives/000741.html</link>
       <description> One more for a Saturday -- see if you can push all the balls off-screen at once! (and no, it won&apos;t try to sell you car insurance) var mX791 = 400; var mY791 = 100; var gNParts791 = 17;...</description>
       <guid isPermaLink="false">741@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<canvas id="c791" width=800 height=250></canvas>

<P>One more for a Saturday -- see if you can push all the balls off-screen at once! (and no, it won't try to sell you car insurance)</P>


<script type="text/javascript">
var mX791 = 400;
var mY791 = 100;
var gNParts791 = 17;
var gPart791 = new Array();

function r255sq() { return Math.floor(Math.random()*Math.random()*255); } // cauchy

function setup_parts791(W,H) {
	var nc;
	for (var i=0; i<gNParts791; i++) {
	   var x = Math.random()*W;
	   var y = Math.random()*H;
	   var dx = 0; // 2.0-Math.random()*4.0;
	   var dy = 0; // 2.0-Math.random()*4.0;
	   var rad = 50.0+Math.random()*Math.random()*80.0;
	   var r = r255sq();
	   var g = r255sq();
	   var b = r255sq();
	   var c = "rgb("+r+","+g+","+b+")";
	   gPart791.push(new Array(x,y,dx,dy,rad,x,y,c)); // we keep the original x & y
	}
}

function advance791(Ar,W,H) {
   // simple motion for now
   var x = Ar[0];
   var y = Ar[1];
   var dx = Ar[2];
   var dy = Ar[3];
   var rad = Ar[4];
   var ox = Ar[5];
   var oy = Ar[6];
   var c = Ar[7];
   // mouse force
	var ddx = (x-mX791);
	var ddy = (y-mY791);
	var s = ddx*ddx+ddy*ddy- rad*rad*2;
	s = Math.max(1.0,s);
	var n = Math.sqrt(s);
	// s *= 150.0;
	s *= 20.0;
	ddx /= n;
	ddy /= n;
	dx += ddx/s;
	dy += ddy/s;
   // home force
	dox = (x-ox);
	doy = (y-oy);
	ddx = dox/80;
	ddy = doy/80;
	s = ddx*ddx+ddy*ddy;
	if (s> 1.0/80) {
		n = Math.sqrt(s);
		n = Math.max(n,1.0);
		ddx /= n;
		ddy /= n;
		dx -= ddx/s;
		dy -= ddy/s;
		}
   var a = dx*dx + dy*dy;
   var o = dox*dox + doy*doy;
	   x += dx;
	   y += dy;
   dx *= 0.9;
   dy *= 0.9;
   var a = new Array(x,y,dx,dy,rad,ox,oy,c);
   return a;
}

var gCv7 = undefined;

var gCount = 0;

function draw_canv791() {
	if (gCv7 == undefined)
		gCv7 = document.getElementById('c791');
	//if (gCv7) {
		if (gCv7.getContext) {
			var ctx = gCv7.getContext('2d');
			var w = gCv7.width; // 500.0;
			var h = gCv7.height; // 300.0;
			// ctx.fillStyle = "rgb(90,10,0);";
			ctx.fillStyle = "rgba(255,255,255,0.35);";
			ctx.fillRect(0,0,w,h);
			ctx.fillStyle = "rgb(0,0,0);";
			// ctx.fillText("frame "+gCount,20,20);
			gCount += 1;
			if (gPart791.length < 1) {
				setup_parts791(w,h);
			}
			ctx.strokeStyle = "rgba(20,20,20,.5);";
			ctx.lineWidth=1.0;
				ctx.beginPath();
				ctx.moveTo(mX791-4,mY791);
				ctx.lineTo(mX791+4,mY791);
				ctx.stroke();
				ctx.beginPath();
				ctx.moveTo(mX791,mY791+4);
				ctx.lineTo(mX791,mY791-4);
				ctx.stroke();
			var i;
			var j;
			var x, y, r;
			for (i=0; i<gNParts791; i++) {
				x = gPart791[i][0];
				y = gPart791[i][1];
				r = gPart791[i][4];
				ox = gPart791[i][5];
				oy = gPart791[i][6];
				ctx.strokeStyle = "rgba(230,200,160.5);";
				ctx.beginPath();
				ctx.moveTo(x,y);
				ctx.lineTo(ox,oy);
				ctx.stroke();
				ctx.fillStyle = gPart791[i][7];
				ctx.beginPath();
				// ctx.fillText("pos "+x+","+y+", r:"+r,20,40+10*i);
				ctx.arc(x,y,r,0,6.2831,false);
				ctx.fill();
			}
			for (i=0; i<gNParts791; i++) {
				gPart791[i] = advance791(gPart791[i],w,h);
			}
		}
	// } else {
		// document.write("no canvas?");
	//}
}
// $(document).ready(function() {
gRActions.push(function() {
    draw_canv791();
	$("#c791").mousemove(function(e) {
	    mX791 = e.pageX-this.offsetLeft;
	    mY791 = e.pageY-this.offsetTop;
	});
    setInterval(draw_canv791,30);
});
</script>

<P>Everything here, on the JS side, is set up using a shared array of initializer functions,
just like the previous entry on that topic.</P>

<P>Next step might be to re-cast it as SVG... amazing that SVG seems really powerful, but
compared to &lt;canvas&gt;, theres' almost no really good documentation...</P>


<IMG SRC="/blog/archives/pix2012/thumb791.jpg" STYLE="display: none;" />
<a href="http://www.botzilla.com/blog/archives/000741.html#comments" title="Comment on: 791">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-05-05T15:02:44-08:00</dc:date>
     </item>
      <item>
       <title>None of These Mean: &quot;Bikes Out of My Way!&quot;</title>
       <link>http://www.botzilla.com/blog/archives/000740.html</link>
       <description>Press for a larger view The state publishes a PDF containing the 2012 California Dept of Transportation Bicycle-Related Roadway Standards. It contained, across several pages, all of the current standards for bicycle-related signage (and much more). I&apos;ve collected the signs...</description>
       <guid isPermaLink="false">740@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<p><a href="/blog/archives/pix2012/CA-BikeSafe-2012-15-med.jpg" target="new"><img alt="CA-BikeSafe-2012-15-botz.jpg" src="http://www.botzilla.com/blog/archives/pix2012/CA-BikeSafe-2012-15-botz.jpg" width="807" height="262" border="0" /><br /><i>Press for a larger view</i></a></p>

<p>The state publishes a PDF containing the <a href="http://www.dot.ca.gov/hq/traffops/signtech/mutcdsupp/pdf/camutcd2012/Part9.pdf">2012 California Dept of Transportation Bicycle-Related Roadway Standards.</a> It contained, across several pages, all of the current standards for bicycle-related signage (and much more). I've collected the signs together here for easier web reference (fabric patterns, anyone?).</p>

<p>Note that the vague legacy "Share the Road" sign seems to be fading out, to be replaced by the much clearer "MAY USE FULL LANE." About time!</p><a href="http://www.botzilla.com/blog/archives/000740.html#comments" title="Comment on: None of These Mean: "Bikes Out of My Way!"">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>The Open Conspiracy</dc:subject>
       <dc:date>2012-05-05T11:00:43-08:00</dc:date>
     </item>
      <item>
       <title>HTML5 (&amp; JQuery) vs Moveable Type, Part 2</title>
       <link>http://www.botzilla.com/blog/archives/000739.html</link>
       <description> Following up on the previous post, here are the details on a simple way to add multiple dynamic scripts to a Moveable Type index page. Like the previous post, try using your mouse on this one! Can you slow...</description>
       <guid isPermaLink="false">739@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<canvas id="c789" width=800 height=250></canvas>

<P>Following up on the <A href="/blog/archives/000738.html">previous post,</a> here are the details on a simple way to add multiple dynamic scripts to a Moveable Type index page.</P>

<P>Like the previous post, try using your mouse on this one! Can you slow down the particles?</p>

<P>Basically, we just need to add an (initially empty) array of function references to the page templates, which we'll use to capture each blog entry's unique scripts (rather than letting them launch themselves), and then iterate on that array for the entire page, once it's loaded and ready.<p>

<script type="text/javascript">
var mX739 = 400;
var mY739 = 100;
var gNParts739 = 22;
gPart739 = new Array();

function setup_parts(W,H) {
	var nc;
	for (var i=0; i<gNParts739; i++) {
	   var x = Math.random()*W;
	   var y = Math.random()*H;
	   var dx = 2.0-Math.random()*4.0;
	   var dy = 2.0-Math.random()*4.0;
	   gPart739.push(new Array(x,y,dx,dy));
	}
	// document.write("made "+gNParts739+" particles.");
}

function advance(Ar,W,H) {
   // simple bouncing motion for now
   var x = Ar[0];
   var y = Ar[1];
   var dx = Ar[2];
   var dy = Ar[3];
	var ddx = (x-mX739)/5;
	var ddy = (y-mY739)/5;
	var s = ddx*ddx+ddy*ddy;
	var n = Math.sqrt(s);
	ddx /= n;
	ddy /= n;
	dx += ddx/s;
	dy += ddy/s;
   x += dx;
   y += dy;
   if (x<0) {
	x = -x;
	dx = -dx;
   } else if (x>W) {
	x = 2*W-x;
	dx = -dx;
   }
   if (y<0) {
	y = -y;
	dy = -dy;
   } else if (y>H) {
	y = 2*H-y;
	dy = -dy;
   }
   return new Array(x,y,dx,dy);
}

var gCv = undefined;

var gCount = 0;

function draw_canv739() {
	if (gCv == undefined)
		gCv = document.getElementById('c789');
	//if (gCv) {
		if (gCv.getContext) {
			var ctx = gCv.getContext('2d');
			var w = gCv.width; // 500.0;
			var h = gCv.height; // 300.0;
			// ctx.fillStyle = "rgb(90,10,0);";
			ctx.fillStyle = "rgba(255,255,255,0.95);";
			ctx.fillRect(0,0,w,h);
			ctx.fillStyle = "rgb(0,0,0);";
			ctx.fillText("frame "+gCount,20,20);
			gCount += 1;
			if (gPart739.length < 1) {
				setup_parts(w,h);
			}
			ctx.strokeStyle = "rgba(20,20,20,.5);";
			ctx.lineWidth=1.0;
			var i;
			var j;
			for (i=0; i<gNParts739; i++) {
				ctx.beginPath();
				ctx.arc(gPart739[i][0],gPart739[i][1],3.0,0,6.2831,false);
				ctx.stroke();
			}
			for (i=0; i<(gNParts739-1); i++) {
				for (j=i+1; j<gNParts739; j++) {
					var dx = gPart739[i][0] - gPart739[j][0];
					var dy = gPart739[i][1] - gPart739[j][1];
					var nsq = dx*dx + dy*dy;
					if (nsq<4000) {
						var v = (nsq-500)/3500;
						var v = Math.floor(v*255);
						ctx.strokeStyle = "rgb("+v+","+v+","+v+");";
						ctx.beginPath();
						ctx.moveTo(gPart739[i][0],gPart739[i][1]);
						ctx.lineTo(gPart739[j][0],gPart739[j][1]);
						ctx.stroke();
					}
				}
			}
			for (i=0; i<gNParts739; i++) {
				gPart739[i] = advance(gPart739[i],w,h);
			}
		}
	// } else {
		// document.write("no canvas?");
	//}
}
// $(document).ready(function() {
gRActions.push(function() {
    draw_canv739();
	$("#c789").mousemove(function(e) {
	    mX739 = e.pageX-this.offsetLeft;
	    mY739 = e.pageY-this.offsetTop;
	});
    setInterval(draw_canv739,30);
});
</script>

<p>I'm using jquery, so I declare the array and my <tt>$(document).ready()</tt> function like so:</P>

<pre>
var gRActions = new Array(); // initially empty array of functions...

$(document).ready(function() {
  for (var a=0; a&lt;gRActions.length; a++) {
	gRActions[a]();
  }
});
</pre>

<P>Then in each blog entry, I write the same anonymous javascript function as I might write for
<tt>$(document).ready()</tt>, but instead I just push it into <tt>gRActions:</tt></p>

<PRE>
gRActions.push(function() {
   draw_canv739();
   setInterval(draw_canv739,30);
});
</PRE>

<P>Now the page, regardless of how many blog entries it might contain, will include all of them in its page initialization. Remember also to make sure that any "global" javascript values (including function names!) in this entry, and all HTML elements like &lt;canvas&gt;, have unique names so that they won't collide with other blog entries, should they for some reason both be presented on the same HTML index page someday.</P>

<P>Also, as we've learned from the previous post: put some human-readbale text into the post <I>before</I> the scripting portion of the post, otherwise Facebook becomes confused.</p>



<!-- <IMG SRC="/photo/journal//may03e-15.jpg" STYLE="display: none;" /> -->
<a href="http://www.botzilla.com/blog/archives/000739.html#comments" title="Comment on: HTML5 (& JQuery) vs Moveable Type, Part 2">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-05-04T22:45:42-08:00</dc:date>
     </item>
      <item>
       <title>HTML5 Canvas vs Moveable Type</title>
       <link>http://www.botzilla.com/blog/archives/000738.html</link>
       <description> var mX = 0; var mY = 0; var gSpreed = 2; var gScroll = 0; var sino = function(V,W,H) { var f = 0.8*Math.sin(V/W); var hh = H/2.0; var y = hh + hh*f; return y; } function...</description>
       <guid isPermaLink="false">738@http://www.botzilla.com/blog/</guid>
       <content:encoded><![CDATA[<script type="text/javascript">


var mX = 0;
var mY = 0;
var gSpreed = 2;
var gScroll = 0;

var sino = function(V,W,H)
{
	var f = 0.8*Math.sin(V/W);
	var hh = H/2.0;
	var y = hh + hh*f;
	return y;
}

function next_loc(X,Scroll,W,H,Freq,Scale)
{
	var y = sino(Freq*(Scroll+X),W,H);
	var dx = (X-mX)/Scale;
	var dy = (y-mY)/Scale;
	var s = dx*dx+dy*dy;
	var n = Math.sqrt(s);
	dx /= n;
	dy /= n;
	var x = X+dx/s;
	y = y+dy/s;
	return new Array(x,y);
}

gFreqs = new Array(19,20,17,50,3,10,18,19.1);
gScales = new Array(340,100,80,250,50,102,44,400);
gColors = new Array();
gScroll = new Array();
gSpeeds = new Array();

function r255() { return Math.floor(Math.random()*255); }
function r255q() { return Math.floor(Math.random()*Math.random()*255); } // cauchy

function setup_colors() {
	var nc;
	for (var i=0; i<gFreqs.length; i++) {
		nc = "rgba("+r255q()+","+r255q()+","+r255q()+",0.5)";
		gColors.push(nc);
		gScroll.push(0.0);
		gSpeeds.push(1.0+Math.random()*2.0);
	}
}

function draw_c1() {
	var cv = document.getElementById('c1');
	if (cv.getContext) {
		var w = cv.width; // 500.0;
		var h = cv.height; // 300.0;
		var ctx = cv.getContext('2d');
		// ctx.fillStyle = "rgb(90,10,0);";
		ctx.fillStyle = "rgba(240,240,240,0.95);";
		ctx.fillRect(0,0,w,h);
		if (gColors.length < 1) { setup_colors(); }
		var i;
		for (i=0; i<gFreqs.length; i++) {
			// ctx.strokeStyle = "rgba(255,255,190,.5);";
			ctx.strokeStyle = gColors[i];
			ctx.lineWidth=(1.0+(399.0/gScales[i]));
			ctx.beginPath();
			var a = next_loc(0,gScroll[i],w,h,gFreqs[i],gScales[i]);
			ctx.moveTo(a[0],a[1]);
			for (var x=1; x<w; x+=2) {
				a = next_loc(x,gScroll[i],w,h,gFreqs[i],gScales[i]);
				ctx.lineTo(a[0],a[1]);
			}
			ctx.stroke();
		        gScroll[i] += gSpeeds[i];
		}
	}
}

// add to page init list
gRActions.push(function() {
   draw_c1();
   $("#c1").mousemove(function(e) {
	    mX = e.pageX-this.offsetLeft;
	    mY = e.pageY-this.offsetTop;
	    //$('#mousy').html(mX+'/'+mY);
   });
   setInterval(draw_c1,30);
});

</script>
<canvas id="c1" width=800 height=250></canvas>

<P>With a little fiddling it's easy enough to use <tt>&lt;CANVAS&gt;</tt> (and <a HREF="http://jquery.com/" TARGET="new">jquery</a>) in tandem with Botzilla's somewhat elderly (and modified) installation of <a href="http://www.movabletype.org/" target="new">Moveable Type.</a></P>

<P>Minor tricks:<UL>
<LI>Remember to suppress Text Formatting -- no automatic <tt>&lt;P&gt;</tt> tags</LI>
<LI>Between different blog entries, don't reuse variable names, or element names, if you think you might ever need to have multiple canvases on the same page (say, in index or search pages). You will disappear into the fourth circle of scoping hell.</lI>
<LI>Likewise, if you think that multiple canvases per page is a real possibility, then put each canvas's prep and render code into a distinct function, so that you can move your <tt>onload()</tt> or <tt>$(document.ready()</tt> functions into the header template, not the body of the entry itself. In the header, declare an initially-empty array of functions, and have your <tt>ready()</tt> function iterate through them. <BR />Then in each scripted entry, add your entry-specific render function(s) to that array. This way, the <tt>ready()</tt> function can just know what's needing to be set up for the specific page, regardless of which entries are being displayed and the # of visible canvases (A perusal of the initial state of this entry will show that I don't always follow my own advice. But adding that feature to Botzilla is one of my next steps). Be sure to put that array and calling function into <I>all</I> of your index and entry templates!</LI>
<LI>Linked sites like Facebook won't show <tt>&lt;Canvas&gt;<tt> or other animating elements, so if you want a good thumbnail, try adding a hidden image like so: <tt>&lt;IMG SRC="/photo/journal//may03e-15.jpg" STYLE="display: none;" /&gt;</tt></LI>
<LI>MT's preview page doesn't have all this extra js etc built-in. I suppose you can add it, and I probably will over time --  but as a quick workaround, to get a preview, I save my entry, press "Publish," then immediately look at the front index page -- if there's anything wrong, immediately change the entry state back to "Draft" and save again. This will remove the entry from the front page and the RSS feed, but: the "permalink" actual page file (in this case, "/blog/archives/000738.html") will still be there on the server! Download it and debug locally, then transport your changes back into MT. A bit of a shuffle but it's a workflow that <i>can</i> get you from points A to B.</LI>
<LI>Beware trying to test-post to Facebook, changing the contents of the blog entry (even for typos) and trying to post it to FB again -- FB caches everything the first time, so... if you want a change that will appear there, you need to make a new copy of your entire post, publish <i>that,</i> and hide the old one (how do I know this?).</LI>
<LI>Google+ is smart enough to recognize the difference between javascript blocks and actual human-readable body text. <i>Facebook is not,</i> and may just insert blocks of random code onto any FB link you create pointing to your entry. Maybe they will learn.</LI>
</UL></P>

<IMG SRC="/photo/journal//may03e-15.jpg" STYLE="display: none;" /><a href="http://www.botzilla.com/blog/archives/000738.html#comments" title="Comment on: HTML5 Canvas vs Moveable Type">Comments (0)</a></p>]]></content:encoded>
       <dc:subject>Nuke Em from Orbit</dc:subject>
       <dc:date>2012-05-04T08:25:32-08:00</dc:date>
     </item>
 




  </channel>
 </rss>