Real Snow in Papervision3D [AS3] · Dec 14, 10:45 PM

Click+Drag to Orbit

Added 12.17.08: Double Snow

Source

Download Source Code"

Using BasicViewPlus

This demo uses BasicViewPlus, a class discussed in Seamlessly Combining 2D and 3D in Flash with Planes, Part 2 [AS3]. The utility function attachDOtoPlane is used to turn a Bitmap object of a snowflake into a 3D snowflake. It looks like this:

  flakePlane = attachDOtoPlane(bmp, {  allowAutoResize: false, doubleSided: true, transparent: true }, 1, 1 ) as Plane;

This is basically just a shortcut for: instantiating a Plane object with 1 horizontal and 1 vertical segment; and assigning a material with the properties { allowAutoResize: false, doubleSided: true, transparent: true }.

Concepts

It also illustrates some common, basic tasks in Papervision3D:

  • Smoothly orbiting a camera around the origin.
  • Using blur filter and useOwnContainer to simulate depth-of-field.
  • Reusing 3d objects for efficiency.
  • Creating a fake-3d gradient background.

Smooth Camera Orbit

This code is based on the article Dragging mouse for camera orbit, however it smooths the camera movement with a simple easing equation.

The mouse event handlers are similar:

  1. private function onMouseDown(event:MouseEvent):void {
  2. isOribiting = true;
  3. previousMouseX = event.stageX;
  4. previousMouseY = event.stageY;
  5. }
  6.  
  7. private function onMouseUp(event:MouseEvent):void {
  8. isOribiting = false;
  9. }
  10.  
  11. private function onMouseMove(event:MouseEvent):void {
  12. if(isOribiting) {
  13. var differenceX:Number = (event.stageX - previousMouseX)*0.5;
  14. var differenceY:Number = (event.stageY - previousMouseY)*0.5;
  15.  
  16. cameraPitch += int(differenceY);
  17. cameraYaw += int(differenceX);
  18.  
  19. cameraPitch %= 360;
  20. cameraPitch = cameraPitch > maxUpPitch ? cameraPitch : maxUpPitch;
  21. cameraPitch = cameraPitch < maxDownPitch ? cameraPitch : maxDownPitch;
  22.  
  23. previousMouseX = event.stageX;
  24. previousMouseY = event.stageY;
  25. }
  26. }

Except that the actual camera orbiting takes place in the ENTER_FRAME listener:

  1. p1 += int(0.15 * (cameraPitch - p1));
  2. y1 += int(0.15 * (cameraYaw - y1));
  3. camera.orbit(p1, y1 % 360, true, cameraTarget);
  4.  

Blur Filter to Simulate Depth-of-Field

The depth of field defines the distance range from the camera where objects appear in or out of focus. Objects between near and far remain in-focus, while all other objects remain out of focus.

  1. private function blurFlakes():void {
  2. for each (var flake:FlakeVO in flakes) {
  3. if (flake.plane.container) {
  4. var depth:Number = int(flake.plane.container.screenDepth);
  5. if (depth < near) {
  6. flake.plane.filters[0].blurX = flake.plane.filters[0].blurY = int((near-depth)*blurMult);
  7. } else if (depth > far) {
  8. flake.plane.filters[0].blurX = flake.plane.filters[0].blurY = int((depth-far)*blurMult);
  9. } else {
  10. flake.plane.filters[0].blurX = flake.plane.filters[0].blurY = 0;
  11. }
  12. }
  13. }
  14. }

Reusing 3D Objects

Each snow flake is a Plane with 2 faces and a doubleSided flake material. The plane is nested inside of two container planes which make it easy to apply animation rotations. When a flake falls to the ground, it is considered dead. However, the objects are left in tact and the flake remains on the ground until the addFlake function needs to create a new flake at which point the dead flake can be reused.

The alternative to this technique is to simply create new flakes whenever one is neaded and immediately destory dead flakes, allowing the garbage collector to free up the unused memory automatically. However, automatic garbage collection can lead to visually disturbing hickups.

Fake-3D Gradient Background

Here, we calculate the horizon point of the gradient based on p1, the current camera pitch. Since the pitch calculation is already smoothed, the gradient movement is smoothed as well. Keep in mind that when the pitch is 180, the camera is at the bottom of it’s orbit and looking at the sky. When the pitch is 0, the camera is at the top of it’s orbit and looking at the ground.

  1. private function drawBG(e:Event = null):void {
  2. //180==up 0==down <---> p1
  3. var a:Number = p1/180;
  4. var m:Matrix = new Matrix();
  5. m.scale(.8, 1);
  6. m.rotate( -90 * radToDegree );
  7. bg.graphics.beginGradientFill(GradientType.LINEAR, [ 0xffffff,0x0080FF ], [1,1], [a*40,a*140], m);
  8. bg.graphics.drawRect(0, 0, viewport.viewportWidth, viewport.viewportHeight);
  9. bg.graphics.endFill()
  10.  
  11. }

— Pickle

---

Comment

Textile Help