New Documentation for Collada
Minko's Collada plugin makes it possible to easily import Collada (*.dae) files using the assets loading API. Working with the API is quite simple and there already is a detailed tutorial about that. But the Collada format has its flaws and it is sometimes very complicated to get your exported files to work properly.
That's why I've compiled a new documentation article that explains how to properly export Collada files from 3D Studio Max:
Export Collada files from 3D Studio Max on Aerys Hub
The article details the export procedure itself but also provides guidelines to make sure the exported file will display properly with Minko. It also give details about the supported features, including material, material properties and how the engine will use them. Similar articles will be released for different editors and formats according to the community's needs.
Of course, as soon as the Minko editor and the MK format will be available we will strongly discourage the use of Collada files in production for many reasons (mainly performances). But you will still need to import those Collada files into the editor first... So here is a little video to show how simple importing assets is with the editor:
Yes: it's as simple as a drag'n'drop! You will also notice that the textures load automatically and that the editor will let you play the animations and make sure everything works out of the box. The editor will be available in open beta in March...
Minko Weekly Roundup #4
Features
- The JointsDebugController makes it possible to display the joints and bones of a skinned mesh in order to check if everything works as expected.
- The VertexPositionDebugController will display the position of each vertex of a mesh.
- The VertexNormalDebugController will display the normal of each vertex. You can use it with the VertexNormalShader to display and debug the normals of a mesh.
Examples
Answers
- Mapping Flex UI components to textures in Minko: an interesting thread about how to emulate mouse-enabled 2D components - such as Flex components - mapped as 3D textures
Tutorials
- Display the position and the normal of each vertex
- Display the bones and joints of a skeleton
- Select scene nodes with XPath
Fixes
- minko-collada will now load the vertex RGBA data when it's available
- min/max computation is always possible upon creation of a VertexStream regardless of its StreamUsage
- frustum culling will now also test the center of the bounding box and not only the 8 corners
Tutorial: Add pixel-perfect 3D mouse interactivity
In this tutorial we're going to see how you can add pixel-perfect 3D mouse interactivity. I've already introduced a technique called "ray casting" in another article. But it works only with very basic static shapes. And sometimes, testing very complex shapes can be very painful performance wise. It's even more expensive when you want it to be very precise.
In this article, we will see a technique called "pixel picking". This technique uses hardware acceleration to provide pixel perfect mouse interactivity. It works very well for both static and animated models. The concept is very simple: we render the scene with one color per mesh. Then, we just have to get the pixel under the mouse cursor to know what mesh is "interactive". Of course, things are much more complicated in the real life: this kind of stunts are pretty hard to push properly in a general purpose rendering pipeline.
But Minko provides everything required out of the box! Even better, the minko-picking extension features a simple controller - the PickingController - that provides all the mouse signals we might need! This tutorial will explain how to setup the PickingController and listen for the mouse signals.

Pixel picking test application (sources)
Create and setup the PickingController
The first step is to instanciate a new PickingController:
var picking : PickingController = new PickingController(); |
The constructor takes only one argument: the "picking rate" of the controller. This value will determine how many times per second the controller will try to execute the picking pass and the relevant mouse signals. The lower the picking rate, the better the performances. A picking rate of 30 should be more than enough for 99% of the applications. You can also set that value at any time using the PickingController.pickingRate property:
picking.pickingRate = stage.frameRate / 2.; |
Setting the picking rate to the half of the frame rate will work just fine for most applications and should be completely painless performance wise. By default, the picking rate is fixed to 15.
Set the mouse events source
The job of the PickingController is to listen for the mouse events on one (or more) specific dispatcher(s) and re-dispatch them as mouse signals. The difference between the original events and the signals executed by the PickingController is that the signals are aware of the 3D scene. To setup the dispatcher to listen, you just have to call the PickingController.bindDefaultInputs() and provide the IDispatcher object to listen:
picking.bindDefaultInputs(viewport); |
Setup the PickingController on the 3D scene
In most cases, you don't want the whole 3D scene to be mouse interactive. Sometimes it's just a Mesh or a Group. The PickingController can be added to any Mesh/Group so it's easy to target precisely what is interactive and what is not. The basic use case is to add mouse interactivity on a single Mesh:
mesh.addController(picking); |
BUt you also might want to listen for the mouse signals trigerred by a whole sub-scene instead of a single mesh. For example, some skinned 3D assets have multiple meshes animated by a single skeleton. To do this, we can add the PickingController on Group:
group.addController(picking); |
In the code snippet above, the PickingController will execute mouse signals for all the Mesh descendants of the target group. You don't have to worry about the descendants of the groups targeted by a PickingController: it will listen for the Group.descendantsAdded and Group.descendantsRemoved to start/stop tracking any descendant Mesh added to this part of the scene.
Thus, if your whole 3D scene is interactive, you can add the PickingController directly on the Scene node:
scene.addController(picking); |
Listen for the mouse signals
To catch 3D mouse events, you just have to add callback(s) to any of the PickingController.mouse* signals. The available signals are:
- mouseClick, mouseDown, mouseUp: executed when the left button is clicked, down or up
- mouseRightClick, mouseRightDown, mouseRightUp: executed when the right button is clicked, down or up
- mouseMiddleClick, mouseMiddleDown, mouseMiddleUp: executed when the right button is clicked, down or up
- mouseDoubleClick: executed when the user makes a double click
- mouseMove: executed when the mouse moves
- mouseWheel: executed when the mouse wheel turns
- mouseRollOver, mouseRollOut: executed when the mouse roll over/out a mesh
The following code sample will catch the left and the right click signals:
picking.mouseClick.add( function(ctrl : PickingController, mesh : Mesh, mouseX : Number, mouseY : Number) : void { trace('click: ' + (mesh ? mesh.name : null)); } ); picking.mouseRightClick.add( function(ctrl : PickingController, mesh : Mesh, mouseX : Number, mouseY : Number) : void { trace('right click: ' + (mesh ? mesh.name : null)); } ); |
It would be too difficult to use the PickingController if the mouse signals where triggered only when an actual 3D object is under the cursor. For example, it would be pretty hard to select/unselect objects without listening to some actual 2D mouse events. The code would then quickly become very complicated to mix both 2D mouse events and 3D mouse signals.
Therefore, the mouse signals are triggered whenever the corresponding mouse event is dispatched (and when the picking rate allows it of course). As a direct consequence, the mesh : Mesh argument is null when there is no actual interactive 3D object under the mouse cursor.
Conclusion
You can find the complete source code of the picking example demo in the minko-examples repository on github. If you have questions/suggestions regarding this comment, you can ask them in the comments or on Aerys Answers, the official support forum for Minko.
Tutorial: your first mobile 3D application with Minko
As you already know I'm sure, you can build Android and iOS devices with the Flash platform. And Stage3D is also available on those devices! As a matter of fact, Stage3D was especially designed to work on mobiles. And so was Minko! We put a lot of efforts in building a robust and fast engine that will work on most mobile devices. This tutorial will start where the "Your first Minko application" tutorial stopped and explain what needs to be done to get it working on mobile.
Create your mobile project
The first thing to do is - of course - create a mobile project. With Flash Builder it is very simple: you just have to go into File > New > ActionScript Mobile Project. If you need a little reminder of how to bootstrap your project/development environment, you can read the "Getting started with Minko" tutorial. The only difference compared to creating a desktop/wepp application is to uncheck "BlackBerry Table OS" in the Mobile Settings panel: Stage3D is not yet available on BlackBerry devices. There is an issue opened on the BlackBerry tracker if you want to vote for it!
Configure the application
Now our project has been created we just have to make sure it can use the Stage3D API. It implies two little changes in the app.xml file (this file is named after your main class, most of the time it's Main-app.xml):
- renderMode has to be set to "direct"
- depthAndStencil has to be set to "true"
Here is a basic example of a properly setup app.xml file for AIR 3.2:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <application xmlns="http://ns.adobe.com/air/application/3.2"> <id>Main</id> <filename>Main</filename> <name>Minko Mobile Example</name> <versionNumber>0.0.0</versionNumber> <initialWindow> <content>[This value will be overwritten by Flash Builder in the output app.xml]</content> <!-- Stage3D --> <renderMode>direct</renderMode> <depthAndStencil>true</depthAndStencil> <!-- /Stage3D --> <autoOrients>true</autoOrients> <fullScreen>false</fullScreen> <visible>true</visible> </initialWindow> <iPhone> <InfoAdditions><![CDATA[ <key>UIDeviceFamily</key> <array> <string>1</string> <string>2</string> </array> ]]></InfoAdditions> <requestedDisplayResolution>high</requestedDisplayResolution> </iPhone> <android> <manifestAdditions><![CDATA[ <manifest android:installLocation="auto"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> </manifest> ]]></manifestAdditions> </android> </application> |
Bootstrap the Main class
That's the beauty of the Flash platform, Stage3D and Minko: the project boostrap aside, the code of the application is exactly the same whether you are working on a desktop, web or mobile application! Therefore, you can bootstrap your Main class by following the "Your first Minko application" tutorial!
Basically, you just have to copy/paste the MinkoApplication sample class...
public class MinkoApplication extends Sprite { private var _viewport : Viewport; private var _scene : Scene; protected function get scene() : Scene { return _scene; } protected function get viewport() : Viewport { return _viewport; } public function MinkoApplication() { super(); // make sure the stage is available if (stage) initialize(); else addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(event : Event = null) : void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // create the viewport _viewport = new Viewport(); // add the viewport to the stage stage.addChild(_viewport); initializeScene(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } protected function initializeScene() : void { // create an empty scene _scene = new Scene(); } protected function enterFrameHandler(event : Event) : void { // render a frame _scene.render(_viewport); } } |
... and make your Main class extend it:
public class Main extends MinkoApplication { public function Main() { super(); } } |
Run your mobile application for the first time
If you use Flash Builder, it will display the Debug Configurations panel when you will try to run/debug your mobile application for the first time. This panel does not have anything special regarding Stage3D or Minko, but it's still a good thing to see the basics! There are two important fields on the panel:
- The "Target platform" field will specify what device you want to target for this debug session.
- The "Launch method" field will specify whether you want to run the application in the desktop device emulator or directly on the device. Of course, the "On device" method is better if you want to have a preview of the actual performances.
Display your first 3D object
Now that our project is setup and that we can launch it on the device or in the emulator, we will display our first 3D object. You just have to follow the "Display your first 3D object" tutorial for your mobile project. Here is what you'll get if you choose to run it on the desktop emulating the iPhone4 device:
You can also directly download the sources for this project!
If you have questions/suggestions regarding this tutorial, please post in the comments or on Aerys Answers, Minko's official support forum.
Tutorial: Display your first 3D object with Minko
Now that we've seen how to bootstrap an empty Minko application, it's time to learn how to display a simple 3D primitive.
Step 1: The Camera
In order to display anything 3D, we will need a camera. In Minko, cameras are represented by the Camera scene node class. The following code snippet creates a Camera object and adds it to the scene:
var camera : Camera = new Camera(); scene.addChild(camera); |
By default, the camera is in (0, 0, 0) and looks toward the Z axis. We must remember this when we will add our 3D object in the scene: we must make sure it's far enough on the Z axis to be visible!
Step 2: The Cube
A Mesh is a 3D object that can be rendered on the screen. It is somekind of 3D equivalent of the Shape class used by Flash for 2D vector graphics. But in 3D. As such, it is made of two main components:
- a Geometry object containing the triangles that will be rendered on the screen
- a Material object defining how that very geometry should be rendered
Creating a Mesh involves passing those two objects to the Mesh constructor:
var geometry : Geometry = new CubeGeometry(); var material : BasicMaterial = new BasicMaterial(); // set the RGBA color of the cube material.diffuseColor = 0x0000ffff; var cube : Mesh = new Mesh(geometry, material); scene.addChild(cube); |
There are many primitives available as pre-defined geometry classes in Minko: cube, sphere, cylinder, quad, torus... Those classes are in the aerys.minko.render.geometry.primitive package. You can easily swap the CubeGeometry with a SphereGeometry to create a sphere instead of cube for example.
The BasicMaterial is the material provided by default with Minko's core framework. It's a simple material that can render using a solid color or a texture. Here, we use it with a simple color. To do this, we simply set the BasicMaterial.diffuseColor property to the color we want to use with an RGBA format.
Remember: the camera is in (0, 0, 0) and - by default - so is our cube. Therefore, we have to slightly translate our cube on the Z axis to make sure it's in the field of view of the camera:
cube.transform.translationZ = 5.; |
We will introduce 3D transformations in details in the next tutorial.
Conclusion
To make it simple, our main class will extend the MinkoApplication class detailed at the end of the previous tutorial. We will simply override its initializeScene() method to create our cube, our camera and add both of them to the scene:
public class BlueCube extends MinkoApplication { override protected function initializeScene() : void { super.initializeScene(); var mat : BasicMaterial = new BasicMaterial(); mat.diffuseColor = 0x0000ffff; var cube : Mesh = new Mesh(new CubeGeometry(), mat); cube.transform.translationZ = 5.; scene.addChild(cube); var camera = new Camera(); scene.addChild(camera); } } |
And here is what you should get:

If you have questions or suggestions, you can post in the comments or on Aerys Answers!
Tutorial: Your first Minko application
In this tutorial we will see how to create your first scene with Minko. At the end of this tutorial, you will have nothing but a colored rectangle. Before you follow this tutorial it is recommended to read the "Getting started with Minko 2" article in order to learn how to setup your programming environment.
Creating the Viewport
Instanciating a new Viewport object
The first step before rendering anything is to have a rendering area. In Minko, this rendering area is called the "viewport" and is represented by a Viewport object. The viewport can be seen as the middle-man between the classic 2D rendering list and the hardware accelerated 3D rendering. Indeed, the Viewport class extends the Sprite class so it will behave like any other rendering element of the display list: it has a (x, y) position, a width, a height, etc...
Creating the viewport is really simple:
var viewport : Viewport = new Viewport(); |
The Viewport constructor accepts the following arguments:
- antiAliasing : uint, the anti-aliasing level to use when rendering in this viewport; this value can be 0, 2, 4 or 8 and the default value is 0
- width : uint, the width of the viewport; the default value is 0 to make the viewport fit its parent width automatically
- height : uint, the height of the viewport; the default value is 0 to make the viewport fit its parent height automatically
There a few things to remember about a viewport though:
- The viewport can only be behind or infront of all the other elements in the display list. This is because of a technical limitation of the Stage3D API. To make the viewport visible infront, you should set the Viewport.alwaysOnTop property to true.
- If the viewport is set to resized itself automatically according to its parent's size (ie. the Viewport constructor was built with width == height == 0), then you have to make sure its parent actually has a size different from 0
The following code snippet will create a 640x480 viewport with 4x anti-aliasing and move it in (100, 200):
var viewport : Viewport = new Viewport(4, 640, 480); |
Adding the viewport to the display list
Just like any DisplayObject, the Viewport must be added to the stage to be visible. As it behaves like any other DisplayObject, you can simply use the addChild() method to add it to the display list:
var viewport : Viewport = new Viewport(); stage.addChild(viewport); |
The viewport can be added to any DisplayObjectContainer, just make sure its parent has a proper width and height if you are working with an automatically resized Viewport.
Rendering into the viewport
As you can see, even with the viewport added to the Stage, there is no visual change. That's because the viewport is empty as long as we don't use it to render a scene. Now that we have a rendering area, we should render something in it! For now, we will just create an empty scene and render it in this viewport:
var scene : Scene = new Scene(); var viewport : Viewport = new Viewport(); stage.addChild(viewport); scene.render(viewport); |
This code snippet creates a new Viewport and a new Scene objects. Then, it adds the Viewport to the Stage and renders the Scene in that very Viewport. The immediate consequence is that our viewport will now be filled with black. Our viewport is completely black because we just rendered an empty scene and the default background color of the Viewport is black.
Manipulating the Viewport
Setting the background color
You can change the background color of the viewport by setting the Viewport.backgroundColor property. This property holds the background color of the viewport in the RGBA format:
// setting the background color to "blue" viewport.backgroundColor = 0x0000ffff; |
The alpha component of the background color is not used for now and is here only for forward compatibility.
Resizing the viewport
You can resize the viewport by setting the Viewport.width and Viewport.height properties:
// set the viewport width to 640 viewport.width = 640; |
Everytime you set the Viewport.width or the Viewport.height property, the Viewport.resized signal is executed. Thus, in order to avoid executing unnecessary signals when you want to set both the width and the height of the viewport, it is recommended to use the Viewport.resize() method:
viewport.resize(640, 480); |
This way, the Viewport.resized signal will be executed only once at the end of the Viewport.resize() method when the viewport has been successfully resized.
Moving the viewport
You can move the viewport using the Viewport.x and Viewport.y properties. It will behave just like any other DisplayObject element: the final position of the viewport is affected by the transformation applied by its parents. Thus, if you add the Viewport in a Sprite and if you move that Sprite, the viewport will move as well.
// move the viewport to the (100, 200) position viewport.x = 100; viewport.y = 200; |
Conclusion
The following code sample describe the basic structure of a main class used to create a new Minko application:
public class MinkoApplication extends Sprite { private var _viewport : Viewport; private var _scene : Scene; protected function get scene() : Scene { return _scene; } protected function get viewport() : Viewport { return _viewport; } public function MinkoApplication() { super(); // make sure the stage is available if (stage) initialize(); else addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(event : Event = null) : void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // create the viewport _viewport = new Viewport(); // add the viewport to the stage stage.addChild(_viewport); initializeScene(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } protected function initializeScene() : void { // create an empty scene _scene = new Scene(); } protected function enterFrameHandler(event : Event) : void { // render a frame _scene.render(_viewport); } } |
You can re-use this class as you main class everytime you want to create a new 3D app!
Procedural Terrain With Minko 2
Being able to create procedural geometry is very important in a 3D engine. Minko is special because it offers 2 ways to work with the 3D geometry:
- The streams API: low level but the fastest solution. You have to create and fill the buffers yourself which becomes rapidly annoying and hard to read.
- The vertex iterators: a high level dynamic API, slow but very very easy to work with.
In this post I will explain how you can create a 3D procedural terrain in just a few lines of code.
TL;DR
You can get the full source code for this example in minko-examples on github.
Read more...
Getting Started With Minko 2
Update: you can read all of Minko's tutorials on our developers Hub
Update: you can also download the developers reference!
Here is a little blog post for anyone who wants to get started using Minko 2 "from scratch". If you want to build Minko from the sources, be able to easily update it whenever necessary and work with the open source samples this tutorial is for you!
But first things first, a little summary of what's available code-wise:
- minko: Minko's core, and that's already a lot of features (old and new). Among them: the scene graph API, the rendering API, ActionScript shaders with the new compiler/API, ray casting...
- minko-collada: the enhanced Collada extension (minko-collada) to load Collada (*.dae) files.
- minko-picking: the extension to add pixel-perfect mouse interactivity.
- minko-examples: a repository full a simple samples targeting one feature at a time.
And now what is about to be released:
- minko-lighting: the lighting engine extension. We've added a lot of cool features and optimizations, such as projected shadows for every light types.
- minko-3ds and minko-obj: extensions to respectively handle the 3DS and OBJ file formats.
- minko-jiglibflash: the extension to plug JigLibFlash into Minko and add 3D physics
A lot of people ask me about tutorials. The tutorials available on the Hub are not for Minko 2 but for the older version. We didn't have enough time to update them, and that's why we provide minko-examples. It's a lot easier to update and to maintain. But of course, the old tutorials will be ported and a lot of new tutorials will be added in June.
Now let's get started...
Read more...
Spritesheets With Minko
Update: the full source code for this tutorial is available in minko-examples on GitHub.
Spritesheets are a nice way to create nice effects with an extensive artistic control. You just have to create a texture with a series of cool-looking sprites to have a nice animation. They are widely used for particles, fog and explosions for example. We used spritesheets to render the explosions and the clouds in our latest game: The Mirage.
When you have the spritesheet itself, you need two things to get it working in your application:
- A "frame id" value that will be updated to tell which frame of the spritesheet should be sampled.
- A shader that will sample the spritesheet accordingly.
And here is what you get:
New Minko Tutorial: Vertex Attributes In The Fragment Shader
Passing values from the vertex to the fragment shader is a very common thing. The simplest use case is when you want to sample a texture: this operation can only be done in the fragment shader, but the texture coordinates to sample are accessible in a vertex attributes in the vertex shader. In the end, any non-trivial shader will require to pass values from the vertex shader to the fragment shader.

The picture above is a very simple use case: we define a per-vertex RGB color and use it to draw a triangle. Everything is explained in the "Work with vertex attributes in the fragment shader" tutorial on the Hub.
The actual shader is pretty simple, but I recommend you read the entire tutorial to understand it properly:
public class RGBShader extends ActionScriptShader { private var _color : SValue = null; override protected function getOutputPosition() : SValue { var xy : SValue = float2(getVertexAttribute(VertexComponent.XY)); _color = getVertexAttribute(VertexComponent.RGB); return float4(xy, 0., 1.); } override protected function getOutputColor() : SValue { return interpolate(_color); } } |
Another interesting thing is optimization. As values are linearily interpolated between the vertex shader and the fragment shader, it makes it possible to perform some per-vertex computations and reuse them in the fragment shader. The only requirement is that those values have to be linearily interpolable. In other words: every linearily interpolable values computed in the fragment shader could be computed in the vertex shader instead. It gives a very important performance boost, as the vertex shader is much faster and runs on a much smaller data set: we always have a lot less vertices than we have pixels. I will soon write an article about this very optimization.
Last but not least, this tutorial uses the latest additions in Minko. Among them, an easier way to declare vertices and fill a vertex stream using a VertexIterator. Indeed, you can now use an (inlined) Object to initialize an entire vertex at once. It was done by overloading the flash_proxy::setProperty() method in the VertexIterator dynamic class. You can now chose between 3 different approaches to fill a vertex stream:
var vstream : VertexStream = new VertexStream(null, format); var vertices : VertexIterator = new VertexIterator(vstream); // the inline version (new!) vertices[0] = {x: 0., y: .5, r: 1., g: 0., b: 0.}; vertices[1] = {x: -.5, y: -.5, r: 0., g: 1., b: 0.}; vertices[2] = {x: .5, y: -.5, r: 0., g: 0., b: 1.}; // the dynamic version vertices[0].x = 0.; vertices[0].y = .5; vertices[0].r = 1.; vertices[0].g = 0.; vertices[0].b = 0.; vertices[1].x = -.5.; vertices[1].y = -.5; vertices[1].r = 0.; vertices[1].g = 1.; vertices[1].b = 0.; vertices[2].x = .5; vertices[2].y = -.5; vertices[2].r = 0.; vertices[2].g = 0.; vertices[2].b = 1.; // the fast version vstream.push( 0., .5, 1., 0., 0., -.5, -.5, 0., 1., 0., .5, -.5, 0., 0., 1. ); |
All those 3 versions do the very same thing, but in a different fashion. You can now use any of those depending on what you are doing.
As always, if you have questions or suggestions, you can post them on Aerys Answers.







Aerys