Erain 3D
--> FDT Pure coding comfort


Author: Max Pellizzaro
Date: December 6th 2008
Update: July 12th 2009
version: 3.1.1

Advance Parsing 3DS MAX - loading group elements

Objective of the tutorial

This is another very simple tutorial, but to me simple things can be very powerful. More than once I have tried to load 3DS files as I have shown in previous tutorials, but nothing was showing on my screen. I was kind of worry if I was doing something wrong, but then I have find the reason Sandy was not showing up anything. Most of the time (in my experience), the 3DS models are not simple objects, rather they are models composed by elements. If we tell Sandy to get only the first child, you will loose the entire model. In this tutorial we will show how to load a generic models made of different elements.

How to

Set up

In this archive you will find all the Flash and AS files, plus a single 3ds file.

example075_a.zip

The new updated version can be found here:
example0075_v3.1.1.zip

The object we want to load it is the one shown here, and it is composed by 7 elements.

The AS Code

package
{
   import flash.display.*; 
   import flash.events.*;
   import flash.ui.*;
   import flash.net.URLRequest;
   
   import sandy.core.Scene3D;
   import sandy.core.data.*;
   import sandy.core.scenegraph.*;
   import sandy.materials.*;
   import sandy.materials.attributes.*;
   import sandy.primitive.*;
   import sandy.parser.*;
   import sandy.util.*;
   import sandy.events.*;

   public class Example0075 extends Sprite 
   {
      private var scene:Scene3D;
	  private var camera:Camera3D;
	  private var tv:TransformGroup;
	  private var tv2:TransformGroup;
	  private var queue:LoaderQueue;
      private var parserStack:ParserStack;
	  
      public function Example0075()
      { 
		 var parser:IParser = Parser.create("tvscreen.3ds",Parser.MAX_3DS, 40, "PNG");
		 parserStack = new ParserStack();
		 parserStack.add("tv",parser);
		 
		 parserStack.addEventListener(ParserStack.COMPLETE, parserComplete );
		 parserStack.start();
		 
    }
 
    private function onError( pEvt:ParserEvent ):void {
	  trace("there is an error in loading your stuff");
    }
 
     private function parserComplete(pEvt:Event ):void
     {	     
		 var root:Group = createScene();
		 camera = new Camera3D( 300, 300 );
         camera.y = 0;
         camera.z = -100;
		 scene = new Scene3D( "scene", this, camera, root );
		 
		 // Listen to the heart beat and render the scene
         addEventListener( Event.ENTER_FRAME, enterFrameHandler );
		 stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressedHandler);
      }
 
    private function createScene():Group {
      
      var g:Group = new Group();

	  tv = new TransformGroup();
	  tv2 = new TransformGroup();
	  tv.addChild(parserStack.getGroupByName("tv"));

	  tv.x = 0;
	  tv.y = -60;	  
	  tv.tilt = -90;
 
      tv2.addChild(tv);
      g.addChild(tv2);
	  
      return g;
    }
 
 private function keyPressedHandler(event:flash.events.KeyboardEvent):void 
	  {
	   switch(event.keyCode) {
		case Keyboard.UP:
			tv2.tilt +=5;
			break;
		case Keyboard.DOWN:
			tv2.tilt -=5;
			break;
		case Keyboard.LEFT:
			tv2.pan -=5;
			break;
		case Keyboard.RIGHT:
			tv2.pan +=5;
			break;
		}
	  }
 
    private function enterFrameHandler( event : Event ) : void {
      scene.render();
    }
  }
}

Examining the code

Now let's see the difference with the loading procedure I was always using before this new approach.
Previously I use to load object in the following matter:

 
private var rifle:Shape3D;
...
 
rifle = parserStack.getGroupByName("rifle").children[0] as Shape3D;

Now instead of declaring a Shape3D objects, we will use a TransformGroup object and we will do something like this:

 
private var tv:TransformGroup;
...
 
tv = new TransformGroup();
tv.addChild(parserStack.getGroupByName("tv"));

We are done!
All the rest of the code is to simple allow to have a better control on the rotation of the tv object on the screen.

The output

You can move the arrow key to see the tvscreen rotating.