So, I currently live in a walkup in New York City. No doorman, no lobby. My frequent Amazon orders come in via a variety of carriers  Fedex, UPS, USPS, and various local logistics third parties that Amazon partners with. The standard protocol is that the deliveryman leaves packages inside my mailroom area, behind the (locked) front door. Quite often, the deliveryman does not have keys to my building's front door, which means he isn't able to leave the package. This makes receiving deliveries quite difficult for me, since I have to take time off to be home to await packages. Even worse, the delivery window is usually "somewhere between 10AM and 8PM" so I can't even go anywhere for fear of missing the package.
All I needed was a way to remotely open the front door when the deliveryman arrives so he can drop off the package. This seemed like an idea for an electronics project!
Instead of the Arduino, I decided to get an ESP8266, which includes a Wifi antenna. There's an arduinocompatible driver for it so I can use the standard Arduino Studio workflow to compile and upload firmware to it via a USBtoserial FTDI adapter.
The server code is 59 lines of typescript at https://github.com/talyian/door_server/blob/master/src/index.ts. Dependencies:
Nothing particularly outrageous, just a standard nodejs+express server that accepts a /door query and holds it open while waiting on another client to respond on the /open endpoint with the appropriate secret token. The token in question is simply a global variable, secret
, but without too much further work this could be adapted to support multiple doors and email addresses.
// endpoint for Button to notify us
app.get('/button', function(req, resp, next) {
var mailer = Sendmail();
secret = Crypto.randomBytes(32).toString('hex');
mailer({
'from': 'doorserver@app.example.com'
'to': 'adminemail@example.com'
'subject': 'door',
'html': `Requesting Access: <a href="http://${req.hostname}/open/${secret}">Click Here</a>`
}, function(err: any, reply: any) {
if (!err) {
...
The client side code is 106 lines of Arduinoflavored C. (https://gist.github.com/talyian/58b93d15451dcb418808213faa7e5a35) Okay, I'll be the first to admit, I'm not an Arduino expert. I kind of bumbled my way through implementing a statemachineviagiantswitchstatement in the main loop for this application, although it smells like something you'd really want a coroutine library for.
void loop() {
static int state = STARTING, counter = 0, status = 0;
switch(state) {
case STARTING:
status = WiFi.status();
if (status == WL_CONNECTED) {
state = READY;
}
case READY: // connected to wifi, wait for button press
if (check_button_pressed()) {
state = NOTIFYING;
}
break;
// Ask the internet for permission to open the door
// will mutate state when done
case NOTIFYING: return client_loop(state);
...
void client_loop (int &main_state) {
enum { BEGIN, CONNECTING, RECEIVING, ...
static int state = BEGIN;
switch(state) {
...
case RECEIVING:
if (!client.connected()) { // disconnected from web server
main_state = READY;
state = BEGIN;
return;
}
else if (!client.available()) { // waiting on bytes to come in
return;
}
// process response!
String content = client.readString();
....
My door intercom unit is a Lee Dan IR204E station. I found some schematics on www.leedan.com website, but mainly I just poked around with a multimeter to figure out which wire led where. There are 4 wires, two of which power the buzzer and two of which control the door.
Currently, the USB connection is providing the power. This is kind of a pain  I'd like to drive it directly off the 11V wires powering the doorbell itself. I have a few buck converters lying around I can use for this.
I need to move this project to a prototype board to cut down on the bulk.
My phone doesn't do a great job of getting emails reliably. I may want to use twilio or something to send texts instead. Also, instead of having to click the link in the email, perhaps just replying "open" or "Y"/"N" would be easier to do from my phone's lock screen.
]]>So this month's procedural generation challenge was 'mountains.' Mountains are one of the most commonly encountered procedural generation subjects, since they are easy to generate using a 2D heightmap. I decided to start with the basic strategy of "simplex noise on a plane" and work out what kind of enhancements I could add from there. This project turned out to be a good exploration into building a noise function as well.
I won't cover this in too great of detail, but broadly speaking you need to be able to do a couple things: Generate a 2D heightmap, and then convert that heightmap to a 3D view. One simple way I could think of is to write out an image to a file, and loading it up in Blender or other program as a heightmap. You could also generate a 3D mesh from the heightmap (I took this route).
Instead of using some variant of Math.Random()
, which is for generating a single pseudorandom stream of data, I'd rather use some hash function applied to the x and y coordinates of the heightmap pixel I'm sampling. A wellwritten hash function should produce pseudorandom output when fed nonrepeating inputs, and this ensures determinism.
Warning! I came up with this hash function (truncating digits of sin()
) without much thought. It doesn't pass as a quality hash function by most metrics. It's random enough for the purposes of this post, but do your research before blindly copying this code!
let hash v = (sin (v * 100.0) * 100.0 + 100.0) % 1.0
let hash2 a b = hash(a + hash(b))
let noise x y = hash2 x y
Hmmm. The last hash function was a bit too much like static. Lets try to tone down how much it changes by only changing every 1 unit of distance (which i've scaled to about 1/10th of a screen).
let squarenoise x y = hash2 (floor x), (floory)
Alright, now lets get rid of those hard edges by taking the 4 corners of each square and blending them together. If wonder what the operation is for "linearly blending 4 values in 2D", you can search for things like "bilinear interpolation". This gets us a continuous noise function.
Note that this smoothnoise
function blends the corners of the square containing the current point. We could also have written a function that calculates the noise value at the corners of a containing equilateral triangle (which is also called a simplex). The simplex experiences less 'bias' in nonaligned directions and scales better into higher dimensions. I actually used a simplexbased smoothnoise, but it involves a small bit of trigonometry so I figured the squarebased noise cell would be easier to understand.
// linearly interpolate between two values A, B
let lerp a b ratio =
(1.0  ratio) * a + ratio * b
// bilinearly interpolate between 4 values
let bilerp (a,b,c,d) (x,y) =
lerp (lerp a b x) (lerp c d x) y
let smoothnoise x y =
let fx, fy = floor x, floor y
let rx, ry = x % 1.0, y % 1.0
(bilerp
(squarenoise fx fy,
squarenoise (fx + 1.0) fy,
squarenoise fx (fy + 1.0),
squarenoise (fx + 1.0) (fy + 1.0))
(rx, ry))
Notice a problem with the previous continuous noise function? The level of detail is too low! If we make each square smaller, we eventually get back to our original problem, which was that the noise is too random!. What we want is called coherent noise, which means that between any two nearby points, the noise doesn't change too much. One easy way to get coherent noise is to Take the noise and overlay itself against smaller copies of itself. Each smaller iteration adds smaller detail, but that detail doesn't have as large an effect. As an analogy, you can think the result of mixing pebbles, boulders, and sand together. One thing you'll notice is instead of just adding noise (2^{i} . x), i use (i + 2^{i} . x). This is to deal with an issue where near x=0, all the noise values tend to be the same value, breaking the randomness. Adding a slight offset to each iteration removes the fixed point and randomness is restored.
let octavenoise x y =
List.sum [for i in 1..8 > (2.0 ** i) * smoothnoise (i + x * 2.0**i) (i + y * 2.0**i)]
I the edge of my zone to be pretty flat so I can admire the mountains in the center. One easy way is to multiply by a curve that approaches 0 in all directions but is 1 near the center:
// N is a scaling value  larger produces a sharp, narrow peak
// smaller produces a smoother wider curve
let N = 1
let curve x y = 1.0 / (1.0 + N * x * x + N * y * y)
let finalFunction x y =
(octavenoise x y) * (curve x y)
As you can see, we can iteratively go from "random values  wat" to a nice, mountainshaped mound! Here are few pictures of stuff I continued to experiment with:
Early On, I tried to export the heightmap to Blender to render. This turned out to be more work than it was worth, but here's a render from when the height function was in "island mode": if y < 0 then y = 0
I had some code for simple spherical harmonic lighting in GLSL available, so I tried a few lighting schemes. The results were interesting, although I copied the spherical harmonics values from somewhere on the internet instead of doing true imagebased harmonics calculations.
There's a super easy way to add a "buriedinsnow effect" to a mountain :) Just take the heightmap, blur it, and use the blurred map as a heightmap for a second plane. "blurring" the heightmap means that the peaks of the snow are lower than the peaks of the rock, but the troughs are higher. This means that the snow covers all the low areas. Then just make minor adjustments to vertical scale and height of the snow to match how much "snowiness" you want in your scene.
To go from a single mountain to a range of mountains, I just decreased the scale of the noise. Also, /u/stewsters on reddit commented that the snow could just as easily be used for sand as well. I liked that idea, so I rendered a sand preview as well.
]]>
I was reading over some old blog posts and stumbled upon a series of blog posts at Comparing a Machine Learning Algorithm Implemented in F# and OCaml and kNN Algorithm in golang and Haskell on "kNN example code" in golang and Haskell. Others on the /r/haskell reddit have already pointed out the applestopeaches comparison going on here, but I think this is a fine way to illustrate a few gotchas / features of F# that may not be super obvious.
To begin, here are some of the numbers on my machine: In the interests of "benchmarking is hard" and isolating just run time, these times do not include compile times (fsc
is an order of magnitude slower) Also, the .NET runtime should be faster than Mono, but I haven't tested on a Windows machine.
$ time ./golangknn
real 0m4.265s
$ time ./golangknnspeedup
real 0.790s
$ time mono fsharpknn.exe
real 18.803s
At the core of the code, the kNN classifier just calls a distance
function to compare two images, and selects the minimum value. This means any optimizations to the distance
function go a long way towards net speedup of the code base. Here's the original F# code:
let distance (p1: int[]) (p2: int[]) =
Math.Sqrt (float(Array.sum (Array.map2 ( fun a b > (pown (ab) 2)) p1 p2) ))
First off, pown foo 2
is going to be slower than foo * foo
, F# does not optimize for that special case. Switching that out instantly gives us a 150% speed improvement:
let distance (p1: int[]) (p2: int[]) =
Math.Sqrt (float(Array.sum (Array.map2 ( fun a b > (ab) * (ab))) p1 p2) ))
$ time mono fsharpknn.exe
> real 11.934s
Secondly, F# doesn't inline functions terribly well  imperativestyle code and tailrecursive functions tend to both generate much more efficient IL than Array.map
and Array.sum
. Here's a tail recursive version:
let distance (p1: int[]) (p2: int[]) =
let rec iterate s = function
 1 > sqrt (float s)
 n > let v = p1.[n]  p2.[n] in iterate (s + v * v) (n1)
iterate 0 (p1.Length1)
$ time mono fsharpknn.exe
> real 4.541s
Aha! We're in the ballpark of the naive golang implementation. Which makes sense, because the above code does basically the same sequence of operations as the golang version (except it should be slightly faster since it operates on int arrays instead of float arrays)
Now, lets see if we can apply the extra set of optimizations in the spedup golang version to our F# code:
The optimized go version parallelizes the computation using goroutines, going from this:
total := 0
for _, test := range validationSample {
if is_correct(test) {
total++
}
}
to this:
total := 0
channel := make(chan float32)
for _, test := range validationSample {
go func(t) {
if is_correct(t) {
channel < 1
} else {
channel < 0
}
})(test)
}
for i := 0; i < len(validationSample); i++ {
total += < channel
}
FSharp's analog to goroutines is the async
Monad computation expression. To parallelize the classification of validationSample, we change:
let num_correct =
validationsample
> Array.map (fun p > if (classify p.Pixels ) = p.Label then 1 else 0)
> Array.sum
by changing the map to return a an array of async objects, which Async.Parallel
dispatches to a task queue and Async.RunSynchronously
unwraps back into a simple int[]
object.
let num_correct =
validationSample
> Array.map (fun p > async { return if (classify p.Pixels ) = p.Label then 1 else 0 })
> Async.Parallel
> Async.RunSynchronously
> Array.sum
$ time mono fsharpknn.exe
real 0m2.194s
Alternatively, the FSharp.Collections.ParallelSeq
module from the Powerpack would be useful here, providing an inplace substitution into our original code:
let num_correct =
validationsample
> PSeq.map (fun p > if (classify p.Pixels ) = p.Label then 1 else 0)
> PSeq.sum
Changing our distance function further cuts the time down
let distance (p1: int[]) (p2: int[]) bailout =
....
 n > if s > bailout then s else let v = p1.[n]  p2.[n] in iterate (s + v * v) (n1)
real 1.724s
At this point, we've improved the time from the inital F# version over tenfold from 18s to 1.7s, by inlining the expensive parts of the distance
function and using the same techniques that were applied to the golang implementation. To further approach the speed of C, work could be done by writing vectorized code using the new System.Numerics.Vector libraries.
My second /r/proceduralgeneration contest entry! I spent less effort on this than the previous round, but apparently there was just a lot less participation in general because of the steep hurdle of having to create a game in order for creating a level to be particularly meaningful. Instead of using F#, I decided to go with Typescript for this round, since I wanted an interactive online demo level that people could play around with. This was my first time using Typescript but it turned out to be pretty nice to work with; The platformer/level generator wound up just shy of 300 lines of code, most of which were not involved in actual level generation.
The core of the generation function is at Github:level.ts. I basically roll a die, randomly chooseing a direction up, upleft, upright, right, or down. Before going in any given direction, I make sure it doesn't interfere too much with the previous direction (for example, I wouldn't go up, then immediate go down.) To build the level, I start with an initial platform at 0, 0, pick a direction, build a random number of platforms out in that direction, and then repeat. In the following example code, for example, I would start with an initial platform, build right, then right again, then upleft.
var platform = new Box(0, 0, 1, 1);
platform = linkRight(platform, 3, 1, 1); // make a 1x1 box 3 units right from the first one
platform = linkRight(platform, 1, 2, 10); // make a 2x10 box 1 unit away from the second box
platform = linkUpl(platform); // make a box up and to the left from the third one
However, a level that goes in a random direction for every platform would turn out looking pretty .. random. While the random walk pattern looks nice for creating a cavelike network structure, it feels pretty aimless for a platformer level. It helps when you have a stronger direction of flow, both locally at the small scale (platforms form 'set pieces' that go in a particular direction) and at the large scale (the entire level doesn't double back on itself too often). For the first point, if I want to build platforms towards the right, I might as well build 3 or 4 platforms in a series. I encapsulate this in the repeat function, which will update the state of the platform and repeatedly call a link function.
platform = repeat(3, linkRight);
For the second point, the generator tracks the last direction it was building new platforms in. Certain transitions are forbidden. RIGHT>RIGHT [which results in a long horizontal string of platforms towards the right] is forbidden, as well as "drops of faith" (large downward drops marked by caution blocks) when you've just been ascending up or leftwards (to prevent dropping back onto previously placed platforms).
var new_dir = randarr([RIGHT, RIGHT, RIGHT, UPRIGHT, UPLEFT, UP, DROP, DROP, DROP]);
switch (new_dir) {
...
case DROP:
if (prev_dir == UPLEFT  prev_dir == UP) continue;
newbox.navi = "drop";
yield * repeat(randi(1, 3), drop); break;
The level looks kind of boring when it's just a bunch of platforms, so I scatter little decorations, like rocks, bushes, and grass, randomly throughout the level. Since we want to keep the distribution uniform, the number of doodads on each block is proportional to the width of the block.
function * getDoodads() {
...
for(var box of this.boxes) {
for(var j = box.w * 2; j > 0;)
if (random() < 0.2)
yield [randarr(["bush", "grass", "rock",
"grass", "bush", "grass",
"rock", "mushroomBrown", "mushroomRed"]),
new Point(box.x + 0.5 + random() * (box.w1), box.t + 0.5)];
}
...
}
Kind of a lastminute feature I threw in: save completed levels to Local Storage. 1) This gives you a sense of progress, and 2) it allows players to share particularly interesting level seeds with each other (or with me, if you want to report a bug).
My goals here were to implement, using F# and OpenTK, a procedural castle village generator. The code should be as clean as you should expect from a monthlong programming challenge and should be simple, elegant, and powerful.
The "front end" of the generator are a set of functions that generate Tree
s, Tower
s, Column
s, etc. As you will
see from the tree example below, the front end is concerned purely with construction rules. For example, the three
basic rules for producing a tower are:
In code, this looks like:
let rec create () =
let stories = rand.Next(4, 8)
let segments = generateSegments (Options.sides) stories
let tower = Capped(segments, Options.topstyle ())
let tower = match rand.Next(4) with
 0 > Buttress(tower, [Capped(generateSegments 4 3, SpireStyle.ConeNoFlag)])
 1 > Foundation(tower)
 _ > tower
Ultimately all the highlevel types like Tower
get converted into a set of primitive types  cylinders, blocks, vertexlists,
etc, in the backend understands. This provides a uniform representation of objects. Utility classes such as boundingboxes
and spatial hashes only ever need to deal with "boxes" and "lists of vertexes" instead of having separate logic
for each object they interact with.
One example of backend logic is calculating the convex hull of a given set of points. This
is useful because we first generate a bunch of structures, and need to figure out
where to build the walls so that they surround all the structures we've built. The algorithm implemented here
is the Graham scan, an O(n log n)
complexity algorithm. To understand this function, it may be
helpful to translate it piecebypiece into English.
English  F#  

Start with the leftmost point  let firstpt = List.minBy (fun (v:Vector3) > v.X) points 

To find the next point, take all the other points ...  `let nextpt pt = List.except [pt] points  >` 
and find the one with the smallest counterclockwise angle  List.reduce (fun p q > if Matrix2(p.Xzpt.Xz,q.Xzpt.Xz).Determinant < 0.0f then q else p) 

Keep taking the next point until you find the first point again  List.unfold (fun p > let n = nextpt p in if n = firstpt then None else Some(p, n)) firstpt 
module ConvexHull =
let FromPoints points =
let firstpt = List.minBy (fun (v:Vector3) > v.X) points
let nextpt pt =
let firstpoint p q = if Matrix2(p.Xzpt.Xz,q.Xzpt.Xz).Determinant < 0.0f then q else p
List.except [pt] points > List.reduce firstpoint
List.unfold (fun p > let n = nextpt p in if n = firstpt then None else Some(p, n)) firstpt
I used a spatial hash to detect collisions when placing objects. When placing a new object, we check for collisions, spiraling outwards from the initial point until we find a location. Not too much to say here, other than if i had more time, I would have preferred using some kind of tree structure instead for more flexibility. Since I wasn't comparing objectobject collisions directly, I could only resolve collisions at the size of a spatial hash cell. This led to a tradeoff between hash resolution (lower resolution means larger gaps between objects) and performance (each insertion and collision check is O(V) where V is the volume of the inserted object)
A tree is one of the most common recursively generated objects out there. There is a fundamental fractal nature about trees that makes it very suitable for generation algorithms.
type Tree =
 Leaf of Vector3
 Branch of Vector3 * float32 * Tree list
The body of the generate
function is three lines: 1 to create a Leaf
node, 1 to create a random point pos
, and 1 and create a Branch
ending on pos
, recursively containing between 2 and 5 subbranches.
let rec generate = function
 0 > Leaf(Vector3.One)
 n > let pos = 0.6f * Vector3.Normalize (r.NextV3(0.5f, 0.5f, 0.2f, 0.6f, 0.5f, 0.5f))
Branch(pos, 0.03f * float32 n, [for i in 0..r.Next(2, 6) > generate (n1)])
The body of the _toPolygon
function is below. Leaves are converted to dark green blocks.
The Branch part is slightly more involved. We find the rotation+scale matrix c
based
on the endpoint of the current branch, and recursively apply it to all child nodes.
After the recursive step, I have a list of child nodes, comprising of a combination of rectangular
Block
objects and Offset
matrices representing a nested transformation.
Both Block
s and Offset
s are primitive types that my rendering function recognizes and can convert to
a triangle array for rasterization.
let rec private _toPolygon (mat:Matrix4) = function
 Leaf(dim) > [ Offset(mat, [Block(Color4.DarkGreen, Vector3.Zero, dim) ])]
 Branch(vec, width, children) >
let b = Vector3.Cross(Vector3.UnitY, vec)
let rot = Matrix4.CreateFromAxisAngle(b, Vector3.CalculateAngle(Vector3.UnitY, vec))
let c = if b.Length > 0.001f then rot * Matrix4.CreateScale (vec.Length) else Matrix4.Identity
let cc = List.collect (fun (b, a) > _toPolygon (Matrix4.CreateTranslation (4.0f * b * Vector3.UnitY)) a) children
[ Offset(c * mat, Block(Color4.Bisque.Mult(0.2), Vector3.Zero, Vector3(width, 4.0f, width)) :: cc)]
let toPolygon t = match _toPolygon Matrix4.Identity t with  [ Offset(c, f) ] > f  n > n
Procedural Generation is about controlled chaos. Instead of manually designing individual elements, we have to specify a design space of what kinds of structure the program randomly generates. This theme came up multiple times during the course of this project. A couple examples:
1) I put off implementing the spatial hash until halfway through the project. Randomly placed Points (https://lucyuki.files.wordpress.com/2015/03/screenshot20150216at45634pm.png) aren't really interesting in the long run. All the interesting details about placement happen around questions like "what is the minimum gap between two adjacent objects?" "Do nearby objects influence each other's orientation?" "do objects of similar size cluster together?" In the end, I found a pretty dumb generation strategy (generate large flat areas first, then add a few small objects to break up the space, then add large castle structures, then fill in the gaps with a final set of smaller objects" that yielded the results I wanted  busy, but not too crowded. Since each new object had to align with at least one previously place object, the smaller units tended to clump and arrange themselves slightly on a grid.
2) My initial stab at random towers was terrible  when you choose a rule that says "pick 5 random tower levels and stack them on top of each other", you get what you'd expect  a tower of barely related objects stacked on top of each other. In the final iteration, I redid the tower grammar to simply generate an Nsided cylinder and simply varied the style of the top and largescale decorations. While this was more coherent, there should be even better rules available for generating structures closer to what you'd see in real life.
http://github.com/talyian/procedural_castle
All in all, This was quite a fun project. Feel free to play with and extend the code  Even if you aren't familiar with F#, the overall structure of the code should make sense. If you're on OSX or Linux, the included Makefile should work assuming you have mono
and fsharp
installed. If you're on Windows, you're on your own, but try to open the included fsproj in Visual Studio.
Dear reader, have you experienced the treat that is Steve Yegge's writing? If not, I suggest that you go read some of his best writings now instead of wasting time here. Partly because his writings are charmingly entertaining, and partly because I want to discuss a topic that he's already written a bit about.
Now let's say one of your users wants to come in and write a little OpinionatedElf monster. ... Let's say the OpinionatedElf's sole purpose in life is to proclaim whether it likes other monsters or not. It sits on your shoulder, and whenever you run into, say, an Orc, it screams bloodthirstily: "I hate Orcs!!! Aaaaaargh!!!"
Steve's elf is a fairly harmless creature; it sits on your shoulder and simply judges everyone it meets. Some creatures it likes, some creatures it hates. Let's example some different ways to tackle this problem. Note that Steve covers a lot of ground, such as extensibility. I'm going to focus on the slightly narrower problem of code ugliness and maintenance hassle, but ultimately adhering to strong principles of encapsulation helps us out with extensibility as well.
Idea #1: Polymorphic method: Standard OOP logic. If you have a behavior that all creatures share but differ on implementation, it should be a virtual method. Make Creature
define a virtual bool doesTheElfLikeMe()
method, and creatures have to extend. The good thing about this is that with a proper type heirarchy, you can defer to base implementations. The bad thing is that a very abstract class, Creature
now has a very specific concern, doesTheElfLikeMe
, in its definition.
Creature::doesTheElfLikeMe () { return true; }
Orc::doesTheElfLikeMe() { return false; }
Spider::doesTheElfLikeMe() { return false; }
HarmlessPetSpider::doesTheElfLikeMe() { return true; }
class Elf {
void Greet(Creature c) {
say(c.doesTheElfLikeMe() ? "hi, friend" : "DIE FIEND");
}
}
In this example, The elf can be perfectly happy about a HarmLessPetSpider
, which subclasses Spider
, while still hating Shelob the EvilGiantSpider, and EvilGiantSpider doesn't even need its own implementation of doesTheElfLikeMe because it defaults to the generic Spider behavior. However, adding a new Elf, or an OpinionatedGoose, involves goine to each individual Creature source file (possibly ones you don't have source access to), and adding a new method. This seems like a maintenance nightmare.
Idea #2: Monkeypatching Steve gives an example of a Ruby definition where when the Elf file gets loaded, it opens up all the classes it cares about and patches in a doesTheElfLikeMe
function. This avoids the design issue of having the Elf's preferences scattered around a large number of different code files. This works in most dynamic languages. Here's an example of Ruby and Javascript.
// in the Elf.rb:
class HarmlessPetSpider
def doesElfLikeMe; return true; end
end
// in Elf.js
Spider.prototype.doesElfLikeMe = function() { return false; };
The main issue that remains with monkeypatching (aside from incompatibility with static type systems) is that the data is still not encapsulated in the Elf
module. Now, this may be simply my preference and experience with statically typed languages, but I don't like the idea of a system design where modules and types are giving each other functions all willynilly. Where is the separation of concerns? the encapsulation?
Idea #3: Runtime type checks Why does Creature
need to define doesTheElfLikeMe
in the polymorphic example? Shouldn't the Elf figure out whether he likes a creature or not? The code does seem to be very backwards. If we added an OpinionatedGoose we shouldn't have to open up every single creature file again to add a doesTheGooseLikeMe
method as well. If we simply put the logic in the Elf or Goose class, maintenance of the feature becomes simpler.
class Elf {
bool DoesElfLike(Creature c) {
if (c instanceof Orc) return false;
if (c instanceof HarmlessPetSpider) return true;
if (c instanceof Spider) return false;
return true;
}
}
Of course, this has its own drawbacks. Now we've lost the typeheirachy. meaning, if I accidentally put the instanceof Spider
check before the instanceof HarmlessPetSpider
check, our type system is not going to tell me that I made a logic error, I've simply introduced a bug into the code.
Idea #4  Visitor Pattern Ah, The good old Gang of Four has not deserted us in our time of need. As it turns out, runtime multipledispatch is a fairly common pattern, common enough that quite programmers frequently independently come up with a pattern on their own that has come to be known as the Visitor pattern.
interface CreatureVisitor {
void DoesElfLike(Creature c);
void DoesElfLike(Orc c);
void DoesElfLike(Spider c);
void DoesElfLike(HarmlessPetSpider c);
}
class Orc : Creature {
void accept(CreatureVisitor v) { v.Visit(this); }
}
class Spider : Creature {
void accept(CreatureVisitor v) { v.Visit(this); }
}
.. etc ..
class Elf : CreatureVisitor {
void DoesElfLike(Creature c) { c.accept(this); }
void Visit(Creature c) { Greet(true); }
void Visit(Spider s) { Greet(false); }
void Visit(HarmlessPetSpider s) { Greet(true); }
void Visit(Orc o) { Greet(false); }
}
hmmm. Well, now we've added a bunch of boilerplate on every single Creature type, since every single one of them has to define its accept method. And now, your "list of all subclasses of creature" is hardwired into your CreatureVisitor. When you need to add a new Creature, you'll have to add it to the list of all your visitors and your base CreatureVisitor interface. This could really be a big issue. Shelob herself is not going to bother us a whole lot, since her GiantEvilSpider can still inherit Spider.accept behavior, but actually adding a new type that the Elf has an opinion on involves changing CreatureVisitor and all its implementors, including any OpinionatedGeese, even if their opinion hasn't changed. Is this much boilerplate really worth the hassle?
Well, maybe. In "enterprise"land, You'd expect the CreatureVisitor bits to be downstream of the Creature bits. So you could manage change by first adding a new Creature, then updating your Visitors in one go. Incidentally, this suggests that writing generaluse visitor types actually leads to more brittle code, since you'd want them packaged as close to the implemetation of the visitors as possible to void breakage. Your Creature taxonomy becomes aggravating to modify, but your Visitor taxonomy becomes easier to modify. The benefit becomes noticeble when you get more Visitorlike things. When your OpinionatedGoose and his pal OpinionatedToaster, or even other functions based on Creatures, such as Serializers or Renderers or whathaveyou, come around and they have their own ideas about what they want to do to a Creature, then your machinery is already there; the accept
s and Visit
slots are ready for implementation. Incidentally, this Creatureaxis rigidity behavior comes up in functional programming languages fairly often, since in one of my random musings I realized the visitor pattern is an OOP analogue of functional pattern matching. But that is another story and shall be told another time.
But there will always be a little nagging voice in the back of your head. Your sense of DRY is tingling a bit because of the duplicated accept on all Creature types, and especially the list of types on the CreatureVisitor interface. Why do we have to add this boilerplate to implement something as fundamental as double dispatch?
Idea #5  polymorphic dynamic dispatch in C# C++/Java/C# resolve virtual functions via runtimedispatch the type of the bound object but not on the types of the arguments. Our dynamic language friends such as Python/Ruby/ do not support a polymorphic dispatch; although they do route method calls at runtime, they do not discriminate method signatures based on type arguments. Some typed languages, such as Lisp, support dispatching based on the runtime types of the argument. While neither naive dynamic binding nor naive static binding can implement multimethods, the introduction of scoped dynamic dispatch in C# gives us a new way of implementing our OpinionatedElf:
class Elf {
bool DoesElfLike(Creature c) { return doesElfLikeType((dynamic)c); }
bool DoesElfLikeType(Creature c) { return true; }
bool DoesElfLikeType(Spider s) { return false; }
bool DoesElfLikeType(HarmlessPetSpider s) { return true; }
bool DoesElfLikeType(Orc o) { return false; }
}
And there we go. We avoid touching external files like Idea #1 (adding methods to all Creatures for each opinion). We have all the logic encapsulated in our class without monkey patching anything like in Idea #2. We are about as succinct as explicit typechecking in Idea #3 without losing the type heirarchy information and being subject to ordering errors. And, we avoid the boilerplate required for Idea #4, the Visitor pattern.
]]>This episode, we're going to add reflection into our system! Luckily, reflections are extremely easy to add to a standard raytracer. Lets take a look at our previous raytrace function:
let raytrace ray =
match closestIntersection (scene > Seq.cast) ray with
 None > Vector3.Zero
 Some(i) > lambert i lights
We first need to add a depthcounter to the Ray
type so we know when to stop reflecting. Otherwise, we'd keep bouncing around for too long in a scene with a lot of reflections. We'll initialize it so something like N=3
when we start the raycast. Then we'll have to calculate the reflected ray for each intersection. Luckily, we already have our incoming ray and normal vector, so it is a matter of simple vector math to arrive at the formula for the reflected ray:
let incident = Vector3.Normalize(ray.Dir)
let reflected = 2.f * item.normal * (dot incident i.normal)  incident
We then recursively call raytrace again with the new ray, taking the current lambert term and adding 30% of the reflected light to our current point.
let rec raytrace ray =
if ray.N < 0 then Vector3.Zero
else match closestIntersection (scene > Seq.cast) ray with
 None > Vector3.Zero
 Some(i) >
let incident = Vector3.Normalize(ray.Dir)
let reflected = 2.f * i.normal * (dot incident i.normal)  incident
lambert i lights + 0.3f * raytrace { Pos = i.point; Dir = reflected; N = ray.N  1 }
]]>Shading is the process of taking a point on a surface and calculating exactly what color we see there. In real life, a surface absorbs and emits light in all directions. The light that we see is the portion of light from that surface that is emitted directly towards our eyes (or camera).
In this installment, we'll simplify the equation down to just the diffuse reflection, i.e. the k_{d} term. This is called Lambertian reflection, after the guy who proposed this model in the 1700's.
Shading function for lambert reflection:
let lambert (i:Intersection<Shape>) =
let rawcolor = dummyshade i
let illumination (l:Light) =
let lm' = l.Pos  i.point > Vector3.Normalize // direction from point to light (normalized)
rawcolor * dot lm' i.normal
Lights > Seq.map illumination > Seq.reduce (+)
Note that we just use our buddy from the last post, dummyshade, to grab a random color for each shape as the base color. We then write a function illumination
that calculates the contribution of color from each light in the scene. then in the final line of F# Lights > Seq.map illumination > Seq.reduce (+)
just a map/reduce
telling us to sum up all the illuminations for every light, and return the sum.
If our naive plan for raytracing is simply "find the intersection of each object with our ray" we still need to write a function that intersects a ray with a sphere. One very valuable compilation of intersection algorithms is the Realtime Rendering website (which has a very excellent companion book).
A Sphere is all the points that are some distance R away from a center point. A ray is the locus of points origin + t * direction
for all t > 0
. Thus, we can substitute the ray equation (point(t) = ray.origin + t * ray.direction
) into the circle equation ( point  center  = radius
) to get rayOrigin  center + t * rayDirection = radius
. This produces a quadratic equation in t
that we can use the quadratic formula to solve.
// solving for t after expanding combined ray and circle equations.
A = rayDirection^2
B = 2 * (rayDirection . (rayOrigin  center))
C = (rayOrigin  center)^2  radius ^ 2
A * t^2 + B * t + C = 0
Full intersection code:
let raysphere pos, r, ray =
let RC = ray.Pos  pos
let A = ray.Dir.LengthSquared
let B = dot (2.0f * ray.Dir) RC
let C = RC.LengthSquared  r * r
let disc = B*B  4.0f * A * C
if disc < 0.0f then None // no intersection
else
// we only take the negative root here so we only take the near (front) point
let t = (Bsqrt(disc))/2.0f/A
if t < 0.0f then None // sphere is behind camera
else
let point = t * ray.Dir + ray.Pos
let normal = Vector3.Normalize(point  pos)
Some({ time = t; point = point; normal = normal; shape = this })
Now that we have a good way of detecting intersections, we need to figure out a good way to decide what color the intersection point should be rendered as. For the next post, I'll talk about one of the most popular and simple shaders out there: Phong shading. For now, we can write a dummy shader that just dumps a random color based on the hash of the object:
let dummyShade intersection =
let n = intersection.shape.GetHashCode()
Vector3(n / 100.f % 1.f, n / 1000.f % 1.f, n / 10000.f % 1.f)
And here is the result, in all its glory:
Up next: Phong shading! So our spheres look a little bit more 3D.
]]>For my inaugural blog series, I think I'll start by talking a bit about ray tracing. 3D Graphics has always been one of my interests, and an easy way to get to understand some of the concepts is by writing your own ray tracer! Plus, the end result is fairly pretty.
Vectors  A vector is a sequence of N numbers that represents a point or direction in space. We'll mostly be using 3D vectors such as (0,0,0), since we're dealing with 3D space. We will have to add vectors, scale vectors, take the length of a vector, and take the cross product of two vectors.
Matrices  Where a vector is a sequence of N numbers, a matrix is a sequence of NxN numbers. Matrices are useful in 3D Math because they can be used to define transformations on vectors. Rotation, translation, scale, perspective, can all be encoded as Matrices.
Coordinate Systems  We commonly work in multiple frames of reference. The one that is most familiar is "world coordinates", in which X,Y, and Z represent direction along 3 orthogonal vectors. By one convention, X is left/right, Y is up/down, and Z is in/out. Another coordinate system we'll be dealing with is "screen coordinates", in which X and Y go from 1 to 1 as the point goes from the bottom left corner of the screen to the top right corner.
Okay. Lets get started. I'm going to use OpenTK as a 3D Matrix/vector library.
The data of our scene we can just define up front. I'm going to simplify things and place the camera at the world origin. Then we can express all object data in world coordinates as well and ignore the difference between object/world/camera space. This laziness allows us to skip using a modelview transformation. Also, I'll only deal with Spheres for now. This simplifies our data definition to:
let scene = [
Sphere(Vector3(0.f, 1000.f, 0.f), 998.f)
Sphere(Vector3(1.f, 0.f, 5.f), 1.f)
Sphere(Vector3(2.f, 0.f, 5.f), 2.f)
]
let Lights = [ ] // TODO
The main body of our ray tracer is going to trace one ray for each pixel on the screen. One key assumption we can start off with is that each ray is independent of every other ray. This way, our main loop is trivially simple.
for y in 0..h1 do
for x in 0..w1 do
data.[x,y] < raytrace(x,y)
for each pixel coordinate, we need to transform to screen space, pick a near/far value for Z, then "unproject" a ray into camera/world space based on our camera values. Since we're working in a vastly simplified "clip space = world space" assumption, unproject simply returns the input vector's X/Y/Z coordinates as the ray endpoint.
let windowToScreen (wx, xy) = (float wx  w) / w, (float wy  h) / h
(* given a point in clipspace, convert to worldspace *)
let unproject (v4:Vector4) =
// our unproject is an identity transform, which is why ray.Dir is v4.XYZ
{ Dir = v4.Xyz; Pos = Vector3.Zero }
let raytrace (row, column) =
let screenx, screeny = windowToScreen (row,column)
let ray = unproject (Vector4(screenx,screeny,1,1))
match closestIntersection scene ray with
 None > Color.Black
 Some(item) > Color.White
Here is our total code so far ... and the output. Haha. It's black! We haven't coded any lighting, ray intersections, or shading yet.
#postcontent { fontfamily: "Quicksand",Helvetica,sans; textalign:center; marginbottom: 300px; }
#leader { fontsize:36pt; margin:200px auto 100px; } strong { color: #f63; } ul { liststyletype: none; display:table; margin:auto; padding:0px;} ul span { padding:2px 50px; display:block; } li { display:tablerow; padding:0px; margin:0px; }
#gh { color:white; background:#555; }
#ln { color:white; background:#55a; }
#tw { color:white; background:#69d; }
#gm { color:white; background:#c33; } a:hover { textdecoration: underline } @media (maxdeviceheight:700px) {
#leader { fontsize:24pt; margin:100px auto 50px; } }
Hey there. I am Jimmy.
A software developer interested in security, 3D graphics, IoT, and programming languages
]]>I keep standard outofthebox web server access logs. This includes IPs and UserAgent headers.
Some third parties are aware that you've been here.
Some scripts are hosted on some thirdparty CDNs. This page is not going to be the authoritative source. Check github or inspect the ContentSecurityPolicy: scriptsrc
header in any request for details.
I use a Google Analytics because they provide a nice dashboard for seeing my user traffic. Google uses cookies to identify unique sessions.