Recipe for a Mixed App with Starling and Away3D

In my first attempt to add 3D to my Starling app I struggled with many problems that seemed trivial. I used Starling for a few good years and consider it one of the most powerful 2D frameworks in the industry. Coupled with the Feathers UI library its a winning stack, and it has a vibrant community that provides excellent support.

However, it’s limited to 2D.

awayScene2

So following one of the tutorials in the wiki, I started building a mixed 2D/3D foundation on top of both frameworks. I had to face problems that had no documented solutions. I figured that would be useful to list them out with the solutions that I used.

Sharing the 3D context -playing the proxy

Start with this basic tutorial:  Away3D and Starling interoperation. Also, if your experience with Away3D is limited, I recommend taking a look at Away3D 101, a series of short tutorials by PolyGeek.

The gist of it is that we need to create 3 instances of Stage3D, with is essentially an instance of Away3D sandwiched between two Starling instances. They are created along with a proxy (stage3DProxy) that  is used to stitch them together. The main class then has to handle the rendering of the frame, and setup a render loop that would render each layer in order.

At this point the tutorial ends, and you need to implement all the above in a a real life project. Typically that consists of handling the proxy and manage the different layers in an app that potentially has many different view classes (or game screens) that the user navigates between.

How you do that is entirely up to the specific architecture of your app, but this can be really confusing . Here are a few tips to help organize  it in a more structured fashion.

In the main entry point (the class that has the code to initialize Starling), keep members for the two Staling instances, the Away3D scene (or view) and the proxy. This class is designated mainly for these tasks:

  1. Create the proxy,  the Away3D ‘world’ instance, and the two Staling instances
  2. Render the 3 layers (enter frame)
  3. Resize handler
	...
	private var mStarlingA:Starling;
	private var mStarlingB:Starling;
	private var worldView:View3D;
	private var stage3DProxy:Stage3DProxy;
	...

The top level instances are Starling A and B and the away view, an instance of View3D. Any external view class that has 3D will need access to all three of them, so place references in some global location. In my case, the main starling root is the root of all views, while the secondary Staling root is used as upper layer, like a HUD.

carshop

Note that when creating the starling layers, you need to pass the proxy’s reference of the stage3D, which in turn uses a shared context3D. The proxy takes care of the rest.

	private function onContextCreated(e:Stage3DEvent):void 
	{
		initAway3D();
 
		mStarlingA = new Starling(rootClass, stage, 
				stage3DProxy.viewPort, stage3DProxy.stage3D);
		mStarlingB = new Starling(starling.display.Sprite, stage, 
					stage3DProxy.viewPort, stage3DProxy.stage3D);
		stage3DProxy.addEventListener(Event.ENTER_FRAME, onEnterFrame);		
	}
 
	private function onEnterFrame(e:Event):void 
	{
		// Render the 3 layers in order
		mStarlingA.nextFrame();
		worldView.render();
		mStarlingB.nextFrame();
	}

In a view class extending starling.Sprite that is a child of ‘Starling A’ root you can place code to create all the 2D and 3D elements, and attaching them to either one of the layers using the global references.

 Coordinate System

It’s very easy to get confused with the different coordinate systems used between the two frameworks. To get your bearings right, use the following:
coords

The standard screen coordinates used in Flash/AIR (and Starling) use X-right/ Y-down with the origin at the top-left. However, the default coordinate system for Away3D is Y-up with the origin in the middle. That means the ground is an XZ plane, and if you place the camera somewhere in the negative Z looking at the origin you’ll get the familiar X-right, Z-far, so that objects would look farther away as the Z coordinate increases.

To avoid confusion, make sure to place the camera in the negative Z, or you would get a flipped (backwards) view where X goes to the left instead of right.

Non Display Concerns

Since the main class handles rendering, there is no actual render loop inside Away or Starling. In fact, you don’t need to call start() on starling to get it to draw. Each of the layers can receive and handle input in the form of mouse or touch events. design the scene so that interactive objects are not obstructed, and make use of the touchable property in starling objects to create click through areas if needed.

A good practice is to avoid any input events on the HUD (upper layer) and process all the input in the lower Starling layer – that way all the input processing is contained in one instance.

On the next post I will show how to share resources between all three layers.

3 thoughts on “Recipe for a Mixed App with Starling and Away3D

  1. Hi there thanks for posting this blog. I am having trouble with feathers when combining these two engines. The feathers components appear but you cannot interact with them. I have used feathers with just starling a lot and don’t ever have any problems. Do you have any ideas why this could be?

  2. ok I sorted that out by using .start() on starling layer.
    The next issue I have is that stage3Dproxy does not work with iOS. Have you experienced this before? The event listeners do not trigger, so I am assuming there is a compatibility issue. Everything works fine when running in a Web project, but not on iOS mobile device.

Comments are closed.