Archive for the ‘ AS3 ’ Category

BaywoodGallery – a little somethin’ for my parents

You know it’s pretty sad when your parents have to beg. But it’s shameful when they’re begging you for work you do on a daily, if not a nightly basis!

So, since they’re heading out to do a show in California in a week, I had to get something out there. I’d intended to just throw up another iTunes coverflow app, but I just couldn’t bring myself to do it. Then I thought that doing a triple carousel viewer would be cool, but thought it would be 3x’s as bad as all the other carousel 3D gallerys that keep hitting the web. Don’t get me wrong, it’s a fine way to present gallery’s, I just wanted to do something that was interesting and possibly different.

I’d had this idea to do an “outer gallery” for a while, so this was the perfect time to flush it out a bit. The concept is that instead of being an “inside gallery” that you walk through, this is an “outer gallery” that conforms to the way you might rotate it around for the best view. You’ll notice that the paintings have a particular rotation that would indicate the best viewing angle. As you rotate around, other paintings and pictures are revealed and are already in the rotation you’re currently at.

One thing that makes this work is that Z rotation never happens. You can invert the model for sure, but it never “rolls” on the Z axis, and that keeps the model at angles that make sense as you rotate around. It’s not a “new” way, it’s really very close to how 3D studio Max or Maya handle the free rotation – just without the ability to roll :)

But because of limiting that Z roll, the model never gets to a rotation that’s completely out of control or upside down and controlling it with the mouse seems pretty intuitive to even the lowest end users I’ve tested with (you know, graphic artists, and lead singers). I’m just kidding, I love graphic artists.

It’s not perfect, and I would like to clean up a few things. I’d really like to flush out this concept further, but I’m pretty happy with how it turned out initially. All told, it’s 3340 polygons and runs pretty smoothly. The biggest hurdle was creating an intuitive structure for this and then dealing with planes sitting over the top of the center model and fixing sorting issues. What keeps this demo running smoothly is the fact that I don’t have to rely on some run-time tessellation. Because of that, I have much more head room in terms of # of poly’s in the scene.

Papervision3D – fixes to VirtualMouse, Interactivity and using UIComponents

First off, I’ll just say that this kind of work is enough to cause you to go barking mad. Just set yer hair on fire and start running the halls naked now.

I’ll start off by archiving what I found, then go into “best practices” on how to create a plane using a movieclip that has UIComponents in it.

Findings:

  • VirtualMouse has a weird issue when stage quality is set to anything other than LOW and you use coordinate conversion on the values passed in. When set to LOW, it works as expected, but when set to any other setting, the UIComponents only lit up when you moused over the label of a component, not the drawn area and the basic movieclip I had in my test with rollover events didn’t even fire. Only when I moved the movieclip to 0,0, then did getObjectsUnderPoint did it work perfectly under all quality settings. Oye – I don’t know why I’m afraid. But in testing in a pure flash IDE test, quality settings didn’t cause any issues with getObjectsUnderPoint() – so, it’s obviously a VirtualMouse issue.
  • When you have a scrollRect defined on a movieclip, getObjectsUnderPoint() does not return any values IF you move the movieclip THEN call getObjectsUnderPoint. Only AFTER the displayList is updated does it work with the movieclip moved. That kinda sucked for what I had to accomplish with PV3D unfortunately. But fortunately, a new feature JUST implemented by Carlos makes this a non issue altogether. I know, you’re asking, why in the WORLD would you be doing such a thing, but it’ll make sense later on as I explain how to use UIComponents with movies used for materials.
  • You might think that if a movieclip/sprite is invisible (visible = false), that it’s not being rendered and therefore, you’re saving on the CPU – this maybe true to a certain extent of course, but if you right click and show redraw regions in the flash player, you can clearly see that if there ARE any visual changes like an animation or rollover state in your movieclip/sprite, you’ll see a redraw region show up right where the animation/visual change is taking place. Now, I’m not at all sure what this means in terms of how much processing is taken up because of it, but it IS causing the flash player to consider that are for SOME type of work.

Now, on to why I’m actually writing this post: How to use UIComponents in materials used on 3D objects with Papervision3D.

Initially, we have to realize what’s happening with UIComponents and what the initial problems are. The UIComponents are, when first added to a movieclip have a certain size, but it’s not the expected/anticipated size you might see when you add them to the Flash IDE stage at design time. What you see is a nice rendered component at design time, but at runtime, if you have *not* added the components to the displayList, you won’t see anything but the component labels, and they’ll be a size you didn’t anticipate.

This is simply because they don’t initialize until ADDED_TO_STAGE event is fired and the Stage property is set. So, for Papervision3D, this poses some problems right off the bat, since we don’t really want the movie clip and components sitting on stage AND wrapped around our 3D object. This means we have to use MovieMaterial and add the movieclip to the stage. Oh, and by the way, there’s another issue – timing. You *can* create movieclip, put it on stage, then create the MovieMaterial and just go on down the list, but there will be the possibility that the user would see this until the components are initialized AND another render has taken place AND the material is told to update:

One thing you’ll notice in this screenshot is that there is a black are at the bottom and the original movieclip is squished. That’s because the original size of the components is much different than after their initialized. In the screen grab below, I’ve put all of the Flash IDE UIComponents on stage and drawn a green bounding box before they intialize and a white bounding box after they initialize. You can see that their sizes change quite drastically and because my checkbox and radiobutton are at the bottom of the movieclip material, the dimensions of the movieclip are thrown off:

You can see in the pic above that checkbox and radiobutton are much taller than their final render and that textArea really never reflects what you visually see. I’m not sure what’s causing it’s size to remain that way, but it is. And the progressbar, slider and color picker don’t have any visual assets until their initialized as you can see.

Ok so what’s the solution to all these issues?!?! I’ll just step down the list in order, post the code and you can play ;)

  • Create your movie clip and then move it off stage where it can’t be seen. In the code below, I move it to -10000. I did some speed tests and it turns out that just simply setting x/y values is faster than using coordinate conversion methods. So, virtualMouse will move your movie to 0,0, then get the objects it needs, then move it back to it’s original location. Since this executes between frame renders, it doesn’t impact the displayList and you never see it happen.
  • Create a method like parseComponents() below. The idea is that you go through all of your components, addEventListeners to when they’re added to stage, THEN when they’re all added, create the MovieMaterial and Plane objects.

[as]

// import UIComponent:
import fl.core.UIComponent;

// later…

var cls:Class = getDefinitionByName(“Mc”) as Class;
movie = new cls() as Sprite;
movie.x = movie.y = -10000;

parseComponents();
addChild(movie);

protected function parseComponents():void
{
uiCounter = 0;
for( var i:int = 0; i<movie.numChildren; i++)
{
var mc:DisplayObject = DisplayObject(movie.getChildAt(i));
if( mc is UIComponent )
{
mc.addEventListener(Event.ADDED_TO_STAGE, handleComponentReady, false, 0, true);
uiCounter++;
}
}
trace(uiCounter);
}

protected function handleComponentReady(e:Event):void
{
var uiComponent:UIComponent = UIComponent(e.currentTarget);
uiComponent.removeEventListener(Event.ADDED_TO_STAGE, handleComponentReady);
uiCounter–;
if( uiCounter == 0 ) createPlane();
}
[/as]

NOTE: if you’re working in FlexBuilder or Eclipse, you’ll need to add the fl classes so that you can add the UIComponent import

  • Now, after we’re sure all components are loaded, create the MovieMaterial and apply it to your 3D object and pass one more NEW argument: Rectangle:

[as]
protected function createPlane():void
{
movieMat = new MovieMaterial( movie, false, true, false, new Rectangle(0,0,256,256) );
movieMat.oneSide = false;
movieMat.setQuality(StageQuality.HIGH, stage, true);
movieMat.interactive = true;
movieMat.smooth = true;

plane = new Plane(movieMat,256,256,6,6);
plane.yaw(-20);
view.scene.addChild(plane);
}[/as]

Now, one extra cool thing to note here is, that the checkbox and radiobutton are STILL to low and actually cause a hairline black area to be drawn on the material. So, to be even MORE dogmatic about making sure our material stays the same dimensions, you can now pass in a rectangle object to the MovieMaterial. The great thing about this is, it’s used that the time the bitmapData object is created from the source movieclip. Soooooooooooo the scrollRect issue I mentioned earlier is no longer an issue, and you don’t have to incure that cost on your movieclip just for the sake of making sure the UIComponents don’t have inappropriate relations with your dimensions :)

[kml_flashembed movie="http://www.rockonflash.com/demos/pv3d/ComponentMaterialTest.swf" width="550" height="400"/]

Get the source

Final code:
[as]
package
{
import fl.core.UIComponent;

import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.utils.getDefinitionByName;

import org.papervision3d.cameras.CameraType;
import org.papervision3d.materials.MovieAssetMaterial;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.view.BasicView;
import org.papervision3d.view.stats.StatsView;

public class ComponentMaterialTest extends Sprite
{
public var mc :MovieClip;

public var view :BasicView = new BasicView(0,0, true, true, CameraType.FREE);
public var plane :Plane;
public var mat :MovieAssetMaterial;
public var movieMat :MovieMaterial;
public var movie :Sprite;
public var uiCounter :Number = 0;

public function ComponentMaterialTest()
{
super();
addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
}

protected function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.quality = StageQuality.MEDIUM;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

var cls:Class = getDefinitionByName(“Mc”) as Class;
movie = new cls() as Sprite;
movie.x = movie.y = -10000;

parseComponents();
addChild(movie);

view.camera.zoom = 1;
view.camera.focus = 1100;

addChild(view);
addChild(new StatsView(view.renderer));
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}

protected function createPlane():void
{
movieMat = new MovieMaterial( movie, false, true, false, new Rectangle(0,0,256,256) );
movieMat.oneSide = false;
movieMat.setQuality(StageQuality.HIGH, stage, true);
movieMat.interactive = true;
movieMat.smooth = true;

plane = new Plane(movieMat,256,256,6,6);
plane.yaw(30);
view.scene.addChild(plane);
}

protected function loop(e:Event):void
{
view.singleRender();
}

protected function handleComponentReady(e:Event):void
{
var uiComponent:UIComponent = UIComponent(e.currentTarget);
uiComponent.removeEventListener(Event.ADDED_TO_STAGE, handleComponentReady);
uiCounter–;
if( uiCounter == 0 ) createPlane();
}

protected function parseComponents():void
{
uiCounter = 0;
for( var i:int = 0; i<movie.numChildren; i++)
{
var mc:DisplayObject = DisplayObject(movie.getChildAt(i));
if( mc is UIComponent )
{
mc.addEventListener(Event.ADDED_TO_STAGE, handleComponentReady, false, 0, true);
uiCounter++;
}
}
trace(uiCounter);
}
}
}
[/as]

Online Papervision3D courses – Optimization techniques

*UPDATE*
Apparently adobe scheduled maintenance this saturday during the scheduled time for the course (which blows tremendously -they could have asked if anyone was doing something during those hours) I guess it could be argued that no time is a good time, but I’d argue back that midnight would be 90% better option I’m willing to bet… Just sayin’

Anyway, we ARE going to reschedule it asap (like in the next week or 2), and RMI is extending the viewable recording of the session to 2 months for the inconvenience to the students. Sorry for the hassle guys

I’m sorry I’m late on announcing this, I’ve been super busy with this current client and trying to get everything else done for the course has just consumed all motor skills and brain cells ;(

I’m taking a break from traveling for a while, so RMI has set me up with some on-line course time and this weekend (saturday), I’m going to pouring over the Winterwonder Land application and talking about optimization techniques for Papervision and the flash Player in general.

In the course files, I’m including nearly all the demo’s I used for the classes I taught in person as well as the source for Winterwonder Land’s animation engine etc.

If you’re interested, you can sign up over at RMI’s site:

http://www.richmediainstitute.com/node/142

Hope to see you there!

Well, Go3D is official – We need base 3D classes that all engines can use

What turned out to be just something to finally scratch a strict typing itch i’d had with tweening has no become and full blown side project. Not only did Moses get me started, but Graeme Asher and John Lindquist fueled the fire as well. Graeme’s been working on Tween3DCamera and John’s been helping me add some other properties like scale/scaleX/scaleY/scaleZ to the property types as well as a small refactor.

If you’ve tried Go3D lately, you’ll notice that I had put static property methods (yeah kinda weird name, but that’s what they do ) in Go3D.as, but have now moved them to Value.as in the properties directory. It seemed to make alot more sense with what their function was, and Go3D.as has been deleted for now since it serves no purpose.

check out the project here:
http://code.google.com/p/goplayground/wiki/JohnGrden

svn:

http://goplayground.googlecode.com/svn/trunk/JohnGrden/GO3D

One thing I added just today was the ability to pass a tweenTarget for a 3D object. If you look at the code samples below, you can now just pass a target and it’s position and rotation will be used to tween to. You can also use constants to just tween to position or just rotation. You can also pass custom properties for it to use with the target. The swf demo I’ve posted in the playground basically tells the Cylinder object to use the properties of the orange sphere.

[kml_flashembed movie="http://www.rockonflash.com/papervision3d/Go3D/sphereAnimation/SphereAnimationsGo3D.swf" width="500" height="400"/]

[as]
protected function tweenAll(e:Event=null):void
{
resettargetObject();
tween = new Tween3D(targetObject, [Value.tweenTarget(middleObject)], duration, Easing.easeOutElastic);
tween.start();
}

protected function tweenXYZ(e:Event=null):void
{
resettargetObject();
tween = new Tween3D(targetObject, [Value.tweenTarget(middleObject, Value.XYZ)], duration, Easing.easeOutElastic);
tween.start();
}

protected function tweenCustom(e:Event=null):void
{
resettargetObject();
tween = new Tween3D(targetObject, [Value.tweenTarget(middleObject, [Value.X, Value.Y])], duration, Easing.easeOutElastic);
tween.start();
}

protected function tweenRandom(e:Event=null):void
{
tween = new Tween3D(targetObject, [Value.x(getRandom()), Value.y(getRandom()*.5), Value.z(getRandom())], duration, Easing.easeOutElastic);
tween.start();
}
[/as]

Value.tweenTarget() returns an array of Go3DProperty objects that Tween3D expects to get to do the tween. It’s basically a convenient, yet strictly typed way of doing things. I’d say we’re having as much fun as untyped objects at this point – Even more probably ;)

Note:
I’ll be teaching on Go3D at the Toronto class in 2 weeks, and if you haven’t signed up yet, I seriously suggest getting out there asap – seats are filling up

Now, the reason I say we need base 3D classes for all 3D engines to use is because in a situation where I want to open this up for Sandy3D or Away3D or any other 3D engine that uses x/y/z/rotationX/Y/Z/scaleX/Y/Z, I’d have to write specific classes tailored to their api and object types.

We need to have one set of common 3D classes that define the atom level of a 3D object with the main 10 properties:

x, y, z, rotationX/Y/Z, scale, scaleX/Y/Z

So, I’m going to be starting such an effort and see how that pans out ;) It makes too much sense especially when you consider any project that has to work with a 3D engine, but isn’t integrated with the code base. ASCollada being one, and Go3D being another.

I’d love to hear people’s thoughts on this matter.

Papervision3D + GoASAP = Go3D

Well, ok the name needs some work, but temporarily I’ll call it this since I’m using GoASAP under the hood of Go3D Tween classes. The idea is simple: Write a tween class specifically catering to a DisplayObject3D with x, y, z, rotationX, rotationY, rotationZ properties. What I ended up with was Tween3D (again, the name will likely change as this is a bit generic).

Now, after all my rants about untyped objects blah blah blah, I’ve really come to at least appreciate *why* people use this approach. It certainly is faster to type and get something up and running. But, I didn’t want to walk down that path with this one AND I wanted something reusable. I think there are situations where you can waste alot of time recreating these transient tweens within the body of your code that could easily be re-executed after being created one time. Tween3D does this.

It’s not a magic trick by any means, I’m simply initializing the “start” values when a Tween3D actually “starts”. It’s very simple and allows for reuse and instantiation.

I really wanted to take this on for a couple of reasons, but mainly to get into writing my own tween classes using Go. I’ve had the pleasure of being able to sit and talk to Moses at length about what Go is and the first thing I wanted to do ever since was try my hand at creating a strongly typed API. So far so good, but I think there’s room for improving the amount of code you have to write. It’s actually pretty compact and very easy to understand, but still, I’d like to see some even shorter ways of creating strongly typed tweens.

As you might expect, if you’ve used Fuse or Tweener in the past, a strongly typed tween might look like this:
[as]
var tween:Tween3D = new Tween3D(target:DisplayObject3D, duration:Number, easing:Function, delay:Number);
tween.x = 2000;
tween.y = 1000;
tween.start();
[/as]

As you can see, its alot like a Tweener call, except the properties aren’t in an untyped object, they set after instantiation. This setup is good for a few reasons:

1. Faster – always faster to set properties after instantiation than it is through the constructor
2. Strict typing – easy to understand what you can and can’t do with the Tween3D
3. reusable – you can create once, and reuse the tween over and over. This is nice in a situation where tweens are kept in a manager class that someone else maintains through out a project. Single point of management can be a very cool thing. This can also keep the CPU hit down when you need a tween.

Another thing about GoASAP is the Sequencing classes that come with it. Alot of times I’ve used Fuse for sequencing events, not necessarily animation tweens :) The sequencing is a very strong and abstract part of GoASAP. If you need it, great, hook it up. If you don’t, then it’s not there apart of the payload. Adding your own custom managers is a snap as well. if you need the OverlapManager that comes with Go, you can hook it in with one line of code. You can also create your own or just leave it out altogether.

I’ll be covering Go3D at the classes in Vancouver (this weekend) and Toronto in June, but you can get the source here and the Rolodex demo files here. Its definitely in early stages, but I think it’d be great to get some input if anyone’s interested. You’ll also need to sync or download GoASAP here. Tween3D is written specifically for use with Papervision3D’s DisplayObject3D, so if you’re gonna play, you obviously need to use it with a 3D scene and 3D objects ;)

+++++++ [ shameless classes plug ]++++++++++
Vancouver: May 3rd & 4th

Toronto: June 7th & 8th

This demo below is something I converted from Tweener to using Go3D. The lines of code were more for sure, but thats because of what GoASAP isn’t assuming for me like other animation engines would have to. So, I had to add a Sequence and an OverlapManager to acheive the same effect. Ok so it’s more complexx, but it’s also a ton more flexible. if I didn’t like Moses’ OverlapManager, i could write my own. if I didn’t like his sequencer, I could write my own and plug it in. The point is, I can completely customize any portion of the Tween engine to my project, company or general tastes at any given level. Companies can actually dictate the API and have maximum control over *what* the tween/sequence engine is doing in their application. I think once people realize what GoASAP is, we’ll see alot of uses for it in many ways we’re not even able to comprehend yet.

[kml_flashembed movie="http://www.rockonflash.com/papervision3d/Go3D/RolodexGODemo.swf" width="550" height="500"/]

Code for this animation sequence:
[as]package {
import com.rockonflash.go3d.Tween3D;
import com.rockonflash.go3d.utils.Equations;

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.getDefinitionByName;

import org.goasap.GoEngine;
import org.goasap.events.GoEvent;
import org.goasap.managers.OverlapMonitor;
import org.goasap.utils.SequenceCA;
import org.goasap.utils.SequenceStepCA;
import org.goasap.utils.customadvance.OnDurationComplete;
import org.papervision3d.cameras.FreeCamera3D;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

//import com.rockonflash.go3d.utils.Equations;

public class RolodexGODemo extends Sprite
{
public var target :Plane;
public var viewport :Viewport3D;
public var scene :Scene3D = new Scene3D();
public var camera :FreeCamera3D = new FreeCamera3D(11);
public var renderer :BasicRenderEngine = new BasicRenderEngine();

public var sequence :SequenceCA;
public var tween_0 :Tween3D;
public var tween_0b :Tween3D;
public var tween_1 :Tween3D;
public var tween_2 :Tween3D;

protected var doLoop :Boolean = true;

public function RolodexGODemo()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
init();
}

public function init():void
{
GoEngine.addManager(new OverlapMonitor());

viewport = new Viewport3D(0, 0, true, false);
addChild(viewport);

var cls:Class = getDefinitionByName(“rolodex”) as Class;
var rolodex:Sprite = new cls() as Sprite;

var mat:MovieMaterial = new MovieMaterial(rolodex, true, false);
mat.smooth = true;

target = new Plane(mat, 292, 168, 4, 4);
scene.addChild(target);

reset();
createTween();

finalizeInit();
}

protected function finalizeInit():void
{
stage.addEventListener(MouseEvent.CLICK, handleClick);
stage.addEventListener(Event.ENTER_FRAME, loop);

loop();
doLoop = false;
}

protected function loop(e:Event=null):void
{
if( !doLoop ) return; // only render when we have to
renderer.renderScene(scene, camera, viewport);
}

protected function handleClick(e:MouseEvent):void
{
doTween();
}

protected function createTween():void
{
sequence = new SequenceCA();
sequence.addEventListener(GoEvent.COMPLETE, handleSequenceComplete, false, 0, true);

tween_0 = new Tween3D(target, 1, Equations.easeOutCubic);
tween_0.x = 0;
tween_0.y = 50;
tween_0.rotationZ = 0;
sequence.addStep(tween_0);
sequence.lastStep.advance = new OnDurationComplete(.2); // advance early/overlap

tween_0b = new Tween3D(target, 1, Equations.easeOutCubic);
tween_0b.z = 200;
sequence.addStep(tween_0b, true); // 2nd param groups it with previous step. param is “addToLastStep”

tween_1 = new Tween3D(target, 1, Equations.easeOutCubic);
tween_1.x = -10;
tween_1.y = 85;
tween_1.rotationZ = 15;
sequence.addStep(tween_1);
sequence.lastStep.advance = new OnDurationComplete(.25); // advance early/overlap

tween_2 = new Tween3D(target, 1, Equations.easeOutBounce);
tween_2.rotationX = 0;
tween_2.rotationY = 0;
sequence.addStep(tween_2);
}

protected function handleSequenceComplete(e:GoEvent):void
{
doLoop = false;
}

protected function reset():void
{
target.x = (Math.random() * (stage.stageWidth*.5));
target.y = -350;
target.z = -1000;
target.rotationY = 30;
target.rotationX = 30;
target.rotationZ = Math.random() *-180;//-10;
loop();
}

protected function doTween():void
{
reset();
//createTween();
doLoop = true;
sequence.start();
}
}
}
[/as]

I gotta say a huge thanks to Moses for putting up with my questions and debugging ;) It was FUN non the less!

Phillip Kerman: What’s he got against the beaver?!

Why FITC?

Ok, I’ve seen many attempts at humor by flash developers in my day, but Phillip puts them all to shame. I think Flash *might* be his side job in reality. The other “why” videos are hilarious, but this one had some added frosting with the intro and ending disclaimers.

He gets a 4 rock on rating for this one ;)

RockOn Rating:   RockOn voteRockOn voteRockOn voteRockOn vote

Papervision3D: Accessing MovieClips used in materials

I’ve often been asked this question and it’s come up quite a few times on the PV3D list, so I thought I’d post about it just for archive sake if anything else.

Right now, in PV3D, you have the ability to use MovieClips/Sprites for Materials on 3D objects. The 2 materials you would use for this are MovieMaterial and MovieAssetMaterial (Asset means that it’s in the Flash IDE library rather than an instance on stage). When you create these materials, they have reference to a MovieClip/Sprite container.

Often times, you need to communicate with these MovieClips via ActionScript, and I’m going to show you how you can do this with a basic sample that uses a sub class that extends MovieClip, and then later we try to access that MovieClip with some strong typing.

First, let’s create a sub class that extends MovieClip and you would use that to assign to a MovieClip in the Flash IDE library:
[as]
package com.rockonflash.pv3d.materials
{
import flash.display.MovieClip;

public class SpecialSauce extends MovieClip
{
public function SpecialSauce()
{
// constructor
}

public function animate():void
{
gotoAndPlay(“animate”);
}
}
}[/as]

Next, we need to create a MovieAssetMaterial, and then create a reference to it so we can talk to it via ActionScript. First we’re going to call setupScene() and create a plane object that has scope in this class. When we call doAnimation(), we cast the material of the plane object first to make sure it’s a MovieAssetMaterial. This helps avoid any RTE’s obviously, but its necessary since Plane’s material property is set to MaterialObject3D. So, if you tried to access the “movie” property of plane.material, you’d get an compile error since plane.material is thought to be a MaterialObject3D.

In the next part of doAnimation(), we cast the movie property as SpecialSauce. This is for the compiler as well since we want to call a custom method called “animate” that doesn’t exist on MovieClip alone. If the cast is successful, mov.animate() will fire and bingo, you’re in business!
[as]
import com.rockonflash.pv3d.materials.SpecialSauce;

protected var plane:Plane;

public function setupScene():void
{
var mat:MovieAssetMaterial = new MovieAssetMaterial(“com.rockonflash.pv3d.materials.SpecialSauce”, true, true, true);
plane = new Plane(mat, 256, 256, 3, 3);
}

public function doAnimation():void
{
// cast as MovieAssetMaterial, then test for null
var mat:MovieAssetMaterial = plane.material as MovieAssetMaterial;
if( mat )
{
// cast as our sub class, then test for null
var mov:SpecialSauce = mat.movie as SpecialSauce;
if( mov )
{
// now you’re talking to the instance directly
mov.animate();
}
}
}[/as]

Now one last thing to note is the 4th argument on MovieAssetMaterial: unique:Boolean. If set to true, you will get a unique instance of the MovieAssetMaterial. You might think that when you create a MovieAssetMaterial, you’d be creating a unique instance, but in reality, you’re not. By default, Papervision3D re-uses instances of MovieAssetMaterials if they’ve already been created – UNLESS you tell it to create a unique instance. We do that to save on memory and in some cases speed.

hope this helps!

UPDATE - interactivity
So, now to take it a bit further, if you want to get Mouse interactivity going with your MovieClip (SpecialSauce), all you have to do is:

1. set your viewport object’s “interactive” property to true
2. set your material’s “interactive property to true
3. addEventListener to your objects inside of your class or to the class itself:

[as]protected var viewport::Viewport3D;
protected var plane:Plane;
public function setupScene():void
{
// forth argument is ‘interactive’
viewport = new Viewport3D(1200, 600, false, true, true, true);
var mat:MovieAssetMaterial = new MovieAssetMaterial(SpecialSauce, true, true, true);
mat.interactive = true;
mat.movie.addEventListener(MouseEvent.CLICK, handleClick);
plane = new Plane(mat, 256, 256, 3, 3);
}

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

At this point, you should see ‘clicked’ in the trace output.

There you go!

Papervision3D class in San Francisco -

I just posted some of the new things we’re throwing into the class for San Francisco over on PV3D’s blog:

* 2.0 (GreatWhite) training
* Un-released 2.0 component ( released to the class members only, includes new materials panel )
* New Sketchup native file support
* Swift3D Overview
* Swift3D giveaway (2 free copies and 15% discount code for class memebers)
* WOW Physics engine
* Shaders/Materials
* Effects
* Pixel3D/PixelModeler

Andy’s gonna be there as well, and it should be a great class

Pixel3D’s conforming to 3D models \m/

Andy’s just added a class that allows someone to create 3D Pixels that adopt the shape of a 3D model – this rocks. There’s also a argument in there for subdivision’s of faces so that even if your model is very simple, you can cover it with quite a bit more pixels.

For more info, check out Andy’s post

Minimal Components: Keith Peters style

I was just putting together a custom UI to record some animation stuff I’m doing on a “winter wonder land” project I meant to have ready for Christmas, but of course, I got anal and well…I’m late…as usual.

But be that as it may, I was just sitting there last night struggling on what I should do with the tool I needed to create. I’m using Flash IDE because I’m creating many MovieClips for materials used on 3D objects, but all the code is being done in FB3. So, when I add a “button”, of course, I have to turn of the “auto keep imports clean” feature (which I think rocks) and use import fl.controls.Button because I’m compiling with Flash IDE.

Yeah, I know we could argue about using the component kit for flex, but so far, I’ve had mixed results with using that. Plus, there’s alot of work done with layers and building out the movieclips…just makes more sense to stay in the flash IDE for now

anyway, then I read about Keith’s minimal component set – it couldn’t have been timed better. There’s probably other packages out there etc that I could use, but I like the way Keith usually thinks and does things ;)

The one little feature I like is how he added the ability to send a reference to the click or change handler in the constructor as well as x/y position and parent container. If you’ve already done alot of as3, you’re all too familiar with creating the component, then addEventListener until your fingers fall off. It’s just a nice convenience for the small one-off’s you’ve got going for sure.

Follow

Get every new post delivered to your Inbox.

Join 794 other followers