Saturday, September 13, 2014

SceneKit Tutorial Part 3 - Geometry and Material

When I was writing this part of SceneKit Tutorial, Xcode 6.0 GM was released. Compared to former Xcode 6.0 beta versions, Xcode 6.0 GM start supporting iPhone6 and iPhone 6 plus iOS simulators:
New iPhone simulators

 Alright, let me start the main topics of this tutorial. In this part, I will show you some subclasses of SCNGeometry. These subclasses presents kinds of geometry shapes like Sphere, Pyramid, Tube etc. Besides that, I will present the material property of the geometry shapes in SceneKit. The material property of a geometry shape refers to a list of objects of SCNMaterial class. To make a material shown up, we need attach the material to a geometry shape first, then connect the shape to a SCNNode and then put the object of SCNNode into an object of SCNScene.

Everyone can get the source code of Part 3 of SceneKit Tutorial at this link.

You may have seen that I created a box in Part 2.  At first of this part, I will show you two types of geometry shapes: Sphere and Pyramid. Similar to box I've shown before, we use SCNSphere and SCNPyramid to create the two types of shapes:


And then put a camera to view the two shapes:

Here we use the default light from scene, so the geometry figures will look like this:
Really Plain Sphere and Pyramid

OK, it is really plain for the two shapes. We want to add more colors and  textures on the two figures. How to do that? We can add materials to the geometry shapes. Here we use these code to add stars to the geometry:

Now the program will show something like this:
Sphere and Pyramid with Star

One thing I want to mention that when assigning materials to a geometry shape, we use a list of materials. Which means we can assign several materials to a shape. But, not all the materials can be shown up. That depends on how many surface a geometry shape could have. For example, if we assign 2 materials to a sphere, because a sphere has only one surface so the second material in the list will be discarded. Here let me try to create another material with a single color and assign two materials to both sphere and pyramid:

Now one side of the pyramid will looks different, but the sphere keeps the same:
After assigning 2 materials to Sphere and Pyramid
Well, you may say that the 2 figures looks so plain and ugly. The reflective property of SCNMaterial can make the figures looks better. Which means, when the light shining on the geometry shape, the material could reflect something so that the geometry looks more like a real object. For example, I want to the Star image reflect blue light and the blue surface to reflect white light, the code looks like:

myStar.reflective.contents = UIColor.blueColor()
myBlue.reflective.contents = UIColor.whiteColor()

Now the scene will look like this:
Geometry Shapes with Reflective Materials
OK, next I will show you some other subclasses of SCNGeometry, these shapes have there specific features than others.

SCNFloor is usually used in a scene as an infinite plain. In a game it usually shows a wall, a background or a land. Objects of SCNFloor has the feature of reflection, so you can see the shadow of the shapes above and beneath the floor. To create a simple floor, here is the code:


Now the scene will looks like this:
Add a Floor to the Scene
Now let me introduce some properties of reflection of SCNFloor.

//
// Use reflectivity properties of SCNFloor
//
myFloor.reflectivity = 0.9
myFloor.reflectionResolutionScaleFactor = 1.0
myFloor.reflectionFalloffStart = 2.0
myFloor.reflectionFalloffEnd = 10.0

Here the property reflectivity specifies the contrast of the reflection compared to the original object. If its value equals to 1,  the floor looks like a mirror.

The property reflectionResolutionScaleFactor specifies the resolution scale factor of the buffer used to render the reflection, the bigger value will cost more effort to render the reflection.

The property reflectionFalloffStart specifies the distance from the floor where scene contents are reflected at full intensity, and reflectionFalloffEnd specifies the distance from the floor where scene contents are no longer reflected.

By using the values from above code, the result will looks like this:
Effect of a Floor with Reflection Properties
Now let's add materials to the floor, remember that the floor only have one surface, so we can just only see one materials if we assign more than one materials to the geometry:

myFloor.materials = [myStar, myBlue]

It will be:
Set Material to the Floor
If you see the floor from another side of surface(from the space beneath the floor), the floor will be invisible:
Ah, the floor disappeared seen from the another side of the floor.
OK, now the discussion on SCNFloor stops here. Let me introduce another useful subclass of SCNText,  this is used for creating 3D texts in the scene. To create some words in the scene, here is an example:

From above code, we initialized an object of SCNText with a string that will be shown in the scene. And set the font of the string in line 5 and the material of the string in line 6. By setting the text's orientation and position, the stuff in the scene will looks like this:
Add Text in the Scene
It is really cool, isn't it? We can see the reflection of the text on the floor.

This part will end at here. In next part, I will dig into the animation in SceneKit.

Monday, September 1, 2014

SceneKit Tutorial Part 2 - Camera and Lights

In Part 1 of this Tutorial, I've created a simple box with yellow light shining on it. In this part, I will introduce SCNCamera which is another important class in SceneKit. And I will also dig into SCNLight and show you the 4 different types of lights in SceneKit. The project to demo the samples in this part of tutorial could be found at here.

As you can read from SceneKit Framework Reference ,  the default camera is orthogonal to the scene plain. Like a real camera, we also want to put it to a point in the 3D space and set its orientation. The position and orientation of a camera is controlled by the SCNNode which contains the camera. Also we also care if the camera has a broad field to view a wider space in the scene. The camera's field is defined by two properties of SCNCamera: xFov and yFov (Fov is short for Field of view). If you give xFov and yFov a bigger value, you will get a broader view to the scene.

Here is the code to create a camera and put it into a scene:

If you've created a box and put it in the center of the scene and enabled the default light like this:

You will see the box from another point of view instead in the front of box:


Notice that the orientation property of a SCNNode is defined by a quaternion.  If you feel complex to calculate the number or confused on how to get the 4 numbers for orientation, a property from SCNView can help you when you set allow camera control to true:

myView?.allowsCameraControl = true

Then you can drag and drop the scene to control the camera, or even zoom in and zoom out the view for the camera. If you want to get the camera's properties like position and orientation when you controlling the camera, you can customize the touchedEnded delegate in view controller:

When you feel the view looks what you expected, you can release the touch and see the position and orientation of the camera in console, and you can use the positions and orientations shows in console in your code. So it is easier than calculating the values by yourself.

Next, I will add different types of lights to the box to demonstrate the light effects in SceneKit.

There are 4 types of light. The first type of light is omni(omnidirectional light) and type is SCNLightTypeOmni, which presents a point light, a light of this type illuminates all directions from a single point. I've used this type of light in Part 1.  Because lights are tied with nodes, this type of light just care about position of the node, the orientation is ignored. Here is the snippet of code to create an omni light:

The second type of light is SCNLightTypeAmbient, this type of light illuminates from all directions with equal effect. So the orientation and position of its node are ignored. Here is the snippet to create an ambient light:

The third type of light is SCNLightTypeDirectional, this type of light illuminates from one direction. So the position of its node is ignored. The orientation of the node defines the light comes from which direction. Here is the snippet to create a directional light:

The fourth type of light is SCNLightTypeSpot, this type of light illuminates a cone-shaped area. The orientation and the position of the light are defined by its node's properties:

Now here are the snapshots of the results of the 4 types of lights using above snippets:
Omni Light
Ambient Light(with default light)
Spot Light
Directional Light

Now I've done my demo in this part, you may now have intuitive feelings on camera and light in SceneKit. But this is just a small set of features offered by SceneKit. You may need more time to investigate other features by yourself.

In next part of this tutorial, I will talk about the materials in SceneKit.

Thursday, August 28, 2014

SceneKit Tutorial Part 1 - Create a SceneKit Project

In Xcode 6 Beta releases, Apple make us develop 3D games more smoothly on iOS8 by using SceneKit. SceneKit is much easier to make 3D effects like lights, shadows and textures. And it also has build-in actions and physical behaviors. This tutorial is a practical guide that show you how to make your game step by step using Xcode 6.

There is a quick start that you can use in Xcode 6.  After you've opened Xcode 6, click File from menu and go to New and then select Project to create a new project, you will see the following dialog box:
The Wizard to Create a New Project in Xcode 6

Select Game from the board and click Next. You will see the parameters for the project:

The Properties of the Project

Pay attention that you can choose SceneKit from Game Technology drop down list and Swift in Language list. After input your Project Name, Organization Name and Organization Identifier, by clicking Next and then Create button, you will create a new project like this:

Workspace of a SceneKit Project
Above are the template code written with Swift. In this tutorial, I will use Swift for demo code. And you can find all the code of this tutorial at here.

Now the new game is ready to run without any changes to the template code! Although it is just a template, you can study and start your game from beginning. The result of the SceneKit template game looks like this:

The Snapshot When SceneKit Template Project is Running
In the running game, you will see the 3D plane is rotating and you can adjust the angle of camera. You may remember the 2D plane in Sprite Kit template project, it is upgraded!

Most of time you may want to start using SceneKit from single view project, you can create one and add SceneKit.framework from Linked Frameworks and Libraries section of project panel to use SceneKit:

Select SceneKit Framework for Single View Project
In this tutorial, I've create a single view application and I will explain SceneKit code line by line. 

The Apple's SceneKit Framework Reference gives you a good introduction to SceneKit 's key concepts like coordinate system and main classes. It will help you going through the code here.

There are some other knowledges you need to know that may not mentioned in Apple's guide. Like SpriteKit, SceneKit also has the concept like scene(SCNScene) and node(SCNNode), and they are in a hierarchy relationship. Where SCNScene has a property called root node, and every other node in the scene is one of the children or descendants of the root node(Apple calls it the root of scene graph). The "other nodes" are connected with the following types of objects: geometry, light, camera and material.
The Hierarchy of a Scene
By observing above diagram, every node and the object to be present are connected. You may imagine the object to be present is a logical concept that just contains data to describe the object. For example, the light has its power and color, the geometry has its shape. But, these objects alone cannot be presented on the scene, just like a light itself cannot shine, it still need electricity to shine and some physical objects to be illumined. So SceneKit use node(SCNNode) tied all things(Geometry, Light, Scene etc) together.

In a word, SCNNode maintain its underlying object's relationship with the scene. SCNNode tell application where to put the light and how to rotate the geometry in the scene.

All right, let's show something in our application. Suppose you have created a single view application and added the SceneKit to your project. Open the Swift source file for view controller(usually named ViewController.swift) and put the following code in viewDidLoad function:


In line 4, the code created an object of SCNView which is derived from UIView. And its size is the same with current frame. Line 5 created an object to SCNScene and put the scene into the SCNView in line 6. To show the scene, we need add the SCNView as the subview of current view.

Right now, we have nothing to show in the scene, we can run the application but you device's screen will just show white blank. To put something in it, we need to create a geometry and put it into the scene:


Well, we create a box here. To create a cubic box or a chamfered box, we use SCNBox which is derived from SCNGeometry, SceneKit also requires the box associated with a SCNNode, so we connect myBox with myBoxNode and put it to the center of the coordinate system, it will be in the center of the screen. To make the cubic box looks more like a 3D box, the code rotated the node in line 4.

It is easy to understand we use SCNVector3 to keep 3 parameters of a coordinate position. SCNVector3 is used frequently in SceneKit to specify a position in 3D space. But you may wonder why we use 4-parameter SCNVector4 here to rotate the box if you are new to 3D framework. You can understand it by breaking SCNVector4 into a point in 3D space and an angle of rotation. The line formed by the point and the center of the coordinate system is the axis for the rotation and the 4th value is the angle to rotate based on the axis.

Right now, we still cannot see anything by running the application, although we have an object in the scene. That's because we haven't put a light in the scene(we can see nothing from complete dark, right?). To put a light into the scene, create a light and a node ties the light and the scene with the code:

Here we put the light on the left-top in front of the box. So the result will looks like the left picture below:


Custom Lighting
Default Lighting
Or you can use default lightning instead of creating a light and a node for light, since SCNView has a property named autoenablesDefaultLighting, we can use the following line to use the default light(the effect is on above right picture):

myView.autoenablesDefaultLighting = true

If you use default light and custom light at the same time, the effect of default lighting will be discard. The default value of autoenablesDefaultLighting is false.

Another property of SCNView that is often used is showsStatistics, it will show statistics like fps in the bottom bar of your device(You can see the bottom bar in the application created by SceneKit template project) with this line of code:

myView.showsStatistics = true

OK, I am going to stop here today, and I will continue to write the tutorial within the series. Before I stop, I want to mention that you can use the playground introduced in Xcode 6 to play with SceneKit code. It is a very cool feature of Xcode so you can use it to see the result every line you put in playground in realtime. You can refer this link for more information to try SceneKit on playground.

Wednesday, August 20, 2014

Use UIWebView to Show Web Pages



If developer want to show a web page in an application, the class UIWebView is a good choice. First, we can define a property of UIWebView in view controller's implementation file:

@interface XXXViewController()
...
@property UIWebView *webview;
@end

Then initialize the UIWebView object in viewDidLoad delegate function of that view controller:

- (void)viewDidLoad
{
    [super viewDidLoad];
    ...
   _webview = [[UIWebView alloc] initWithFrame:CGRectMake(00, self.size.width, self.size.height)];
    _webview.tag = 55;
    NSString *fullURL = @"https://www.facebook.com/BricKiller";
    NSURL *url = [NSURL URLWithString:fullURL];
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
    [_webview loadRequest:requestObj];
}

Above code initiate the UIWebView object by assigning a frame of it. The code give it a view of full screen size. The tag property of UIWebView identify the view object. It is a number and we will refer this tag number later. I also established an object of NSURL and request the content of this URL in above code.

But it hasn't been shown yet, if you want to show the web page by clicking a button, you can add the following code to button press delegate:

[self.view addSubview:_webview];

You may find an issue, if you opened the web view in your application, there is no place to close this web view and return to your original application UI. So you can add a close button on this web view by putting below code before showing the web view:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.backgroundColor = [SKColor colorWithWhite:1.0 alpha:0.5];
[button setTitle:@"Close" forState:UIControlStateNormal];
button.frame = CGRectMake(0, _webview.frame.size.height - 100, self.size.width, 100);
[button addTarget:self action:@selector(close:) forControlEvents:UIControlEventTouchUpInside];

I set the button with white color and alpha to 0.5.  Put the button at the bottom of the web view with height 100px. And let it call close function when touch leaves the button. Next, implement close function in the same implementation file like this:

- (IBAction)close:(id)sender {
    [[self.view viewWithTag:55] removeFromSuperview];
}

Now I use the tag value to find the object of UIWebView, and then remove it from super view in close function. Here is what looks like of the running UIWebView:









Wednesday, August 6, 2014

Run Swift in Terminal and Script

You may have heard that the Apple's new programming language Swift can work interactively, which means when you type a line of code, you could see the result in Terminal. It's very useful when developer want to try some line of code of Swift and not for sure it is correct. Or it is a perfect way for new comer to learn the new language from beginning. How to do that? Please follow instructions here.

First, run the following command to set the path of a developer directory:

$ sudo xcode-select -switch /Applications/Xcode6-Beta5.app/Contents/Developer/

This step doesn't started a session of Swift shell, but this step is must-to-have. You may use another version of Xcode, so the developer's directory maybe different. Please check if the directory you switch to exists. It is usually with the format like /Applications/<Xcode-Version>.app/Contents/Developer/.

Remember you have to add sudo prior to the xcode-select command, otherwise you will get the error message like this:

xcode-select: error: --switch must be run as root (e.g. sudo xcode-select --switch <xcode_folder_path>).

Second, run xcrun swift to start a Swift interactive session(we don't require adding sudo anymore this time), here we run a "Hello World!" sample:

$ xcrun swift
Welcome to Swift!  Type :help for assistance.
  1> println("Hello, world!")
Hello, world!

And then type the following code to try a function which is from Apple's Swift Tour:

  2> func sumOf(numbers: Int...) -> Int { 
  3.     var sum = 0 
  4.     for number in numbers { 
  5.         sum += number 
  6.     } 
  7.     return sum 
  8. }    
  9> sumOf()
$R0: Int = 0
 10> sumOf(42, 597, 12)
$R1: Int = 651

You can see that the return values of the function is printed as the format $R<num>: <RetType> = <RetValue> with different color. That's much more clear and user friendly.

OK, that's what I show you the way to play around Swift session. An alternative way you can start the session is using lldb --repl command. The session started by the command looks the same.

You may want to see the history of the session, you can use arrow keys up and down to check previous or next Swift code line you typed. The history of Swift session of each user is kept in the file located at ~/.lldb/lldb-swift-history.

Hmm... It looks like other scripting language like Unix Shell and Python. Similar to these scripting language, Swift also works in script.

For example, create a file named swift_test like this:

#!/usr/bin/env xcrun swift
println("Hello World!")

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

println("Shape's simple description : " + shapeDescription)

Here we define a Swift class to see if it works, everything goes well it we run the script in command line:

$ ./swift_test 
Hello World!
Shape's simple description : A shape with 7 sides.

Very powerful, isn't it? It looks Swift not only works for developing App. With the library support, it could also be used for system management and automation.

Friday, June 13, 2014

BricKiller 1.0.6 is released



The Main Menu
Now, we have BricKiller 1.0.6 released. This new version brings new features that make you enjoy more on the game!

Go to App Store

In BricKiller,  User Interface of the game is enhanced. You'll have a new view of app icon, main menu and play boards.

You may find it is hard to bypass some of levels in World III, this version introduced 3 types of props that helps you to win the hard levels easily and more funny. 

The Prop Box
Now, we have three types of props: Eraser, Bomb and Exchanger. As you can see that in Props Box Dialog:

The prop ERASER means you can erase one brick by one eraser. When a brick is blocking your way, you can use it to erase the brick. However, you can not remove black bricks by using eraser.

The prop BOMB can eliminates bricks in one 3x3 area or at most 9 bricks at one time.  Bombs can not eliminate black bricks either. If the 3x3 area contains 2 black bricks and 5 colored bricks, only the 5 colored bricks can be removed.

The prop EXCHANGER is the most funny tool among the three. You can exchange the positions of two colored bricks by using an exchanger. No matter whether there other bricks block the two colored bricks to move or not. Or you can use exchanger to move one brick to another blank space without caring about other bricks blocking it. However, you cannot change the location of a black brick by using exchanger.


The power of Bomb
The Bomb is selected


How can you gain props? Every time you get 3 stars for a single level, you will get a prop. The type of the prop you will get is random.

Another new feature of BricKiller 1.0.6 is that the In-Store Purchase is added at settings screen after clicking the "Settings" Button in main menu. You can pay to remove Ads and buy more props for play. 

By the way, BricKiller has added five more levels in World I and 5 more levels in World III, go ahead to explorer them!

Monday, April 28, 2014

Use R to connect with HDFS and Hive

This document will provide some tips of R on how to connect Hive and HDFS with R. The RHive manual has a good document on how to do installation and initial setup for RHive before we start. In this document, I will provide more information on Hive and HDFS related stuff.

As we know the following command will connect HiveServerHost at port 10000 with HiverServer2:

> library(RHive)
> rhive.connect("HiveServerHost", 10000, hiveServer2)


If we give no arguments for rhive.connect, it will connect the Hive server with port number 10000 on local host:

> rhive.connect()

Then you can do query works on the Hive server by rhive.query(...), however, you need more power by using RHive, such as access HDFS and write a table onto it.

If you want to access a HDFS, you need to connect the name node of the HDFS first:

> rhive.hdfs.connect("hdfs://namenode:8020")

If above command doesn't work or not supported, add a dot(.) before the command, like:

> .rhive.hdfs.connect("hdfs://namenode:8020")


Next, we can try to create a 3-column table named "test" in Hive and save it in HDFS by using R: 

> L3 <- LETTERS[1:3]
> d <- data.frame(cbind(x=1, y=1:10), fac=sample(L3, 10, replace=TRUE))
> rhive.write.table(data=d, tableName="test")
[1] "test"


And show the content in table test:
> rhive.query("select * from test");
   x  y fac
1  1  1   B
2  1  2   A
3  1  3   A
4  1  4   B
5  1  5   B
6  1  6   A
7  1  7   C
8  1  8   A
9  1  9   B
10 1 10   A


You should check that there is a file located at /user/hive/warehouse/test/ in HDFS by the command:
> rhive.hdfs.ls("/user/hive/warehouse/test/")

Which means the content of the table has been saved to HDFS.

There are two good slides that you can refer on how to use RHive basic functions and functions related to HDFS:

RHive Basic Functions Tutorials
RHive HDFS Functions Tutorials