Papervision Training at Flash on Tap

Man, I was just over at Keith’s blog and saw him realizing that FOT is just 3 weeks away!!! I instantly had the same reaction – holy beer batman!

I thought it’d be good a good idea to post what Andy and I will be covering and what you’ll need.  We’re giving a live full day workshop the day before the event starts.  If you haven’t signed up and you’re interested in going to the 1 day work shop (you don’t have to attend FOT for this), email me at neoriley at gmail dot com and I can get you the same $70 off discount code.

What we’ll be covering:

John first half of day:

  1. Papervision basics – scenes, cameras, setup
  2. cameras and animation
  3. Primitives
  4. Materials
  5. Collada
  6. Papervision3D component for Flash IDE (requires CS3 unfortunately)

Andy will cover:

  1. Effects and Layers
  2. Effects Filters
  3. Shaders

The class has filled up nicely I so far and I’m really glad to get out and teach again.  Its something I really enjoy doing

Change to my Session at FOT

It was a year ago when i’d put up my description for my Session at Flash on Tap and I’d really intended just to follow through with that, but now that we’re getting much closer to the actual event, I think my topic is really not in sync with what I’v been working with in the past 6+ months.

So, I’m going to be covering the development crossovers between Papervision/actionscript3, to Unity3D/Javascript, to iPhone 3D gaming.  I’ll be showing the differences and similarities between Papervsion and Unity3D and talk about the caveats to iPhone 3D gaming with its abilities and limitations.  I’ll also being showing the Unity3D IDE,  features and workflow.

Stunt Bike iPhone game in Unity3D IDE

Stunt Bike running on iPhone

Many of the issues we deal with in Papervision3D are applicable to the iPhone 3D gaming development.  With Unity as a middle man for development, I think there’s plenty to talk about ;)

Hope to see many of you there!

Online Papervision3D training – Nov 8th. Optimization Techniques

We’re doing one more of these before the year’s end and won’t likely do it again until February 2009.  We weren’t going to do it at all, but we’d had a great response to do one more, so we’re squeezing this one in before the holidays really kick in.

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/277

Hope to see you there!

On Demand Papervision Course: Optimization Techniques

For a few months now, I’ve been doing live workshops online through RMI and those have been going very well.  So finally, after this last run, we archived the class (recorded it) and are offering it up as an on demand course you can take any time you like!

We’d received alot of feed back to provide an on demand version since not everyone can make it on the days we hold them.  Given that a fair amount of you are coming from over seas, it’s even more difficult to make the time slots.  One person was taking the class at 1am in the morning ;)   So I think this will help!

This course covers the Winter Wonder Land animation and engine.  You get all the source files for the application along with alot of other demo files that I typically hand out when I teach.  It covers:

  • Materials preparation and best usage with animation
  • BitmapData concepts to replace traditional MovieClip animations at runtime
  • SWF settings that can cause better performance (or worse)
  • Using multiple viewports and BitmapViewport3D
  • Simple tricks for getting decent effects (cheaply on the cpu)
  • Shaders ( bonus material )

Title: Papervision3D 2.0 Optimization

Duration:~200 minutes

Description: We’re going to take the Winter Wonderland demo from Zero fps to the 20’s by practicing a few some less known and some well known tips and tricks concerning both the Flash Player and Papervision3D. We’ll cover image preparation and rules, the Flash Player’s idiosyncrasies and what makes Papervision3D really sing. The Winter Wonderland animation started out as slow as 2fps and ended up in the mid 20’s after all of these techniques were applied. That leaves plenty of room for additional animations and bells and whistles later on! We’ll take the source for Winter Wonderland and crawl through it together to squeeze every last FPS out possible.

Who this course is for: Flash designers / developers with Papervision3D experience.

Check it out here

Papervision3D Training: Saturday, Sept 27th!

Because of hurricane Ike, the training was rescheduled to the 27th :) I apologize for the hassle

The info on this post is still relevant, even though it lists Sept 14th as the date on Papervision’s Blog – Hope to see you there!

Papervision3D Training: Sept 14 this weekend!

I just posted the info on Papervision’s Blog – Hope to see you there!

Flash on Tap conference

You know, i’ve been to quite a few Flash conferences ( not as many as Grant or Keith however ), and I’ve often wondered what it’d be like to put on a conference – what would I do with it? How would it be different and, for love of God – why another one?!

I mean really, do we need another conference? People already have a pretty big selection and usually can only swing one or maybe two with their company to pay for, so it’s really a task to pick very best ones! There are 4 one day workshops, and Andy Zupko and I are teaching Papervision3D at one of them. Andy will be teaching Effects/layers and I’ll be teaching optimization techniques.

Ok yeah, FOT is put on by IR5 along with the guys at influxis (we love you guys!!), so it’s natural I’d show up for this one conference. BUT, what’s unique is that this is a conference BY Flashers FOR Flashers. I have a feeling we’ll see some inspired work for sure, given the atmosphere is zero pressure and it mixes beer tasting from local brewery’s. It’ll probably be one giant “sit back and relax with some flashin’ and friends” party.

Anyway, this one you won’t want to miss – it’ll likely be a one time wonder where everyone had a mindblowingly good time, and nothing like it will ever occur on the face of the planet like it again – ever.

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 drawing demo

2 classes in a row now, I’ve done this same demo live in front of everyone :) Sooooo sensing a trend here, and after someone asked if I’d post it, I’m putting out out here. It’s a very simple demo, but the exercise in class was to demonstrate what you get back with the InteractiveScene3DEvent object. You literally get back x and y properties that represent where your cursor is over the 3D object in your scene.

So, we took those values from an OBJECT_MOVE event that the ISM dispatches and use it to draw circles on the MovieClip used for the material – and there you go, simple as that ;)

[kml_flashembed movie="http://www.rockonflash.com/papervision3d/drawingDemo/DrawingDemo.swf" width="550" height="400"/]

Here’s the code and you can download it here:
[as]
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.cameras.FreeCamera3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.core.utils.InteractiveSceneManager;
import flash.filters.DropShadowFilter;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

var viewport:Viewport3D = new Viewport3D(0, 0, true, true);
addChild(viewport);

var renderer:BasicRenderEngine = new BasicRenderEngine();

var scene3d:Scene3D = new Scene3D();
var camera:FreeCamera3D = new FreeCamera3D();
camera.focus = 1100;
camera.zoom = 1;

// create material and object
var mat:MovieMaterial = new MovieMaterial(material, false, true);
mat.oneSide = false;
mat.interactive = true;

var sp:Sprite = new Sprite();// add drawing layer
sp.scrollRect = material.getBounds(material); // this keeps you from drawing off the edges and messing up the mapping
sp.filters = [new DropShadowFilter(4, 45, 0x111111)];
material.addChild(sp);

var plane:Plane = new Plane(mat, 500, 500, 4, 4);
plane.moveRight(200);
plane.yaw(60);

plane.addEventListener(InteractiveScene3DEvent.OBJECT_MOVE, handleMouseMove);

function handleMouseMove(e:InteractiveScene3DEvent):void
{
if( !InteractiveSceneManager.MOUSE_IS_DOWN ) return;
var g:Graphics = sp.graphics;
g.beginFill(0×333333);
g.drawCircle(e.x, e.y, 4);
g.endFill();
}

scene3d.addChild(plane);

stage.addEventListener(Event.ENTER_FRAME, handleEnterFrame);

function handleEnterFrame(e:Event):void
{
camera.x = camera.y = camera.z = 0;
camera.yaw(.5);
camera.moveBackward(1500);
// render camera
renderer.renderScene(scene3d, camera, viewport);
}
[/as]

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 :P lane;
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!