<?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>Conal Elliott &#187; geometry</title>
	<atom:link href="http://conal.net/blog/tag/geometry/feed" rel="self" type="application/rss+xml" />
	<link>http://conal.net/blog</link>
	<description>Inspirations &#38; experiments, mainly about denotative/functional programming in Haskell</description>
	<lastBuildDate>Thu, 25 Jul 2019 18:15:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.17</generator>
	<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2F&amp;language=en_US&amp;category=text&amp;title=Conal+Elliott&amp;description=Inspirations+%26amp%3B+experiments%2C+mainly+about+denotative%2Ffunctional+programming+in+Haskell&amp;tags=blog" type="text/html" />
	<item>
		<title>Thoughts on semantics for 3D graphics</title>
		<link>http://conal.net/blog/posts/thoughts-on-semantics-for-3d-graphics</link>
		<comments>http://conal.net/blog/posts/thoughts-on-semantics-for-3d-graphics#comments</comments>
		<pubDate>Mon, 23 Nov 2009 07:41:30 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[arrow]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[geometry]]></category>
		<category><![CDATA[semantics]]></category>
		<category><![CDATA[type class morphism]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=90</guid>
		<description><![CDATA[The central question for me in designing software is always What does it mean? With functional programming, this question is especially crisp. For each data type I define, I want to have a precise and simple mathematical model. (For instance, my model for behavior is function-of-time, and my model of images is function-of-2D-space.) Every operation [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Thoughts on semantics for 3D graphics

Tags: semantics, design, 3D, arrow, type class morphism, geometry

URL: http://conal.net/blog/posts/thoughts-on-semantics-for-3d-graphics/

-->

<!-- references -->

<!-- teaser -->

<p>The central question for me in designing software is always</p>

<blockquote>
  <p>What does it mean?</p>
</blockquote>

<p>With functional programming, this question is especially crisp.
For each data type I define, I want to have a precise and simple mathematical model.
(For instance, my model for behavior is function-of-time, and my model of images is function-of-2D-space.)
Every operation on the type is also given a meaning in terms of that semantic model.</p>

<p>This specification process, which is denotational semantics applied to data types, provides a basis for</p>

<ul>
<li>correctness of the implementation,</li>
<li>user documentation free of implementation detail,</li>
<li>generating and proving properties, which can then be used in automated testing, and</li>
<li>evaluating and comparing the elegance and expressive power of design decisions.</li>
</ul>

<p>For an example (2D images), some motivation of this process, and discussion, see Luke Palmer&#8217;s post <em><a href="http://lukepalmer.wordpress.com/2008/07/18/semantic-design/" title="Blog post by Luke Palmer">Semantic Design</a></em>.
See also my posts on the idea and use of <em><a href="http://conal.net/blog/tag/type-class-morphism/" title="Posts on type class morphisms">type class morphisms</a></em>, which provide additional structure to denotational design.</p>

<p>In spring of 2008, I started working on a functional 3D library, <a href="http://haskell.org/haskellwiki/FieldTrip" title="Library wiki page">FieldTrip</a>.
I&#8217;ve designed functional 3D libraries before as part of <a href="http://conal.net/tbag/" title="Project web page">TBAG</a>, <a href="http://conal.net/papers/ActiveVRML/" title="Tech report: &quot;A Brief Introduction to ActiveVRML&quot;">ActiveVRML</a>, and <a href="http://conal.net/Fran" title="Functional reactive animation">Fran</a>.
This time I wanted a semantics-based design, for all of the reasons given above.
As always, I want a model that is</p>

<ul>
<li>simple, </li>
<li>elegant, and </li>
<li>general.</li>
</ul>

<p>For 3D, I also want the model to be GPU-friendly, i.e., to execute well on (modern) GPUs and to give access to their abilities.</p>

<p>I hadn&#8217;t thought of or heard a model that I was happy with, and so I didn&#8217;t have the sort of firm ground I like to stand on in working on FieldTrip.
Last February, such a model occurred to me.
I&#8217;ve had this blog post mostly written since then.
Recently, I&#8217;ve been focused on functional 3D again for GPU-based rendering, and then Sean McDirmid <a href="http://mcdirmid.wordpress.com/2009/11/20/designing-a-gpu-oriented-geometry-abstraction-part-one/">posed a similar question</a>, which got me thinking again.</p>

<!--
**Edits**:

* 2008-02-09: just fiddling around
-->

<!-- without a comment or something here, the last item above becomes a paragraph -->

<p><span id="more-90"></span></p>

<h3>Geometry</h3>

<p>3D graphics involves a variety of concepts.
Let&#8217;s start with 3D geometry, using a <em>surface</em> (rather than a <em>solid</em>) model.</p>

<p>Examples of 3D (surface) geometry include</p>

<ul>
<li>the boundary (surface) of a solid box, sphere, or torus,</li>
<li>a filled triangle, rectangle, or circle,</li>
<li>a collection of geometry , and</li>
<li>a spatial transformation of geometry.</li>
</ul>

<h4>First model: set of geometric primitives</h4>

<p>One model of geometry is a set of geometric primitives.
In this model, <code>union</code> means set union, and spatial transformation means transforming all of the 3D points in all of the primitives in the set.
Primitives contain infinitely (even uncountably) many points, so that&#8217;s a lot of transforming.
Fortunately, we&#8217;re talking about what (semantics), and not how (implementation).</p>

<p><em>What is a geometric primitive?</em></p>

<p>We could say it&#8217;s a triangle, specified by three coordinates.
After all, computer graphics reduces everything to sets of triangles.
Oops &#8212; we&#8217;re confusing semantics and implementation.
Tessellation <em>approximates</em> curved surfaces by sets of triangles but loses information in the process.
I want a story that includes this approximation process but keeps it clearly distinct from semantically ideal curved surfaces.
Then users can work with the ideal, simple semantics and rely on the implementation to perform intelligent, dynamic, view-dependent tessellation that adapts to available hardware resources.</p>

<p>Another model of geometric primitive is a function from 2D space to 3D space, i.e., the &#8220;parametric&#8221; representation of surfaces.
Along with the function, we&#8217;ll probably want some means of describing the subset of 2D over which the surface is defined, so as to trim our surfaces.
A simple formalization would be</p>

<pre><code>type Surf = R2 -&gt; Maybe R3
</code></pre>

<p>where</p>

<pre><code>type R  -- real numbers
type R2 = (R,R)
type R3 = (R,R,R)
</code></pre>

<p>For shading, we&#8217;ll also need normals, and possibly tangents &amp; bitangents,
We can get these features and more by including derivatives, either just first derivatives or all of them.
See my <a href="http://conal.net/blog/tag/derivative/" title="Posts on derivatives">posts on derivatives</a> and paper <em><a href="http://conal.net/papers/beautiful-differentiation/" title="Paper: Beautiful differentiation">Beautiful differentiation</a></em>.</p>

<p>In addition to position and derivatives, each point on a primitive also has material properties, which determines how light is reflected by and transmitted through the surface at the point.</p>

<pre><code>type Surf = R2 -&gt; Maybe (R2 :&gt; R3, Material)
</code></pre>

<p>where <code>a :&gt; b</code> contains all derivatives (including zeroth) at a point of a function of type <code>a-&gt;b</code>.
See <em><a href="http://conal.net/blog/posts/higher-dimensional-higher-order-derivatives-functionally/" title="blog post">Higher-dimensional, higher-order derivatives, functionally</a></em>.
We could perhaps also include derivatives of material properties:</p>

<pre><code>type Surf = R2 :~&gt; Maybe (R3, Material)
</code></pre>

<p>where <code>a :~&gt; b</code> is the type of infinitely differentiable functions.</p>

<h4>Combining geometry values</h4>

<p>The <code>union</code> function gives one way to combine two geometry values.
Another is morphing (interpolation) of positions and of material properties.
What can the semantics of morphing be?</p>

<p>Morphing betwen two <em>surfaces</em> is easier to define.
A surface is a function, so we can interpolate <em>point-wise</em>: given surfaces <code>r</code> and <code>s</code>, for each point <code>p</code> in parameter space, interpolate between (a) <code>r</code> at <code>p</code> and (b) <code>s</code> at <code>p</code>, which is what <code>liftA2</code> (on functions) would suggest.</p>

<p>This definition works <em>if</em> we have a way to interpolate between <code>Maybe</code> values.
If we use <code>liftA2</code> again, now on <code>Maybe</code> values, then the <code>Just</code>/<code>Nothing</code> (and <code>Nothing</code>/<code>Just</code>) cases will yield <code>Nothing</code>.
Is this semantics desirable?
As an example, consider a flat square surface with hole in the middle.
One square has a small hole, and the other has a big hole.
If the size of the hole corresponds to size of the portion of parameter space mapped to <code>Nothing</code>, then point-wise interpolation will always yield the larger hole, rather than interpolating between hole sizes.
On the other hand, the two surfaces with holes might be <code>Just</code> over exactly the same set of parameters, with the function determining how much the <code>Just</code> space gets stretched.</p>

<p>One way to characterize this awkwardness of morphing is that the two functions (surfaces) might have <em>different domains</em>.
This interpretation comes from seeing <code>a -&gt; Maybe b</code> as encoding a function from a <em>subset</em> of <code>a</code> (i.e., a <em>partial</em> function on <code>a</code>).</p>

<p>Even if we had a satisfactory way to combine surfaces (point-wise), how could we extend it to combining full geometry values, which can contain any number of surfaces?
One idea is to model geometry as an <em>structured</em> collection of surfaces, e.g., a list.
Then we could combine the collections element-wise.
Again, we&#8217;d have to deal with the possibility that the collections do not match up.</p>

<h3>Surface tuples</h3>

<p>Let&#8217;s briefly return to a simpler model of surfaces:</p>

<pre><code>type Surf = R2 -&gt; R3
</code></pre>

<p>We could represent a collection of such surfaces as a structured collection, e.g., a list:</p>

<pre><code>type Geometry = [Surf]
</code></pre>

<p>But then the type doesn&#8217;t capture the number of surfaces, leading to mismatches when combining geometry values point-wise.</p>

<p>Alternatively, we could make the number of surfaces explicit in the type, via tuples, possibly nested.
For instance, two surfaces would have type <code>(Surf,Surf)</code>.</p>

<p>Interpolation in this model becomes very simple.
A general interpolator works on vector spaces:</p>

<pre><code>lerp :: VectorSpace v =&gt; v -&gt; v -&gt; Scalar v -&gt; v
lerp a b t = a ^+^ t*^(b ^-^ a)
</code></pre>

<p>or on affine spaces:</p>

<pre><code>alerp :: (AffineSpace p, VectorSpace (Diff p)) =&gt;
         p -&gt; p -&gt; Scalar (Diff p) -&gt; p
alerp p p' s = p .+^ s*^(p' .-. p)
</code></pre>

<p>Both definitions are in the <a href="http://haskell.org/haskellwiki/vector-space" title="Library wiki page">vector-space</a> package.
That package also includes <code>VectorSpace</code> and <code>AffineSpace</code> instances for both functions and tuples.
These instances, together with instances for real values suffice to make (possibly nested) tuples of surfaces be vector spaces and affine spaces.</p>

<h3>From products to sums</h3>

<p>Function pairing admits some useful isomorphisms.
One replaces a product with a product:</p>

<!-- $$(a to b) times (a to c) cong a to (b times c)$$ -->

<pre><code>(a → b) × (a → c) ≅ a → (b × c)
</code></pre>

<p>Using this product/product isomorphism, we could replace tuples of surfaces with a single function from <em>R<sup>2</sup></em> to tuples of <em>R<sup>3</sup></em>.</p>

<p>There is also a handy isomorphism that relates products to sums, in the context of functions:</p>

<!-- $$(b to a) times (c to a) cong (b + c) to a$$ -->

<pre><code>(b → a) × (c → a) ≅ (b + c) → a
</code></pre>

<p>This second isomorphism lets us replace tuples of surfaces with a single &#8220;surface&#8221;, if we generalize the notion of surface to include domains more complex than <em>R<sup>2</sup></em>.</p>

<p>In fact, these two isomorphisms are uncurried forms of the general and useful Haskell functions <code>(&amp;&amp;&amp;)</code> and <code>(|||)</code>, defined on arrows:</p>

<pre><code>(&amp;&amp;&amp;) :: Arrow       (~&gt;) =&gt; (a ~&gt; b) -&gt; (a ~&gt; c) -&gt; (a ~&gt; (b,c))
(|||) :: ArrowChoice (~&gt;) =&gt; (a ~&gt; c) -&gt; (b ~&gt; c) -&gt; (Either a b ~&gt; c)
</code></pre>

<p>Restricted to the function arrow, <code>(|||) == either</code>.</p>

<p>The second isomorphism, <code>uncurry (|||)</code>, has another benefit.
Relaxing the domain type to allow sums opens the way to other domain variations as well.
For instance, we can have types for triangular domains, shapes with holes, and other flavors of bounded and unbounded parameter spaces.
All of these domains are two-dimensional, although they may result from several patches.</p>

<p>Our <code>Geometry</code> type now becomes parameterized:</p>

<pre><code>type Geometry a = a -&gt; (R3,Material)
</code></pre>

<p>The first isomorphism, <code>uncurry (&amp;&amp;&amp;)</code>, is also useful in a geometric setting.
Think of each component of the range type (here <code>R3</code> and <code>Material</code>) as a surface &#8220;attribute&#8221;.
Then <code>(&amp;&amp;&amp;)</code> merges two compatible geometries, including attributes from each.
Attributes could include position (and derivatives) and shading-related material, as well as non-visual properties like temperature, elasticity, stickiness, etc.</p>

<p>With this flexibility in mind, <code>Geometry</code> gets a second type parameter, which is the range type.
Now there&#8217;s nothing left of the <code>Geometry</code> type but general functions:</p>

<pre><code>type Geometry = (-&gt;)
</code></pre>

<p>Recall that we&#8217;re looking for a <em>semantics</em> for 3D geometry.
The <em>type</em> for <code>Geometry</code> might be abstract, with <code>(-&gt;)</code> being its semantic model.
In that case, the model suggests that <code>Geometry</code> have all of the same type class instances that <code>(-&gt;)</code> (and its full or partial applications) has, including <code>Monoid</code>, <code>Functor</code>, <code>Applicative</code>, <code>Monad</code>, and <code>Arrow</code>.
The semantics of these instances would be given by the corresponding instances for <code>(-&gt;)</code>.
(See posts on <a href="http://conal.net/blog/tag/type-class-morphism/" title="Posts on type class morphisms">type class morphisms</a> and the paper <em><a href="http://conal.net/blog/posts/denotational-design-with-type-class-morphisms/" title="blog post">Denotational design with type class morphisms</a></em>.)</p>

<p>Or drop the notion of <code>Geometry</code> altogether and use functions directly.</p>

<h3>Domains</h3>

<p>I&#8217;m happy with the simplicity of geometry as functions.
Functions fit the flexibility of programmable GPUs, and they provide simple, powerful &amp; familiar notions of attribute merging (<code>(&amp;&amp;&amp;)</code>) and union (<code>(|||)</code>/<code>either</code>).</p>

<p>The main question I&#8217;m left with: what are the domains?</p>

<p>One simple domain is a one-dimensional interval, say [-1,1].</p>

<p>Two useful domain building blocks are sum and product.
I mentioned sum above, in connection with geometric union (<code>(|||)</code>/<code>either</code>)
Product combines domains into higher-dimensional domains.
For instance, the product of two 1D intervals is a 2D interval (axis-aligned filled rectangle), which is handy for some parametric surfaces.</p>

<p>What about other domains, e.g., triangular, or having one more holes?  Or multi-way branching surfaces?  Or unbounded?</p>

<p>One idea is to stitch together simple domains using sum.
We don&#8217;t have to build any particular spatial shapes or sizes, since the &#8220;geometry&#8221; functions themselves yield the shape and size.
For instance, a square region can be mapped to a triangular or even circular region.
An infinite domain can be stitched together from infinitely many finite domains.
Or it can be mapped to from a single finite domain.
For instance, the function <code>x -&gt; x / abs (1-x)</code> maps [-1,1] to [-∞,∞].</p>

<p>Alternatively, we could represent domains as typed predicates (characteristic functions).
For instance, the closed interval [-1,1] would be <code>x -&gt; abs x &lt;= 1</code>.
Replacing <code>abs</code> with <code>magnitude</code> (for <a href="http://hackage.haskell.org/packages/archive/vector-space/latest/doc/html/Data-VectorSpace.html#t%3AInnerSpace">inner product spaces</a>), generalizes this formulation to encompass [-1,1] (1D), a unit disk (2D), and a unit ball (3D).</p>

<p>I like the simple generality of the predicate approach, while I like how the pure type approach supports interpolation and other pointwise operations (via <code>liftA2</code> etc).</p>

<h3>Tessellation</h3>

<p>I&#8217;ve intentionally formulated the graphics semantics over continuous space, which makes it resolution-independent and easy to compose.
(This formulation is typical for 3D geometry and 2D vector graphics.
The benefits of continuity apply to generally <a href="http://conal.net/Pan/Gallery" title="Pan image gallery">imagery</a> and to <a href="http://conal.net/Fran/tutorial.htm" title="Animated tutorial: &quot;Composing Reactive Animations&quot;">animation/behavior</a>.)</p>

<p>Graphics hardware specializes in finite collections of triangles.
For rendering, curved surfaces have to be <em>tessellated</em>, i.e., approximated as collections of triangles.
Desirable choice of tessellation depends on characteristics of the surface and of the view, as well as scene complexity and available CPU and GPU resources.
Formulating geometry in its ideal curved form allows for automated analysis and choice of tessellation.
For instance, since triangles are linear, the error of a triangle relative to the surface it approximates depends on how <em>non-linear</em> the surface is over the subset of its domain corresponding to the triangle.
Using <a href="http://en.wikipedia.org/wiki/Talk:Interval_arithmetic" title="Wikipedia page on interval analysis/arithmetic">interval analysis</a> and <a href="http://conal.net/blog/tag/derivative/" title="Posts on derivatives">derivatives</a>, non-linearity can be measured as a size bound on the second derivative or a range of first derivative.
Error could also be analyzed in terms of the resulting image rather than the surface.</p>

<p>For a GPU-based implementation, one could tessellate dynamically, in a &#8220;geometry shader&#8221; or (I presume) in a more general framework like CUDA or OpenCL.</p>

<h3>Abstractness</h3>

<p>A denotational model is &#8220;fully abstract&#8221; when it equates observationally equivalent terms.
The parametric model of surfaces is not fully abstract in that reparameterizing a surface yields a different function that looks the same as a surface.
(Surface reparametrization alters the relationship between domain and range, while covering exactly the same surface, geometrically.)
Properties that are independent of particular parametrization are called &#8220;geometric&#8221;, which I think corresponds to full abstraction (considering those properties as semantic functions).</p>

<p>What might a fully abstract (geometric) model for geometry be?</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=90&amp;md5=3a9d3f59c6f8c7d6110dbfab2555bddf"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/thoughts-on-semantics-for-3d-graphics/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fthoughts-on-semantics-for-3d-graphics&amp;language=en_GB&amp;category=text&amp;title=Thoughts+on+semantics+for+3D+graphics&amp;description=The+central+question+for+me+in+designing+software+is+always+What+does+it+mean%3F+With+functional+programming%2C+this+question+is+especially+crisp.+For+each+data+type+I+define%2C+I+want...&amp;tags=3D%2Carrow%2Cdesign%2Cgeometry%2Csemantics%2Ctype+class+morphism%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
