Archive for the ‘ Papervision3D ’ Category

Wanna click that button on that 3D object? Now you can. Oh, and it’s so easy, a caveman could do it.

[kml_flashembed movie=”http://www.acmewebworks.com/papervision3d/interactiveBoxDemo/boxDemo.swf” width=”450″ height=”350″/]

So, lately, on the Papervision3D list, we’ve been getting alot of requests for the ability to have mouse events on elements in a MovieClip/Sprite used as a material on a 3D object. Tons in fact.

Well, with a bit of research and help from guys like De’Angelo Richardson and Jim Kremens, we were able to finally crack this nut and make it work out of the box! It’s so easy a caveman could do it 🙂

The magic is really supplied by Pierre Lepers with his 3D>2D point conversion methods and drawing demo (see blackpawn explanation).

Inspiration, was really provided by Patrick Matte over at Blitz Agency with his original cube demo and interaction – really an ingenious implementation and idea! This was actually where the bar was set in my mind – if we couldn’t provide this level of interactivity with our way of implementing it, then it wasn’t going to be good enough. Well, thankfully, it DOES work 😉

The new ISM sports Face level interactivity now. This opens up a whole new world of accessibility with your 3D scene and the 2D screen. ISM now makes it easier than ever to give you interactivity with your movieclip materials.

Here are the steps:

  • create MovieClip
  • add objects that you want to be clickable (IE: UI components, or other movieclips/sprite objects)
  • use this MovieClip with an InteractiveMovieMaterial
  • apply InteractiveMovieMaterial to 3D object
  • done.

With the addition of the new VirtualMouse by Trevor McCauley, we were able to modify is slightly to work with multiple objects that might not necessarily exist on a stage 🙂 With VirtualMouse, you’re able to receive the pure events from those objects in your MovieClip/Sprite container.

The code you end up writing looks like any other day at the office:

[as]public function createPlane():void
{
var movie:MovieClip = formUIContainer.formUI;
material = new InteractiveMovieMaterial( movie );

material.animated = true;
material.smooth = true;

// establish your MouseEvent listeners as normal

movie.btn.addEventListener(MouseEvent.CLICK, handleBTNClick);
movie.btn.addEventListener(MouseEvent.MOUSE_OVER, handleBTNOver);
movie.btn.addEventListener(MouseEvent.MOUSE_OUT, handleBTNOut);

var plane:Plane = new Plane(material, 250,250,8,8);
scene.addChild(plane);
}
[/as]

There are 5 demos for you to sample and learn from in the FaceLevelInteractivity branch of the google repository:

updated docs here:http://www.rockonflash.com/demos/pv3d/docs/index.html

Now, there’s alot that went into getting the ISM to this level and there’s alot of features that have been added to give developer the best possible scenario in getting the most FPS possible. You can use object level mode, like we’ve been doing, and now face level mode.

InteractiveSceneManager.faceLevelMode = false; // object level interaction
InteractiveSceneManager.faceLevelMode = true; // fade level interaction

We’ve also added a new static boolean property to DisplayObject3D (DO3D for short) – faceLevelMode. When set to true, all DO3D’s will create sprite containers for their faces. This is a bit heavier on the cpu, and should only be done when necessary.

The cool thing about the ISM is that, it only draws the faces you specifiy. By using an Interactive material, you designate which object will have it’s faces drawn in the ISM. Now, you can be utlra picky about WHICH objects are getting face level interactivity!

We went even a step further with mouseInteractionMode property. This basically tells the ISM “don’t draw anything unless they’re mouse interaction”. Now we have a completely new level of determining WHEN something needs interaction and not.

Also, a note about the ISM: it only receives drawing instructions if the face of a DO3D is actually drawn. So with the new culling features, we’re only drawing whats absolutely necessary to save on CPU.

Anyway, theres’ just the tip of the iceberg, but with the docs and samples, you should be well on your way to using the ISM features!

I’ll be covering the ISM in detail at the RMI classes in Toronto, so don’t miss that!
UI components notes

Now that we have this level of interactivity, we need help from the community to figure out the remaining details of *how* to use UI components with this setup. You’ll see in the formUITest that I’ve put the movieclip container inside of a parent container and set a blendMode to that parent. This allows the components to be on stage and hide the content from screen.

The UI Components will not work without a stage property being set. Also, there are issues with some of the components and their registered sizes, which if you put a component too far down on a material, it’ll change the size of the movieclip, and the mapping will be wrong if you’re using a model you textured in a 3D app like 3D Studio Max.

So, any and all help would be greatly appreciated as we figure out how to deal with the UI components and streamline the process as much as possible – thanks!

Advertisements

Optimizations for AS3 calculations

Well, I’m not the math whiz by any means, but thought enough of what I’ve been playing around with lately to throw this out there and see how it sticks to the flash wall (yes, Tink, i’m inviting you thrash this around a bit! )

Now, you’ve probably heard the tip about “use multiplication instead of division when dividing by 2”, right?

faster:
var n:Number = value *.5;

slower:
var n:Number = value / 2;

run it with a test:
[as]import flash.utils.getTimer;

var time:Number = getTimer();

function runDivisionTest():void
{
time = getTimer();
for(var i:Number=0;i<10000000;i++)
{
var test:Number = i/2;
}
trace(“DivisionTest: “, (getTimer()-time));
}

function runMultTest():void
{
time = getTimer();
for(var i:Number=0;i<10000000;i++)
{
var test:Number = i*.5;
}
trace(“MultTest: “, (getTimer()-time));
}
runDivisionTest();
runMultTest();
[/as]

traces out:
DivisionTest: 162
MultTest: 110

Alright, so it’s not miles faster, but in a 3D engine like Papervision3D, this becomes the difference between a fast engine and a slow engine real quickly.

Well, there’s one still that’s even faster: Bitwise shift operations

Divide by 2 with a right shift:
trace(10 >> 1);
// traces:
5

Multiply by 2 with a left shift:
trace(10 << 1);
// traces:
20

Now, run the test against the Division and Multiplication tests above:
[as]function runBitTest():void
{
time = getTimer();
for(var i:int=0;i> 1;
}
trace(“BitTest: “, (getTimer()-time));
}
runBitTest();[/as]

traces out:
DivisionTest: 152
MultTest: 112
BitTest: 63

HOLY CRAP Batman – that’s nearly 1/2 the speed?? or should I say, 1*.5 the speed 😉

So, I was looking at some other stuff with uint and this seems to be a real gem when it comes to Math.floor and Math.ceil operations. I was reading through Flash’s help (I have to say, I really enjoy the new help – I live in there) on uint and realized that, like int, when you pass a number, it strips everything passed the decimal (like Math.floor). So, I thought, what the hey, let’s give er’ a speed test.

Sure enough, it was much faster to use uint(n) than Math.floor(n) – nearly 10x’s as fast

*** UPDATE ***
After Paulius Uza’s comments about using int, I went back and added tests for int with the floor/ceil tests, and sure enough, they’re even faster than using uint. floor’s test wasn’t that drastic, but ceil’s was 1/2 the time of uint’s version
*** /UPDATE ***

fast:
var test:int = int(1.5);
//test equals 1

slow:
var test:Number = Math.floor(1.5);
//test equals 1

Now, I know what yer thinkin’: what about Math.ceil? +1? yes 😉

fast:
var test:int = int(1.5)+1;
//test equals 2

slow:
var test:Number = Math.ceil(1.5);
//test equals 2

Time for a test:
[as]function runFloorTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:Number = Math.floor(n);
}
trace(“FloorTest: “, (getTimer()-time));
}
function runUintFloorTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:uint = uint(n);
}
trace(“UintFloorTest: “, (getTimer()-time));
}
function runIntFloorTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:int = int(n);
}
trace(“IntFloorTest: “, (getTimer()-time));
}
function runCeilTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:Number = Math.ceil(n);
}
trace(“CeilTest: “, (getTimer()-time));
}
function runUintCeilTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:uint = n == uint(n) ? n : uint(n)+1;
}
trace(“UintCeilTest: “, (getTimer()-time));
}
function runIntCeilTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = 1.5;
var test:int = n == int(n) ? n : int(n)+1;
}
trace(“IntCeilTest: “, (getTimer()-time));
}
runFloorTest();
runUintFloorTest();
runIntFloorTest();
runUintCeilTest();
runIntCeilTest();
[/as]

traces out:
FloorTest: 1733
UintFloorTest: 176
IntFloorTest: 157
UintCeilTest: 650
IntCeilTest: 384

**** New - Math.abs ****

I was thinking about another one that I use sometimes which was using *-1 instead of Math.abs on a number

faster:
var nn:Number = -23
var test:Number= nn < 0 ? nn * -1 : nn;

slower:
var nn:Number = -23
var test:Number = Math.abs(nn);

Lets test!
[as]function runABSTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = -1.5;
var test:Number = Math.abs(n);
}
trace(“ABSTest: “, (getTimer()-time));
}

function runABSMultTest():void
{
time = getTimer();
for(var i:uint=0;i<10000000;i++)
{
var n:Number = -1.5;
var test:Number = n < 0 ? n * -1 : n;
}
trace(“ABSMultTest: “, (getTimer()-time));
}
runABSTest();
runABSMultTest();
[/as]

traces out:
ABSTest: 1615
ABSMultTest: 153

Now, I know in alot of cases, the speed differences here are not going to matter. But in a game situation, or 3D engine – these types of changes in the render loop can make a HUGE difference in performance. The Papervision3D engine has really been scrutinized for details like this, and I firmly believe that’s why it’s one of the fastest engines out there.

I realize too, that not being a total math nut, some of this is probably very obvious to other people and some of you might think “well DUH”, but for the rest of us, this could be very handy 😉

Please let me know where I’ve gone horribly wrong on any of this !

Mouse events on drawn/hidden objects

**** UPDATE ****
After a lengthy discussion with Tink over IM (you can see in my comment below), we determined that you don’t need to set the alpha to .0051 – this was a trick that Keith used with his Apollo app to make the BG clickable, but I assumed it was true for flash and never bothered to think past that 😉 You can set the alpha to 0 and still click on a Sprite on stage.

Now, I tried the suggestion of using a Sprite container and drawing in it, then assigning that as the hit area of a parent sprite container, but that was horribly slow compared to the blendMode method.

So, BlendMode, has shown to be the fastest of the 3 methods described here. Of course, causing the player to deal with alpha is going to cost you in CPU, so since BlendMode.ERASE essentially skips those calcs, it seems to be the fastest solution so far.

**** END UPDATE ****

Well, leave it to Carlos to come up with this little gem. I’d been at Keith Peter’s talk on “thinking outside the box” at FITC Toronto (which completely \m/), and one of the little gems I got from that (besides, bang/hole/shoot) was that the lowest alpha value you could set on a sprite and still have Mouse interactivity was .0051. Apparently, Keith sat there and entered in values until he hit a number that worked 🙂

*Note:Tink has helped me dispell this myth – .0051 was used for Keith’s Apollo app for the background, but is not necessary to do in flash for this type of thing. Setting alpha to 0 will allow you to interact with your containers.

Now, I’d used this little bit o’ happiness in InteractiveSceneManager with Papervision3D and it’s worked well. However, we knew this came at a price with the render.

Carlos just hit me with this work around by using BlendMode.ERASE on the sprite container – and it’s fast 🙂 He got the idea off of Tinic’s blog with a nice explanation of why it’s so much faster.

Anyway, for what I was doing, this was a rockin’ solution especially when we’re trying to preserve as much CPU for 3D as we can 😉

[as]var mc:MovieClip = new MovieClip();
addChild(mc);

mc.graphics.beginFill(0x000000,1);
mc.graphics.drawCircle(0, 0, 10)
mc.graphics.endFill();

mc.blendMode = BlendMode.ERASE;

mc.addEventListener(MouseEvent.CLICK, handleClick);

function handleClick(e:MouseEvent):void
{
trace(“click”);
}[/as]

Hope that helps, sorry for the confusion

Video Demo: Papervision3D CS3 Component 1.5 new features


I usually go back and edit stuff out like coughing, sneezing, phone rings, kids yelling. But this time, this blooper just made me laugh so I left it in there. I end up unplugging the phone and dropping it on the desk (if you’re wondering what the sounds after my pounding the desk are)

This shows how to use an interactive material to setup mouse events for 3D objects. It also covers the new Tools: ActionScript templates and how to generate code for either a class or timeline. Finally, it shows what the new Scene Rotation feature does 😉

Papervision3D CS3 Component Update v1.5

I’m glad I got a chance to get this out before the move to Texas – the performance increase in the engine and the new InteractiveScene3D / materials stuff is a great addition to the component.

I also added a new “tools” panel to the UI where you can generate quick code for either pasting right into the timeline or creating a new class document. The code is copied right to your systems Clipboard. I also made it easier for you to add your own custom templates for use. The only thing you need to do, is add them to the commands/papervision3d/templates folder as “.as” files and the UI will load all files in that directory next time you reopen the panel.

IE:C:\Documents and Settings\[username]\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration\Commands\Papervision3d\templates

I would suggest creating your own versions and not altering the ones that I put in there. Point being that they may be overwritten in future revisions of the component.

Papervision3D Component v1.5 update notes

* . New 1.5 Papervision3D engine – 40%+ faster than previous version
* . InteractiveScene3D is now default scene type
* . Interactive materials are now enabled via a new “interactive” boolean flag
* . Preloader events for collada preload
* . Error handler events for collada load errors
* . Auto-code generation – create new Class or code for timeline use
* . Create your own custom code templates
* . Scene Rotation option added to component – makes for quick mouse rotation of a collada scene
* . DisplayObject3D mouse events with Interactive materials being used

Get it!

NOTE: I’ve updated the MXP with the fix, but if you already downloaded 1.5, you can just grab this update:
Template update

And check out the updated docs

Advertisements