Web Design & Dev

Papervision 3D Flash Gallery Tutorial

MotoCMS Editorial 13 November, 2008

In our previous posts we have considered several examples of creating really cool Flash Galleries with the help of 3D. As promised, today I’ll try to explain how to make papervision gallery. At the end we’ll get something like this – awesome papervision flash gallery. Probably at this stage the gallery looks a bit unfinished, one would wish to add progress bars for the images, image names and descriptions, navigation buttons next & previous, and etc. I’d like to cheer you up by saying it’s just the beginning. In this tutorial we’ll try to write the basics, that is to say an engine for our application. Over the next several steps we’ll add functionality to this gallery. Note we plan to write more tutorials based on this example.

In this tutorial we’ll try to build a Flash Gallery using Papervison 3D. First of all I’d like to mention that the main aim of this article is passing through all stages of flash application development. At the same time we would like to discuss all contradictory questions one may face while working with Papervision 3D. More likely this tutorial will consist of several parts. Together with Papervision 3D library we’ll use Tweener for a better smooth animation and BulkLoader for a better image preloading.

You’ll need this archive in order to through this tutorial. This archive includes all libraries and applications which are necessary for the final swf creation. Flash CS3 or Flex Builder to be exact. If you know what Flex SDK is and you work with its compiler this archive is really useful for you. There is a lot of information regarding Papervision 3d on the net. You can easily find tutorials which teach how to download and install Papervision 3d and other libraries, how to adjust classpaths, and etc. It’s beside our purpose. Simply download this archive. Note you can use its structure and libraries like a start point for the other projects.

Papervision3D gallery

Tutorial difficulty level: Basic-Intermediate. We suppose even those of you who are the beginners in Actionscript 3.0 will do this tutorial with awesome results.

One more thing to mention: in this tutorial we deal with the second version of Papervision 3d. Note this version of Papervision 3d hasn’t been released yet.

1. Initial configuration

So, at the very beginning you should download papervision gallery source the archive which includes an initial project. Having unpacked the archive you should see the next file structure:

src – all necessary “as” files such as Papervision3d, Tweener and BulkLoader will be stored here. These are the libraries we’ll use in order to create the gallery. All the files we create will be added here as well. Gallery Project is a basic class which is used as Document Class in Flash CS3 and it’s being compiled while creating swf file. So I’ve put it into root. The other files we create for this project will be stored here com/flashmoto/gallery.

fla – this folder will include fla files. It already includes GalleryProject.fla with changed settings: the folder ../src is added to classpath, Document Class is GalleryProject.as

bin – the application called GalleryProject.swf is stored here. All xml files and images that make an application work are kept here as well. Saving your time I’ve already created an xml file with images data. All images are stores in images folder.

For the beginning let’s start compiling the application. As I’ve already mentioned there are two ways of compilation: using Flash CS3 and on your own (means using Flex SDK compiler). As a rule experienced users apply Flex SDK compiler while creating Flash movies. They definitely know what one should do with the source code in order to get a working swf. So I’ll describe how you can compile movie in Flash CS3. To do so I should run GalleryProject.fla from the fla folder and compile the movie having clicked Ctrl+Enter. In the flash output panel you should see something like this – Welcome to our 3D gallery!

Papervision3D gallery

2. Problem Description

Let’s build a gallery by following our step-by -step guide. First of all we should decide what to do. So our main tasks are:

– Application Initialization
– Application Initialization
– Loading XML Data
– Loading Images
– 3D Engine Initialization
– 3D Objects Creation
– Adding Objects to the Stage
– Adding Interactivity

3. Application Initialization

Let’s open file named src/GalleryProject.as. If you’ve noticed it is set as the Document Class in publish settings of the fla file. So the code which is inside GalleryProject functon (constructor) runs after the application has been launched. As for the start let’s set some stage properties – align and scaleMode.

package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

public class GalleryProject extends Sprite
{
public function GalleryProject()
{
// Set some stage properties
stage.align = StageAlign.TOP;
stage.scaleMode = StageScaleMode.NO_SCALE;
}
}
}

Now we should create another class that will be responsible for gallery creation. It’s the right approach if we want to use it for any of our future applications. Considering the fact that it’ll be an ordinary Sprite we can add it anywhere using addChild() method. We can also change different parameters for its positioning.

Let’s create class called Gallery.as in the src/com/flashmoto/gallery folder. At first it will look this way.

package com.flashmoto.gallery
{
public class Gallery extends Sprite
{
/**
* Gallery Constructor
*/
public function Gallery()
{
}
}
}

And we can now add the gallery to our application. To accomplish this we should add some lines to our main file called GalleryProject.as:

package
{
import com.flashmoto.gallery.Gallery;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
public class GalleryProject extends Sprite
{
public function GalleryProject()
{
// Set some stage properties
stage.align = StageAlign.TOP;
stage.scaleMode = StageScaleMode.NO_SCALE;
// Create gallery
var gallery:Gallery = new Gallery();
addChild( gallery );
}
}
}

All changes are marked with bold type. I always dislike when tutorials which include source code write new lines or code changes separately from the whole class which requires these changes.) It’s always confusing and time taking process to deal with such code. I prefer using more traffic but seeing how the source code receives new functions and expressions with every step I make.

In order to use Gallery class we need to import it first. If you want to make sure that the code is working and the gallery has been really added you can write trace (‘This is your gallery’) into the gallery class constructor and you’ll see this message in the flash output panel.
Ok, let’s go to the next stage.

4. Loading XML Data

Now we should get information regarding images and where they should be taken from for download. Of course there is a simpler way to define them as constants directly in our code. Though, this way isn’t very flexible. So all information will be stored in XML file. (If you want to read more about this format you should read Wiki! 🙂 ). At the fist stage all we need is an image file path. So XML file will look like this. (Finished file can be found here: xml/gallery.xml)

Papervision 3D gallery

For xml file and images loading I’ll use BulkLoader. Let’s add a few function called loadImagesData() which will be called from the Gallery constructor. In this function we’ll initialize a new loader. Having added our xml file to this loader we’ll start to load images and listen for the loader’s progress, complete and error events. After you make the changes the class will look like this. As you’ve probably noticed a lot of new features and functions has appeared. I did my best to write the comprehensive comments for each feature and function, and in front of every line. So I don’t think it’s necessary to describe them in a more detailed way. Just have a look at the code we’ve created.

package com.flashmoto.gallery
{
import br.com.stimuli.loading.BulkErrorEvent;
import br.com.stimuli.loading.BulkLoader;
import br.com.stimuli.loading.BulkProgressEvent;

import flash.display.Sprite;
import flash.events.Event;

public class Gallery extends Sprite
{
/**
* Loader for the gallery xml and gallery images
*/
public var loader:BulkLoader;

/**
* Collection of images urls
*/
public var galleryImagesCollection:Array;

/**
* Flag that indicates if xml is loaded
*/
private var _galleryXMLLoaded:Boolean = false;

/**
* Path to the gallery xml file
*/
public static const GALLERY_XML:String = ‘xml/gallery.xml’;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{
// Create new loader
loader = new BulkLoader( ‘galleryLoader’ );
// Loader events
loader.addEventListener(BulkLoader.COMPLETE,
onGalleryLoaded);
loader.addEventListener(BulkLoader.PROGRESS,
onGalleryLoadingProgress);
loader.addEventListener(BulkErrorEvent.ERROR,
onGalleryLoadingError);
// Add gallery xml to the quenue
loader.add( GALLERY_XML );
// Start loading
loader.start();
}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{
// Start loading images
}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{
// Show gallery xml loading progress
trace( ‘Loading XML: ‘ + event.percentLoaded*100 + ‘%’ );
}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{
trace( ‘ERROR: Data xml loading failed.’ )
}
}
}

5. Loading Images

Now we have all image files paths. So we can load images. We have two variants to load images – loading all the images and then adding them to the stage or making the user tired showing a procedure of image load. For the beginning we’ll follow an easier way and choose the first variant. We’ll add several lines to the methods we already have. Now we should parse loaded xml, choose image file paths and upload the images. Loading status information can be received via onGalleryLoadingProgress method. At this very stage I’ve simply traced this information to the output panel.

package com.flashmoto.gallery
{
// Import statements ...

public class Gallery extends Sprite
{
/**
* Loader for the gallery xml and gallery images
*/
public var loader:BulkLoader;

/**
* Collection of images urls
*/
public var galleryImagesCollection:Array;

/**
* Flag that indicates if xml is loaded
*/
private var _galleryXMLLoaded:Boolean = false;

/**
* Path to the gallery xml file
*/
public static const GALLERY_XML:String = ‘xml/gallery.xml’;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{

}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{
if( !_galleryXMLLoaded ) {
// Parse loaded gallery xml
galleryImagesCollection = new Array();
var galleryImagesData:XML = loader.getXML(
GALLERY_XML, true );
for each ( var image:XML in
galleryImagesData.elements() ) {
var imageSrc:String = [email protected]();
if( imageSrc && imageSrc.length > 0 ) {
galleryImagesCollection.push( imageSrc );
loader.add( imageSrc );
}
}
_galleryXMLLoaded = true;
// Start loading images
loader.start();
} else {
// TODO: Init 3D components
}
}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{
if( !_galleryXMLLoaded ) {
// Show gallery xml loading progress
trace( ‘Loading XML: ‘ +
event.percentLoaded*100 + ‘%’ );
} else {
// Show images loading progress
trace( ‘Loading image: ‘ + event.itemsLoaded + ‘/’ +
event.itemsTotal + ‘,
‘ + event.percentLoaded*100 + ‘%’ );
}
}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{
if( !_galleryXMLLoaded ) {
trace( ‘ERROR: Data xml loading failed.’ )
} else {
trace( ‘ERROR: Images loading failed.’ )
}
}
}
}

So we are close to Papervision3d. Let’s start…

6. 3D Engine Initialization

In order to use Papervision3d while moving objects in 3d space we should initialize 3D engine first and create all necessary flash components such as viewport, camera, scene and renderer. Let’s write a new function called init3DEngine(). We’ll write a new function named init3DEngine() which will be called in onGalleryLoaded() method after the download has been finished.

package com.flashmoto.gallery
{
// Import statements ...

public class Gallery extends Sprite
{
/**
* Loader for the gallery xml and gallery images
*/
public var loader:BulkLoader;

/**
* Papervision3d components – Viewport
*/
public var viewport:Viewport3D;

/**
* Papervision3d components – Scene
*/
public var scene:Scene3D;

/**
* Papervision3d components – Camera
*/
public var camera:Camera3D;

/**
* Papervision3d components – BasicRenderEngine
*/
public var renderer:BasicRenderEngine;

/**
* Collection of images urls
*/
public var galleryImagesCollection:Array;

/**
* Flag that indicates if xml is loaded
*/
private var _galleryXMLLoaded:Boolean = false;

/**
* Path to the gallery xml file
*/
public static const GALLERY_XML:String = ‘xml/gallery.xml’;

/**
* Viewport width
*/
public static const VIEWPORT_WIDTH:Number = 800;

/**
* Viewport height
*/
public static const VIEWPORT_HEIGHT:Number = 800;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{

}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{
if( !_galleryXMLLoaded ) {
// Parse loaded gallery xml
galleryImagesCollection = new Array();
var galleryImagesData:XML = loader.getXML(
GALLERY_XML, true );
for each ( var image:XML in
galleryImagesData.elements() ) {
var imageSrc:String = [email protected]();
if( imageSrc && imageSrc.length > 0 ) {
galleryImagesCollection.push( imageSrc );
loader.add( imageSrc );
}
}
_galleryXMLLoaded = true;
// Start loading images
loader.start();
} else {
// Init 3D components
init3DEngine();
}
}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{

}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{

}

/**
* Inits 3D engine. Creates viewport, scene, camera and
* renderer and also creates and adds scene objects.
* Creates event listener for the enter frame event for
* the scene rendering.
*/
private function init3DEngine():void
{
// Create viewport
viewport = new Viewport3D( VIEWPORT_WIDTH,
VIEWPORT_HEIGHT, false, true );
addChild( viewport );

// Create scene
scene = new Scene3D();

// Create camera and set its zoom and focus
camera = new Camera3D();
camera.zoom = 5;
camera.focus = 100;

// Create BasicRenderEngine
renderer = new BasicRenderEngine();
}
}
}

As you can see some new features including two constants such as VIEWPORT_WIDTH and VIEWPORT_HEIGHT have been added. These constants define render area. Seems it would be better to define them while creating Gallery object. I think we’ll correct it a bit later. The case is that at this stage we have the other tasks. The same relates to other engine configurations such as camera zoom and focus, viewport scaling and interactivity. It would be better to change them dynamically from an external text file. I think we’ll do it for sure.

7. 3D Objects Creation

Now we should create objects in order to add them to the stage. Of course we could add them at once. It would make the code simpler but we’ll not go this way. One should understand that the application gains its flexibility thanks to dynamic object placement. So I recommend separating these two actions from the very beginning. At first we’ll create objects and then set their positions. For this we should update our class a little bit:

package com.flashmoto.gallery
{
// Import statements ...

public class Gallery extends Sprite
{

/**
* Collection of images urls
*/
public var galleryImagesCollection:Array;

/**
* Collection of gallery planes to be added to the scene
*/
public var galleryPlanesCollection:Array;

/**
* Flag that indicates if xml is loaded
*/
private var _galleryXMLLoaded:Boolean = false;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{

}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{

}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{

}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{

}

/**
* Inits 3D engine. Creates viewport, scene, camera and
* renderer and also creates and adds scene objects.
* Creates event listener for the enter frame event for
* the scene rendering.
*/
private function init3DEngine():void
{
// Create viewport
viewport = new Viewport3D( VIEWPORT_WIDTH,
VIEWPORT_HEIGHT, false, true );
addChild( viewport );

// Create scene
scene = new Scene3D();

// Create camera and set its zoom and focus
camera = new Camera3D();
camera.zoom = 5;
camera.focus = 100;

// Create BasicRenderEngine
renderer = new BasicRenderEngine();

// Create Gallery Planes
createGalleryImages();
}

/**
* Creates display objects from loaded images and updates
* gallery objects collection.
*/
private function createGalleryImages():void
{
galleryPlanesCollection = new Array();
// Go through all images and create planes
for( var i:uint=0; i
var galleryPlane:DisplayObject3D =
createGalleryDisplayObject(
galleryImagesCollection[i] );
// Add plane to collection
galleryPlanesCollection.push( galleryPlane );
}
}

/**
* Creates gallery 3D object using loaded image bitmap.
*
* The method returns DisplayObject3D object, and gallery
* do not need to know if there is a plane, cube or sphere,
* so later I can rewrite this method to create any objects
* needed.
*/
private function createGalleryDisplayObject(
image:String ):DisplayObject3D
{
// Get loaded image bitmap using loader getBitmap method
var bitmap:Bitmap = loader.getBitmap( image );
var bitmapHolder:Sprite = new Sprite();
bitmapHolder.addChild( bitmap );
// Create movie material for the plane
var material:MovieMaterial =
new MovieMaterial(bitmapHolder);
// Use new material rect property to crop image if it is
// larger that plane’s dimensions
material.rect = new Rectangle( 0, 0, GALLERY_PLANE_WIDTH,
GALLERY_PLANE_HEIGHT );
// Make material double sided and interactive
material.doubleSided = true;
material.interactive = true;
// Create and return plane
return new Plane( material, GALLERY_PLANE_WIDTH,
GALLERY_PLANE_HEIGHT, GALLERY_PLANE_SEGMENTS_W,
GALLERY_PLANE_SEGMENTS_H );
}
}
}

As you see a method called createGalleryDisplayObject() creates a 3D object and this objects isn’t for sure a Plane. It can be any object. So in a case we wish to draw spheres instead of planes we’ll basically have to rewrite this method.

8. Adding Objects to the Stage

As I’ve already mentioned I comment the code without explaining what should be done and how to do it because our code already goes with comprehensive comments. Almost every code line has its own description. So read the code attentively and comment this tutorial in a case you have any questions. I’ll be more than happy to answer your questions.

So we have a collection of 3D objects which can be added to the stage and placed in a way we wish. In the future I plan to update this example in order to develop several image placement strategies. So we could dynamically change the gallery appearance. At the first stage you can see the first variant: I’ve placed images one by one. Let’s add new method called addGalleryImages()

package com.flashmoto.gallery
{
// Import statements ...

public class Gallery extends Sprite
{

/**
* Collection of gallery planes to be added to the scene
*/
public var galleryPlanesCollection:Array;

/**
* Collection of scene gallery planes
*/
public var galleryPlanes:Array;

/**
* Flag that indicates if xml is loaded
*/
private var _galleryXMLLoaded:Boolean = false;

/**
* Holder for the gallery planes
*/
private var _planesHolder:DisplayObject3D;

/**
* Path to the gallery xml file
*/
public static const GALLERY_XML:String = ‘xml/gallery.xml’;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{

}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{

}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{

}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{

}

/**
* Inits 3D engine. Creates viewport, scene, camera and
* renderer and also creates and adds scene objects.
* Creates event listener for the enter frame event for
* the scene rendering.
*/
private function init3DEngine():void
{
// Create viewport
viewport = new Viewport3D( VIEWPORT_WIDTH,
VIEWPORT_HEIGHT, false, true );
addChild( viewport );

// Create scene
scene = new Scene3D();

// Create camera and set its zoom and focus
camera = new Camera3D();
camera.zoom = 5;
camera.focus = 100;

// Create BasicRenderEngine
renderer = new BasicRenderEngine();

// Create Gallery Planes
createGalleryImages();

// Add Gallery Planes to the scene
addGalleryImages();
}

/**
* Creates display objects from loaded images and updates
* gallery objects collection.
*/
private function createGalleryImages():void
{

}

/**
* Creates gallery 3D object using loaded image bitmap.
*
* The method returns DisplayObject3D object, and gallery
* do not need to know if there is a plane, cube or sphere,
* so later I can rewrite this method to create any objects
* needed.
*/
private function createGalleryDisplayObject(
image:String ):DisplayObject3D
{

}

/**
* Adds gallery display objects to the scene and arranges
* them. Later I will add more arrangent strategies to
* this application, and all I need to do is to update
* this method which will get the stategy name as
* parameter.
*/
private function addGalleryImages():void
{
// Create holder for the gallery objects
_planesHolder = new DisplayObject3D();
scene.addChild( _planesHolder );

galleryPlanes = new Array();

// Add gallery planes
var flag:int = 1;
for( var i:uint=0; i
var galleryPlane:Plane = galleryPlanesCollection[i]
as Plane;
galleryPlane.z = _firstPlaneZ + i*200;
galleryPlane.x = 5000*flag;
galleryPlanes.push(_planesHolder.addChild(
galleryPlane));
flag *= -1;
Tweener.addTween( galleryPlane, {
x: 0,
time:2*(galleryPlanesCollection.length-i)/20+1,
transition:”easeOutBack”
} );
}
}
}
}

9. Adding Interactivity

The last thing that should be added is interactivity. Seems it should be described in detail.

The first thing you should do to see the objects that have been added to the stage is rendering the stage. In Papervision3d you can do it with this code

renderer.renderScene( scene, camera, viewport );

as you see all 3D engine elements are activated in this code. Having executed this code you’ll see what is added to your stage. However you should remember one thing – without calling this method you won’t see such changes as:

– changing object location or object properties;
– changing camera position or rotation;
– refreshing something.

Basically it’s called on every onEnterFrame event, but it’s sometimes difficult for browser to accomplish this. Especially if you have a lot of objects and refining or you need fast rendering and good quality graphics.) So Flash developers find various ways to optimize the application. Having analyzed different requirements they define if a stage should be rendered at the moment or not. If to speak about our example the stage should be rendered every moment because our main aim is camera and mouse interaction. So we should continually refresh the image. In the future I’ll add a requirement to avoid such rendering. For instance in a case we’ve clicked the first image and it has been enlarged.

Papervision uses InteractiveScene3DEvent in order to respond to such mouse events as hitting, pointing and tracking. Note if you want these events work the object material and viewpoint should be interactive.

Material has an interactive feature to accomplish this

material.interactive = true;

Viewport has this feature as well. We set its value while creating – the 4th parameter = true

viewport = new Viewport3D(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, false, true);

Of course adding interactivity isn’t limited to listening for the mouse events only. It also includes response to these events. This is the way logic is added to the code. Note logic is an inseparable part of the application.

It’s time for the most interesting part which can be difficult for an ordinary animator. So this part is usually done by a Flash programmer. Considering the fact that our tutorial relates to Papervision 3d I suggest you to explore application logic by yourself. Note all application logic is described in event listener handlers such as onPlanePress(), onPlaneOver(), onPlaneOut(). Camera moving logic is described in render() method.

Here is the final code. Let’s try to compile it. You should succeed!

package com.flashmoto.gallery
{
// Import statements ...

public class Gallery extends Sprite
{

/**
* Holder for the gallery planes
*/
private var _planesHolder:DisplayObject3D;

/**
* Flag that indicates zoomed image state
*/
private var _imageZoomed:Boolean = false;

/**
* Current plane ( first in the line ) index
*/
private var _currentPlaneIndex:uint = 0;

/**
* First plane z coordinate, planes shift
*/
private var _firstPlaneZ:Number = 0;

/**
* Flag that indicates if planes are moving
*/
private var _planesAreMoving:Boolean = false;

/**
* Path to the gallery xml file
*/
public static const GALLERY_XML:String = ‘xml/gallery.xml’;

/**
* Gallery Constructor
*/
public function Gallery()
{
// Load images data
loadImagesData();
}

/**
* Loads images data from xml file.
*/
private function loadImagesData():void
{

}

/**
* Parses gallery xml file and starts images loading process.
*/
private function onGalleryLoaded( event:Event ):void
{

}

/**
* Shows loader progress info.
*/
private function onGalleryLoadingProgress(
event:BulkProgressEvent ):void
{

}

/**
* Shows loader error info.
*/
private function onGalleryLoadingError(
event:BulkErrorEvent ):void
{

}

/**
* Inits 3D engine. Creates viewport, scene, camera and
* renderer and also creates and adds scene objects.
* Creates event listener for the enter frame event for
* the scene rendering.
*/
private function init3DEngine():void
{
// Create viewport
viewport = new Viewport3D( VIEWPORT_WIDTH,
VIEWPORT_HEIGHT, false, true );
addChild( viewport );

// Create scene
scene = new Scene3D();

// Create camera and set its zoom and focus
camera = new Camera3D();
camera.zoom = 5;
camera.focus = 100;

// Create BasicRenderEngine
renderer = new BasicRenderEngine();

// Create Gallery Planes
createGalleryImages();

// Add Gallery Planes to the scene
addGalleryImages();

// Render the scene every enter frame
addEventListener( Event.ENTER_FRAME, render );
}

/**
* Creates display objects from loaded images and updates
* gallery objects collection.
*/
private function createGalleryImages():void
{

}

/**
* Creates gallery 3D object using loaded image bitmap.
*
* The method returns DisplayObject3D object, and gallery
* do not need to know if there is a plane, cube or sphere,
* so later I can rewrite this method to create any objects
* needed.
*/
private function createGalleryDisplayObject(
image:String ):DisplayObject3D
{

}

/**
* Adds gallery display objects to the scene and arranges
* them. Later I will add more arrangent strategies to
* this application, and all I need to do is to update
* this method which will get the stategy name as
* parameter.
*/
private function addGalleryImages():void
{
// Create holder for the gallery objects
_planesHolder = new DisplayObject3D();
scene.addChild( _planesHolder );

galleryPlanes = new Array();

// Add gallery planes
var flag:int = 1;
for( var i:uint=0;
i
var galleryPlane:Plane =
galleryPlanesCollection[i] as Plane;
galleryPlane.z = _firstPlaneZ + i*200;
galleryPlane.x = 5000*flag;
galleryPlanes.push( _planesHolder.addChild(
galleryPlane ) );
flag *= -1;
Tweener.addTween( galleryPlane, {
x: 0,
time:2*(galleryPlanesCollection.length-i)/20+1,
transition:”easeOutBack”
} );
}

// Listen for the events only from the first
// gallery object
galleryPlane =
galleryPlanes[_currentPlaneIndex] as Plane;
galleryPlane.addEventListener(
InteractiveScene3DEvent.OBJECT_PRESS,
onPlanePress );
galleryPlane.addEventListener(
InteractiveScene3DEvent.OBJECT_OVER,
onPlaneOver );
galleryPlane.addEventListener(
InteractiveScene3DEvent.OBJECT_OUT,
onPlaneOut );
}

/**
* Gallery plane mouse over event handler
*/
private function onPlaneOver(
event:InteractiveScene3DEvent ):void
{
// Check for the app state
if( !_imageZoomed && !_planesAreMoving ) {
// Tween plane
var plane:Plane = event.target as Plane;
Tweener.addTween( plane, {
z: _firstPlaneZ-200,
time:2,
transition:”easeInSin”
} );
}
}

/**
* Gallery plane mouse out event handler
*/
private function onPlaneOut(
event:InteractiveScene3DEvent ):void
{
// Check for the app state
if( !_imageZoomed && !_planesAreMoving ) {
// Tween plane
var plane:Plane = event.target as Plane;
Tweener.addTween( plane, {
z: _firstPlaneZ,
time:2,
transition:”easeInSin”
} );
}
}

/**
* Renders the scene.
*/
private function render( event:Event ):void
{
// Check for the zoomed image state
if( !_imageZoomed ) {
// Calculate distances
var xDist:Number =
root.mouseX – stage.stageWidth * 0.5;
var yDist:Number =
root.mouseY – stage.stageHeight * 0.5;
var newDist:Number = Math.round(
Math.sqrt(xDist*xDist + yDist*yDist) ) * 0.08;
// Calculate camera rotation values
var cameraRotationX : Number = -xDist * 0.1;
var cameraRotationY : Number = yDist * 0.1;
var cameraRotationZ : Number = (xDist*yDist >= 0)
? -Math.abs(newDist*0.1) :
Math.abs(newDist*0.1);
// Tween camera
Tweener.addTween( _planesHolder, {
x: xDist,
y: yDist,
rotationY : cameraRotationX,
rotationX : cameraRotationY,
rotationZ : cameraRotationZ,
time:1.2,
transition:”easeOutCubic”
} );
}
// Render the scene
renderer.renderScene( scene, camera, viewport );
}
}
}

Please let me know if you have any questions regarding this tutorial. I’ll be pleased to answer them.

10. Conclusion

So we’ve finished a first pass through creating an interactive Papervision Flash Gallery. If you are the beginner I advise you to download the source project and follow it step-by-step. Though, in a case you are an experienced user you can download the complete sources for the gallery.

This tutorial we’ll be of a great help for us in the future. It’ll help us explore the other 3D engine features. Also, I’d like to explore some ways to optimize Papervison3d applications and make them work faster. I plan to learn different ways of image positioning, navigation, dynamic gallery appearance and logic changing, creating reflections, mouse wheel navigation, and etc. New tutorials are waiting for you in the nearest future.

62 responses to “Papervision 3D Flash Gallery Tutorial”

  1. […] as i’ve told you here is a papervision gallery tutorial. Tags: flash, gallery, papervision previous post next […]

  2. Jim says:

    Great tutorial but I seem to be having an Error 1069 issue with _bezier on Line 395 of Gallery.as. It’s not part of Plane Primitives or Caurina Tween. What’s it referring to? The the plane freezes after it is clicked.

  3. Jim says:

    Ok, looks like I’ve got it sorted now. Your source code is missing the two things from Caurina.

    import caurina.transitions.properties.CurveModifiers;

    and an init statement down by the code…
    caurina.transitions.properties.CurveModifiers.init();

  4. tk says:

    Hey thanks for the great tutorial! I’m fideling around with the source atm! Not only is this one of the best papervision3d intro’s I’ve seen but a great resourcee for newbs like me trying to take our as3 knowledge to the next level.

  5. Difort says:

    @Jim, the source code I have provided is compiling without any errors. It seems you are using another version of caurina Tweener classes, may be more newer one. To avoid such kind of problems I’ve provided the source with all libraries included.

  6. Jim says:

    @Difort, You probably are able to run your version because your using Flex instead of Flash IDE and have a Library path set to a SWC of Caurina. In this case you wouldn’t experience my error. In Flash you will need the import statement.

  7. Difort says:

    @Jim, It is not matter what to use Flex or Flash to compile this source code, cause all needed libraries (in this case only .as files, no swc) are in the src folder and you do not need any other files to get this gallery working.

    Also if you check src/caurina/transitions folder you will not find properties folder and CurveModifiers class cause you are using the latest tweener version and mine is not.

    So just check your classpaths and good luck!

  8. Jim says:

    oops, I overlooked the difference in your caurina. Sorry. Thanks for the explanation.

  9. Difort says:

    @Jim, no problem. Be my guest! 🙂

  10. Jim says:

    @Difort. Looking forward to your next tutorial. I’m really struggling here! : ) I’m simply trying to connect four buttons that relaunch the effect each time. I had planned to either parse the new data from the same xml file or reload different xml files each time. I’ve almost got it working but can’t seem to clear the previous DisplayObject3D or the associated data Arrays. I’ll check back soon! : )

  11. […] Using a simple example I’d like to show you main principal of working with Papervision 3D and tell you the truth of it’s power and strength. In my previous posts you’ve seen tons of awesome flash galleries using 3D effects. So I created simple papervision gallery which is using XML file as an images database in this case in 3D! […]

  12. […] Readings / Tutorial: Find out here Share this post: Share this post with the […]

  13. Luca says:

    Hi, very very good tutorial!! In there the photos are arranged in a single row ok? But if I want to make a circle with my photo where I have to made changes?

    Thanks!!

    Great Job!!

  14. Luca says:

    ok for the circle… but now for a listener in every photo and not only on the first one? I’ ve tried to set _planesHolder like target listener and set useCapture=true, but nothing… Some ideas?

  15. Luca says:

    How can I set the transparency in a plane?

    plana.alpha = value doesn’t work….

  16. Difort says:

    @ Luca,
    Please sorry for a late reply.
    To make the plane transparent you should add 2 lines of the code. Open Gallery.as file, and look at the createGalleryDisplayObject() method. First, let’s change the alpha of bitmapHolder Sprite that is used for creating plane movie material, for example:

    bitmapHolder.alpha = 0.2;

    Second, look at the MovieMaterial creation:

    var material:MovieMaterial = new MovieMaterial( bitmapHolder );

    The second parameter is material transparency that is false by default, set it true. Like this:

    var material:MovieMaterial = new MovieMaterial( bitmapHolder, true );

    That’s all!

    But you should remember that the material transprarency will slow down your movie and fps.

  17. richUK says:

    Luca: not looked at any code just see the quesion, make sure the scene is type MovieScene3D opposed to Scene3D, this way all 3D displayobjects automatically get placed in their own movieClip containter when added to the scene – you can adjust the overall alpha level of the plane, thus scene.myPlane.container.alpha = .5; hope that helps.

  18. Charles Denmark says:

    Hi, I get this error when I try compiling the swf
    1061: Call to a possibly undefined method drawFace3D through a reference with static type org.papervision3d.core.proto:MaterialObject3D. and it refers to line 169 in the Face3D.as file. What seems to be the problem…Thanks

  19. Difort says:

    Hi! Are you sure that you are using right papervision library sources (they are included)? Cause the engine was changed from the moment I created that gallery and it is possible that my code will not work perfectly with newer version of this lib. Please check your classpaths and point them to the included source.

  20. […] Papervision 3D Flash Gallery Tutorial […]

  21. Darhena says:

    I can’t see any pictures in this tutorial, besides screens of gallery. Could you return them? I would learn, but I have not any code here… Please help 🙂

  22. Phuc Pham says:

    Does anybody know how I can change the size of the images? I’m looking through the actionscript but I cannot find it.

  23. vinoddanims says:

    excellent component’s

  24. scott says:

    awesome tutorial – thanks so much for sharing.

  25. this says:

    Hi, could someone give me idea how to modify code to create more columns for photos?

  26. Sensono says:

    if i want replace the planes for an sphere carrousel what cani do?

  27. jrath says:

    This is really great! Thank you for this tutorial, it’s really giving me a great start with PV3D. I’m going to try and modify the plane so the images are curved and they rotate around the camera. Hopefully I’ll get somewhere.

    @this, this is what I did to add more columns (replace the addGalleryImages() function with as below), I had to comment out the tween but I’m sure you can take the code that arranges the grid and use tweener to animate them into their positions…

    ////[AS SCRIPT]///////////////////////////////////////////////////////////////////
    private function addGalleryImages():void
    {
    // Create holder for the gallery objects
    _planesHolder = new DisplayObject3D();
    scene.addChild( _planesHolder );

    galleryPlanes = new Array();

    // Add gallery planes
    var flag:int = 1;
    var cols:uint = 4;
    var rows:uint = 4;
    var x_counter = 0;
    var y_counter = 0;

    for( var i:uint=0; i<galleryPlanesCollection.length; i++ ) {
    var galleryPlane:Plane = galleryPlanesCollection[i] as Plane;

    //first set z coord
    galleryPlane.z = _firstPlaneZ;

    //set columns
    galleryPlane.x = ( GALLERY_PLANE_WIDTH + 10 ) * x_counter;
    galleryPlane.y = ( GALLERY_PLANE_HEIGHT + 10 ) * y_counter;

    if (x_counter+1 < cols){
    x_counter++;
    } else {
    x_counter = 0;
    y_counter++;
    }

    galleryPlanes.push( _planesHolder.addChild( galleryPlane ) );
    flag *= -1;

    /* Tweener.addTween( galleryPlane, {
    x: 0,
    time:2*(galleryPlanesCollection.length-i)/20+1,
    transition:"easeOutBack"
    } );
    */
    }
    ////[/AS SCRIPT]///////////////////////////////////////////////////////////////////

  28. Qg19Sophie says:

    Yeah doubtless very
    fortunate for the peruser it was pleasant to read about this good post! If you need to get a great job firstofall you need
    resume writers. Study and don’t forget – if you have to work and study at the same time, there areexperts who are ready to guidance you with your resume when you under time crushing and looking for a great job.

  29. aliciacelina says:

    hello,

    thank you so much for this tutorial!
    my question to you, how do I put this into an HTML file?
    I know how to insert an .SWF file, but I won’t load the file.
    I problably have to insert something else?

  30. sara says:

    plez what i must make to change the image if i double click on it , becuze one click make it bigger…
    thank you .. i need this help necessry thank you..

  31. Alex says:

    How can I delete or turn of this gallery on my site? I tried but I can’t do it. When I want to click on some button the gallery still being on all of the pages over all of them. Help me please

  32. imagesrc says:

    […] File About To Be Overwritten Via FTP / FileUpload By Using ASP.NET's FileInfo Class Search for: …Papervision 3D Flash Gallery Tutorial | FlashMotoIn our previous posts we have considered several examples of creating really cool Flash Galleries […]

  33. Not only is this one of the best papervision3d intro’s I’ve seen but a great resourcee for newbs like me trying to take our as3 knowledge to the next level.

  34. Pradeep says:

    Hi Difort,

    Its a great tutorial. Thanks. I am trying to display these images in sphere with each item clickable. Is it possible and what should i need to change. I am pretty new to P3D.

  35. Dear author thanks for sharing this great tutorial. Actually I also think of creating similar blog for myself and my users.

  36. . I am trying to display these images in sphere with each item clickable.

  37. Share this great tutorial Dear authors said. I also want to create their own user like my blog.

  38. Altcomvis says:

    Hi… I,m creating a presentation using this tutorial and
    How to load .swf or .flv files from XML?
    Thanks!

  39. Share this great tutorial Dear authors said. I also want to create their own user like my blog.

  40. […] Papervision 3D Flash Gallery Tutorial In our previous posts we have considered several examples of creating really cool Flash Galleries with the help of 3D. As promised, today I’ll try to explain how to make papervision gallery. At the end we’ll get something like this – awesome papervision flash gallery. Probably at this stage the gallery looks a bit unfinished, one would wish to add progress bars for the images, image names and descriptions, navigation buttons next & previous, and etc. I’d like to cheer you up by saying it’s just the beginning. In this tutorial we’ll try to write the basics, that is to say an engine for our application. Over the next several steps we’ll add functionality to this gallery. Note we plan to write more tutorials based on this example. […]

  41. I also want to create their own user like my blog.

  42. Now, a lot of college students are assured that the professional custom writing services will be the great point to order essay topic from. Moreover, it is really perfect way to improve the writing skills!

  43. A PhD level seems to be very important thing for everyone. Who could assist students in dissertation idea close to this good post writing? I will suggest to buy the dissertation in the dissertation writing service. I hope that this suggestion would help people!

  44. Its a great tutorial. Thanks. I am trying to display these images in sphere with each item clickable. Is it possible and what should i need to change. I am pretty new to P3D.

  45. […] Papervision 3D Flash Gallery Tutorial (52) […]

  46. Tom Cools says:

    Amazing tutorial, after a lot of research i finaly can understand some real cool effects of PV3D
    And they are less difficult then I expected

    For the image loading i can advise Digital Surgeons BulkLoader which gives the right percentage loaded of the images

    http://www.digitalsurgeons.com/blog/the-lab/getting-the-total-percent-loaded-from-bulkloader-with-flash-actionscript-3/

    Great job!!! Big Thanx!!! ☮

  47. divya says:

    hey guys..im having a problem while running the galleryproject.as file in flash builder 4..there are no errors while compiling..but no output is obtained !! i am just gettung an empty html page..if anyone knows the solution, pls help asap ..thanx

  48. bedding says:

    I have seen your past papervision gallary but this tutorial is more then all .Ofcourse i have many questions also but i want to know about mostly 3D object initialization.Hoe we move an object…

  49. akshit says:

    JUST GREAT, MINDBLOWING tutorial. u just rocks man………..

  50. santosh kumar says:

    this project i like ….

  51. how to says:

    how to…

    […]Papervision 3D Flash Gallery Tutorial | MotoCMS[…]…

  52. It is an excellent tutorial stuff…thank you very much admin

    kristen

Leave a Reply

Your email address will not be published. Required fields are marked *

Tags: papervision tutorial
Author: MotoCMS Editorial
Here are the official MotoCMS news, releases and articles. Find out the latest info about product, sales and updates.