The Secret of Reading Mouse Input in Flash Sandy3D – part 2

3D mouse input in Flash

This posts is a continuation of the previous post and goes into more detail on how to greatly speed up the 2D > 3D mapping by analyzing what actually happens. Usually I’d let Sandy3D do everything for me, but in this case, it turns out it is too slow and the calculation is not complicated at all.

What actually happens in part 1 is this:

  • We have a camera with a viewport of 300 by 300 pixels looking at (0,0,0)
  • There is a plane centered at (0,0,0) and perpendicular to the z-axis. So it faces us.
  • This means the plane will be projected perfectly onto the screen. As is shown in the following figure.

Because of this, it is really simple to calculate the mouse coordinate in the 3D space. The top left corner (0,0) maps to the “plane”-coordinate (-150, 150) and the bottom right corner (300,300) maps to (150,-150). The necessary calculation is easy and can be found in the event handler in the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package  {
 
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import sandy.core.Scene3D;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.Group;
	import sandy.core.scenegraph.Shape3D;
	import sandy.materials.Appearance;
	import sandy.materials.BitmapMaterial;
	import sandy.primitive.Plane3D;
 
	public class MappingOurown extends Sprite {
 
		[Embed(source = 'library/capoeira.jpg')]
		private var capoeira:Class;
 
		private var scene:Scene3D;
		private var camera:Camera3D;
		private var shape:Shape3D;
		private var dir:int = 1;
 
		public function MappingOurown()
		{
			camera = new Camera3D (300, 300);
 
			var root:Group = createScene();
			scene = new Scene3D("scene", this, camera, root);
 
			addEventListener (Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener (MouseEvent.MOUSE_MOVE, stageMoveHandler);
		}
 
		private function createScene () : Group
		{
			var g:Group = new Group ('scene');
			shape = new Plane3D ('plane', 10, 15);
			shape.tilt = 45;
 
			shape.appearance = new Appearance (new BitmapMaterial (new capoeira ().bitmapData));
 
			g.addChild (shape);
 
			return g;
		}
 
		private function enterFrameHandler (event : Event) : void
		{
			if (shape.pan > 60) {
				dir = -1;
			} else if (shape.pan < -60) {
				dir = 1;
			}
			shape.pan += dir*3;
			scene.render();
		}
 
		private function stageMoveHandler (event : MouseEvent) : void
		{
			var x:Number = event.localX - 145;
			var y:Number = -1 * (event.localY - 145);
			shape.x = x;
			shape.y = y;
		}
	}
}

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Notes:

  • The dimensions of the Flash applet are put at 300 x 300. In FlashDevelop you can do this in the Project > Properties dialog.
  • The mouse move handler is attached to the stage, so it no longer receives 3D events, but just the ordinary MouseEvent.
  • I’ve left out the “camera.z = -300;” statement, because -300 is the default z-value for the camera in Sandy 3D
  • I have replaced the “*” import statements with specific classes. This is not required, but it does have the advantage to clearly show which dependencies exist in your program.
  • You’ll notice that the 3D object does not follow the mouse exactly. I could just hide the cursor and be done with it (few people will notice). But it is nagging me and I have no idea why that is. I’ll ask around and see if any one can explain this to me.

And that’s really all there is to it. This really only works because the playing field is exactly the same as the screen. You might be tempted to rotate the field for cool perspective effects, but as soon as you do that, the calculation becomes more complicated.

Now it’s about time to introduce some interesting 3D objects and get some real action going. But that’s for a next post.

If you liked this, why not share it with your friends?
    This entry was posted in Flash and ActionScript and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.

    2 Comments

    1. Posted November 29, 2008 at 11:49 pm | Permalink

      The 2D > 3D mapping by analyzing what actually happens.
      I’d let Sandy3D do everything for me, but in this case, it turns out it is too slow and the calculation is not complicated at all.

    2. Posted November 30, 2008 at 9:49 am | Permalink

      The 2D > 3D mapping by analyzing what actually happens.
      I’d let Sandy3D do everything for me, but in this case, it turns out it is too slow and the calculation is not complicated at all.

    • Feedback or questions? Contact me right away.

      Comments have been disabled on my posts. Not because I don't want to hear from you, but because they were adding very little to the conversation (most of them were spam anyway). I do listen to you and try to keep as much posts as possible up-to-date and error free. So if you have a question, if something isn't working the way you hoped or you have general feedback, please use the contact form below. I guarantee an answer to every honest question or remark.
    • Get in touch
      1. (required)
      2. (valid email required)
       

      cforms contact form by delicious:days