Feb 262011
 

Well, it’s finished.  Ladies and Gentlemen, may I proudly present…


(version 1.1, .zip, 49.3Mb)

Super Hover Blast, as mentioned in the earlier preview, is a free 3D action/puzzle game that I’ve been working on for a while now (about 18 months on-and-off, I think) and which I have finally decided to release into the wild.  It began as a project to create a physics engine from scratch and to teach myself C++ and morphed into something a bit more…

Tasked with single-handedly bringing down the regime of the evil kitten-hating General Al Imakhbeel, your mission is to clear out a series of heavily-defended military bases.  However, to make things interesting the only weaponry at your disposal is a hovercraft armed with a powerful – but basically harmless – air cannon.  The enemy, on the other hand, has missiles, machine guns, land mines, spinning blades, pointy spikes and a whole load of other tools of destruction.  If you’re going to survive you’ll need to figure out some way of turning their own weapons against them…

The game then is kind of a shoot-em-up but without any actual weapons.  Your air cannon does zero damage but can be used to clear your path of obstacles, push enemies into hazards, deflect missiles…  Completing each level requires a certain amount of point-n-shoot skill, sure, but it also needs clever positioning, lateral thinking and forward planning in order to defeat all the enemies in each stage using only the weapons and traps they’re trying to use against you.

The best description I’ve managed to come up with for how this works in practice is “a bit like billiards, only in real-time and with all the balls trying to murder you”.  If that sounds vaguely appealing to you then here’s that download button again:


(version 1.1, .zip, 49.3Mb)

Then simply unzip the file somewhere on your computer.  To change your display options run setup.exe.  If you enjoy it, please tell your friends!

Credit where it’s due: The game uses the 3d graphics engine ‘Irrlicht’ by Nikolaus Gebhardt and his crew; the music is by Kevin Macleod; everything else is by me, but with help, playtesting and advice from: Kim Loo, Dustin Gunn, Robert Garford-Tull, Daniel Brown, Daniel Sheppard and everybody who posted something in this thread.

Update 28/02/2011: Version 1.1: Added support for AZERTY keyboards and added some missing .dlls for the setup utility that somehow avoided inclusion the first time. Sneaky .dlls!

Feb 252011
 

Four examples this time around, showing how to take all that sexy VB.NET stuff we covered last time and stick it in grasshopper.  First up, a super-simple example of how you can write your own version of the standard line component.

Using the code:

Private Sub RunScript(ByVal P1 As Point3d, ByVal P2 As Point3d, ByRef A As Object)
'This subroutine is the one that will be run whenever the component is updated.
'Note that the names and data types we set up outside the code are here as subroutine arguments
'The last one is our output - it is 'ByRef' so that changes we make here are not merely local</p>
Dim L As Line 'This declares that we are going to be using a line called 'L'
L = New Line(P1, P2) 'This creates a line using one of the built in constructors that takes two points
A = L 'This sets the line we have created as our output object A.

End Sub

You can download the example here: http://www.vitruality.com/Teaching/Example3.ghx (Right click, save as…)

That example will follow the same basic rules on data-matching as most other components; namely if you input a list or a tree it will be run once matching the first item in both lists, again with the second and so on.  If you want, however, you can take control of how that works by bringing in lists of objects as inputs instead.  This can be set up by right clicking on an input and selecting ‘List Access’:

This script will take two lists of points and draw a zig-zag between them.

Private Sub RunScript(ByVal P1 As List(Of Point3d), ByVal P2 As List(Of Point3d), ByRef A As Object)</p>
Dim i As Integer
'We calculate the maximum index we're going to go to.
'This is the minimum of the highest indices of the two lists
Dim maxi As Integer = math.Min(P1.Count, P2.Count) - 1
Dim OutList As New List(Of Line) 'This is to store our output lines

'Here we loop through both lists
For i = 0 To maxi
'We take the ith point from P1 and the ith point from P2 and draw a line between them
Dim fromPt As Point3d = P1(i)
Dim toPt As Point3d = P2(i)
Dim L As New Line(fromPt, toPt)
'We add our line to the output list
OutList.Add(L)
'If there is another point still to go in P2...
If i &lt; P2.Count - 1 Then
'...we do the same to the ith point from P1 and the (i+1)th point from P2
Dim ToPt2 As Point3d = P2(i + 1)
Dim L2 As New Line(fromPt, toPt2)
OutList.Add(L2)
End If
Next

A = OutList 'This will set the output of the component

End Sub

Aaaaand you can download it here: http://www.vitruality.com/Teaching/Example3a.ghx (Right click, save as…)

Now things get a little more interesting.  All of the above could be done in grasshopper just using the built-in components, but there are a few things that are impossible in grasshopper normally but that we can do via code.  One of these things is recursion, which you might recall is the tool we use for creating fractals.

So, the next example uses this principle to create a fractal branching structure.  Here’s some I made earlier:

Which were made with this script:

Private Sub RunScript(ByVal startLine As Line, ByVal Factor As Double, ByVal Angle As Double, ByVal Axis As Vector3d, ByVal Iterations As Integer, ByRef branches As Object)
Dim OutList As New List(Of Line)</p>
'Start the branching
Branch(startLine, factor, angle, axis, iterations, outlist)

branches = OutList

End Sub

'&lt;Custom additional code&gt;

'Branch() is a separate subroutine so that we can call it recursively from within itself
Private Sub Branch(ByVal startLine As line, ByVal factor As Double, ByVal angle As Double, _
ByVal axis As vector3d, ByVal iterations As Integer, ByRef outList As List(Of Line))
'We pass in everything we need to calculate the new lines.  Note that outList is ByRef so we can change
'the original rather than just create a copy

If iterations &gt; 0 Then
'Vectors have 'operators' defined, meaning that we can use them in mathematical equations like numbers
'Operators are things like + - * / etc.
'This is vector subtraction, i.e. |A| - |B| = (A.x - B.x, A.y - B.y, A.z - B.z)
Dim VectorA As Vector3d = startLine.To - startLine.From
VectorA *= factor 'This scales our vector by a factor

'We want two branches, so we create a copy of vector A:
Dim VectorB As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)

'Then we rotate them in opposite directions:
'Vector3d has a built-in 'Rotate' sub we can use for this.
VectorA.Rotate(angle, Axis)
VectorB.Rotate(-angle, Axis)

Dim LineA As Line
Dim LineB As Line

'The endpoint of our new lines will be the end of our starting line plus our vectors
Dim EndPointA As Point3d = startLine.To + VectorA
Dim EndPointB As Point3d = startLine.To + VectorB

'We now draw lines from the end of our old line to the points we just found
LineA = New Line(startLine.To, EndPointA)
LineB = New Line(startLine.To, EndPointB)

'We add the lines to our output lists
outlist.Add(LineA)
outlist.Add(LineB)

'Now we use recursion (calling a function from within itself) to branch further
'Note that we subtract one from the iterations.  This lets us 'count down' branchings and stop.
Branch(LineA, factor, angle, axis, iterations - 1, outList)
Branch(LineB, factor, angle, axis, iterations - 1, outList)
End If

End Sub

Get the definition here: http://www.vitruality.com/Teaching/Example4.ghx (Right click, save as)

And finally, here’s a tweaked version of the Branch() subroutine that does the same thing in 3d:

Private Sub Branch(ByVal startLine As line, ByVal factor As Double, ByVal angle As Double, _
ByVal axis As vector3d, ByVal iterations As Integer, ByRef outList As List(Of Line))</p>
If iterations &gt; 0 Then
Dim VectorA As Vector3d = startLine.To - startLine.From
VectorA *= factor

Dim VectorB As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)

'======================================================================================
'This is the only bit that's changed: we now rotate twice, once about our given axis and
'again using the line itself as an axis (we copy vector A again to use as this axis)
Dim NewAxis As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)

VectorA.Rotate(angle, Axis)
VectorA.Rotate(math.PI / 2, NewAxis)
VectorB.Rotate(-angle, Axis)
VectorB.Rotate(math.PI / 2, NewAxis)
'The key thing is that by rotating it the second time, we are changing the plane that
'the branches are in.  We thus need to rotate the first rotation axis as well
Axis.Rotate(math.PI / 2, NewAxis)
'=====================================================================================

Dim LineA As Line
Dim LineB As Line

Dim EndPointA As Point3d = startLine.To + VectorA
Dim EndPointB As Point3d = startLine.To + VectorB

LineA = New Line(startLine.To, EndPointA)
LineB = New Line(startLine.To, EndPointB)

outlist.Add(LineA)
outlist.Add(LineB)

Branch(LineA, factor, angle, axis, iterations - 1, outList)
Branch(LineB, factor, angle, axis, iterations - 1, outList)
End If

End Sub

Which you can download here: http://www.vitruality.com/Teaching/Example4a.ghx (Right cl- oh, you know the drill by now)

Feb 172011
 
AreaCalculator

For reference, here are some lecture slides that go through some of the fundamental theory behind object-oriented programming as it relates to VB.NET.  It’s primarily aimed at people moving to VB.NET from RhinoScript, but is possibly still a useful reference for anybody else interested in starting out with Visual Basic as well.

Download it here:

VisualBasic.pdf

The main example this week doesn’t use grasshopper at all, instead it is a simple standalone application written in Visual Basic to calculate the areas of different shapes.  Not the most useful tool in the entire universe, but hopefully it does demonstrate how concepts such as classes, inheritance and polymorphism can be implemented in VB.NET.

This example was created using Visual Basic Express 2008; to recreate the form create a new windows form project and set up a form with Text Boxes called ‘WidthBox’, ‘HeightBox’ and ‘OutputBox’, a ComboBox called ‘TypeCombo’ and a Button called ‘CalculateButton’.  (Since this is a grasshopper course not a Visual Studio one I won’t go over again how to set this up: google is your friend here.)  Add code like this:


Public Class Form1

'This subroutine will get run whenever the 'CalculateButton' is clicked by the user
Private Sub CalculateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CalculateButton.Click

Dim W As Double
W = CDbl(WidthBox.Text) 'Extract the data from the 'WidthBox' textbox and convert it (if possible) to a Double (Double-precision Floating Point Number)
Dim H As Double
H = CDbl(HeightBox.Text) 'And the same for height...

'Here we declare that we are going to use a Shape.
'Note that this will not actually *create* a Shape
Dim Shp As Shape

If TypeCombo.SelectedItem IsNot Nothing Then 'This if statement merely checks that something has been selected by the user

If TypeCombo.SelectedItem = "Rectangle" Then
'This line actually creates a rectangle and stores it in 'Shp'.
Shp = New Rectangle(W, H)
'Even though Shape and Rectangle are different types, because Rectangle derives from Shape we can still store it as such
'(i.e. a Rectangle is also a Shape)
Else
'Ditto for triangle:
Shp = New Triangle(W, H)
End If

'At this point in the code we don't necessarily know what *sort* of shape we have here, because 'Shp' is just generically defined as a 'Shape'
'However, we don't actually *need* to know.  When we call Area() the right function will be called depending on the class we have actually stored.
OutputBox.Text = Shp.Area()

End If

End Sub

End Class

'Shape is a base class, which means that it only exists to hold the code shared between our Rectangle and Triangle classes
Class Shape

'These are properties which will be common to all Shapes:
Public Width As Double
Public Height As Double

'Shape has no constructor (a 'New' subroutine) - this means you cannot actually create an instance of this class.

'By declaring this function 'overridable' it means that we expect classes which inherit from this to have their own Area() function to replace this.
'By defining this here in the base class, it means that we can access the function Area() from objects which are simply dimensioned as a 'Shape'
Public Overridable Function Area() As Double
Return 0
End Function
End Class

'Rectangle is one of our sub-classes of shape, that represents a rectangle(!)
Class Rectangle
Inherits Shape 'This line sets the rectangle as inheriting from 'Shape'
'Because Rectangle inherits from Shape, it will automatically have all the properties and methods that Shape has.

'This is a constructor - any class that you want to be able to create an instance of will need one of these of some form, even if it's empty!
Public Sub New(ByVal WidthValue As Double, ByVal HeightValue As Double)
Width = WidthValue
Height = HeightValue
End Sub

'This replaces the Area() function in Shape with more specific code for Rectangles
Public Overrides Function Area() As Double
Dim A As Double = Width * Height
Return A
End Function

End Class

'Triangle is our other sub-class of shape, works pretty much the same as Rectangle:
Class Triangle
Inherits Shape

Public Sub New(ByVal WidthValue As Double, ByVal HeightValue As Double)
Width = WidthValue
Height = HeightValue
End Sub

Public Overrides Function Area() As Double
Dim A As Double = Width * Height / 2
Return A
End Function

End Class

You can download the complete source code here:

ExampleAreaCalculator.zip

Feb 112011
 
Pixellation2

This example creates a ‘pixellated’ (to be more exact, voxellated) approximation of any solid or surface by eroding a 3D grid of cubes until only those within a certain distance from your target object remain.

You can download the annotated definition from here:  http://www.vitruality.com/Teaching/Example2.ghx (right click, save as)

This example demonstrates how to create a conditional definition (equivalent to an ‘if’ statement in code) inside grasshopper.  A function component is used to evaluate whether a condition is met, and the boolean result from that is used to sort objects into ‘pass’ and ‘fail’ groups.

This is also a useful definition in and of itself, since it can be used to approximate any shape and (although I’ve used a cube grid here to keep things simple) could be easily adapted to use any kind of packing system.

Feb 062011
 
DSC_0248

I didn’t actually know about this until I accidentally stumbled accross it in iplayer, but Cecil Balmond (my boss when I was in Arup’s AGU (Advanced Geometry Unit), until he went off to do his own thing) did a radio series for the BBC a little while ago about the evolution and use of mathematics in design.  As it turns out, they’re pretty good, and well worth a listen if you’re at all interested in anything ever.

You can listen to all three episodes here.

Episode 3 is where he gets into the sort of things that we actually do for a living, but episode 2 in particular is well worth listening to for the part where Cecil interviews the previously mentioned (and sadly recently deceased) Benoit Mandelbrot.  I geeked out a bit over that part and it sounds like Cecil did too.

Feb 052011
 
Cookie Cutter

This is an example grasshopper definition intended to go through the ‘advanced’ features of grasshopper, principally the characteristics of trees.  [Note for civillians: Grasshopper is a parametric modelling plugin for the 3d software Rhino.]

Download here: http://www.vitruality.com/Teaching/Example1.ghx (right click, save as)

The definition

The example takes in a NURBS surface, turns it into a 3d BRep (Boundry REPresentation) by giving it a thickness, then creates a series of cylinders throughout the surface which it uses as ‘cookie cutters’ to create holes in it.

Here's one I made earlier...

As a bit of theory: In the early days of grasshopper (which was actually only about a year and a half ago), grasshopper had no trees – only single items and lists could be passed around between components.  The problem with this was that there wasn’t any way of doing something like a ‘loop’ in code – if you wanted to do the same operation multiple times you had to copy and paste the components you were using to do it multiple times and this was obviously not particularly flexible.  We all moaned about this until David (creator of Grasshopper and all-round nice bloke) added trees, which are essentially lists of lists, where each sub-list or ‘branch’ is considered separately by the components (after which, we all still moaned, because trees can be a bit tricky to wrap your head around).

Say, for example, you performed an operation such as putting a list of curves into a ‘divide curve component.  In the bad old days, the division points would have come out all in one list, which meant it was difficult to determine which point belonged to which curve.  Now, this component produces a tree, with each of the original curves having their own branch on which the subdivsion points of that curve are stored.  When passing this data into other components, each branch is treated separately; so for example if we put the tree into a polyline component to create a faceted version of the original curve, rather than drawing a polyline through all the points, it will draw a separate polyline for each branch (and therefore, each original curve).

Et Voila, two separate polylines