I argued in a previous article that Scene Kit can be used to improve the UX of an app. One of the examples I mentioned was that of a seatbooking system. To argue my case, I sat down and wrote an actual demo for such a system.
As shown in Picture 1 the demo consists of the 4 components SASeatFactory, SASeatBookingView, SACameraControl and SAViewController.
I modelled the seat for the demo in Xcode's Scene Kit editor. I originally wanted to use a seat from one of those 3D modelling sites but decided later against it. What I needed for my purposes was a simple seat to keep the number of polygons down. Hence, I created one with 2 boxes. One box for the actual seat and another one for the seat's rest. Since I wanted to give each seat its individual seat number, I added a dedicated badge node. I need to say here if this was a real production app, I wouldn't have done this. I'd rather have used one of the seat's surfaces to show the seat number as part of the texture, since having a dedicated geometry for the badge further increases the polygon count. After that, I gave each seat node a proper name and combined them in a parent node 'chair'. Since I wanted to show seat selection as well, I created a person sitting in the seat using the basic shapes available in the editor for head, body, arms and legs. Having done that, I combined those nodes in a parent node 'body'.
To instantiate 'chair' and 'body' later on, I created SASeatfactory. It needed to provide an occupied seat and an available one, each with a unique texture, such that all occupied and available seats share the same geometry. Hence, I created an occupiedSeatNode and an availableSeatNode property and cloned them depending on which seat the class was asked to return.
Let's talk about SASeatBookingView first before we get to SAViewController, the component that ties it all together. SASeatBookingView is a subclass of SCNView and is responsible for visualising the seat map. For this purpose and to keep it flexible and loosely coupled, it works like a UITableView. It has a datasource property which enables it to ask for the number of rows and columns and a method to ask for a seat node when laying out the seat map. Like a UITableview, it has a delegate method to inform the delegate when a seat has been selected.
Furthermore, since I wanted to allow the user to change the position and angle of the camera I added some code to do just that which I encapsulated in SACameraControl and is used by SASeatBookingView via a property. SACameraControl uses UIPanGestureRecognizer and UIPinchGestureRecognizer and translates their feedback into vectors and actions to act on SASeatBookingView's camera.
Being a controller, SAViewController mediates between SASeatFactory and SASeatBookingView. When it instantiates SASeatBookingView, it sets itself as its delegate and datasource. For the seat map I used a static 2-dimensional array whose size is returned via one of the datasource methods. The datasource call to return a seat node is propagated to SASeatFactory which then returns the requested seat. The delegation methods handle the animation to show and hide the 'body' node I created in the Scene Kit editor. I didn't add the logic there but in SAViewController to keep SASeatBookingView flexible, since it doesn't need to know how a 'chair' node is setup.
Video 1: seat reservation based on Scene Kit
I used this demo as a project to get a better understanding of Scene Kit. It was clear to me that having watched a bunch of WWDC video's and having read one book was not enough. I needed something to apply my new learned knowledge. This demo helped me to manifest what I learned and to lay out the learning path of what I still need to learn.
What this demo shows is just the tip of the iceberg. There is so much more you can do with Scene Kit. Although a lot of maths is not required to use it, is surely helps when creating more advanced effects.
By the way while writing this demo I also learned that Swift now has proper SIMD support which comes in handy for any vector or matrix manipulation. An introduction can be found here.