<?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>nklein software &#187; lisp</title>
	<atom:link href="http://nklein.com/lisp/feed/" rel="self" type="application/rss+xml" />
	<link>http://nklein.com</link>
	<description>software development and consulting</description>
	<lastBuildDate>Tue, 16 Feb 2010 21:29:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Better Text Rendering with CL-OpenGL and ZPB-TTF</title>
		<link>http://nklein.com/2010/01/better-text-rendering-with-cl-opengl-and-zpb-ttf/</link>
		<comments>http://nklein.com/2010/01/better-text-rendering-with-cl-opengl-and-zpb-ttf/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 07:07:26 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1121</guid>
		<description><![CDATA[Last month, I posted some code for rendering text under CL-OpenGL with ZPB-TTF.  Toward the very end of that post, I said:
Technically, that check with the squared distance from the calculated midpoint to the segment midpoint shouldn’t just compare against the number one. It should be dynamic based on the current OpenGL transformation. I [...]]]></description>
			<content:encoded><![CDATA[<p>Last month, I posted <a href="http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/">some code for rendering text</a> under CL-OpenGL with ZPB-TTF.  Toward the very end of that post, I said:</p>
<blockquote><p>Technically, that check with the squared distance from the calculated midpoint to the segment midpoint shouldn’t just compare against the number one. It should be dynamic based on the current OpenGL transformation. I should project the origin and the points  and  through the current OpenGL projections, then use the reciprocal of the maximum distance those projected points are from the projected origin in place of the one. Right now, I am probably rendering many vertexes inside each screen pixel.</p></blockquote>
<p>It was pretty obvious that when you tried to render something very small, it looked quite jaggy and much more solid than you would expect.</p>
<p><center><a href="http://nklein.com/wp-content/uploads/2010/01/anti-aliasing.png"><img src="http://nklein.com/wp-content/uploads/2010/01/anti-aliasing.png" alt="" title="anti-aliasing" width="540" height="480" class="size-full wp-image-1129" /></a></center><br />
As you can see in the above image, the old version was placing up to 63 vertices for the same parabolic arc within a pixel.  The new code is much more careful about this and will only place two vertices from a given parabolic arc within a pixel.  You can see that in the upper rendering, the <b>s</b> is almost totally obliterated and the tiny bits sticking down from the <b>5</b> and <b>8</b> are much darker than in the lower rendering.</p>
<p>Here is the new code:</p>
<ul>
<li><a href="http://nklein.com/wp-content/uploads/2010/01/draw.lisp">draw</a>: better anti-aliasing</li>
<li><a href="http://nklein.com/wp-content/uploads/2010/01/gl.lisp">gl</a>: smaller &#8216;frames-per-second&#8217; indicator and some parameters to make it easier to toggle the main display</li>
<li><a href="http://nklein.com/wp-content/uploads/2010/01/test.lisp">test</a>: small tweak to make it work better under SLIME</li>
</ul>
<h3>Using a better cutoff value</h3>
<p>The <q>squared distance</q> check that I mentioned now employs a cutoff value:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> interpolate <span style="color: #66cc66;">&#40;</span>sx sy ex ey int-x int-y cutoff <span style="color: #66cc66;">&amp;</span>optional <span style="color: #66cc66;">&#40;</span>st 0<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>et 1<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>mx <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sx ex<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>my <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sy ey<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>mt <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ st et<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>nx <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-x mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>ny <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-y mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>dx <span style="color: #66cc66;">&#40;</span>- mx nx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>dy <span style="color: #66cc66;">&#40;</span>- my ny<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&lt;</span> <span style="color: #66cc66;">&#40;</span>* cutoff cutoff<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>+ <span style="color: #66cc66;">&#40;</span>* dx dx<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* dy dy<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interpolate sx sy nx ny int-x int-y cutoff st mt<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> nx ny<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interpolate nx ny ex ey int-x int-y cutoff mt et<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>I have tweaked the <b>(render-string &#8230;)</b> and <b>(render-glyph &#8230;)</b> accordingly to propagate that value down to the interpolate function, and I have added a method to calculate the appropriate cutoff value.</p>
<h3>Calculating the appropriate cutoff value</h3>
<p>The appropriate cutoff value depends upon the font, the desired rendering size in viewport coordinates, and the current OpenGL transformations.  The basic idea is that I prepare the OpenGL transformation the same way that I will later do for rendering the font; I will reverse-project <a href="http://wordpress.org/extend/plugins/easy-latex/" target="_blank" title="(0,0)"><img src="http://l.wordpress.com/latex.php?latex=%280%2C0%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="(0,0)" /></a>, <a href="http://www.Thulasidas.com/latex" target="_blank" title="(1,0)"><img src="http://l.wordpress.com/latex.php?latex=%281%2C0%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="(1,0)" /></a>, and <a ><img src="http://l.wordpress.com/latex.php?latex=%280%2C1%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="(0,1)" /></a>; I will calculate the distances from the reverse-projected <img src="http://l.wordpress.com/latex.php?latex=%280%2C0%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(0,0)" style="vertical-align:-20%;" class="tex" alt="(0,0)" /> to each of the other two reverse-projected points; and then I will take half of that as my cutoff value.  This effectively means that once the midpoint of my parabola arc is within half of a screen pixel of where the midpoint of a line segment would be, I just use a line segment.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> calculate-cutoff <span style="color: #66cc66;">&#40;</span>font-loader size<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>ss <span style="color: #66cc66;">&#40;</span>/ size <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">units</span>/em font-loader<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">scale</span> ss ss ss<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>modelview <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">get-double</span> <span style="color: #66cc66;">:</span><span style="color: #555;">modelview-matrix</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>projection <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">get-double</span> <span style="color: #66cc66;">:</span><span style="color: #555;">projection-matrix</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>viewport <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">get-</span><span style="color: #b1b100;">integer</span> <span style="color: #66cc66;">:</span><span style="color: #555;">viewport</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>labels <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>dist <span style="color: #66cc66;">&#40;</span>x1 y1 z1 x2 y2 z2<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">max</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">abs</span> <span style="color: #66cc66;">&#40;</span>- x1 x2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">abs</span> <span style="color: #66cc66;">&#40;</span>- y1 y2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">abs</span> <span style="color: #66cc66;">&#40;</span>- z1 z2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>dist-to-point-from-origin <span style="color: #66cc66;">&#40;</span>px py pz ox oy oz<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>multiple-value-bind <span style="color: #66cc66;">&#40;</span>nx ny nz<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>glu<span style="color: #66cc66;">:</span><span style="color: #555;">un-project</span> px py pz<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">modelview</span> modelview<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">projection</span> projection<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">viewport</span> viewport<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>dist nx ny nz ox oy oz<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>multiple-value-bind <span style="color: #66cc66;">&#40;</span>ox oy oz<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>glu<span style="color: #66cc66;">:</span><span style="color: #555;">un-project</span> 0<span style="color: #66cc66;">.</span>0 0<span style="color: #66cc66;">.</span>0 0<span style="color: #66cc66;">.</span>0<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">modelview</span> modelview<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">projection</span> projection<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">viewport</span> viewport<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">min</span> <span style="color: #66cc66;">&#40;</span>dist-to-point-from-origin <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span> ox oy oz<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>dist-to-point-from-origin <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">0</span> ox oy oz<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2010/01/better-text-rendering-with-cl-opengl-and-zpb-ttf/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Woolly Application Underway</title>
		<link>http://nklein.com/2009/12/woolly-application-underway/</link>
		<comments>http://nklein.com/2009/12/woolly-application-underway/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 00:36:55 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1062</guid>
		<description><![CDATA[I started building an application on top my Sheeple/CL-OpenGL library Woolly.
I coach a volleyball team.  I often sit down with a piece of paper and try to determine new serve-receive and defensive positions for my team.  This is quite tedious because I can&#8217;t just move the players around on the page.  Additionall, [...]]]></description>
			<content:encoded><![CDATA[<p>I started building an application on top my Sheeple/CL-OpenGL library <a href="http://nklein.com/software/woolly/">Woolly</a>.</p>
<p>I <a href="http://mnvolleyballhq.com/">coach a volleyball team</a>.  I often sit down with a piece of paper and try to determine new serve-receive and defensive positions for my team.  This is quite tedious because I can&#8217;t just move the players around on the page.  Additionall, I have to figure this out for all six rotations while keeping the overlap requirements in mind the whole time.</p>
<p>I tried once doing it with cut-out players.  This worked better, but still suffered from having to track the rotations and overlap requirements all myself.</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/12/rotations.png"><img src="http://nklein.com/wp-content/uploads/2009/12/rotations-300x235.png" alt="rotations" title="rotations" width="300" height="235" class="alignright size-medium wp-image-1063" /></a> After adding checkboxes to Woolly, I had a usable application for doing these rotations in 300 lines of code.  Yellow are front-row players, blue are back-row players, and green are sidelined players.  It still needs some work so that I can change player identifiers, substitute players in off the bench, save/load the rotations, and make print-outs.</p>
<p>I&#8217;m not sure yet whether I&#8217;m going to print just by slurping the OpenGL buffer into ZPNG, or if I am going to make a separate callback hierarchy for printing with Vecto or CL-PDF so that I can print at higher than screen resolution.</p>
<p>I&#8217;m also having trouble getting SBCL&#8217;s <b>save-lisp-and-die</b> function happy with the whole CL-OpenGL setup under MacOSX.  I thought I had figured this out before.  Alas, my own hacked version of CL-OpenGL isn&#8217;t working any better for me than the current CL-OpenGL release is when I try to run the saved image.  *shrug*  I&#8217;ll fight with that later.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/woolly-application-underway/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rendering Text in CL-OpenGL with ZPB-TTF</title>
		<link>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/</link>
		<comments>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 01:24:02 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1051</guid>
		<description><![CDATA[I promised in an earlier post that I would share my code for rendering anti-aliased text in CL-OpenGL using ZPB-TTF to load the fonts.
Overview
I use a three step process to render a string.  First, I render the outline of the string using anti-alised lines.  Then, I render the string as solid polygons into [...]]]></description>
			<content:encoded><![CDATA[<p>I promised in <a href="http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/">an earlier post</a> that I would share my code for rendering anti-aliased text in <a href="http://common-lisp.net/project/cl-opengl/">CL-OpenGL</a> using <a href="http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF</a> to load the fonts.</p>
<h3>Overview</h3>
<p>I use a three step process to render a string.  First, I render the outline of the string using anti-alised lines.  Then, I render the string as solid polygons into the stencil buffer.  Then, I fill a rectangle having OpenGL only fill where the stencil buffer is set.</p>
<p>Why the three-step process?  OpenGL can draw polygons.  In fact, it can draw anti-aliased polygons.  However, it can only draw convex polygons.  Most of the polygons involved in fonts are non-convex.  The stencil buffer, however, has a drawing mode where you can flip the bits of the value in the stencil buffer each time OpenGL goes to write to it.</p>
<p>Imagine for a moment the letter <q>O</q>.  It is made of two separate contours&#8230; one for the exterior of the circle and one for the interior of the circle.  If I rendered each of these to the color buffer in OpenGL, I would end up with one big filled in circle.  However, if I render each of these to the stencil buffer with the invert operation, then I end up setting all of the bits in the filled circle area when I draw the exterior contour and turning the middle bits off again when I render the internal contour.  I am left with only the bits in the letter itself filled in.</p>
<p>The same sort of thing works even for more complicated letters like the letter <q>C</q>.  As I am progressing along the outer edge, I am inadvertently filling the interior region. But, as I progress along the inner edge, I am inadvertently erasing that region again.</p>
<p>Once I am done, I use the stencil buffer as a stencil, draw a rectangle over it, and Bob&#8217;s your uncle.</p>
<p>The problem with the stencil buffer is that it has no subtlety.  Bits are either set in it or not.  So, I cannot anti-alias in the stencil buffer.  I am left to draw the outline with anti-aliased lines.</p>
<p>Here are the relevant files:</p>
<ul>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/draw.lisp">draw.lisp</a>: The code which actually draws strings in a given font.</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/gl.lisp">gl.lisp</a>:  The code that makes a basic OpenGL window and invokes the font rendering on a given font and string.</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/test.lisp">test.lisp</a>:  Some simple code that loads the required libraries and opens a window.</li>
</ul>
<p>The test program assumes that <q>okolaksRegular.ttf</q> is in your current directory.  Tweak it to some TTF you do have.  Or, get <a href="http://openfontlibrary.org/media/files/gluk/240">Okolaks</a> itself.</p>
<h3>Drawing a string</h3>
<p>Here is the basic outline of the string drawing function.  I am centering the string at the origin.  I first calculate the bounding box.  Then, I determine the scaling factor needed to get from the font-units into my own units and I scale the universe accordingly.  Then, I translate the universe to center the bounding box.  Then, I draw the anti-aliased outline of the text.  If desired, I then draw the filled text to the stencil buffer and paint in the stencil.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> draw-string <span style="color: #66cc66;">&#40;</span>font-loader string <span style="color: #66cc66;">&amp;</span>key <span style="color: #66cc66;">&#40;</span>size 48<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>filled t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span>* <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>box <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">string-bounding-box</span> string font-loader <span style="color: #66cc66;">:</span><span style="color: #555;">kerning</span> t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>bx1 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box 0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>by1 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box 1<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>bx2 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box 2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>by2 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> box 3<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>ss <span style="color: #66cc66;">&#40;</span>/ size <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">units</span>/em font-loader<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">scale</span> ss ss 1<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>- bx1 bx2<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>- by1 by2<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">&#41;</span> 0<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-attrib</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">current-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">color-buffer-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-bit</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">hint-bit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-buffer-bit</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;&lt;</span>draw antialiased lines<span style="color: #66cc66;">&gt;&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> filled<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;&lt;</span>fill stencil buffer with filled-in-glyph<span style="color: #66cc66;">&gt;&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;&lt;</span>fill in area subject to stencil<span style="color: #66cc66;">&gt;&gt;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>To <q>draw antialiased lines</q>, I turn on blending.  I tell it to blend the color in according to the alpha value of the portion of line it is trying to draw.  I tell it to draw smooth lines in the nicest way it knows how.  Then, I save the transformation-state so that I can move around inside the actual string rendering and still get back to this exact same place later.  When I am done, I no longer need blending.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">blend</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">blend-func</span> <span style="color: #66cc66;">:</span><span style="color: #555;">src-alpha</span> <span style="color: #66cc66;">:</span><span style="color: #555;">one-minus-src-alpha</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-smooth</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">hint</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-smooth-hint</span> <span style="color: #66cc66;">:</span><span style="color: #555;">nicest</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>render-string string font-loader <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>To <q>fill stencil buffer with filled-in-glyph</q>, I turn off writing to the color buffer.  I turn on the stencil testing.  I set myself up to use a 1-bit stencil buffer.  I set the buffer up so that when I clear it, it will all be zero-ed.  I clear the stencil buffer.  I set the stencil test to always write one bit.  And, I set the stencil buffer to always write in <q>invert</q> mode.  Then, I draw the string filled.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">color-mask</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">enable</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-test</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-mask</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">clear-stencil</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">clear</span> <span style="color: #66cc66;">:</span><span style="color: #555;">stencil-buffer-bit</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-func</span> <span style="color: #66cc66;">:</span><span style="color: #555;">always</span> <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-op</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span> <span style="color: #66cc66;">:</span><span style="color: #555;">invert</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-pushed-matrix</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>render-string string font-loader t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>To <q>fill in area subject to stencil</q>, I set myself up again to write to the color buffer.  I set up the stencil test to let me write to my buffers only where the stencil is set to one.  Then, I draw a filled rectangle over the whole bounding box.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">color-mask</span> t t t t<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">stencil-func</span> <span style="color: #66cc66;">:</span><span style="color: #b1b100;">equal</span> <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-primitives</span> <span style="color: #66cc66;">:</span><span style="color: #555;">quads</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx1 by1<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx2 by1<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx2 by2<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> bx1 by2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<h3>Rendering the string</h3>
<p>To render the string, I loop through each character in it.  For characters other than the first one, I adjust their position based on the kerning offset.  Then, I render the character glyph and adjust the position so that I am ready to start the next character.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> render-string <span style="color: #66cc66;">&#40;</span>string font-loader fill<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>loop <span style="color: #66cc66;">:</span><span style="color: #555;">for</span> pos <span style="color: #66cc66;">:</span><span style="color: #555;">from</span> 0 <span style="color: #66cc66;">:</span><span style="color: #555;">below</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">length</span> string<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">for</span> cur <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">find-glyph</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">aref</span> string pos<span style="color: #66cc66;">&#41;</span> font-loader<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">for</span> prev <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">nil</span> <span style="color: #66cc66;">:</span><span style="color: #555;">then</span> cur<br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #b1b100;">do</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> prev<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>- <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">kerning-offset</span> prev cur font-loader<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">left-side-bearing</span> cur<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>render-glyph cur <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> fill <span style="color: #66cc66;">:</span><span style="color: #555;">polygon</span> <span style="color: #66cc66;">:</span><span style="color: #555;">line-strip</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">translate</span> <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">advance-width</span> cur<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<h3>Rendering a glyph</h3>
<p>Here&#8217;s where the rubber really meets the road.  My <q>render-glyph</q> function takes two arguments: a glyph and the mode in which to render it.  The mode is <q>:polygon</q> for filled polygons and <q>:line-strip</q> for just the outline.</p>
<p>I loop through each contour in the glyph.  With each contour, I tell OpenGL that I am going to render either a single polygon or a single line strip (according to the mode).  To render the contour then, I loop through each contour segment.  Each contour segment is either a straight line or a quadratic spline.  If it is a straight line, then I have it easy.  I just have to render the end points.  If it is a spline, I have to render the starting point, create some interpolators to interpolate points along the spline, use those interpolators, and then render the end point.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> render-glyph <span style="color: #66cc66;">&#40;</span>glyph mode<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">do-contours</span> <span style="color: #66cc66;">&#40;</span>contour glyph<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">with-primitives</span> mode<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">do-contour-segments</span> <span style="color: #66cc66;">&#40;</span>start ctrl end<span style="color: #66cc66;">&#41;</span> contour<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>sx <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> start<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>sy <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> start<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>cx <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> ctrl<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>cy <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> ctrl<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>ex <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">x</span> end<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>ey <span style="color: #66cc66;">&#40;</span>zpb-ttf<span style="color: #66cc66;">:</span><span style="color: #555;">y</span> end<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> sx sy<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> ctrl<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>int-x <span style="color: #66cc66;">&#40;</span>make-interpolator sx cx ex<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>int-y <span style="color: #66cc66;">&#40;</span>make-interpolator sy cy ey<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interpolate sx sy ex ey int-x int-y<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> ex ey<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>The starting point of one contour segment is always the ending point of the previous contour segment.  So, if I wanted to bother, I could save myself a few OpenGL calls by remembering the first starting point of the first segment of the contour, not rendering the end points of any contour segment, and then rendering the starting point of the first segment again at the end (when I&#8217;m in outline mode).  Instead, for clarity, I just always render the end point.</p>
<h3>Making spline interpolators</h3>
<p>If I want to make an quadratic spline that goes from <a href="http://wordpress.org/extend/plugins/easy-latex/" target="_blank" title="x_0"><img src="http://l.wordpress.com/latex.php?latex=x_0&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="x_0" /></a> to <a href="http://www.Thulasidas.com/latex" target="_blank" title="x_1"><img src="http://l.wordpress.com/latex.php?latex=x_1&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="x_1" /></a> with control point <a ><img src="http://l.wordpress.com/latex.php?latex=c&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" style="vertical-align:-20%;" class="tex" alt="c" /></a> as time <img src="http://l.wordpress.com/latex.php?latex=t&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="t" style="vertical-align:-20%;" class="tex" alt="t" /> goes from zero to one, I would use the polynomial <img src="http://l.wordpress.com/latex.php?latex=%28x_0%20-%202c%20%2B%20x_1%29%20t%5E2%20%2B%202%28%20c%20-%20x_0%20%29%20t%20%2B%20x_0&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(x_0 - 2c + x_1) t^2 + 2( c - x_0 ) t + x_0" style="vertical-align:-20%;" class="tex" alt="(x_0 - 2c + x_1) t^2 + 2( c - x_0 ) t + x_0" />.  So, given the parameters of a contour segment, I&#8217;m going to create interpolators for the x and y coordinates independently like so:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> make-interpolator <span style="color: #66cc66;">&#40;</span>ss cc ee<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>xx <span style="color: #66cc66;">&#40;</span>+ ss <span style="color: #66cc66;">&#40;</span>* -2 cc<span style="color: #66cc66;">&#41;</span> ee<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>yy <span style="color: #66cc66;">&#40;</span>* 2 <span style="color: #66cc66;">&#40;</span>- cc ss<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>zz ss<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; #'<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>tt<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>+ <span style="color: #66cc66;">&#40;</span>* xx tt tt<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* yy tt<span style="color: #66cc66;">&#41;</span> zz<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<h3>Interpolating the spline</h3>
<p>To interpolate the spline, I use a recursive function.  It is given the x and y coordinates of the starting and ending points for the current portion of the spline, the starting and ending time coordinates of the current portion of the spline, and the interpolators created above.  From there, it calculates the midpoint of a line segment from the start to the end and the x and y coordinates that the midpoint should be at based on the spline interpolator functions.  If the calculated spline midpoint is really close to the line-segment midpoint, we just break off the recursion.  If it is not really close, then we interpolate the first half of the current portion, render the calculated spline portion midpoint, and interpolate the second half of the current portion.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> interpolate <span style="color: #66cc66;">&#40;</span>sx sy ex ey int-x int-y <span style="color: #66cc66;">&amp;</span>optional <span style="color: #66cc66;">&#40;</span>st 0<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>et 1<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>mx <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sx ex<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>my <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ sy ey<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>mt <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>+ st et<span style="color: #66cc66;">&#41;</span> 2<span style="color: #66cc66;">.</span>0<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>nx <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-x mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>ny <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">funcall</span> int-y mt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>dx <span style="color: #66cc66;">&#40;</span>- mx nx<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>dy <span style="color: #66cc66;">&#40;</span>- my ny<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">when</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#40;</span>+ <span style="color: #66cc66;">&#40;</span>* dx dx<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* dy dy<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interpolate sx sy nx ny int-x int-y st mt<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gl<span style="color: #66cc66;">:</span><span style="color: #555;">vertex</span> nx ny<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interpolate nx ny ex ey int-x int-y mt et<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Technically, that check with the squared distance from the calculated midpoint to the segment midpoint shouldn&#8217;t just compare against the number one.  It should be dynamic based on the current OpenGL transformation.  I should project the origin and the points <img src="http://l.wordpress.com/latex.php?latex=%281%2C0%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(1,0)" style="vertical-align:-20%;" class="tex" alt="(1,0)" /> and <img src="http://l.wordpress.com/latex.php?latex=%280%2C1%29&#038;bg=FFFFCC&#038;fg=000000&#038;s=0" title="(0,1)" style="vertical-align:-20%;" class="tex" alt="(0,1)" /> through the current OpenGL projections, then use the reciprocal of the maximum distance those projected points are from the projected origin in place of the one.  Right now, I am probably rendering many vertexes inside each screen pixel.</p>
<h3>Summary</h3>
<p>So, there you have it.  Should you ever need to render text in CL-OpenGL, I hope this saves you many hours of trial-and-error and keeps you from resorting to rendering the glyphs to a texture map and dealing with how poorly they scale.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/rendering-text-with-cl-opengl-and-zpb-ttf/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>GUI Discussion &#8212; TC Lispers November Meeting</title>
		<link>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/</link>
		<comments>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 12:05:41 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[user interface toolkits]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1045</guid>
		<description><![CDATA[Cross-posted from TCLispers.org:

Lisp GUI Discussion on Vimeo.
Robert Goldman, Paul Krueger, and Patrick Stein gave short presentations on different approaches to Graphical User Interfaces with Common Lisp.

Lisp GUIs or &#8220;Bloodied but Unbowed&#8221; by Robert Goldman
CCL/Cocoa Interface by Paul Krueger
GUIs with CL-OpenGL by Patrick Stein

]]></description>
			<content:encoded><![CDATA[<p><em>Cross-posted from <a href="http://tclispers.org/">TCLispers.org</a>:</em></p>
<p><object width="640" height="480"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=7933728&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="640" height="480" src="http://vimeo.com/moogaloop.swf?clip_id=7933728&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><a href="http://vimeo.com/7933728">Lisp GUI Discussion</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Robert Goldman, Paul Krueger, and Patrick Stein gave short presentations on different approaches to Graphical User Interfaces with Common Lisp.</p>
<ul>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/lisp-guis.pdf">Lisp GUIs or &#8220;Bloodied but Unbowed&#8221;</a> by <a href="http://rpgoldman.real-time.com/">Robert Goldman</a></li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/TCL-Slides-Nov-2009.pdf">CCL/Cocoa Interface</a> by Paul Krueger</li>
<li><a href="http://nklein.com/wp-content/uploads/2009/12/CL-OpenGL-GUI.pdf">GUIs with CL-OpenGL</a> by <a href="http://nklein.com/">Patrick Stein</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/12/gui-discussion-tc-lispers-november-meeting/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Development</title>
		<link>http://nklein.com/2009/11/cross-platform-development/</link>
		<comments>http://nklein.com/2009/11/cross-platform-development/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 01:31:04 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[vmware]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1018</guid>
		<description><![CDATA[In preparation for the upcoming TC Lispers meeting, I was testing my Sheeple-based CL-OpenGL GUI code on all of the different systems that I use.  This was important because part of my goal in starting from bare-bones OpenGL was to make something that was pretty easy to port.  The OpenGL libraries are the [...]]]></description>
			<content:encoded><![CDATA[<p>In preparation for the <a href="http://tclispers.org/events/november-meeting">upcoming TC Lispers meeting</a>, I was testing my <a href="http://sykosomatic.org/sheeple/">Sheeple</a>-based <a href="http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/">CL-OpenGL GUI</a> code on all of the different systems that I use.  This was important because part of my goal in starting from bare-bones OpenGL was to make something that was pretty easy to port.  The OpenGL libraries are the only non-Lisp dependencies, and they are pretty standard.</p>
<p>I run Mac OS X 10.6.2 as my primary development machine.  I knew everything I had so far worked there under SBCL 1.0.30 and CMU-CL 20a.  It took a little tweaking to get Sheeple built under Allegro CL 8.1 (Trial Edition), but after that I was five-by-five under Allegro, too.  Unfortunately, I cannot get CL-OpenGL to run under Clozure 1.3-r11936 on Mac OS X.  Also, ECL 9.10.2 doesn&#8217;t support weak key hashtables which Sheeple needs.  And, my install of clisp broke somewhere along the lines, so I haven&#8217;t tried it.</p>
<p>I have an Ubuntu Linux box.  There, I am using SBCL 1.0.11.debian (eeps).  Everything ran perfectly over there (even displaying through X Windows back to my Mac).</p>
<p>I also run Windows Vista under VMWare Fusion on my Mac.  I hadn&#8217;t done any development on it for months and months.  Fortunately, in Google-ing to find out how to fix it, I stumbled upon <a href="http://nklein.com/2009/05/emacs-slime-sbcl-on-windows-vista/">what I had written about how I got things set up originally</a>.  Over the last two hours, I got SBCL upgraded to 1.0.29 under Vista.  I got ASDF-Install set up with a bunch of help from <a href="http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html">this article</a>.  And, from there, I got CFFI and cl-opengl and ZPB-TTF and Sheeple installed.</p>
<p>ZPB-TTF and Sheeple both used some tar format options that <a href="http://www.method-combination.net/blog/archives/2007/04/30/new-archive-release.html">archive_0.7.0</a> didn&#8217;t like.  For those, I had to jump through some hoops to untar and retar them to get them to install.</p>
<p>Here was my final <b>/Users/Patrick/.sbclrc</b> file:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>require <span style="color: #66cc66;">:</span><span style="color: #555;">asdf</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;; from Zach Beane</span><br />
<span style="color: #66cc66;">&#40;</span>defmethod asdf<span style="color: #66cc66;">:</span><span style="color: #555;">perform</span> <span style="color: #66cc66;">:</span><span style="color: #555;">around</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>o asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>c asdf<span style="color: #66cc66;">:</span><span style="color: #555;">cl-source-file</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>handler-<span style="color: #b1b100;">case</span> <span style="color: #66cc66;">&#40;</span>call-next-method o c<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>#+sbcl sb-ext<span style="color: #66cc66;">:</span><span style="color: #555;">invalid-fasl</span><br />
&nbsp; &nbsp; &nbsp;#+allegro excl<span style="color: #66cc66;">::</span><span style="color: #555;">file-incompatible-fasl-</span><span style="color: #b1b100;">error</span><br />
&nbsp; &nbsp; &nbsp;#+lispworks conditions<span style="color: #66cc66;">:</span><span style="color: #555;">fasl-</span><span style="color: #b1b100;">error</span><br />
&nbsp; &nbsp; &nbsp;#+cmu ext<span style="color: #66cc66;">:</span><span style="color: #555;">invalid-fasl</span><br />
&nbsp; &nbsp; &nbsp;#-<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">or</span> sbcl allegor lispworks cmu<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">error</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">perform</span> <span style="color: #66cc66;">&#40;</span>make-instance 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">compile-op</span><span style="color: #66cc66;">&#41;</span> c<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>call-next-method<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">dolist</span> <span style="color: #66cc66;">&#40;</span>pkg &nbsp;'<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;alexandria/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;archive_0.7.0/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;asdf-install/asdf-install/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;babel_0.3.0/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;cffi_0.10.5/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;cl-opengl/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;flexi-streams-1.0.7/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;gzip-stream_0.2.8/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;salza2-2.0.7/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;sykopomp-sheeple-ceab213/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;trivial-features_0.6/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;trivial-gray-streams-2008-11-02/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;woolly/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;zpb-ttf-1.0/&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>pushnew <span style="color: #66cc66;">&#40;</span>merge-pathnames pkg<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;asdf<span style="color: #66cc66;">:</span>*central-registry*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'asdf-install<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;; for my sanity</span><br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> asdf-install<span style="color: #66cc66;">:</span>*locations*<br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">list</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">list</span> <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span> <span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>merge-pathnames <span style="color: #ff0000;">&quot;ASDF-Systems/&quot;</span> <span style="color: #66cc66;">&#40;</span>user-homedir-pathname<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;My install spot&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;; via http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html</span><br />
#+win32<br />
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'gzip-stream<span style="color: #66cc66;">&#41;</span><br />
<br />
#+win32<br />
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">oos</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'archive<span style="color: #66cc66;">&#41;</span><br />
<br />
#+win32<br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> asdf-install-extractor <span style="color: #66cc66;">&#40;</span>to-dir tarball<span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">name</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>gzip-stream<span style="color: #66cc66;">:</span><span style="color: #555;">with-open-gzip-file</span> <span style="color: #66cc66;">&#40;</span>ins tarball<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">with-open-archive</span> <span style="color: #66cc66;">&#40;</span>archive ins<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>*default-pathname-defaults* <span style="color: #66cc66;">&#40;</span>pathname to-dir<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">do-archive-entries</span> <span style="color: #66cc66;">&#40;</span>entry archive <span style="color: #b1b100;">name</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #555;">extract-entry</span> archive entry<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>unless <span style="color: #b1b100;">name</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> <span style="color: #b1b100;">name</span> <span style="color: #66cc66;">&#40;</span>archive<span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> entry<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>string <span style="color: #b1b100;">name</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
#+win32<br />
<span style="color: #66cc66;">&#40;</span>push 'asdf-install-extractor asdf-install<span style="color: #66cc66;">:</span>*tar-extractors*<span style="color: #66cc66;">&#41;</span></div></div>
<p>The list of packages in the middle were about half installed manually to get the archive extraction code working and half installed through ASDF-Install.  If I recall correctly, I had to manually install: <b>archive_0.7.0</b>, <b>flexi-streams-1.0.7</b>, <b>gzip-stream_0.2.8</b>, <b>salza2-2.0.7</b>, <b>trivial-gray-streams-2008-11-02</b>, and a fresh copy of <b>asdf-install</b>.  I also had to download a compiled version of <b>freeglut.dll</b> and tuck it into my Windows\system32 directory.</p>
<p>Getting SBCL to use the fresh copy of <b>asdf-install</b> was annoying.  I ended up starting up a Command Prompt as Administrator (right click on the &#8220;command.exe&#8221; icon or menu-item and select &#8220;Run as Administrator&#8221;).  Then, I went to the SBCL directory (&#8220;C:\Program Files\Steel Bank Common Lisp\1.0.29\&#8221;) and did the following:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">%</span> rename asdf-install asdf-install.old<br />
<span style="color: #000000; font-weight: bold;">%</span> mklink <span style="color: #000000; font-weight: bold;">/</span>d asdf-install <span style="color: #ff0000;">&quot;C:\Users\Patrick\ASDF-Systems\asdf-install\asdf-install<span style="color: #000099; font-weight: bold;">\&quot;</span></span></div></div>
<p>I had extracted the tar-ball from the ASDF-Install distribution into my ASDF-Systems directory.</p>
<p>Then, I went back and made my GUI code use double-buffered OpenGL windows because running Lisp to OpenGL to Windows Vista to VMWare to Quartz had some wicked flickering going on.</p>
<p>Two hours is a long time for something that&#8217;s supposed to be <q>easily portable</q>.  But, I would have spent at least 95% of that time even if I were using an all-Lisp solution.  And, this is far less time than I ever spent porting anything else to Windows.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/11/cross-platform-development/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Playing with Sheeple-based GUI atop CL-OpenGL</title>
		<link>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/</link>
		<comments>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 16:59:55 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[woolly]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=1007</guid>
		<description><![CDATA[Inspired by the previous TC Lispers meeting and spurred on by the probable topic of the next TC Lispers meeting, I have spent the little bit of coding time I&#8217;ve had over the past two weeks on making a GUI layer using Sheeple atop CL-OpenGL and employing ZPB-TTF for font-loading.
I have dubbed this project Woolly [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by the <a href="http://tclispers.org/news/sheeple-presentation">previous TC Lispers meeting</a> and spurred on by the <a href="http://tclispers.org/should-we-discuss-question-cl-and-uis-november-meeting">probable topic of the next TC Lispers meeting</a>, I have spent the little bit of coding time I&#8217;ve had over the past two weeks on making a GUI layer using <a href="http://sykosomatic.org/sheeple/">Sheeple</a> atop <a href="http://common-lisp.net/project/cl-opengl/">CL-OpenGL</a> and employing <a href="http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF</a> for font-loading.</p>
<p>I have dubbed this project <q>Woolly</q> (because it&#8217;s made from Sheeple and because <q>Woolly</q> sounds sorta like <q>GUI</q>).</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/11/woolly-peek.png"><img src="http://nklein.com/wp-content/uploads/2009/11/woolly-peek-300x235.png" alt="woolly-peek" title="woolly-peek" width="300" height="235" class="alignright size-medium wp-image-1008" /></a>I spent about half of my coding time so far getting the basic framework in place (proven through clickable buttons with labels).  I am trying to keep it cleanly separated between generic GUI stuff and the CL-OpenGL specifics in the event that someone would like to port it to some other I/O spec.</p>
<p>The other half of my coding time was spent getting the font-rendering to be anti-aliased.  I promise to write more about how I accomplished the font-rendering in a future post so that if you&#8217;re ever stuck rendering fonts in OpenGL, you won&#8217;t be stuck with pixelated blockiness or resorting to rendering to a texture-map and letting the mipmapper figure it out.</p>
<p>For this post, however, I&#8217;ll just show you the code that sets up the interface depicted here.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>require <span style="color: #66cc66;">:</span><span style="color: #555;">asdf</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>asdf<span style="color: #66cc66;">:</span><span style="color: #555;">operate</span> 'asdf<span style="color: #66cc66;">:</span><span style="color: #555;">load-op</span> 'woolly-gl <span style="color: #66cc66;">:</span><span style="color: #555;">verbose</span> <span style="color: #b1b100;">nil</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;; make it easier to change renderer/controller later</span><br />
<span style="color: #66cc66;">&#40;</span>rename-package 'woolly-gl 'toolkit<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> test <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>font <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>font<span style="color: #66cc66;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">em-size</span> <span style="color: #cc66cc;">48</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">pathname</span> <span style="color: #ff0000;">&quot;okolaks/okolaksRegular.ttf&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>app <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>app<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>win <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>window<span style="color: #66cc66;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">title</span> <span style="color: #ff0000;">&quot;Woolly Window 1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">width</span> <span style="color: #cc66cc;">640</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">height</span> <span style="color: #cc66cc;">480</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>but <span style="color: #66cc66;">&#40;</span>sheeple<span style="color: #66cc66;">:</span><span style="color: #555;">object</span> <span style="color: #66cc66;">:</span><span style="color: #555;">parents</span> toolkit<span style="color: #66cc66;">:=</span>button<span style="color: #66cc66;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">offset-x</span> <span style="color: #cc66cc;">40</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">offset-y</span> <span style="color: #cc66cc;">40</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">width</span> <span style="color: #cc66cc;">300</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">height</span> <span style="color: #cc66cc;">100</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">font</span> font<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">label</span> <span style="color: #ff0000;">&quot;Button&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">display-window</span> win<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">add</span> win but<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">main-loop</span> app<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>woolly<span style="color: #66cc66;">:</span><span style="color: #555;">destroy-window</span> win<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Next up on my agenda is to make the background and button prettier.  It should be easy enough to do with <b>GL_LIGHTING</b> and some vertex-coloring for gradations.  After that, it&#8217;s on to more controls like labels, panels, checkboxes, drop-downs, borders, and (my dread) text input boxes.  Then, it&#8217;s on to a layout manager.</p>
<p><a href="http://nklein.com/wp-content/uploads/2009/11/woolly-peek1.png"><img src="http://nklein.com/wp-content/uploads/2009/11/woolly-peek1-150x117.png" alt="woolly-peek" title="woolly-peek" width="150" height="117" class="alignright size-thumbnail wp-image-1013" /></a>Edit: Here&#8217;s the same GUI a day later.  I&#8217;m using a simple lighting scheme and rendering the button in 3D.  I haven&#8217;t yet hooked in the bit to render it depressed when the button is pressed.  I&#8217;ve tested the code that draws it the other way, but I haven&#8217;t hooked it into the mouse handlers yet.</p>
<p>Edit #2: Actually, it only took a few minutes for me to hook in the rendering it pressed vs. unpressed.  When I did it though, it looked like the label was sliding around because the effect of the contrast between the light and dark edges of the button was so great that you perceive the whole button sliding when it&#8217;s pressed.  So, I added a little bit in there to actually slide the text by an amount close to what is perceived.  So, now&#8230; it looks pretty spiffy.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/11/playing-with-sheeple-based-gui-atop-cl-opengl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>DSL for Drawing Floor Plans</title>
		<link>http://nklein.com/2009/10/dsl-for-drawing-floor-plans/</link>
		<comments>http://nklein.com/2009/10/dsl-for-drawing-floor-plans/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 04:06:00 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=999</guid>
		<description><![CDATA[Last week, I needed create a scale drawing of my basement floor plan.  My license for OmniGraffle Professional are long since out-of-date.  I didn&#8217;t want to pay $200 for a new license or even another $75 if I can dig up one of my old license keys.  So, what&#8217;s a hacker to [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I needed create a scale drawing of my basement floor plan.  My license for <a href="http://www.omnigroup.com/applications/omnigraffle/">OmniGraffle Professional</a> are long since out-of-date.  I didn&#8217;t want to pay $200 for a new license or even another $75 if I can dig up one of my old license keys.  So, what&#8217;s a hacker to do?  Roll his own (on top of Zach&#8217;s <a href="http://www.xach.com/lisp/vecto/">Vecto</a> library).</p>
<p>My first cut worked, but was pretty ugly:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>with-floor-plan #P<span style="color: #ff0000;">&quot;basement.png&quot;</span> 200<span style="color: #66cc66;">.</span>0<br />
&nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>interior-wall <span style="color: #66cc66;">:</span><span style="color: #555;">start</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cons</span> <span style="color: #66cc66;">&#40;</span>- <span style="color: #cc66cc;">91</span> <span style="color: #cc66cc;">31</span> <span style="color: #cc66cc;">1</span>/<span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">; hose cover</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">north</span> 18<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">east</span> &nbsp;<span style="color: #66cc66;">&#40;</span>+ 31 1/2<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>interior-wall <span style="color: #66cc66;">:</span><span style="color: #555;">start</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cons</span> <span style="color: #cc66cc;">91</span> <span style="color: #66cc66;">&#40;</span>- <span style="color: #cc66cc;">103</span> <span style="color: #cc66cc;">27</span> <span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">; storage wall</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">south</span> <span style="color: #66cc66;">&#40;</span>- 103 27 30<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>interior-wall <span style="color: #66cc66;">:</span><span style="color: #555;">start</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cons</span> <span style="color: #66cc66;">&#40;</span>+ <span style="color: #cc66cc;">91</span> <span style="color: #cc66cc;">83</span><span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">103</span><span style="color: #66cc66;">&#41;</span> &nbsp;<span style="color: #808080; font-style: italic;">; fish-tank wall</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">to</span> '<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">91</span> <span style="color: #66cc66;">.</span> <span style="color: #cc66cc;">103</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">south</span> <span style="color: #cc66cc;">27</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#41;</span></div></div>
<p><a href="http://nklein.com/wp-content/uploads/2009/10/basement.png"><img src="http://nklein.com/wp-content/uploads/2009/10/basement-120x150.png" alt="basement" title="basement" width="120" height="150" class="alignright size-thumbnail wp-image-1000" /></a><br />
I ended up with large calculations like that <b>(-&nbsp;103&nbsp;27&nbsp;30)</b> you see there.  It worked.  I got an okay looking floor-plan out of it.  But, it was obvious that it needed some rethinking.</p>
<p>My next thought was turtle graphics!  Tell things where to move.  Tell it to start drawing an interior wall.  Tell it where to move.  Tell it to start drawing a window.  Tell it where to move.  Tell it to stop drawing a window.  Etc.  This has possibilities, especially for an internal representation (which I need because I want to autoscale the drawing to fit on a sheet of paper well, so I can&#8217;t start drawing until I&#8217;ve determined the extents).  However, it seems awkward to go with all of the start/stop commands.  I am thinking of going more in this sort of direction:</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:300px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">;; The floor-plan stuff works in units. &nbsp;To facility readability, I am</span><br />
<span style="color: #808080; font-style: italic;">;; going to make some simple functions that use feet and inches instead</span><br />
<span style="color: #808080; font-style: italic;">;; of units. &nbsp;If you want centimeters and meters, go for it.</span><br />
<br />
<span style="color: #66cc66;">&#40;</span>flet <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>feet <span style="color: #66cc66;">&#40;</span>n<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* n <span style="color: #cc66cc;">12</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>inches <span style="color: #66cc66;">&#40;</span>n<span style="color: #66cc66;">&#41;</span> n<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; <span style="color: #66cc66;">&#40;</span>with-floor-plan <span style="color: #66cc66;">&#40;</span>#P<span style="color: #ff0000;">&quot;floor-plan.png&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">max-width</span> &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">8.0</span> &nbsp;<span style="color: #808080; font-style: italic;">; maximum width of output (units)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">max-height</span> &nbsp; &nbsp; <span style="color: #cc66cc;">10.0</span> &nbsp;<span style="color: #808080; font-style: italic;">; maximum height of output (units)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">dots-per-unit</span> <span style="color: #cc66cc;">300.0</span> &nbsp;<span style="color: #808080; font-style: italic;">; resolution of output</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">:</span><span style="color: #555;">grid</span> &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">; size of background-grid</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>compass <span style="color: #66cc66;">:</span><span style="color: #555;">north</span> <span style="color: #cc66cc;">180.0</span><span style="color: #66cc66;">&#41;</span> &nbsp; <span style="color: #808080; font-style: italic;">; draw north indication 180 degrees CCW from right</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>exterior-wall &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">; start drawing an exterior wall</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">closed</span> t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">; that closes at the end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>left <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; extend wall left 10 feet</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">; extend wall up 6 feet</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>window<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">; draw 30&quot; window</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; draw 8&quot; wall</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>door <span style="color: #66cc66;">:</span><span style="color: #555;">starts</span> <span style="color: #66cc66;">:</span><span style="color: #555;">hinge-side</span> &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; or :latch-side</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">opens</span> <span style="color: #66cc66;">:</span><span style="color: #555;">left</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">; or :right seen from direction of motion</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; this door goes up, so :left is to</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">; the left of the page</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>right <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>left <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; move four feet to the left</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>interior-wall<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>up <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>right <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>door <span style="color: #66cc66;">:</span><span style="color: #555;">starts</span> <span style="color: #66cc66;">:</span><span style="color: #555;">latch-side</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">:</span><span style="color: #555;">opens</span> <span style="color: #66cc66;">:</span><span style="color: #555;">right</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>right <span style="color: #66cc66;">&#40;</span>inches <span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>right-to <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">; move to an absolute left-right coordinate</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>move <span style="color: #66cc66;">&#40;</span>feet <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>feet <span style="color: #66cc66;">&#40;</span>+ <span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">1</span>/<span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>label <span style="color: #ff0000;">&quot;Bathroom&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Has anyone tackled this problem well already?  Or, have any suggestions of how to improve this?</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/10/dsl-for-drawing-floor-plans/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Sheeple Presentation from TC Lispers Meeting</title>
		<link>http://nklein.com/2009/10/sheeple-presentation-from-tc-lispers-meeting/</link>
		<comments>http://nklein.com/2009/10/sheeple-presentation-from-tc-lispers-meeting/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 06:03:19 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[TC Lisp]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=996</guid>
		<description><![CDATA[
Sheeple on Vimeo.
Presentation by Josh Marchán to the Twin Cities Lisp Users Group. The presentation is an introduction to the Sheeple  Prototype-based Object Oriented Programming Framework. The presentation was recorded on 2009-10-22.
]]></description>
			<content:encoded><![CDATA[<p><object width="640" height="400"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=7242003&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=7242003&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="400"></embed></object>
<p><a href="http://vimeo.com/7242003">Sheeple</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>Presentation by Josh Marchán to the Twin Cities Lisp Users Group. The presentation is an introduction to the Sheeple  Prototype-based Object Oriented Programming Framework. The presentation was recorded on 2009-10-22.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/10/sheeple-presentation-from-tc-lispers-meeting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Common Lisp vs. C/ASM:  Battle FFT</title>
		<link>http://nklein.com/2009/10/common-lisp-vs-casm-battle-fft/</link>
		<comments>http://nklein.com/2009/10/common-lisp-vs-casm-battle-fft/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 21:24:59 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cl-fft]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=987</guid>
		<description><![CDATA[Dr. David McClain of Refined Audiometrics sent me his code for interfacing with the Apple vDSP library.  Here it is along with a Makefile that I put together for it: vdsp-wrapper.tar.gz.  I have not actually run the code myself.  I started to convert his Lispworks FLI code to CFFI code, but bailed [...]]]></description>
			<content:encoded><![CDATA[<p>Dr. David McClain of <a href="http://refined-audiometrics.com/">Refined Audiometrics</a> sent me his code for interfacing with the Apple vDSP library.  Here it is along with a Makefile that I put together for it: <a href="http://nklein.com/wp-content/uploads/2009/10/vdsp-wrapper.tar.gz">vdsp-wrapper.tar.gz</a>.  I have not actually run the code myself.  I started to convert his Lispworks FLI code to CFFI code, but bailed on it in favor of making a minimal CFFI interface to <a href="http://www.fftw.org/">FFTW</a>.</p>
<p>Dr. McClain says that Apple&#8217;s vDSP library usually gains him 20% or so versus FFTW.  Further, there may well be plenty of alignment issues that should be taken into account in allocating the foreign buffers.  Regardless, here is my very basic wrapper around FFTW&#8217;s <b>fftw_plan_dft_1d()</b> function:  <a href="http://nklein.com/wp-content/uploads/2009/10/fftw.lisp">fftw.lisp</a>.</p>
<p>To get this working with SBCL on my Mac, I needed to get FFTW compiling 32-bit shared libraries.  By default, it compiles 64-bit static libraries on my system.</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">####### for 32-bit</span><br />
<span style="color: #000000; font-weight: bold;">%</span> <span style="color: #007800;">CC</span>=<span style="color: #ff0000;">&quot;gcc -arch i386&quot;</span> .<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--prefix</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #660033;">--enable-shared</span></div></div>
<p>Before I recompiled for 32-bit though, I manually moved the <b>libfftw3.*</b> files in <b>/usr/local/lib</b> into <b>libfftw3_64.*</b> files (of course, moving both the symlink <b>libfftw3.dylib</b> and its target).</p>
<p>Doing the FFI to FFTW does a 1,048,576-sample buffer in 0.202 seconds under SBCL 1.0.30 versus 0.72 seconds for <a href="http://nklein.com/software/cl-fft/">my all-Lisp version</a>.  Under Clozure-64, it takes 0.91 seconds versus nearly 30 seconds for the all-Lisp version.  I should check to make sure FFTW performs as well when my buffer is randomly filled instead of filled with a constant value.  But, yep.  There you have it.</p>
<p>So, certainly, if you need high-performance FFTs, you&#8217;ll want to FFI wrap something rather than use my all-Lisp version.  If you don&#8217;t need such high-performance, I give you no-hassle portability.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/10/common-lisp-vs-casm-battle-fft/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Adventures in Package Dependencies</title>
		<link>http://nklein.com/2009/10/adventures-in-package-dependencies/</link>
		<comments>http://nklein.com/2009/10/adventures-in-package-dependencies/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 16:04:13 +0000</pubDate>
		<dc:creator>pat</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cl-fft]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://nklein.com/?p=984</guid>
		<description><![CDATA[A variety of people have asked how the speed of my Lisp Fourier Transform Library compares to an FFI call to the FFTW Library.  I downloaded the FFTW Library, built it, and installed it.  Then, I tried to get someone else&#8217;s FFI wrappers for the FFTW Library going.  I worked on this [...]]]></description>
			<content:encoded><![CDATA[<p>A variety of people have asked how the speed of my <a href="http://nklein.com/software/cl-fft/">Lisp Fourier Transform Library</a> compares to an FFI call to the <a href="http://www.fftw.org/">FFTW Library</a>.  I downloaded the FFTW Library, built it, and installed it.  Then, I tried to get someone else&#8217;s FFI wrappers for the FFTW Library going.  I worked on this for two hours several weeks ago.  Today, I put almost an hour into it.  If it&#8217;s going to get done, I&#8217;m just going to have to write my own wrapper.</p>
<p>Here&#8217;s the problem&#8230;. package dependencies.  This wouldn&#8217;t be so much of a problem if all of the packages were in the <a href="http://cliki.net/">Cliki</a> and thus accessible to ASDF-Install.  Most of them are not.</p>
<p>To install fftw-ffi, I needed to install ch-image and clem.  One of those depended on ch-util.  That (and fftw-ffi) depended on ch-asdf.  That depended on smarkup.  Something there depended on cl-typesetting which depends on cl-pdf.  The ch-asdf also depended on cl-bibtex and ch-bib (who knows why? or where to find it?).  And, something in the above depended on cl-fad.  CL-FAD was the only one in that list that ASDF-Install could find on its own.  Several of the typesetting and PDF libraries along with the ch-image library did not build properly.  There was much reassuring ASDF-Install that everything was going to be okay even if there were no PGP signatures for half of this or if the PGP signatures didn&#8217;t jive with the owner of the website.  There was also much reassuring ASDF-Install that I wanted it to try to forge ahead even if it couldn&#8217;t build cl-bibtex for me.</p>
<p>I couldn&#8217;t find a list of projects supported by <a href="http://common-lisp.net/project/clbuild/">clbuild</a>, so I went to build <a href="http://darcs.net/">darcs</a> to fetch clbuild.  Did you know darcs needs the GNU Multi-precision Library?  I&#8217;m assuming it uses its own hashing functions that want big integers or something, but I wasn&#8217;t really expecting all of that.  So, after a half hour getting clbuild, it knows nothing about fftw-ffi.</p>
<p>Alright, maybe I managed to get enough stuff installed that I can just load fftw-ffi now?  No dice.  The fftw-ffi seems to have been generated with some tool that spits out an XML file and a corresponding C file.  Then, it tries to use special ASDF tricks to get the C file compiled.  Alas, these blow up on me.</p>
<div class="codecolorer-container lisp blackboard" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">debugger invoked on a ASDF<span style="color: #66cc66;">::</span><span style="color: #555;">FORMATTED-SYSTEM-DEFINITION-</span><span style="color: #b1b100;">ERROR</span><span style="color: #66cc66;">:</span><br />
&nbsp; <span style="color: #555;">don</span>'t recognize component type FFTW-FFI-GCC-XML-C-SOURCE-FILE</div></div>
<p>Erf.  Defeated.</p>
]]></content:encoded>
			<wfw:commentRss>http://nklein.com/2009/10/adventures-in-package-dependencies/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
