Code: getting Away3D to work with a 2D GPU library (Starling)

Software: Away3D 4.x

DinkMcDinkleman, Newbie
Posted: 30 April 2012 09:41 PM   Total Posts: 30

Just want to throw out this code and the info for anyone who is interested.  I plan on using Starling for UI and Away3D for in-game objects. 

I’m calling on anyone who would like to add, correct, or contribute in any way, feel free.

This has now been edited to reflect a fix for depth issues.

* HUGE PROPS to afrosquared for figuring things out and being willing to share! *

If you’d like to use this code - it is provided as is, with no implication of fitness or warranty made by myself, Gamua (Starling), or Away3D.  Be warned - the below requires that you make modifications to both the Starling and Away3D libraries - do so at your own risk.  I recommend you comment any changes made should you like/need to revert.

First, follow the below steps.

1. Create Away3D View3d first and addChild.
2. In the Stage3DProxy class (Away3D\core\managers\Stage3DProxy.as) - setProgram method, comment out:
“if (_activeProgram3D == program3D) return;”
3. Create Starling with the same context as Away3D.
“mStarling = new Starling(Game, stage, viewPortRectangle, stage.stage3Ds[0]);”
4. Modify Starling\core\Starling.as and comment out: “RenderSupport.clear(mStage.color, 1.0);” in render().
5. Modify Starling\core\Starling.as updateViewPort():
mContext.configureBackBuffer(mViewPort.width, mViewPort.height, mAntiAliasing, true);
(Change the word false to true, highlighted in blue above.)
6. Modify Away3d\containers\View3D.as and comment out: “_stage3DProxy._context3D.present();” in render().
7. Modify Away3d\core\render\RendererBase.as and comment out:
“if (_swapBackBuffer && !target) _context.present();” in executeRender();

I have some basic code all typed up.  If anyone notices errors in the above, or in the code, please let everyone know!

Main code:

package 
{
 import flash
.display.Sprite;
 
import flash.display.StageAlign;
 
import flash.display.StageScaleMode;
 
import flash.geom.Rectangle;
 
 
import away3d.containers.Scene3D;
 
import away3d.containers.View3D;
 
import away3d.cameras.Camera3D;
 
import away3d.materials.ColorMaterial;
 
import away3d.primitives.CubeGeometry;
 
import away3d.entities.Mesh;
 
 
import starling.core.Starling;
 
 
import Game;
 
 
[SWF(frameRate='60'width='960'height='640'backgroundColor='#000000')]
 
 
public class Main extends Sprite 
 {
  
//Away3D vars
  
private var scene:Scene3D;
  private var 
camera:Camera3D;
  private var 
view:View3D;
  
  
//Starling vars
  
private var inst_Starling:Starling;
  
  public function 
Main()
  
{
   view 
= new View3D();
   
scene view.scene;
   
camera view.camera;
   
   
addChild(view);
   
   var 
viewPortRectangle:Rectangle = new Rectangle();
   
viewPortRectangle.width stage.stageWidth;
   
viewPortRectangle.height stage.stageHeight;
   
   
stage.align StageAlign.TOP_LEFT;
   
stage.scaleMode StageScaleMode.NO_SCALE;
   
   
// create our Starling instance
   
inst_Starling = new Starling(GamestageviewPortRectanglestage.stage3Ds[0]);
   
inst_Starling.start();
  
}
  
 }
 

Game code:

package  
{
 import flash
.geom.Vector3D;
 
 
import away3d.cameras.Camera3D;
 
import away3d.cameras.lenses.PerspectiveLens;
 
import away3d.containers.Scene3D;
 
import away3d.containers.View3D;
 
import away3d.lights.PointLight;
 
import away3d.materials.lightpickers.StaticLightPicker;
 
import away3d.events.MouseEvent3D;
 
import away3d.materials.ColorMaterial;
 
import away3d.primitives.CubeGeometry;
 
import away3d.entities.Mesh;
 
 
import starling.display.Sprite;
 
import starling.events.Event;
 
 public class 
Game extends Sprite 
 {
  
  
public function Game() 
  
{
   super
();
  
}
  
 }

As it sits this will compile for me in FlashDevelop, the result being a blank screen.

My next steps are hopefully to get a 3D demo with 2D UI going.  I’ll gladly post the updated code when I get time and figure it all out.

   

miquael, Newbie
Posted: 02 May 2012 05:55 AM   Total Posts: 8   [ # 1 ]

Excellent.  Looks good!  I’ve been experimenting with how to have Starling and Away3D work together also ...

I have some experience with Starling, and very little experience with Away3D. Since the View3D instance has been created in the main class, what is the best way to access (add primitives to) the view from Game?

   

DinkMcDinkleman, Newbie
Posted: 02 May 2012 02:40 PM   Total Posts: 30   [ # 2 ]

Unfortunately my understanding of the code and the setup isn’t too deep…I copied the info here to the best of my knowledge:  http://forum.starling-framework.org/topic/away3d-compatibility

My understanding is that addChild(view) adds the view to the stage/context.  When the stage/context is passed as a parameter to Starling it *should* work.  Assuming I got my code right.

Apparently there are some depth issues as well, so I’m checking in to that now and will hopefully be able to post some updated code.

   

theguaz, Newbie
Posted: 02 May 2012 04:46 PM   Total Posts: 8   [ # 3 ]

hey, i’m having the same doubt on starling+away3D. i’m doing an app that it would benefit from using starling for 2D UI and away3D for 3D visualization.
by now i have not succeded on my attemp, my instructions to setup both are like:

public function Startup(){
      _starling = new Starling(FirstScreen, stage, null, stage.stage3Ds[1]);
      _starling.start();
  setAway();
    }
 
private function setAway():void{
  _awayView = new AwayView();
  addChild(_awayView);
  _awayView.setAway();
}

Can i determine where in the stack of stage3Ds i want my away3D so i can have my away3D view behind my starling items and stil see trough the starling view if that view has transparent bitmaps?

regards.

   

DinkMcDinkleman, Newbie
Posted: 02 May 2012 05:07 PM   Total Posts: 30   [ # 4 ]

@theguaz:

I agree with your frustrations - Away3D seems to have the best documentation as well as the easiest to learn and work with - but I’m still not sure how to implement a UI without the use of a 2D library such as Starling.

If I may, on your post above, what is the purpose of this code:
private function setAway():void{
  _awayView = new AwayView();
  addChild(_awayView);
  _awayView.setAway();
}

I’ve also noticed in your Startup() function you refer to stage.stage3Ds[1] as opposed to stage.stage3Ds[0] as I have seen elsewhere - is this by design?

   

theguaz, Newbie
Posted: 02 May 2012 06:05 PM   Total Posts: 8   [ # 5 ]

My intention as to start&add; my away3D instance and over that instance a starling class that’s why i used the index [1].
My idea was to tell away to use the index[0] of the stage3Ds to render the away3D view and [1] for starling.

But a still cannot find how to tell away3D to use index [0] in the way starling does it.

I accept suggestions, opinions etc.

smile

   

DinkMcDinkleman, Newbie
Posted: 02 May 2012 06:13 PM   Total Posts: 30   [ # 6 ]

@theguaz,

I don’t know much about it, but it’s my understanding they have to share contexts, hence passing the context 0 to Starling.  I’m not sure though.  Does your code compile?

I have updated my Game.as file to add a button, as follows:

package  
{
 import flash
.geom.Vector3D;
 
import starling.display.Button;
 
 
import away3d.cameras.Camera3D;
 
import away3d.cameras.lenses.PerspectiveLens;
 
import away3d.containers.Scene3D;
 
import away3d.containers.View3D;
 
import away3d.lights.PointLight;
 
import away3d.materials.lightpickers.StaticLightPicker;
 
import away3d.events.MouseEvent3D;
 
import away3d.materials.ColorMaterial;
 
import away3d.primitives.CubeGeometry;
 
import away3d.entities.Mesh;
 
 
import starling.display.Sprite;
 
import starling.textures.Texture;
 
import starling.events.Event;
 
 public class 
Game extends Sprite 
 {
  [Embed
(source "../assets/TestButton.png")]
  
public static const testButtonClass:Class;
  
  
  
  public function 
Game() 
  
{
   super
();
   
   var 
texture:Texture Texture.fromBitmap(new testButtonClass());
   var 
testButton:Button = new Button(texture""null);
   
   
testButton.10;
   
testButton.10;
   
   
addChild(testButton);
   
testButton.addEventListener(Event.TRIGGEREDbuttonClick);
  
}
  
  
private function buttonClick(event:Event):void
  {
   trace
("clicked");
  
}
  
 }

It compiles, runs, and I see the trace statement, however the button graphic is not visible.  Does anyone see problems with the above code?

   

miquael, Newbie
Posted: 03 May 2012 12:14 AM   Total Posts: 8   [ # 7 ]

the code above compiles, runs, AND shows a button image for me (of course, I made my own PNG).  Perhaps check your PNG file.

Otherwise, that’s Starling working in the way it usually does.  Now, how to get Away3D working also?  I’m trying something now ... and will post code soon ...

   

miquael, Newbie
Posted: 03 May 2012 01:51 AM   Total Posts: 8   [ # 8 ]

I’m not that familar with Away3D, and I’m having a particularly hard time finding a “Hello World” type example that WORKS.  Most of the examples or tutorials out there don’t seem to work, probably because they are for a version of Away3D before 4.0. It would be nice to just have a simple rotating cube example for 4.0.

I did incorporate this example into your main class (which I now call StarlingAway): http://www.adobe.com/devnet/flashplayer/articles/creating-games-away3d.html

You need the vase.awd file for this to work.

With the inst_Starling.start() line commented out (so Starling does not start), the Away3D object shows up.  If the inst_Starling.start() line is activated, then the Starling button shows up—but no Away3D object.

Even if this was working with both Away3D and Starling working at the same time, I also want to know how to add and control Away3D object from the Game class (and not from the main class).

package 
{
 import away3d
.containers.View3D;
 
import away3d.loaders.Loader3D;
 
import away3d.loaders.parsers.Parsers;
 
import away3d.events.LoaderEvent;
 
 
import flash.net.URLRequest;
 
import flash.display.Sprite;
 
import flash.display.StageAlign;
 
import flash.display.StageScaleMode;
 
import flash.geom.Rectangle;
 
import flash.events.*;
 
 
import net.hires.debug.Stats;
 
 
import starling.core.Starling;
 
 
import Game;
 
 
[SWF(frameRate='60'width='960'height='640'backgroundColor='#000000')]
 
 
public class StarlingAway extends Sprite 
 {
  
//Away3D vars
  
private var view View3D;
  private var 
loader Loader3D;
  
  
//Starling vars
  
private var inst_Starling:Starling;
  
  public function 
StarlingAway()
  
{
   stage
.frameRate 60;
   
   
// stats
   
var stats:Stats = new Stats();
   
this.addChild(stats);
   
   
// create Away3D
   
view = new View3D();
   
view.backgroundColor 0x222222;
   
view.antiAlias 4;   
   
addChild(view);
   
this.addEventListener(Event.ENTER_FRAMEonEnterFrame);
   
   
Parsers.enableAllBundled();
   
   
loader = new Loader3D();
   
loader.addEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
loader.load( new URLRequest('vase.awd') );
   
   var 
viewPortRectangle:Rectangle = new Rectangle();
   
viewPortRectangle.width stage.stageWidth;
   
viewPortRectangle.height stage.stageHeight;
   
   
stage.align StageAlign.TOP_LEFT;
   
stage.scaleMode StageScaleMode.NO_SCALE;
   
   
// create Starling 
   
inst_Starling = new Starling(GamestageviewPortRectanglestage.stage3Ds[0]);
   
//inst_Starling.start();
  
}
  
  
private function onEnterFrame(ev Event) : void
  {
   view
.render();
  
}
  
  
private function onResourceComplete(ev LoaderEvent) : void
  {
   loader
.removeEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
view.scene.addChild(loader);
  
}
   
 }

 

   

miquael, Newbie
Posted: 03 May 2012 02:39 AM   Total Posts: 8   [ # 9 ]

Oh actually ... I had just realized that I neglected to follow the steps at the top of this post to edit the code in the Starling and Away3D packages.  I just did that now, and then ran my code (^above), and it works!  I have both Away3D and Starling showing their objects at the same time!

Again, just uncomment inst_Starling.start() so that starling starts.

   

miquael, Newbie
Posted: 03 May 2012 02:41 AM   Total Posts: 8   [ # 10 ]

Now I’m going to work on a more complex Away3D example, and also see how to get Away3D to be manipulated from the Game class.

   

DinkMcDinkleman, Newbie
Posted: 03 May 2012 05:03 AM   Total Posts: 30   [ # 11 ]

@miquael,

I could be wrong but when you addChild(view) isn’t that making the view a child to the context/stage?  And therefor when the context is passed to Starling as a parameter would it then not be able to share the view.  I don’t know if declaring the view as public would help either…


Edit: the answer is no…the view is not recognized by FlashDevelop when trying to reference it.  However, if view, scene and camera are declared in the Game.as that may work.  Trying now.

   

logotype, Newbie
Posted: 03 May 2012 08:08 AM   Total Posts: 3   [ # 12 ]

Hi

The code above works fine, the only problem I can’t figure out is how to place Away3D at the top, and Starling underneath. Any ideas or suggestions?

Thanks!

   

DinkMcDinkleman, Newbie
Posted: 03 May 2012 11:27 AM   Total Posts: 30   [ # 13 ]

@logotype, I don’t know that it’s possible to do so.  In the above code, you create a context and then pass it to Starling.  There is no way that I know of to pass an already created context to Away3D.  Then again, I’m unsure why you would want 3D objects to appear on top of Starling - the purpose of getting Starling to appear on top is to create UI elements.

The other problem we’re facing is how a typical Starling program is set up.  A call to inst_Starling.start(); above gives control to the class named in the line just above it, in this case, Game.  The reason that’s a problem is that once you’ve made a call to Game, your Away3D view is no longer in scope and therefor not recognized by the compiler.

Sadly, after some testing I have not been able to get it figured out - but plan to keep trying.  Perhaps the solution is using the keyword ‘this’ instead of naming another class such as my ‘Game’ example above?  Hopefully that would mean not having to hand control to another class and the Away3D view would still be in scope.

   

logotype, Newbie
Posted: 03 May 2012 02:13 PM   Total Posts: 3   [ # 14 ]

@DinkMcDinkleman
Thanks for the reply. The reason to have the reverse order, is because the game is a isometric 2d game (Starling/IsoHill) with a 3D GUI/HUD layered on top.
Will continue to try to get this working somehow.

   

afrosquared, Newbie
Posted: 03 May 2012 06:39 PM   Total Posts: 5   [ # 15 ]

I know of a “dirty” way to call back down to the Main.as from Game.as.  It’s not ideal and I plan to find a better method but the following will work.

In Main.as:
public function somePublicFunctionInMain():void {
}

In Game.as:
flash.display.MovieClip(Starling.current.nativeStage.getChildAt(0)).somePublicFunctionInMain();

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X