Papervision3D 2 Essential Training

Papervision3D 2 Essential Training

with Seb Lee-Delisle

 


Papervision3D is an open-source ActionScript code library that enables Flash projects to render 3D objects in real time. In Papervision3D 2 Essential Training, author Seb Lee-Delisle shows how to add 3D content to the Flash stage, dynamically and without pre-rendering. This course demonstrates how to import 3D models from external applications such as Maya into Flash Builder, and then add lighting and surface detail using shaders, reflections, and bump maps from the Papervision library. The course also shows how to build an augmented reality scene that brings 3D objects into the real world with FLARToolkit. Exercise files accompany the course.

Users should have a basic knowledge of Flash Builder and Actionscript 3.
Topics include:
  • Creating 3D primitive shapes
  • Controlling rotation
  • Moving the camera in 3D space
  • Creating a particle field with depth-of-field blur
  • Importing models from external applications
  • Making a simple 3D game
  • Using ViewportLayers to selectively render and sort layers
  • Placing a custom 3D model into an augmented reality scene
  • Creating interactive carousals
  • Creating interactive grids
  • Working with particles and billboards

show more

author
Seb Lee-Delisle
subject
3D + Animation, Web
software
Papervision 3D 2
level
Beginner
duration
3h 57m
released
Jul 09, 2010

Share this course

Ready to join? subscribe


Keep up with news, tips, and latest courses.

submit Course details submit clicked more info

Please wait...

Search the closed captioning text for this course by entering the keyword you’d like to search, or browse the closed captioning text by selecting the chapter name below and choosing the video title you’d like to review.



Introduction
Welcome
00:04Hi there! I'm Seb Lee-Delisle.
00:06I'm really happy to welcome you to Papervision 3D Essential Training.
00:11Papervision 3D is an open source ActionScript code library that can be used in
00:14your Flash projects to render 3D objects in real time.
00:18With Papervision, you can have truly interactive and engaging 3D Flash content.
00:22We'll look at how you can import 3D models from apps like Maya and then we'll
00:26add simple lighting and glossiness using shaders.
00:30Then we'll build a skybox complete with star fields and nebula to take your
00:34models into outer space.
00:36Making 3D games doesn't have to be rocket science.
00:39I'll show you how to build on effects dimension 2D games and what projects would
00:43be complete without shiny reflections?
00:46Finally, we'll make an augmented reality project with FLARToolkit.
00:49This will bring models out of the browser and into the space around you.
00:53Don't worry if you've never done any 3D before.
00:57if you have a basic understanding of Flash Builder and ActionScript 3, you'll
01:00have no problems with Papervision, and you'll be pleased to hear I have
01:03several clever ways to avoid those tricky math problems.
01:06As one of the Papervision developers,
01:09I'm really looking forward to sharing what we've learned at Plug-in Media to
01:12really get the most out of what is possible in Flash in 3D.
01:16So, let's get started with Papervision 3D Essential Training.
Collapse this transcript
Using the exercise files
00:00If you're a premium member of the lynda.com Online Training Library, or if
00:04you're watching this tutorial on a DVD- ROM, you'll have access to the Exercise
00:08Files used throughout this title.
00:11I've downloaded them and they're here on my desktop. I'm going to click into this folder.
00:14You'll see there's two folders here.
00:16MayaFiles, that contains the 3D models for our course, and Workspace and this is
00:21the main Flash Builder workspace for all of our projects.
00:24So now I'm going to go ahead and open Flash Builder.
00:26You can see this is the default workspace when you install Flash Builder.
00:31I'm going to click on File > Switch Workspace > Other, and then browse to the
00:39workspace in the Exercise Files and select Choose and then OK.
00:46Flash Builder restarts itself, now pointing at our workspace. All being well,
00:51you'll see all the projects in this Package Explorer here.
00:54Anything missing from this is the FLARToolkit code.
00:57So let's go to the Libspark page for the FLARToolkit project and we'll scroll
01:03down to this item here, the Source code.
01:07If you're comfortably using subversion, you can check it out here.
01:10Otherwise we can browse it here, and as we're using the alchemy branch of the
01:15FLARToolkit, we can click on alchemy > bin and then FLARToolkit.swc.
01:23Now my Japanese isn't all that good, but I'm assured that this says that the
01:27font size exceeds this number of bytes and therefore we need to download it from this link.
01:32I'll do so by clicking on it.
01:35Now we have our FLARToolkit.swc file. We need to drag that into the folder for
01:40our augmented reality project, which is here in our Workspace folder.
01:45That needs to go in this swc folder there.
01:53So let's go back to Flash Builder.
01:55It's building the workspace and now the arrow has gone.
01:59We can see that our workspace is fully up and running.
02:03It may be that when you switch the workspace, you can't see any of the project
02:07folders in your Package Explorer.
02:09The way it's fixed back is to right- click on here, select Import, open
02:14this General folder if it's not already open, click on Existing Projects
02:18into Workspace, click Next, and then browse towards your Workspace folder
02:23in the Exercise Files.
02:26Choose. All being well, you'll see the projects here in this window.
02:31Click Finish and that goes right ahead and imports all of your projects.
02:37So now we've got all of our projects in our workspace, let's just make sure that
02:41Flash Builder is set up properly.
02:43So we'll double-click into the first project and then source > default
02:47package > PV3DQuickStart2.
02:51To verify that this works okay, we'll click on the green Debug icon.
02:57All being well, you'll see a big wireframe sphere and it might not be the
03:00same color as this one.
03:02What we need to check now is that this is actually running the debug version
03:06of the Flash Player.
03:07It's very easy for me to see this because it says Flash Player Debugger at the top,
03:11but there are standalone debug versions of the Flash Player that are just
03:15called Flash Player.
03:16The way to verify that it is a debug version is to right-click and if this
03:20option is in the menu, Show Redraw Regions, then it means that you are in fact
03:25running the debug version of the Flash Player and everything is good.
03:27Note also that this is the Flash Payer 10 version of the debug player, and we'll
03:32need that for later projects.
03:34Now, if you find that when you hit the Debug button, that it doesn't open the
03:38debug version of the Flash Player.
03:40we'll need to adjust our system so that it opens the debug player by default.
03:45So if we navigate into our Exercise Files again and find that SWF that we just
03:51opened, or any SWF will do, and we'll right-click, Get Info, and we'll scroll
03:57down and check this item here, Open with Flash Player Debugger.
04:02Now we'll talk about how to do this on a PC in a moment, but I'm just going to
04:06talk through the OS X version first.
04:09Now, if this isn't the right Flash Player, then we'll click on this, choose
04:12Other, and the easiest way to find the standalone debug version of the Flash
04:17Player is to navigate into Flash Pro CS5, in the Players sub-folder, Debug > Flash
04:26Player Debugger, and to be safe, let's check Always Open With and then Add.
04:31You don't necessarily have to use the debug player out of the Flash CS5 folder.
04:35You can use the one from CS4 or download the standalone Flash Player debug
04:40version from the Adobe web site.
04:42And again, just to be doubly safe, let's click on the Change All button here and then confirm.
04:48I've sometimes encountered unexpected behavior for the way that OS X handles SWF files
04:53and that even when I've told it to open all SWFs by default using the
04:57debug player, it still reverts back into other applications.
05:02There's a solution that I posted on my blog.
05:04So check this out if you're still continuing to have problems.
05:08Now if you're on Windows and you want to change the default app that load SWFs,
05:12right-click on a SWF file, select Open with, then Choose default program and now Browse.
05:18So we're going to browse into the folder that contains our Flash Professional,
05:27and then in Players, then Debug, then Flash Player Debugger.
05:35Make sure that Always use the selected program to open this kind of file is checked.
05:38Click OK and our SWF opens in the debug version of the player, and again, if you
05:45don't have Flash Pro installed on your machine, then you can download the debug
05:49version of the players from Adobe's web site.
05:52If you're a monthly or annual subscriber to lynda.com, you wouldn't have access
05:55to the Exercise Files, but you can still follow along from scratch with your own assets,
05:59although you'll need to follow through the next movie, which shows you
06:02how to set up Papervision within your own workspace.
06:05So let's get started.
Collapse this transcript
Setting up Papervision3D
00:00Now I'm going to show you how you can download the Papervision and
00:05FLARToolkit code and set them up in your Flash Builder workspace ready to use
00:08in your own projects.
00:10If you have the Exercise Files and you've been through the process outlined in
00:13the Exercise Files movie, then you won't need to do this as everything is
00:17already set up for you to get up and running.
00:19However, if you wanted to use the Papervision or FLARToolkit code in your
00:23own workspaces in the future, then you'll find the following information very useful.
00:27First of all, we are going to download the Papervision source code library from
00:31the Google code project page.
00:32As with all Google code projects, the source files are stored on a subversion
00:36server, and you can check out the files from this URL.
00:41This is the best way to get the files, as it makes sure that you always have
00:43the latest version.
00:44If you're not sure how to use subversion, there's more information here on the
00:48Wiki, in the Download from SVN page, and also more detailed instructions in the
00:54Getting Started FAQ.
00:56You can also download a zip type version of the files here on the Downloads page, [00:01:00:14] but this may not be the latest version of the code, but if you're in a
01:03hurry, you can download all of the file's zip type here.
01:05So let's do that now.
01:07So now we've got the Papervision source code. Let's go ahead and set up as Flash
01:12Builder Library Project.
01:13So if we'll open up Flash Builder, right-click within our Package
01:17Explorer > New > Flex Library Project, and we'll select that.
01:22So now we'll call our project PV3D, the default location is fine, and we're also
01:30going to be using the Flex 4 SDK.
01:32So now click Finish.
01:34Now we're going to place all the Papervision source code files into this Library project.
01:39So let's navigate to where we downloaded those files and then open Flash
01:45Builder. Let's just make sure both of those folders are visible.
01:48So now I can select everything within this source folder and just drag it into
01:53the source folder in our Papervision Library Project.
01:58Just to check that this Flex Library Project is using all of those files,
02:01we'll right-click on the project, select Properties and then Flex Library Build Path
02:08and then the Classes tab.
02:10This radio button here is selected that tells the Library project that we're
02:14using all of the files within this source library.
02:16So that ensures that we've got all of the Papervision classes.
02:19So now let's click OK.
02:21So now we have this Library project set up.
02:25If we create our new projects for ourselves, and I'm just going to make an
02:29ActionScript Project here, and call that PVTest and click Finish.
02:36Now currently, this project doesn't have access to the Papervision files, but if
02:39I right-click on the project itself, select Properties, then Build Path and
02:46Library Path here and then click on the Add Project, you can see that the
02:50Papervision Library project comes up in this window.
02:52So I'll select that and click OK, and now if I click OK from this requester,
02:57it updates the compiler settings and all of the Papervision class files are
03:00available to us from within this project.
03:03At this point you may also want to set up the FLARToolkit code, as we'll be
03:07building an augmented reality project much later in the course.
03:11So let's head on over to the Libspark project page, where the FLARToolkit code
03:15is hosted, scroll down this page and we're going to browse the source code.
03:21So again, like the Papervision code, this is actually hosted on a subversion server.
03:26So you can check out the codes using your subversion clients, but as we're just
03:30using the alchemy version of FLARToolkit, there's only one file that we need to
03:34download and it's here in branches > alchemy > bin, and it's this swc that we need.
03:42So I'm going to click on that.
03:45Now again, we get this Japanese message that says that this file is above 262000
03:50bytes, which means we have to click this link in order to download it.
03:53So now we have that swc, let's look at how we get that into Flash Builder.
03:58So we're just going to navigate to the file and it's here.
04:01So now I'm going to go back to Flash Builder.
04:04Now, what I'm going to do in this Project folder is create a new folder and call that swc.
04:10This is where we store the compiled swc files.
04:13Now go back to our Finder window, click and drag that swc file into the swc
04:19folder, and you can see it's there.
04:21One final thing to do to ensure that that works within our project,
04:25again right-click on the project and select Properties.
04:28This time we're going to add an SWC folder.
04:32You know the folder is just called swc.
04:33So I'm going to type that in there and click OK.
04:36Now you can see in this window that the FLARToolkit code will be compiled into our project.
04:41So I'm going to select OK.
04:44Now this PVTest project is all set up and ready to go and we have full access to
04:48all of the Papervision classes and also the FLARToolkit alchemy branch and we're
04:52ready to move onto the rest of the course.
Collapse this transcript
1. Getting Started
Understanding Papervision3D concepts and terminology
00:00Before we get started on our practical exercises, I'm just going to give you a
00:03bit of background information about Papervision.
00:06First of all, what exactly is Papervision?
00:08Well, often people think that it's either a plug-in for Flash or an application
00:12in itself, but it's neither of those things.
00:13It's actually a library of ActionScript classes that you can compile into your
00:18SWF along with you custom ActionScript.
00:20This means that it doesn't exactly give Flash any special powers. All that's
00:24really going on under the hood is that the Papervision code is calculating where
00:28all of the 3D objects should be in 2D, then it's using the standard Flash 2D
00:32drawing API to draw those shapes.
00:35So with the drawing API, we see things like beginFill, moveTo, and lineTo,
00:38commands that you would use in your Flash projects if you've ever done any
00:42graphical programming in ActionScript.
00:44Now naturally, because it's just using ActionScript code to convert the 3D
00:48points into 2D and project them onto your screen, it's not going to be as
00:52powerful as native built 3D engines, but this doesn't mean that you can't do
00:56some really cool stuff with that. Particularly if you want 3D on the web,
01:00there's no best supported way than to do it in Flash, using an ActionScript 3D
01:04engine like Papervision.
01:05It was created by Carlos Ulloa and now that's an international team of
01:10developers including Tim Knip, Andy Zupko, John Gorden, John Lindquist, myself,
01:15and a couple of other. There's a very active community of developers.
01:18So, your first post call if you ever have any problems with Papervision would be
01:22the forum at forum.papaervision.org and also on the OS Flash mailing list.
01:26Of course, when you're dealing with this amount of ActionScript, there are
01:29hundreds of classes within Papervision
01:31you're going to need a decent code editor such as Flash Builder and of course,
01:35because there are literally hundreds of classes within Papervision, it's no
01:38longer really practical to do your coding within Flash Pro.
01:41Throughout this course, we're going to be using Flash Builder.
01:44So it's obviously going to be easier to work along with the examples if you also
01:47have Flash Builder, but for Papervision projects in general, you're going to
01:51need some sort of decent coder like Flash Builder, FDT or Flash Develop.
01:55Now I could spend the next few hours talking about all the various features
01:58within Papervision and explaining them, but I find it's a lot easier if I just
02:02show you through examples.
02:04And throughout every chapter within this course, you'll learn a new feature
02:07within Papervision, but working this way means that you can get up and
02:10running straight away
02:11and before the end of the first chapter you'll have your first 3D objects rendering.
02:15So now you have a brief background in Papervision, we're ready to start working
02:18with some practical examples.
Collapse this transcript
Using BasicView to render your first 3D object
00:00Now we're going to look at the best way of creating Papervision projects in Flash Builder.
00:04Now, if you've ever seen any tutorials about Papervision before, you might have
00:08seen many different ways to get going and certainly a lot of the early tutorials
00:12for PV where to go through the process of making a viewport and camera and scene
00:16and setting up all of the individual items that you need separately.
00:20There actually it is much better way to do it and that's using BasicView.
00:23In fact, we don't even need to create a BasicView object. We can actually
00:27literally have our document class extending BasicView.
00:30So let's just see quickly how to view this.
00:31Often when I'll do presentations, to show you how easy this is, I'll set myself a
00:36little challenge of doing it in 10 seconds.
00:38Now, it might take a bit longer this time, but let's see how fast I can do it.
00:41So, first of all rather than extending sprite we want to say extend the
00:45Papervision BasicView.
00:47If I hit Ctrl+Space to make sure it imports, that makes sure that we can compile that.
00:51Now, what we're going to do is add a new sphere into our scene, and then start rendering.
00:59That wasn't bad.
00:59It was probably a little longer than 10 seconds, but let's check it out. Great!
01:06So now we have our first 3D object rendering in Papervision.
01:09So you can see how easy that was.
01:11Now as we're extending BasicView, we should really call the super and if
01:15you're used the object oriented programming practices, then you'll know what they say is.
01:18But essentially, it's just calling the constructive on the parent class for us
01:22and we're just going to make sure that the width and height of BasicView is the
01:25same as our document class.
01:27Now we're just going to look at some of the options within the Sphere constructer here.
01:30The first parameter is material.
01:32Now, by default it just uses a random wireframe material.
01:36So it could be any color.
01:37I am going to leave that as null for now.
01:39The second parameter is the radius.
01:40I am going to leave that as well as the default at 100.
01:43Now we have the number of divisions.
01:45So, segment W has the number of divisions vertically.
01:48So that's like the segments in an orange.
01:51So we're going to up that to maybe, well, I say 15 that should be.
01:54A slightly smoother sphere.
01:56Then segment H is the number of horizontal divisions.
01:59So, we're going to up that as well to let's say 12.
02:01So let's see what a difference that makes to our sphere.
02:05You can see now it's a little bit more spherical.
02:06So that's smoother.
02:07So, the next thing I want to do is actually adjust the camera settings.
02:12By default, the camera within BasicView has a very wide-angle lens.
02:16So I'm going to adjust its field of view using this fov property and by
02:21default I think it's something like 60.
02:22So we're just going to make it a bit more zoomed in, maybe 30.
02:25So that's 30 degrees.
02:26That defines the field of view angle for our camera.
02:28So let's just see what that looks like.
02:30So now I can see the sphere is a lot bigger.
02:32Now we haven't actually made a bigger sphere.
02:33We've just literally zoomed in the camera.
02:36So you'll find that the default very wide -angle lens for Papervision can be very
02:39useful, because when you start working in 3D in Flash, you often find that you
02:43lose the stuff that you make.
02:45It might be behind the camera or it might be off-screen.
02:47So by having a very wide camera as the default it means that you're less
02:50likely to lose things.
02:52But of course, if you want a slightly more natural look to your 3D objects,
02:55you probably don't want such a wide-angle lens.
02:57That's why we zoomed in here.
03:00So that's brilliant!
03:01We've actually got up and running.
03:01We've put our first 3D object into our scene and we started rendering and we've
03:05also learned how to adjust the camera lens angle.
03:08So now you know how easy it is to extend BasicView in your document class and
03:12add 3D objects and render them.
Collapse this transcript
Making a sphere and controlling rotation
00:00Now we're going to look at how we can take over the render cycle within
00:03BasicView so that we can manipulate the objects in our scene.
00:07So this is pretty much how our last exercise file ended up except that instead
00:12of using a local variable for our sphere, now we're declaring it as a member
00:16variable of our document class.
00:17Here we are calling startRendering.
00:21What happens here, what happens under the hood, is that the BasicView class
00:24adds an EventListener to the enterFrameEvent and it calls the Render command every frame.
00:31But we are going to actually manually manage that update ourselves.
00:35So the first thing we're going to do is actually delete startRendering,
00:36the startRendering command, and add our addEventListener, and of course we are going
00:42to listen for an enter frame event, and make sure that imports and we're going to
00:48call a function called enterFrame, which we now have to declare.
00:53And as it's being called on an event, we have to pass through an event object into it as a parameter.
01:00Of course in this example we're not going to be using that.
01:04We have to put it there otherwise the ActionScript Compiler complains.
01:07So now we're calling our own enterFrame method every frame.
01:12We can update the render cycle of BasicView by calling the singleRender command.
01:17Okay, so now before we call the singleRender function we can actually
01:21manipulate the objects in our scene.
01:22So we're going to look at how we can rotate this sphere.
01:25But before we do that I'm just going to remind you about the
01:28Papervision co-ordinate system.
01:30So we have the X, Y, and Z axis and the X axis is the same as the 2D Flash X
01:35axis, i.e. it's going over to the right.
01:39Y axis is the opposite of the Flash 2-dimensional Y axis.
01:42It actually goes up instead of down and the Z axis goes into the screen so it
01:47increases as it goes into the screen.
01:50We can actually rotate objects around each of these axes and we call a rotation
01:55around the X axis a pitch, call rotation around the Y axis a yaw, and finally
02:00roll is a rotation around the Z axis.
02:03And if we display object 3D in Papervision, can be rotated around each of these
02:09axes using the pitch, roll or yaw method.
02:11So in this example I'm going to rotate this sphere around the X axis, maybe
02:184 degrees per frame.
02:19Let's just take a look at that.
02:20So you can see our sphere rotating and that's what a pitch looks like.
02:25Now we're going to do a roll, which is around the Z axis. Let's take a look at that.
02:31That's pretty much the same as a two dimensional rotation in Flash.
02:36Finally, we're going to do a yaw, which is a rotation around the Y axis, and
02:42of course that's you know around the central axis pretty much how you'd expect a planet to rotate.
02:47Now we're going to take a look at our next exercise file, which takes over the
02:52render cycle in the BasicView in a slightly different way.
02:55Now to figure out how BasicView does its rendering,
02:59let's just Command+Click or Ctrl+Click on a PC to get into the startRendering
03:03method within BasicView.
03:04So now we are looking at the render code within the BasicView itself, and you
03:08can see that it's adding an event listener against the ENTER_FRAME like we
03:11expected to and it calls the onRenderTick method.
03:15So now instead of actually calling singleRender ourselves and adding the event
03:19listener we can actually just overwrite that method that we've done here.
03:23So now we've overwritten that method. We can actually put the stuff in there
03:27to update our modules.
03:29But of course we have to call onRenderTick in the parent class as well.
03:34So that's just another way of doing the same thing.
03:36I guess straightly speaking it would be slightly more optimized, but I find it
03:40a little bit harder to recognize and understand, but I just thought I'd show it
03:43to you for the sake of completeness.
03:45So now we have two different ways to update the render cycle within a BasicView,
03:50which means that we can now animate and update our 3D objects in real-time.
Collapse this transcript
Creating Cylinder, Cone, Plane, and Arrow primitives
00:01So now we are going to learn about all of the different primitives that are
00:05available to us in Papervision3D and we're also going to learn about how to
00:07create a wireframe material along the way.
00:10So first of all let's just take a look at what we've got.
00:12Well, this is the same pretty much as the last exercise where we have a sphere,
00:16and we're adding it into the scene.
00:18The only difference is that now on every frame, we're actually rotating that
00:23primitive around, dependent on the mouse's X and Y position.
00:27We can see here we're subtracting mouse's X position from 400, which means that
00:33we have a value between negative 400 and plus 400, depending on where the mouse
00:38position is, and we're going to rotate the primitive around the Y axis
00:42depending on this value.
00:43Likewise here we're going to rotate the primitive around the X axis depending on
00:48the mouse's Y position.
00:50Let's just take a quick look at what that looks like.
00:52So here we have our sphere, we can move the mouse left and right, rotates around
00:55Y as if we move up and down, rotates around the X axis.
00:59This is quite useful and a very quick way to have some sort of minor control
01:04over our 3D objects.
01:06So now let's look at the Cone primitive.
01:09First primitive of the cone is a material.
01:13Now this is like the sphere primitive, in that we'll use a random
01:16wireframe material, but this time we are going to actually declare our own
01:20wireframe material.
01:21So we can decide what color is it going to be and it doesn't keep changing all the time.
01:25So we're going to declare a local variable called wmat, which is short for
01:30wireframe material, set it up here like this.
01:33First parameter is the color. Let's make it Cyan.
01:38Now for value of 1, which means it's fully opaque, and a thickness of 1, which
01:42means it will be one pixel thick.
01:44So now when we create our cone we will pass through the wireframe material.
01:48Just make sure that's imported okay, hitting Ctrl+Space.
01:53The second parameter of our Cone primitive is the radius.
01:55So let's just give that radius of 200 and a height of 200 and the segments W and
02:00H are the same as the segments W and H in the sphere.
02:03In other words, it's the vertical and horizontal subdivisions.
02:06So let's make that maybe 20 let's say.
02:09Let's take a look at our Cone.
02:11Here it is and we can rotate it around with the mouse.
02:14So that's the Cone primitive.
02:17Let's move on to the Cylinder primitive.
02:21Ctrl+Space again to make sure it's imported.
02:25Here we have a coding. It's flat again.
02:27First parameter is a material.
02:29So we'll pass through the wireframe material that we've created it.
02:32Radius again, leave it to 100 and the height, which we'll make 200. Segments W
02:38and H again like all of the other primitives let's say 20 and 20.
02:42We'll take a look at the other primitives in a moment, but because they have
02:46default values, we don't need to declare them so let's just take a look at our
02:49cylinder and there it is rotating.
02:51That's the cylinder.
02:54So there are also options in the cylinders to have a different top radius from
02:59the bottom radius so you can make actually kind of slightly conical shapes.
03:03Just make the top radius a bit smaller and we can see what I mean there.
03:06And the next parameters for the cylinder constructor are whether to leave out
03:12the top face and the bottom face.
03:14So, by default let's say it's true which means that those top and bottom
03:17faces will be there.
03:18But if for any reason I didn't want those faces to be in my cylinder I could
03:22set either one or both of those to be false.
03:23We're not going to do that now. Instead we are going to move on to the next
03:28primitive, which is a Plane.
03:33Again hit Ctrl+Space to make sure that's imported, hit Enter to choose that
03:38that's the one we want.
03:39Again passing through the wireframe material. The plane also has a width and
03:43height, and segments width and segments height.
03:47So let's take a look at our Plane, and there it is, rotating with the mouse.
03:54You might notice something there. Our plane seems to have disappeared.
03:56But it hasn't disappeared.
03:59It's just facing away from us and here it's back again, thank goodness!
04:03So Papervision only renders trying those that are actually facing you in order
04:08to save process time.
04:10This is known as back-face culling, and it's usually very desirable because
04:14usually triangles are facing away as long as they are in sort of coherent 3D objects.
04:20They wouldn't normally be seen anyway.
04:22But we can turn that effect off by setting the double-sided property of
04:27our material to true.
04:33Now we can see as our plane faces away and that's we can still see it.
04:36There are just two more primitives that we'll be looking at right now.
04:39The first is the Arrow. The only parameter that the arrow takes is actually the materials.
04:45Let's just take a look at that.
04:46Here's the arrow. The arrow is kind of a strange one, but it's useful for
04:51seeing which direction objects are facing in or if you want to represent 3D
04:55rotations in space somehow.
04:57It can be just a useful thing to use from time-to-time.
05:00Likewise our last primitive that we're looking at is the PaperPlane, which
05:04is somewhat of a strange primitive, but it's a bit of fun and it can be useful sometimes.
05:09Now you might have noticed that we left off the Cube primitive, but we'll be
05:12covering that in later exercise.
05:14So in this movie we've learned all about primitives and also how to
05:19create our own wireframe material.
Collapse this transcript
2. Hello (3D) World!
Making a model of the Earth with a BitmapMaterial
00:00In this example we are going to look at how we can take bitmap and apply to a
00:05sphere to create an Earth.
00:07Obviously, if you've learned any programming languages before, you've probably
00:09done some kind of Hello World tutorial, and the Papervision version of Hello
00:13World is Hello Earth I guess.
00:15It's a big spinning globe.
00:16So, let's just take a look at what we've got.
00:19Well, we have like in our previous examples, we have a Sphere object and we are
00:23adding it into the scene and on the frame, on the enterFrame event, we're
00:28rotating it around the Y axis using sphere.yaw.
00:30Let's take a quick look at this.
00:33Here we have our spinning globe. Yes, pretty impressive,
00:36if you like wireframe materials, but now we're going to replace that wireframe
00:40material with a bitmap material.
00:41First of all we're going to take a quick look at the bitmap that we're going to
00:46apply into our sphere, this one here called Earth.jpg.
00:48Now this obviously is the globe, spread out across a rectangle.
00:54You might notice that its aspect ratio is 2:1.
00:57So it's two by one.
00:58Materials for spheres are usually better if they are twice as wide as they are high.
01:03So how do we get that onto this sphere?
01:04Well, first of all we need to make sure that that bitmap is actually embedded
01:09into our SWF, and here we use the flex directive here which actually embeds
01:14that JPG into the SWF and makes it available as a class through whatever we define here.
01:19In this case, we're creating a Class called EarthMap.
01:21So then to get the bitmap out of that Class, we need to extract the bitmapData
01:27property from that, after we've constructed it of course.
01:30And then we're going to create a BitmapMaterial using that bitmap.
01:33So, remember we use wireframe materials in the last example. Well a
01:37BitmapMaterial is pretty much the same except that it just wraps a bitmap around our sphere.
01:42So, a BitmapMaterial has one main parameter, this one that is the bitmap to use.
01:48Okay, so when we create this sphere, we can pass in that bitmap material.
01:52So, now let's take a look at our sphere.
01:56See it looks a lot better. It's much more like the Earth.
01:59Okay, so that's what we do if we want to embed the bitmap into a SWF, but there
02:05is also another way to load in bitmaps into our object, and that is actually by
02:09loading them at runtime. So rather than compress them into the SWF itself,
02:13we actually load it in a runtime.
02:15So instead of using that standard BitmapMaterial, we're going to use
02:19the BitmapFileMaterial.
02:27And the BitmapFileMaterial just takes one parameter, which is the URL.
02:32Now, don't forget that when you are loading in bitmaps or anything at runtime,
02:36the path name will have to be relative to where that SWF is, and then if you
02:41look at our folder structure, you can see that our SWFs will be published into
02:44this bin-debug folder.
02:45But in order to actually load that Earth from down there, we need to go up a
02:49level and into the assets folder to get the Earth.jpg there.
02:52So the relative path name form the SWF to that bitmap would be up a level there
02:58and down into the assets folder and note the Earth.jpg.
03:01Now, when we run this, it looks identical.
03:07So thaat this time, the Earth bitmap is not embedded into the SWF.
03:10It's actually picked up and loaded into the Flash Player runtime and applied to the sphere.
03:15Obviously, if this was loading off a webpage, you might notice a short delay if
03:18that JPEG is loading.
03:19As opposed to, if you embedded the JPEG into the SWF, it should be there ready
03:26to use when your SWF is loaded.
03:28So now we've learnt about the BitmapMaterial and the BitmapFileMaterial and how
03:34to apply that onto a sphere.
Collapse this transcript
Using a shader to create simple lighting effects
00:00There is a system of shaders in Papervision3D that can be used to create
00:04simple lighting effects.
00:05These were created by Ralph Howard primarily, one of the Papervision team.
00:10It's a real achievement that Flash can even do anything like this.
00:13However, I should just warn you that they are quite processor intensive.
00:16So you can't realistically put down too many objects or your frame rate might go down.
00:21So, let's look at how we can set up a Light, a shader and a ShadedMaterial in
00:25order to create this simple lightening effect.
00:27So here, we have our examples.
00:29Again we are using our Embed directive here to create a bitmap for our Earth.
00:33We're creating the BitmapData there from the asset.
00:37Then we're creating like before, just like before, a BitmapMaterial from that bitmap.
00:42These lines of code here define a PointLight3D.
00:45This is what the shader uses to decide which direction the light's coming from.
00:49Therefore which areas of the object should be light and which should be dark.
00:53So, then we create a shader and the shader is what puts the light and the object
00:58together and calculates where the lighting should go.
01:01And then finally, we create the ShadedMaterial, which takes the shader and
01:05the BitmapMaterial and puts them together, so that we can then apply them to our sphere.
01:11So here we can see when we're creating our sphere we are actually passing
01:14through that ShadedMaterial onto this sphere.
01:16In this example, we're using a FlatShader.
01:19Now, FlastShader takes three parameters.
01:20The first one is the light to use, the second is the brightness color or the
01:26color of the light, and the third parameter is the ambientColor.
01:29The ambientColor is basically how dark it gets in the shadows.
01:32So, let's see what's our Earth looks like now with new FlatShader.
01:37So you can see the Earth now has a simple lightening effect applied to it, based
01:44on where the light is.
01:45This actually helps to make our Earth look a lot more three-dimensional.
01:49Being a FlatShader, you can merely tell the geometry of the sphere and it
01:53doesn't really look like a very convincing rounded sphere anymore.
01:57But thankfully, we can use a different type of shader called the
02:00GouraudShader, named after a French man called Henri Gouraud who invented this method of shading.
02:06Just like the FlatShader, it also takes the first parameter as a light,
02:10the second parameter to be the lightColor, and the third parameter to be the
02:15ambientColor of the shadows.
02:17Let's see what this looks like.
02:19You can see now this is a much smoother shading effect and our Earth now
02:23looks quite convincing. It's very cool.
02:25This means that we can actually reduce the number of polys that is in our Earth.
02:29At the moment it's quite a high poly count, 24x12. Let's just reduce that down
02:34to maybe 16x8. You can see now that around the edges of the Earth, you can still
02:39see the geometry quite clearly, but across the surface of the Earth, the shading
02:44is smoothed out really nicely and it's still a fairly convincing sphere.
02:47So you can see that you can use the GouraudShader in order to reduce the triangles.
02:52Don't forget that using the shaders are quite processor intensive.
02:55So by reducing the numbers of triangles further, you are giving the processor a
02:59little bit of a chance to get the frame rate back up to what you want it to be.
03:03So, now we've looked at the FlatShader and the GouraudShader and how we can use
03:09those to create simple lighting effects on our Earth.
Collapse this transcript
Applying bump maps, Phong shading, and environment maps to make a detailed and reflective surface
00:00In this movie, we're going to be using the PhongShader along with bump maps
00:03and environment maps and look at how we can add extra detail and reflections to our objects.
00:08So, let's just scroll down here.
00:09Now you remember in the last exercise we set up the PointLight3D here.
00:14Now, this actually creates the Point Light and also these lines of code
00:18here where we set in the Z, X and Y values. We're actually positioning that
00:21Point Light in 3D space.
00:23Let's just say that that is a parameter in the PointLight3D constructor that's a Boolean.
00:29This parameter dictates whether it creates geometry for the object or not.
00:32If it's got geometry in it, it means that we can edit into the scene and use it
00:37to tell where our light is.
00:39So, we'll uncomment this line of code here.
00:41So, by having the true there, it creates the geometry and then we can add it in
00:44scene and we should be able to see that light.
00:47Now if we scroll down the file here, if we look at the enterFrame function,
00:51we have a line of code there.
00:53Positions that light depend on mouse's X and Y position.
00:54So, now we've got that light. I'm just going to show you the
00:59PhongShader Constructor here.
01:00So, rather than using a GouraudShader in this example, we're going to be
01:03using the PhongShader.
01:04Now, just like the GouraudShader, it has these three parameters: the light, the
01:08light color, and the ambient or shadow color.
01:10Also, this fourth parameter here in the constructor, which is the specular level,
01:16and this currently isn't implemented in Papervision, so just leave that at 0.
01:18So, let's take a look at our PhongShader.
01:22So, now you can see, we have a very smooth Earth, much like the GouraudShader. It just
01:28uses a slightly different algorithm to smooth out the areas of light and dark
01:32between each triangle.
01:33You can also see this yellow diamond that represents the light so you can see
01:37exactly where your light is coming from. Okay.
01:39So, let's go back to our Phong.
01:41Now, you can see there is a little bit of commented code there.
01:43I'll uncomment that.
01:44It adds a fifth parameter to the PhongShader constructor, which is a bump map.
01:49Now the bump map is actually a bitmap.
01:51If we scroll up to the top, I can see here we are embedding the Earth bump.jpg
01:55into our SWF using the Embed directive.
01:58Here, we are creating a bump map out of that embedded asset and setting it to
02:03this bump map variable.
02:04Let's take a quick look at that Earthbump.jpg.
02:07You can see it's a grayscale image and there are areas of darkness and lightness.
02:11The light areas represent where the land is raised at those points.
02:15I can see there are bits of light here along those mountains.
02:18The dark areas represent places which are recessed or low levels on the Earth.
02:21So, by applying this bump map into our PhongShader, we can use this data to
02:26create more detailed light and dark areas.
02:29Let's just take a look at our bump map in action.
02:31So now you can see, on the Earth, there is a very slight embossed effect there.
02:36Can you see around South America there?
02:38There is a little bit of light on the edges and obviously not much going on in the sea.
02:43Perhaps we'll have a look at Africa.
02:46Yes, very picturesque, I'm sure.
02:48Okay, so let's move on.
02:51Before we move onto the environment map, I just want to show you what's going on
02:55under the hood of Papervision and how these shaders work.
02:57There is a line of code here called showShaderBitmap.
03:01This is the function that I've written for you.
03:02Have a look down here.
03:03What that does is it takes the bitmap out of the shaded material and places it on the stage.
03:09We can actually see how that bitmap is getting updated relative to where the lighting is.
03:14Let's just take a look at that now.
03:16So, you can see there in the bottom- left, this is actually the bitmap for
03:21this Earth material.
03:22So, what the shader is doing is actually drawing that lighting onto a bitmap and
03:26just applying that bitmap directly to the sphere in just the same way as if it
03:30was a normal bitmap material.
03:32So, it's incredibly clever what's going on there.
03:34So I just show you how that works, and you can also see that it's only drawing
03:38the bits of that bitmap that are actually visible.
03:40So, it's very highly optimized and very smart.
03:42Okay, so I'm just going to re-comment that.
03:45So, now we're going to take a look at the EnvMapShader.
03:48Now the EnvMapShader, we can use to create reflections.
03:52So, it has these parameters here.
03:54The first parameter like the other shaders is a light object.
03:57Then we have an environment map, which is a bitmap.
04:00So, the front and the back, there are two separate ones.
04:03We're using the same bitmap for both in this example.
04:05The fourth parameter is the ambient color for that environment map shader.
04:10We're just going to leave that as black for now.
04:11Now, before I show you the effect of this, I just want to show you our
04:15environment map bitmap that we're using.
04:17Up here again, we're embedding it into our SWF using the Embed directive.
04:22Then here we're creating that environment map's bitmap data just like we've done
04:26for the other bitmaps.
04:27Let's have a look at that bitmap. Now, here it is.
04:32Now, this is a picture that I took.
04:34In my living room, I have a shiny spherical ball.
04:37If you take a picture of that, it sets up an image that is exactly right
04:41for environment maps.
04:43We essentially need a circular image representing all of the reflections that
04:47you would see in a silver ball like this.
04:49So, now we've created the Environment Map Shader and we've applied this
04:53environment map to it.
04:54Let's just take a look and see how it looks.
04:56Now you can see as I move the light, it actually moves the reflection around.
05:01This is probably an unwanted effect.
05:03So, it's probably best to keep the lights in the same place when you're using
05:06environment map shaders.
05:09One of the really cool things about environment map shaders is that you can also
05:12apply a bump map to that.
05:14Let's just un-comment those lines, and I'm also just going to scroll down here
05:18and re-comment the lines of codes that moves the light, because I don't want
05:21that moving anymore.
05:22Finally, I'm just going to remove the geometry for that light, so we no longer
05:27see that in our scene.
05:27So, let's take a look now at our environment map with a bump map.
05:31YOu can see that this is a really nice detailed effect and you can really the
05:35shininess on those embossed areas on the Earth.
05:38So, this is a really good way to add that extra detail into your shaded objects
05:42without adding extra triangles.
05:44So, now we've learned how to use the PhongShader along with bump maps
05:49and environment maps.
Collapse this transcript
Combining different textures with a CompositeMaterial to create clouds
00:00In this movie, we're going to look at using transparent bitmaps for our bitmap
00:05materials, and we're also going to look at how we can combine different
00:08materials to make a composite material.
00:11So, first of all, here in this exercise file, it's pretty much the same as the
00:15last one, except we also have this variable here, clouds, which is in fact a
00:20bitmap data again embedded into our SWF here using the Embed code there.
00:24Let's just take a quick look at that Earthcloudmap.png.
00:29Now, it looks very gray.
00:31Now, that's because it's actually a transparent PNG.
00:33You can apply transparent bitmaps to your objects or to any bitmap material just
00:38like you can a nontransparent bitmap material.
00:41Just take a look at that.
00:41So, here is where we're creating the cloud material.
00:48It's a bitmap material.
00:49We're passing through the cloud's bitmap and here is where we now apply that
00:53cloud material to our sphere.
00:54So let's take a look at our cloud material on our sphere.
00:58So, this is in fact actually a transparent bitmap.
01:04Well, because there's nothing behind it, you can't really see through it.
01:07Of course, you might expect to see the inside of the sphere on the other
01:10side through the clouds, but you can't because of the backface culling that
01:13we explained earlier.
01:14So, let's just turn on the double- sided property of that material, so that we
01:18can see both sides of the clouds and take a look.
01:22I actually really like this effect.
01:23It's really nice to see the other side of the transparent things and
01:26it's something I've used a couple of times in the past and it's usually
01:28worked really well.
01:29But in this example, we don't need to see the other side of clouds at this stage.
01:32So I'm going to turn that back off again.
01:38Now, the other thing you'll notice in this cloud material is that as the front
01:42of the Earth gets close, you can see the pixilation in that bitmap data.
01:47If you want to turn interpolation on, on that bitmap, you can do so by setting
01:52the smooth property of the bitmap material.
01:55We haven't looked to that so far.
01:57All that really does is it sets Papervision to draw the bitmap-fill with the
02:01smooth property to being true.
02:02So, this means that our cloud bitmap is perfectly smooth.
02:05Although this is obviously very effective, beware because it does take a
02:10little bit more process at time.
02:11But for certain objects, you should usually be able to just get away with one or
02:15two smoothed objects.
02:16So, now we have our smooth bitmap clouds.
02:20We're going to look at how we can actually add that in to the existing Earth material.
02:26Now, remember here, we're still using the shader and the shaded material from
02:29the past example, but this time, we're going to create a composite material.
02:35Now, composite material allows you to combine multiple materials into a single material.
02:39So, the way we set that up is by just creating a new composite material.
02:44There aren't any parameters in the constructor that you need.
02:47Then you actually can add different materials to it.
02:50So, the first line there, compositeMaterial.addMaterial, we're adding the shaded
02:55material and that's the Earth material with the lighting and the bump map on
03:00from the last exercise.
03:01Then here we're adding on top of that the cloud material.
03:05Because the cloud material is transparent, you should be able to see the
03:08Earth underneath it.
03:09So now, instead of adding the cloud material to our sphere, we're going to add
03:13the composite material.
03:15Let's take a look at that now.
03:18So, now we have our shaded Earth underneath clouds.
03:21Bear in mind that when you make composite materials, you can't really adjust how
03:26those materials are mapped onto the sphere.
03:28They are all mapped on together.
03:30So, I can't really move the clouds independently of the Earth.
03:33If you want to see that, you probably need to create two spheres.
03:36We're going to do that in a later chapter about viewport layers.
03:39So, now you've learned how to create transparent bitmap materials and apply
03:45multiple materials into a single composite material.
Collapse this transcript
Moving the camera and creating a particle field
00:00In this movie, we're going to look at how we can oscillate a camera left and
00:04right using a sine wave.
00:06We're also going to add a particle field into our scene to get an extra idea of
00:09how we're moving through 3D space.
00:12First of all, let's take a look at where we are right now.
00:15This is similar to the last example where we have a shaded Earth in our scene,
00:19and also an enterFrame event here where we're updating to render ourselves.
00:23Let's just take a quick look.
00:24You can see here is our Earth spinning happily in space.
00:28What I want to do now is actually oscillate the camera left and right using a sine wave.
00:33Now, don't be too scared.
00:34It's not that complicated, but what we're doing here is adjusting the camera's X
00:38position and we're setting it to the sin of the counter, times by 0.02.
00:46Now, counter is an integer that we are incrementing every frame here.
00:50So, as counter gradually increases, this Math.sin value will return a value that
00:56goes between -1 and +1, in a really nice smooth curve.
01:00Then we multiply that value between -1 and +1 by 2000.
01:03So, this means that we now have the camera X position that oscillates
01:08between -2000 and +2000.
01:11Let's take a look at that.
01:12Okay, so this might not be what you exactly expected to see.
01:18Because it doesn't really look like the camera is moving left and right at all.
01:22Instead, it seems to be moving in and out towards the Earth.
01:26Now, this is because the default camera in Papervision is what's known as a Target Camera.
01:31This means that the camera is always pointing towards a target, and the default
01:36target for a camera is an empty display object that is at (0, 0, 0).
01:40So It's the origin of the scene, which also just happens to be at the center of our Earth.
01:45So, our camera is actually moving left and right, but it's always turning back
01:50to look at the Earth.
01:52Now, the way to stop it being a target camera is you can set that up as one
01:55of the parameters in our basic view. So here is the super constructor for our basic view.
02:01Let's look at the other parameters that we've got, the first two, a width and height.
02:05Now the third one is scaleToStage.
02:06We're going to leave that as true for now.
02:08Fourth is interactive and we'll be looking at interactivity later, but I'll
02:11leave that set to the default of false.
02:14The fifth parameter here is the camera type.
02:16We can pass in a camera type, which is an object, which still are these
02:21settings. We're going to give it a free camera.
02:24In actual fact, this creates the same type of camera as if it were a target camera.
02:29But if the target of the camera is not set, then the camera just looks anyway
02:33that it happens to be angled at that point.
02:36So, by specifying CameraType.FREE, it doesn't give that camera a default target,
02:40and that camera is free to look wherever it wants.
02:43Let's just take a look at what difference that makes.
02:46Now you can see that we are actually moving left and right.
02:49But of course, we can barely ever see the Earth.
02:52We can only see as we kind of fly by.
02:54So let's go back and reset this back to the default, so it is a target camera
02:59again, so we know it's always looking at the Earth.
03:02But instead, we're going to give ourselves a particle field.
03:05So we're going to put in some particle stars that actually help us to get a grip
03:10on where exactly in space we are and where we are looking.
03:12Of course, we haven't looked at particles yet.
03:14So let's just take a quick look, and use a very simple particle field.
03:19I'm going to talk more about particles in a later chapter, but for now, here is
03:23the easy way to add a particle field, using an actual particle field object.
03:28The particle field object takes a particle material.
03:32There are different types of particle materials, and we'll talk about those
03:35again in the particles chapter.
03:36But this is a simple particle material that is going to be a small white circle.
03:42The second parameter of the particle field is the number of particles that you want.
03:46So, we're going to create a particle field with a thousand little
03:49white particles in it.
03:51There are other parameters in this particle field object, which dictate the
03:54particle size, the field width, height, and depth.
03:57But we're just going to leave those as the default for now.
04:00Once we've created our star particle field, we add it into the scene.
04:03So now we have a space scene with full of stars, let's take a look.
04:07So, not only can you see that now we have loads of small white round particles,
04:11we also have a much greater sense of exactly how we're moving through space.
04:16So, it no longer looks like we're moving in and out of the Earth, we now
04:20genuinely do get an idea of how we're moving left and right through space,
04:24angling the camera back to look at the Earth every frame.
04:26So, now we've learned how to move the camera left and right on a sine wave,
04:30and also how to add a particle field into our scene to give a greater idea of
04:34where we are in 3D space.
Collapse this transcript
3. Importing 3D Models
About the COLLADA.dae file format
00:00In this chapter, we are going to learn about how you can export your 3D models
00:04from your favorite 3D modeling app into Papervision.
00:08Of course, working with Flash in 2D is easy.
00:10We just open Flash Pro and start drawing, but obviously, it's not quite so
00:14easy with Papervision.
00:16The best 3D file format for use with Papervision is the Collada format.
00:20It was originally developed by Sony but now it's an open format.
00:23It's XML-based so it's actually a text file.
00:26So the most popular 3D apps have an export of Collada files, but if you are
00:31using Maya or Max then your best option is to install the Collada Exporter
00:35from opencollada.org.
00:38So you'll find plug-ins for Max and Maya here for both Windows and OS X.
00:44Once you follow the install instructions, you should then find the plug-in in
00:48the Plug-in Manager in Maya.
00:50Just make sure that it's loaded and that it's running by checking both of these boxes.
00:55Assuming that you've installed the plug -in correctly, you can now export and
00:59import Collada files.
01:00So here we have our cow that we've modeled, and we are going to look at how to
01:05export that as a Collada file now for use in Papervision.
01:09If you go into the File menu and choose Export All, this will export
01:13everything in your 3D scene.
01:16If it isn't selected already, select the OpenCollada exporter from the list here.
01:20Note that this DAE exporter down here is not quite as reliable as the
01:25OpenCollada exporter, so I'd stick with that.
01:27We'll just scroll down some of the options in this window.
01:31Just enlarge that to make it a bit easier to see.
01:32There are a lot of settings that you can adjust in this exporter and you don't
01:36need to worry about most of them.
01:39But I'll just talk through some of the most important ones.
01:41First of all, this checkbox here for Relative paths, that's really important.
01:46Because a DAE file is just a text file, it doesn't have any of the images that
01:50the models need. Instead it just specifies which image files should be loaded
01:55and applied to that model.
01:57By checking the Relative paths checkbox, this ensures that the entire path name
02:01for your image files isn't stored in the DAE file.
02:04That's important because obviously when you deploy these files on to the web,
02:08the DAE importer will be looking for a file on your computer.
02:12Copy textures actually copies the images into the folder you saved the DAE file
02:16into and Triangulate is very, very important because the only type of polygons
02:22that Papervision can render are triangles.
02:25If we scroll down we'll see some of the other options.
02:28So here we have the list of objects that we want to export into our DAE.
02:31The only things that we absolutely need are the Polygon meshes, the Texture
02:36coordinates, and the Normals and the Normals per vertex.
02:40If we just scroll down, you'll find that the default options here should
02:43be absolutely fine.
02:44The final checkbox here, Export double precision, increases the accuracy of the
02:50numbers that are stored in your DAE file.
02:52This will make it bigger file, but if your models are very, very small, you
02:56might need to turn that on to get extra accuracy.
02:59So now we've selected that. Let's click on Export All.
03:02So I am just going to save this file to the Desktop for now.
03:05So now that we know how to export Collada files from our 3D app, we are ready to
03:13start importing them into our Papervision projects.
Collapse this transcript
Loading a DAE file into your scene
00:00In this movie, we are going to look at how we can load those DAE objects into
00:05Papervision and start rendering them.
00:08We are also going to look at how we can change the size of those objects once
00:10they are in our scene.
00:12So if you take a look at this line of code here, this is the line where we are
00:16actually creating that DAE object.
00:18Of course, there is nothing in it at the moment.
00:20It's just an empty object.
00:21So we call this method here, dae.load, and you put in the path name to the file
00:27that you want to load.
00:28As these objects are loaded at runtime, bear in mind that this file's path name
00:33is going to be relative to that SWF itself.
00:36So here we are looking at the folder called assets at the same level as that SWF
00:40here in the bin-debug folder where all of your SWF are published to.
00:43So by looking in this assets folder, here we are actually looking in this assets
00:48folder here and you can see that our DAE file is there.
00:53Let's just take a quick look at that so we can explore what a DAE file looks like.
00:57Here it is.
00:58It's a pretty messy looking XML file.
01:01There is an awful lot of stuff in there.
01:03You don't need to worry about it too much.
01:04I thought it might be interesting for you to see it, particularly here.
01:08These lines here define all the 3D points for this DAE object.
01:13Then further down you can see this line of code here defines which points are
01:18used in each triangle.
01:20Like I said, don't worry about that too much.
01:22All you need to know is that DAE file is simply an XML file that defines
01:26where all these points are, and also which bitmaps to load in for which bit of the model.
01:31So once this DAE file is loaded, it loads the XML file, passes the data and then
01:39it loads the bitmaps that it needs and applies them into that geometry.
01:43Of course, this line of code here adds it to the scene as with any display object 3D.
01:49You might realize that this is actually getting added to the scene before the
01:53DAE has finished loading.
01:54This isn't a problem at all.
01:55The DAE object is just updated with that geometry as the file loads.
02:00So let's take a quick look at that.
02:03So here we have our cow model spinning around relative to the mouse as
02:08in previous examples.
02:11You might notice it's a little smaller than I expected, and so you'll often find
02:15that with files particularly from Maya, they are sometimes really, really small.
02:19Sometimes they are so small that you can't even see them.
02:21That can be a little confusing.
02:23So watch out for that.
02:24If you can't find your model, try scaling it up a little.
02:27So we are going to do that now.
02:29So let's look at how we can adjust the size of that DAE.
02:32The DAE object, like in any display object 3D, has a scale property.
02:38This is the same as the Flash display object 2D's scale X and scale Y property.
02:43So that 1 represents 100%.
02:45So let's make it twice as big with a value of 2.
02:47So now you can see our cow is twice as big.
02:52So now we've looked at how to load a DAE into Papervision.
02:58We've also learned how to change the size of that DAE.
Collapse this transcript
Using baked textures to improve render speed
00:01Now we are going to learn about how we can use bake textures just to pre-render
00:04the lighting on to the materials for the objects.
00:07But first of all let's just look at a 3D object without any baked textures on.
00:12So here you can see it's our knotted torus.
00:14It's just a simple flat color.
00:16It doesn't really look very three dimensional.
00:18Now we could at real-time shaders to it. As real-time shade is a pretty processor
00:22intensive, certainly in Papervision,
00:23I am going to show you how we can apply baked textures to this object in order
00:28to give it a three dimensional feel.
00:30So here is the same model but with a baked texture already applied. Let's take a look.
00:36So you can see it's a lot more three dimensional.
00:39You really get much greater sense of the shape of the object.
00:44That's because it has lighting applied to it.
00:45But this lighting effect is actually pre-rendered and baked onto the image that
00:50we are applying to this model.
00:52Let's just take a look at that texture image.
00:55It's here in our assets folder.
00:58So you can see it has light areas and dark areas, and when that's wrapped onto
01:03our knotted torus it gives the effect of lighting.
01:07Most 3D apps can render lighting on to their materials.
01:10And I am going to show you how to do it in Maya.
01:12So let's open up Maya and see here is our knotted torus shape.
01:17At the moment there aren't any textures mapped onto it.
01:21This is just the default shaded material for Maya.
01:23But before we can bake any lighting into our texture then we need to
01:27actually add a light.
01:29If I turn off the default lighting from the scene you'll see that this is
01:33using the natural lights there in the scene and there aren't any lights so
01:37it's a very flat shape.
01:38So before we can render the lighting on to the texture we need to add a light.
01:42I am going to go into the menu option Create and then Lights > Directional Lights.
01:48The Directional Light stimulates a light source from very, very far away.
01:52So it kind of stimulates you the sun as opposed to a small lamp which
01:55you can move around.
01:56I am just going to use the default settings for this directionalLight in this case.
02:01So now we have our model and our light.
02:04Let's look at how we can actually convert that into a bitmap texture.
02:08I am going to click on this icon here that opens the Hypershade.
02:13This is what Maya uses to create all of its materials and textures.
02:16Now I click on the model and then I Shift+ Click on the ColorMaterial for that model.
02:22And then I go into the menu option in the Hypershade Editor.
02:25Edit > Convert to File Texture.
02:28I am going to click on this box to bring up some extra options.
02:31So this is the dialog box for converting the texture into a file.
02:37I am not going to go over every option here, but the important ones are bake the
02:41shading group lighting and bake shadows.
02:43I am going to scroll down.
02:46The other important thing is to check the X and Y resolution of our image.
02:51If these values are a power of two then they are going to work better in Papervision.
02:56So let's keep that as 512.
02:58And very important thing here is the actual file format that we are using.
03:01Because Papervision and indeed the Flash Player itself can only load PNGs
03:06and JPEGs at runtime we need to make sure that our texture is exported to
03:10one of these formats.
03:12We are going to select PNG.
03:14So now we could Convert and Close.
03:15So Maya has created a bitmap in the background, created a new surfaceShader with
03:22that bitmap, and applied it to our model.
03:25It kind of looks just completely black.
03:27That's because we are not previewing textures.
03:29To preview textures click on this little checkbox here.
03:34Because when we weren't previewing the textures this just had a black surface,
03:37we can now be sure that this lighting is now only on the bitmap itself and not
03:42being rendered with Maya's default light settings.
03:45As Maya has created a surfaceShader for our bitmap material, we are going to
03:50need to convert it into a material that Papervision can understand.
03:54So the process of doing that would be to right-click on our model, Assign New Material.
03:58We are going to use a Lambert shader.
04:03The Lambert shader is the best shader to use if you are just literally trying to
04:07export bitmap textures.
04:09Now before we adjust the settings of this Lambert shader I am just going to take
04:13a look at the surfaceShader that we created before, because this surfaceShader
04:17has a reference to the file that we've created.
04:20By default Maya will render that image into its own textures folder inside the project.
04:26But we don't need to know exactly where that is because we can just click on the
04:29File tab within the surfaceShader and we have the file reference for that image.
04:34So we are going to select that and copy it into the Clipboard.
04:37So now when it comes back to clicking on our material and adjusting the Lambert
04:42shader, we can paste in that file name.
04:45So rather than using a color we want our Lambert shader to use a file.
04:50So we'll click on this little checked box here and select File.
04:56Now we can paste in that file name from before and Reload.
05:01So now we've rendered the lighting onto a texture or baked it on.
05:05And then we've applied that bitmap texture to a Lambert shader so we can export
05:09it into Papervision.
05:10So the final thing we have to do is actually export that as a Collada file, same
05:15settings as in the previous movie.
05:18But just make sure that this checkbox here, Copy textures, is checked.
05:21This will actually take that bitmap image as well as the DAE file and copy it
05:26into the target folder.
05:28Scroll down, click Export All.
05:30So now we are going to navigate to our Workspace folder and the project
05:37folder for this chapter.
05:38As these are loaded in at runtime we need to use the assets folder within bin-debug.
05:42So that the SWF files that we compile have direct access to them.
05:46So let's save this in that folder as torusbaked.
05:49So let's go back now to Flash Builder.
05:54You can see now that there is a new DAE file there, torusbaked, and it's also
05:58saved out the bitmap material that we just created.
06:01Let's take a look at it and there it is.
06:03So finally let's just check that works okay.
06:06So let's load it into our Papervision scene and compile.
06:11So now we've learned how we can save render time by pre-baking the textures into our model.
06:17We find that this is an incredibly useful technique, especially if you're trying
06:21to create very soft and warmly lit environments.
06:24It's not really possible to apply shaders to everything in real-time.
06:27So by pre-baking these textures into the materials we can create these soft warm
06:32lit environments with no extra processing time at all.
Collapse this transcript
Changing a material once it's loaded
00:00So now we can look at how to change the materials once your DAE is loaded.
00:05Let's just start at the top of this file. You can see like before we are
00:09creating a new DAE object and loading our baked knotted torus into it.
00:14Here we are just adding a new StatsView object.
00:17Now this is a tool in Papervision to help you see what's going on with
00:21Papervision, how many triangles it's rendering, how many triangles it's culling,
00:24and all kinds of other useful stuff.
00:27It takes a reference to the renderer, which is just a property of BasicView.
00:31We'll see in a minute what that looks like.
00:34Unlike previous examples, instead of adding the DAE to the scene straight
00:38away, we are going to wait until it's loaded, and it's complete and ready to
00:42render before we do so.
00:43So here we are actually adding an event listener.
00:46We are listening out for the Load_Complete event from a DAE.
00:51Once it's loaded, we are going to call daeLoadComplete here.
00:52There is a couple of lines of code adjusting the camera's field of view and Z position.
01:00But here is the function which is called once the DAE is loaded.
01:03At the top of this function, we've got a couple of traces. So we can now see in
01:08the Console that the DAE has definitely loaded.
01:10Then we are going to trace out the materials property of the DAE.
01:14Now this is a materials list, which describes every material that is in the DAE.
01:18If we trace this out, it will just show us the names of all those materials.
01:22We'll look at all of these other code in a moment, particularly this
01:26commented out stuff, but here at the bottom of this method, we are actually
01:30adding that DAE to our scene.
01:32Let's take a quick look at that now.
01:35So here is our knotted torus on the screen.
01:38You can see in the top-left hand corner that's our StatsView with all the
01:42information about what's happening, including our frame per second, triangle
01:46count and lots of other stuff which you don't need to worry about right now.
01:51More importantly, if we look in our Console, you can see that traced out message
01:55that the DAE has actually loaded.
01:56And also, here is the list of materials. In this case, there is only one and
02:01it's called torus_mat.
02:03So this is the name of the material in the torus for that baked texture.
02:09So what we are going to do is actually replace that material with a different
02:12material once the DAE is loaded, but before we've added it to the scene.
02:17So look at this line of code here. We are creating a new wireframeMaterial.
02:21It's white, 20% opaque and it's 0 width, which means that it'll be at least a pixel wide.
02:29Then this line of code here, we'll uncomment that, DAE.replaceMaterialByName.
02:32Replace Material By Name is a method on any display object in 3D.
02:39You can use it to replace materials in any object with a materials list.
02:43The first parameter is the material that you want to replace it with and the
02:47second is the name of that material, in this case, torus_mat.
02:52And we saw that there when we traced out all of the materials in that torus.
02:56Let's just see if that works.
02:58So now you can see our torus has a wireframe material.
03:02Likewise, we can replace that material with any other source material that we want.
03:08Here is a FlatShadeMaterial.
03:14Now the FlatShadeMaterial is an easy way to add flat shading to any object.
03:19Unlike with the method we used earlier which requires a bitmap material and a shader.
03:23This is an easy way to get lighting on to an object, which doesn't have a bitmap material.
03:29Likewise, here we have the GouraudMaterial, which again doesn't require a bitmap
03:34material so it's much easier to set up.
03:38You can see also we've got a PhongMaterial here, which is a little bit shinier
03:44than the GouraudMaterial and then we have the CellMaterial.
03:47Now this is meant to recreate the effect of cartoon shading.
03:52You can see there it's got just a few divisions of color in there. Quite a nice effect.
03:58And then finally, we are going to apply an EnvironmentMapMaterial to our torus.
04:02So you can see that's really shining,. Now this is really cool.
04:05You can just replace any of your materials with this reflective surface.
04:09So that's all cool as long as you are just discarding the material that is in the DAE.
04:14But if you want to actually take that BitmapMaterial and apply a shader to that,
04:20it's a little bit more tricky.
04:22To show you that I am going to actually load a different DAE now.
04:25Actually, this dice.dae that I created earlier.
04:29I know this dice is a little bit bigger than our knotted torus so I am just
04:32going to scale it down a little.
04:34Now when that object is loaded, I know that the main material in that dice is
04:39called dicematerial.
04:40So here we have these lines of code there.
04:43The first one uses dae. getMaterialByName to actually reach into that DAE and
04:50get the material out.
04:51We know the material is called dicematerial and it's a BitmapMaterial.
04:54We can store it here in bmmat.
04:58Then we create an EnvironmentMapShader that uses the light and the same
05:02environment map that we used earlier.
05:04And then we created a ShadedMaterial out of that BitmapMaterial and the shader
05:09that we just created.
05:11And finally, we replace the material within that DAE with this new
05:16ShadedMaterial that we've just made.
05:18So what we've done is we've extracted the BitmapMaterial out of the DAE object,
05:23created a ShadedMaterial using that, and then reapplied it back into the model.
05:27So let's just take a look at that.
05:30So here we have our shiny dice object.
05:34So now we've learned how to replace materials within a DAE once they are loaded.
05:37And we've also learned how to extract the BitmapMaterial out of the DAE and
05:42apply it to a ShadedMaterial, and then reassign that material back into the DAE.
Collapse this transcript
Managing hierarchy to add one object to another
00:00So now in this movie, we're going to look at how we can add one object inside
00:04another, and then rotate the parent objects and see what effect that has on its child.
00:10So, let's just take a look at this Exercise File.
00:12Scroll down here. You can see this bit is actually creating our Earth object
00:17and same is the example as before, and then we're adding that into the scene here.
00:22And then here, we're creating a DAE object loading in the file and moving it
00:26over to the right of 300 units.
00:28Then crucially instead of adding that into the scene, we're adding it inside the sphere.
00:33So, we're going to add it inside the Earth objects.
00:36Of course, it's moved over to the right.
00:39So it's not going to be inside of the Earth itself.
00:41It's going to over to the right of that Earth.
00:43Here, we're adjusting the camera settings, adding an event listener to the
00:47enterFrame as before.
00:49Let's take a look at the enterFrame function here.
00:51You can see that the sphere is rotating around the Y axis and then the dae
00:55model is actually rotating it around its own axis as well.
00:59So let's take a look at that.
01:00Now you can see we've got the Earth there and as it rotate, you can now see our
01:05cow model also rotating around the Earth.
01:07So, the cow model actually inherits the rotation from the Earth.
01:14You could say that the cow is a child of the Earth.
01:16So, in order to properly understand exactly what's going on here, let's take a
01:21look inside Flash CS5.
01:24Now, here's a little example to illustrate what's going on here.
01:27On the left, we've a circle and that's rotating here on the Timeline there.
01:33Here is a little square. This is set for display object and this is set for
01:37a movie clip on the stage.
01:38Let's just publish this file.
01:40You can see that the wheel is turning around and the square is not
01:44getting affected by it.
01:46Now, let's cut this off the stage and double- click into this movie clip and paste it in.
01:52So now, this object is inside this wheel movie clip.
01:55So now when we come up to the parent, you can see as that wheel rotates around,
02:01the square also rotates around with it.
02:03So, this happens in the 2D display object hierarchy in Flash and it also works in
02:08exactly the same way in the 3D hierarchy in Papervision3D.
02:11So, let's just look out at the 3D version again.
02:16And here it is exactly the same thing excep of course this works fully
02:19in three-dimensions.
02:20So now, you've learnt in this movie, how you can add one Display Object 3D
02:26inside another, and how that child object then inherits the properties of its parent.
Collapse this transcript
4. Cubes and Skyboxes
Making a Cube primitive and modifying materials
00:00In this movie, we're going to take a look at the Cube primitive.
00:04Now Cube primitive is slightly different from the other primitives in that it needs
00:086 materials, not just one like the others.
00:11That's because it has 6 faces and it needs to know which material goes on which face.
00:15Okay, so let's take a look at the constructor for the cube.
00:19You can see that it has a first parameter, which is a MaterialsList.
00:23MaterialsList essentially is a list of materials, and we'll look at how we
00:27create that in a moment.
00:28But for now, let's just pass-in a variable name ml, which we will define in a moments.
00:33The next three parameters are for Width, Depth and Height, followed by the
00:38number of segments that it is divided into in each of the three planes.
00:42Now, let's just take a look at the constructor for the cube.
00:46You can see that there are some handy AS docs style comments here, which
00:50describes all of the parameters.
00:52So, these ones here describe the number of subdivisions sagitally.
00:55That's perpendicular the Width.
00:57SengmentsT, which stands for the number of segments transversely, which is
01:02perpendicular to depth, and finally, SegmentsH, which is the number of
01:06horizontal segments.
01:07So, let's go back to our file.
01:09So, we're actually just going to leave all of the default values for our cube.
01:13We're just literally going to pass it in the MaterialsList.
01:16So, let's define that MaterialsList here.
01:19What you have to do is create a new MaterialsList. There's nothing in the constructor.
01:27So that's all you need.
01:28So, the way to add a material to the MaterialsList is using the addMaterial
01:35method and you pass it through the material that you want to add.
01:39In this case, we're going to make a new ColorMaterial.
01:41We haven't seen a ColorMaterial yet but it's essentially the same as a
01:45WireframeMaterial except it draws the triangles with a solid color.
01:49So, let's pass-in a color to make it dark red.
01:55And we're going to make it fully opaque.
01:57The second parameter when you add a material is actually the name of the material.
02:02We're going to call this material Aal.
02:06This is the name for the DefaultMaterial that a cube uses. If it doesn't have a
02:10specific material for the side than it just reverts to this one called all.
02:15So this means that it our cube should use this material for all of its sides.
02:20So then finally, all I need to do is add the cube into the scene.
02:27So, let's take a look.
02:28So now you can see, we've a very, very large cube and all of the sides are red,
02:32so you can't really see what's going on.
02:34So, let's make it a little bit smaller.
02:42So now, we can see the cube properly.
02:44Of course, all the sides being red, you can't really get an impression of how
02:48that object is shaded or how three-dimensional it is.
02:52So, let's color each side of the cube a different color.
02:55So now, let's look at the next file in our list.
02:58And you can see now that we've some commented out lines of code here.
03:03So lets Uncomment those and you can see that we're adding materials to the
03:08MaterialsList. One for the right-hand side of the cube, one for the bottom, one
03:11for the top and one for the left.
03:13Now the back and the front of the cube will just use the DefaultMaterial, which
03:17is defined up here, and added to the MaterialsList here.
03:19So, let's take a look at the cube now.
03:23So now you can see that, because we've shaded each of the cube with a different color,
03:28it's a little bit easier to see how three-dimensional it is.
03:31This is exactly the same technique that we used for Major League Baseballs
03:34project for the Game Day 3D where we've created a batter object and instead of
03:40applying bitmaps to him, we actually just colored the different triangles in his
03:44body different colors which gave it the look of shadows and solidity.
03:49So it's a very, very fast technique and it's much faster than using bitmaps.
03:52So now, we've learnt how to create Cube material.
03:54We've also learnt how to make a MaterialsList and assign different materials to
03:59each side of a cube.
Collapse this transcript
Creating a 3D environment by building a skybox, adding particles, and flying around
00:00In this movie, we're going to add special materials to each side of our cube
00:06to create a skybox.
00:07The Skybox uses special images on each side, so that when you're inside the
00:10cube, it looks like a seamless environment.
00:12In this case, we're going to create a space environment.
00:15So first of all, we're creating our cube and our MaterialsList like before, but
00:21instead of using ColorMaterials, we're using BitmapMaterials.
00:24And the bitmaps that we're using get embedded here.
00:26Let's just take a look at a couple of those, and look at the back face of the cube there.
00:31And that's the left-hand side of the cube. You can see they join up perfectly.
00:37All sides of this cube should join up.
00:39So now, when we apply those to the cube, you can see when we run it, we have a
00:46cube with like space textures on each side and you can't see the edges at all.
00:51Now these space textures are actually specially distorted so that when you are
00:54inside the cube, you shouldn't really see the corners of the cube.
00:57It should feel like you're just in a panoramic environment.
01:02But of course, it's not going to look like that unless you're actually inside the cube.
01:07So remember from before that the default z position of the camera is -1000.
01:10So you're always going to pretty much be looking at stuff that you add into the
01:15scene at the origin.
01:17But of course, we want to move the camera forward to the origin so that we're
01:20now inside the skybox there.
01:22Let's take a look now.
01:24So you are probably fairly unimpressed by this because we can't actually see anything.
01:29You find as you're working with Papervision, there's going to be many reasons why
01:32you run your file and there's nothing there.
01:34It's not really the same as Flash in 2D where you put stuff on the stage
01:38and it's pretty much always going to be there, no matter what you do,
01:40unless you move it off.
01:42But in Papervision, there's any number of reasons why you can't see the things
01:45that you put into your scene.
01:47Like for example, the camera might not even be looking at it.
01:50It might be behind you.
01:51But in this case, because we're inside the cube and Papervision only renders
01:55the triangles on the outside, it means that you can't see anything. You're only seeing the inside faces.
02:00So, let's look at the next example, Cube3a.
02:05You can see here now we are setting the doubleSided flag on each one
02:09of those materials.
02:10So we can make sure that when we're inside of the cube, we'll still see the outer edges.
02:15We're also making the cube a lot bigger so that we can make sure that we're not
02:20too close to the edges of the cube.
02:22Let's take a look at that.
02:24Ah, so this is better.
02:26Now, we're inside our space environment.
02:28You can see I can move the mouse and look around and you can't really see the
02:33edges of the cube at all.
02:34It's fairly seamless.
02:38Let's take a look at the next example.
02:40Now, the idea behind a Skybox is that as you move around, the Skybox moves with you.
02:46This ensures that you don't actually hit the edges of the Skybox and that always
02:50stays kind of at infinity.
02:51So, on our enter frame now, we're going to move the camera forward four units
02:55every frame using the moveForward method.
02:59moveForward is a method in every displayObject3D and the camera.
03:03We'll be looking at interesting ways of using that later, but this version is
03:07just moving the camera forward, no matter which way it's facing.
03:11And then these lines of code here update the cube's position so that they always
03:16follow the camera around.
03:18Now, in order to get a better idea of how we're moving, we're also going to add
03:21a star field into our scene.
03:23So you can see here, we're creating a star particle field here using this
03:27ParticleMaterial that we are defining the line above. We're just using the
03:32basic ParticleMaterial that we used in another chapters, just a circular white particle.
03:37So, the camera moves around and the Skybox moves with it, but this particle
03:42filled doesn't move. Let's take a look at that.
03:44So now, you can see as we move around, we're flying through space and the
03:50particle has really helped to give us an impression of where we're moving.
03:54But of course, no matter how far we move, we're never going to hit the edge of
03:58the Skybox because that's moving around with us.
04:00So in our final file, Cube4, this is pretty much the same as the last example
04:07except instead of using a normal circular particular material, we're using this
04:11BitmapParticleMaterial.
04:13We are going to be looking at particles in more depth later but this is a way of
04:17applying a bitmap to a particle rather than just a simple shape.
04:21Let's just take a quick look at our BitmapParticleMaterial that's here.
04:24It's a little transparent star shape.
04:27We're embedding it into the file up here as before using the Flash Builder Embed directive.
04:35So now we have star-shaped particles but we're also chucking in a DAE model for good measure.
04:40Let's take a look at this final finished scene.
04:43So now, you can see our star particles are much more star-shaped and also we
04:48should have our friend somewhere here, our Space Cow. Careful not to hit him.
04:55So now we've learned how to create a Skybox and apply these special materials
05:00to each edge to make it look like a seamless environment.
05:03We've also added a particle field to give us the impression of how we're moving,
05:07relative to the real environment because we're not advocating any closer to the skybox.
05:11And finally, we've learned about the BitmapParticleMaterial to make specially
05:16shaped particles that aren't just simple shapes.
Collapse this transcript
5. Making a 3D Game
Starting with a 2D Ping-Pong game
00:00Throughout this chapter, we're going to be looking at how we can take a simple
00:042D Flash game and convert it into 3D.
00:07Now, of course, when you usually think about 3D gaming, I'm sure the first
00:10thing that comes to mind is a first- person shooter or a fully immersive
00:14environment on your console.
00:16But of course, this type of game can be incredibly difficult to do with Flash,
00:19even with Papervision.
00:20But that doesn't mean that you can't make fun 3D games and of course Flash is
00:24particularly suited to casual gaming.
00:27So, we're going to take a retro style 1970s or 1980s ping-pong game. Let's just
00:32take a look at it first before we do anything.
00:35So, you can see here, it's very simple game.
00:38The top paddle is controlled with my mouse, and the bottom paddle is taken care
00:43of with some very simple logic, you'll see in a moment.
00:44Of course, it's green, because it's super-retro.
00:48All right, so let's take a look at its 2D game code before we start
00:53converting it into 3D.
00:54So, of course, we're setting up the objects here that for the bats, the player1
00:59and player2 bats. We've got the arena that has all the lines which represent the
01:04table-tennis court or table.
01:06Here is object for the ball is bouncing around.
01:09We also have GAME_WIDTH and GAME_HEIGHT.
01:11At the moment that's in pixels.
01:13When we convert it into 3D, that will be Papervision units.
01:15If we look at the constructor for this class, you can see that the first thing
01:20we do is move the origin down to 320 x 320.
01:25That's the center of the screen.
01:26Of course, this isn't strictly necessary.
01:292D Flash game can have the normal origin in the top left-hand corner of Flash.
01:33But as we are converting this into 3D, by default, the origin in Papervision is
01:37in the center of the screen.
01:39By moving with 2D origin to the middle, this is going to help with
01:42the conversion process.
01:43There are a few methods here.
01:46First of all, initObjects.
01:47That sets up the player paddle and the computer-controlled paddle and the ball
01:51and all the things in the game.
01:53Then initListeners sets up the enterFrame listener, which runs the game loop every frame.
01:59Here is the startGame method.
02:00Let's just scroll down there. The initListerners function, very simple.
02:05We've covered that already.
02:06Now, the game loop itself is what is actually called every frame.
02:11I like to keep these things very readable without too much complicated code.
02:16I want to see a game loop and I want to see methods like ball.update.
02:19It's very obvious what that does.
02:21moveAiPaddle updates the computer-controlled paddle.
02:25movePlayerPaddle updates the position of the player's paddle relative to the mouse.
02:29checkCollisions does all the collision detection between the ball and the
02:33paddles and the walls.
02:35startGame just resets the ball's X and Y velocity to be a kind of diagonal.
02:39Here are the checkCollision methods.
02:42First of all, we check collisions between the players and the ball and we'll
02:47drill down into those methods in a moment, but then this conditional here
02:51checks to see if the ball's Y position is greater than half the game's height.
02:55That means that the ball is below the bottom of the screen.
02:59If that's true, then we reset the ball back to the middle.
03:02Likewise, this conditional here checks to see if the ball is off the top of
03:06the screen by comparing with ball's Y position to minus the GAME_HEIGHT
03:10divided by 2, which is the top of the screen. Remember this document class
03:14is centered in the middle.
03:15This set of conditionals here checks to see whether the ball is collided with
03:20the left or right-hand side of the game.
03:22So, here we're checking to see if the ball's right-hand side is greater than
03:26that GAME_WIDTH divided by 2.
03:27That means it's hit the right-hand wall.
03:29So, we move the ball back so that it's actually touching the right-hand side
03:34of the wall, and then we reverse its X velocity. That means it bounces back
03:38towards the left side.
03:40Then this conditional here does the opposite for the other side of the wall.
03:43Here is the code that updates the computer-controlled paddle.
03:47it's very, very simple.
03:48It just compares the ball's X position to the player2's X position.
03:53If it's less than player2 X position, then we move the player2 paddle to the left.
03:58If it's greater than the player2 X position, we move over the right.
04:02So, it's very, very simple.
04:03Here's the bit that updates players1's paddle relative to the mouse position.
04:08Very simple method there for resetting the ball position.
04:12Here is the bit of code that initializes all the objects.
04:16So, I just wanted to take you through some of these.
04:18First thing we're going to look at is the Ball object.
04:22Ball object has an X and Y velocity, and here in the update function, we're
04:26adding that X velocity to the X position and we're adding the Y velocity to the Y position.
04:32Notice that this class extends the Square class.
04:34I'm just going to Command+Click or Ctrl+ Click if you're on the PC to get into this file.
04:39Now, you can see that this is our base class for the ball and this is what
04:44takes care of drawing that square-shaped ball.
04:48There's also some other useful getters/ setters for checking the left-hand side,
04:52right, top, and bottom of this object.
04:55If we look at the constructor, we're passing in width and height here and also a color.
05:01So, this is the color that we want our square to be.
05:04Of course, this is green, because this is a retro game.
05:08We're also storing halfWidth and halfHeight.
05:11This makes it quicker for us to calculate the edges of this object.
05:15Then finally, there's this method, drawSquare, which actually draws that square
05:19object using the Flash 2D drawing API.
05:23Here are the getter and setter methods that I mentioned that are very quick ways
05:27to access and set the left, top, bottom, and right-hand side of this square.
05:31So, by extending that square, ball has all of that useful functionality that we
05:37have defined in the base class.
05:39Okay, so now let's look at the Bat object, which is what we're using for
05:44player1 and player2.
05:45So again, Command+Click into there or Ctrl+Click on a PC. You can see that this
05:49Bat object also extends Square, because there is a lot of functionality that we
05:53need in square that we also need in the Bat class.
05:56Unlike the Ball, it's not a square.
05:57It's actually rectangular.
05:59So, it has a width of 86 and a height of 16.
06:03Then there is this checkBallCollision which checks to see if the ball has
06:07collided with the paddle, either on the top side or the bottom side.
06:10I'm just going to very quickly take you through this code.
06:14The first line here checks to see whether the ball has overlapped the bottom of
06:19the paddle between frames.
06:21So, it's checking the current top position of the ball.
06:23So if it's less than or equal the bottom of the paddle, that means that the ball
06:28is below the paddle.
06:30The second part of this conditional checks to see whether the top of the ball
06:34minus the ball's Y velocity is greater than the bottom of the paddle.
06:37What that means is it's checking the ball's last position to see whether in the
06:42last frame it was actually greater than the bottom of the paddle, which means
06:46that in the last frame, the ball was below the bottom of the paddle and in the
06:49current frame, the ball is above the bottom of the paddle.
06:52So, between frames, the ball has overlapped the bottom edge of the paddle.
06:57The second part of this collision detection is to tell whether the horizontal
07:01bounds of the bat and ball are overlapping.
07:04So, what we're actually doing is the inverse check here.
07:07So, this is kind of a clever technique we can use to very quickly test an overlap.
07:13Essentially, all it's doing is checking to see if the ball is completely outside
07:17of the bats on the left-hand side, or the ball is completely outside of the bats
07:21on the right-hand side.
07:23Then using this exclamation point here, we're checking the inverse of that.
07:27So, what that means is that the ball is definitely overlapping the
07:31paddle horizontally.
07:33If that's true, then we're setting the top of the ball to be the bottom of the
07:36bat, and we're reversing the Y velocity of the ball, by multiplying it by -1.
07:41The second half of this collision detection check is exactly the same, but
07:45this time we're checking the collision between the bottom of the ball and the top of the paddle.
07:49So, that's for the other paddle at the other end of the screen.
07:52So, now we fully understand how this 2D version of Ping-Pong works, we're ready
07:56to start converting it into 3D.
Collapse this transcript
Converting a 2D game to 3D
00:01So now we understand how our 2D version of Ping-Pong works,
00:04let's start the process of converting it into 3D.
00:07The first thing is that our document class extends Sprite currently, which is
00:11the standard Flash 2D display object.
00:13We're going to change that so it is now extending a BasicView object, which
00:17means it's all ready to start adding Papervision objects into it.
00:22The next thing we want to do is if we look at the constructor for this, remember
00:26that we moved the coordinate system so the origin of this document class is in
00:30the middle of the screen.
00:31We don't need to do this anymore, because the Papervision coordinate system by
00:34default is centered in the middle of the screen.
00:36So, I delete those lines there.
00:39Let's move down to the bit that initializes the object.
00:41So, we have an arena, two bats and a ball.
00:44These four items are things that we need to convert into 3D.
00:48So, let's Command+Click, or Ctrl+ Click on a PC, into this Ball object.
00:53Now, remember that both the Ball and the Bat extends Square. This is really
00:57fortuitous, because it means that by converting this Square object into a Cube,
01:00our bat and our ball will both become 3D.
01:04So, instead of extending Sprite, let's make this object extend to
01:08the Papervision3D Cube object.
01:10If we scroll down here, you can see this method that actually draws the square.
01:14You no longer need that, because by extending the cube, it means that we have
01:18all that geometry for the cube built for us.
01:21So we don't have to worry about drawing it.
01:23So, I'm going to delete the drawSquare method.
01:26But of course, the super constructor for the cube requires some parameters.
01:29Do you remember in the chapter about cubes and skybox, we talked about
01:34the materials list?
01:35So we're going to have to create a materials list for our cube here.
01:41Then we add the default material to it, which will be a basic ColorMaterial.
01:47Of course, because it's retro, it will be pure green.
01:50The name of this material because we want it to be the default cube is all.
01:57So, remember that means that if the cube can't find another material for a
02:02specific side, it just defaults to all. So, now we've created that materials list,
02:06we can just pass that into the super-constructor.
02:08It can be a width, depth and height that reflects what we wanted for the original 2D
02:14ones, and we want the width to be the same as it was before.
02:16We want the depth to be the same as the height, and we want the height to be
02:20the same as the height.
02:21So, this means that our cube now has the same depth as it has height.
02:27By converting the square objects into a cube, it means that now both our ball
02:30and our bat are both 3D objects, which means that our Flash Builder no longer
02:35likes the fact that we're adding that at this stage. We actually need to add
02:38these 3D objects into our 3D scene objects.
02:44The final object that we need to convert to 3D is the arena.
02:47If we take a look at this Arena object by Command+Clicking in, or Ctrl+Clicking
02:51on the PC, you'll see that this uses the Flash 2D drawing API to draw the lines
02:57that represent the table-tennis court itself.
03:01To convert this into 3D, we're going to use the Papervision Lines3D object.
03:06Lines3D is a special display object 3D that's used only for rendering lines.
03:11We can't render triangles or particles in it. It's just for lines.
03:14We're still going to call drawArena, but we're going to actually change this,
03:18so it adds 3-dimensional lines to our Lines object, using the addNewLine method of Lines3D.
03:25We're going to make the lines 3 units wide.
03:29The addNewLine method requires a point at the start of the line and at a point
03:33at the end of the line.
03:34Of course, these are 3D points.
03:36So we need 3D X, Y, and Z for both the start and end point of the line.
03:39Now, if we look down here, these two lines of code draw the left-hand side of our Arena.
03:46So we're going to need to convert these coordinates into 3D.
03:49But we have X and Y there, but we also need Z. Because our arena is still going
03:55to be along the X-Y plane, it means that we can just have a Z value at zero,
03:59which means that the arena will be in space at the zero point.
04:04In the end points of the line, we're going to pass in the next point in 2D for
04:08which we've got X and a Y. The third coordinate, the Z value again, 0.
04:12So, that's the first line in our arena. The second line in our arena will do
04:17exactly the same thing.
04:18So addNewLine, width of 3, cut-and- paste the X and Y coordinates, add a Z
04:24coordinate, same with the end point of the line.
04:27That is the right-hand side of our arena.
04:33Then we just have one more line to add, which is the line that goes across the middle.
04:39Again, cut-and-paste the X and Y coordinates, add a Z value of 0, likewise for
04:45the end of that line.
04:49Just one more thing we need to do before we can go.
04:52In the constructor for the Lines3D object, we have to pass a line material in.
04:55We're just going to make a plane line material, pure green of course and fully opaque.
05:02So now, our ball, bat, and arena are all 3D objects, but of course, now the
05:08arena is 3D. We can't add it to the stage. We're going to add it to our scene.
05:13So, let's see where we are.
05:13We've converted everything into 3D. Let's take a look.
05:16Now, of course, you're seeing that there's nothing really there. I'm sure you're
05:19not very impressed with that.
05:20But that's for one very simple reason. Remember that in Flash in 2D, you put
05:24stuff on the stage, it's automatically there, but in Papervision3D, you don't
05:28see anything until you stop rendering.
05:31So, up here after we've initialized everything, let's actually call the
05:34startRendering method.
05:40Okay, so all our objects are in 3D.
05:43They're being rendered.
05:44That's mostly excellent!
05:45You'll notice that the offset on the mouse X position is a little wrong.
05:49So the player paddle doesn't go quite from the very left-hand side to the
05:52right-hand side of the arena.
05:53Also notice that whereas before our mouse was controlling the paddle at the top
05:59of the screen, and now we're controlling the paddle at the bottom.
06:01So, that's just a reminder for you that the Papervision Y-axis points the
06:07opposite way from the Flash.
06:09It points upwards, so Y gets greater at it goes up, whereas in Flash Y gets
06:14greater as it goes down.
06:15So, by converting this from 2D into 3D, you can see that the arena has actually flipped.
06:21But that's okay. I'm quite happy for the player's paddle to be at the bottom.
06:24Let's check the width of the document. It's 640.
06:27So, by subtracting the mouse's X position from 640, we should have a value
06:33between -320 and +320.
06:35Let's take a look at that now.
06:38So now you can see the extent of the mouse movement are a lot better than they were.
06:44Final thing that I want to do is actually move the camera a little bit closer to
06:48the arena, because it's a little bit far away.
06:50So, I'm just going to do that up the top here.
06:52Before we start rendering, I'm just going to set the camera position.
06:56Well, let's just try it. Remember the camera Z position by default is -1000.
07:00Let's try maybe -600 and see how that looks.
07:02So, now you can see that we're a lot closer to the arena.
07:07So, this completes the process of converting this game from 2D into 3D, ready
07:13for us to start adding some more interesting looking effects.
Collapse this transcript
Laying the game flat in 3D space
00:01So now we have got our basic ping pong in 3D. We are going to look how we can
00:05refine that a little further by moving the game arena down flat so it's on the ground.
00:10We will also look at coloring the bats and the ball to make them look more 3D,
00:14and finally we will be orbiting the camera around the entire arena.
00:18Okay, first things first, let's take a quick look at this file. It's pretty
00:22much as it was before. Let's just run it.
00:24Now you can see that this is obviously in 3D, but it's not very exciting.
00:29It pretty much looks identical to the 2D version.
00:31So the first thing we are going to do is actually rotate the entire game around
00:36the X-axis and so it's lying flat on the ground.
00:39So at the moment in the XY plane and we are going to move it into the XZ plane.
00:42I am at the last version.
00:43We are actually calling singleRender every frame as part of the game move now.
00:50So we are managing when that render occurs.
00:53It's usually a good practice to do this so you can make sure you know exactly
00:56when the render cycle happens within your game logic.
00:59Okay, so let's scroll down to look at the part which sets up our 3D objects.
01:04We are creating an arena, two bats and a ball, and adding them into the scene.
01:10We want to rotate all of these things around.
01:12The easiest way to do that is to create an empty DisplayObject3D.
01:16We are going to call it gameContainer, and just like the Flash 2D display object
01:22hierarchy, we can add children to a Papervision DisplayObject3D.
01:27That's what we are going to do here.
01:28The base DisplayObject3D class has no geometry and no 3D content whatsoever.
01:33It's just an empty container that you can put things in, and that's great
01:37for what we need now.
01:38So now, instead of adding these objects into the scene, we are going to add them
01:42into the gameContainer.
01:47But of course, we mustn't forget to add that container into our scene.
01:53And then finally, we are going to rotate that gameContainer around the X-axis.
01:57We could do this with pitch, but this time we are going to use the rotationX
02:00property of the DisplayObject3D.
02:04We are going to set that to 90 degrees.
02:05Using the rotationX property allows you to set an arbitrary value for the
02:11X-rotation as opposed to pitch, which is relative to where it currently is.
02:15So let's take a look at this now.
02:17So you can see that now it's not ideal.
02:21We are looking completely to the side onto the game arena, which looks very, very
02:25strange. You can't really get an idea of where things are.
02:28I am just about managing to play it but I need to adjust.
02:30So the other thing that you will notice is that the bats and the ball are kind
02:35of split by the arena and I'd rather they sat on top of the arena.
02:40So let's just look at fixing that first.
02:41So normally, to move the arena down we'd expect it move it along the Y-axis.
02:46So let's do that now.
02:47Remember that Y is up so if you want to move it down, we give it a negative value.
02:51We are going to move it to -8. Remember that the bats and the ball are
02:56both 16 pixels high.
02:57So if you move it down by -8, that should make a clear half the height of those
03:02objects making it here underneath.
03:05When we run this, we will see that it's not all as it should be.
03:08In fact, nothing has changed at all.
03:09So let's figure out why that is.
03:13Now, if you remember, we have actually put that arena and all of the objects
03:18inside the gameContainer and the gameContainer is rotated, which means that
03:22all the objects inside it along with their local coordinate systems will also be rotated.
03:27If you remember how the game was before we rotated it, it was on an XY plane.
03:33So if you wanted to move the arena to underneath where they are now, it would
03:37mean at that coordinate system we would push it back into the Z-axis.
03:42So that's what we will do now.
03:43Instead of setting the Y-position, we are going to adjust the Z-position and as
03:47we want to push it away from us, which would be right when the game is in the XY plane,
03:51we are going to adjust the Z value and give it a positive value of 8.
03:56That is into the screen.
03:58So now what we have done is if you imagine the game as it was in the XY plane,
04:02 we have pushed the arena back into the screen to be behind the paddles and the ball.
04:08Let's just save that fixed step.
04:10So now you can see that the arena itself is slightly lowered down than the paddles.
04:15So by figuring out which coordinate system the arena is now in, we can
04:19make those adjustments.
04:20It can get very confusing but hopefully, with a bit of thought, you can work it out.
04:26But of course, that wasn't a very interesting looking view. We are still looking
04:28at it very much side on.
04:30So what we are going to do now is actually lift up the camera so we can see more of our arena.
04:35As we are adjusting the camera Z- position here at the top, we might as well do
04:40this here as well. Although if this is a final project, we would probably
04:45expect that setup to go in a different method, but for now, it's fine.
04:48We are just going to lift up the camera by adjusting Y-position, and remember
04:52the coordinate system is Y up, so we are going to give it a positive value.
04:57Let's try 500 and see how that looks.
04:59So now we are looking down on our arena and it's much more playable now.
05:05We can actually see what's going on.
05:08And remember that because the default camera in Papervision is a target camera,
05:12and the default target for that target camera is an empty DisplayObject at 000.
05:15It means that as we have lifted up the camera, it is then pointed downwards to
05:21look at the origin in our scene.
05:23Also notice that because our bats and the ball are all colored in with one color
05:28of green, they don't look very solid.
05:30And remember in the Cubes in the Skybox chapter, we learned how to
05:35apply different colors to each side of the cube to make it look more three dimensional.
05:38So let's do that now.
05:39Let's take a look back in our Square class, and remember this is the base class
05:44that the bat and the ball both extend.
05:47So if we add different colors to this material's list, that should propagate
05:50through all the classes that extend this.
05:52So I am going to add a new material to this material's list.
05:56I am going to set this material for the bottom of the cube.
06:00I am going to make that slightly darker green, and I am going to apply that
06:06to the bottom face.
06:07Then we will add another material for the left-hand side, another colorMaterial,
06:15this time fairly green.
06:16Then I am going to add another material for the right-hand side.
06:27Then finally, I am just going to make the default material a little bit darker.
06:31So we have specified colors for bottom, left, and right and all the other sides
06:36of the cube ball default to the all value.
06:38Let's take a look and see what difference that makes.
06:41So now you can see that our paddles and our ball both look a lot more three dimensional.
06:47So now we have learned that by putting all of our game elements into a container
06:52and then adjusting that gameContainer, we can convert our ping pong game from
06:57the XY plane into the XZ plane.
Collapse this transcript
Orbiting the camera
00:00In this movie, we are going to learn how to rotate the camera around in an orbit.
00:04So it's going to be orbiting around our game arena.
00:08If you wanted to do this with math, it would be pretty tricky.
00:10You would need some trigonometry to work out the position of the camera as it spins around.
00:15I am going to show you a really simply technique for doing that.
00:18But first, I am just going to add a method that initializes the camera before we
00:22get started in a moment.
00:24See here I am adjusting the camera in the constructor but I am just going to
00:27break that out into a method called init3d.
00:30I am going to delete these lines of code for now because we no longer need those.
00:35And if I scroll down to the bottom, let's define that function.
00:38So first of all we are going to set a position of our camera.
00:45And the Y-position of the camera, lift it up.
00:48We are also going to adjust the field of view of the camera.
00:51So it's not quite a wide angle. It's a bit more zoomed in.
00:54Let's take a look as this.
00:58All right, so it's a bit better.
00:59We have got a slightly more zoomed in view.
01:01So our game appears a little larger.
01:03Now before we move on to the bit of code that actually starts our camera
01:07orbiting, I just want to add some more segments into each one of these lines.
01:11The reason I would want to do that is to avoid what's known a Z-depth conflict issues.
01:16By default, Papervision will sort each of these lines dependent on that
01:20average Z-position.
01:22So of course, with these lines, the average Z-position is right in the middle of
01:25the stage, which means that those lines will be rendered in front of the paddle
01:29and the ball when it's in the back half of the arena.
01:32So let's just take a look at how we could fix that.
01:34It's very, very simple.
01:35Let's go into our Arena class, where we are calling the addNewLine function here.
01:41We are going to call the addNewSegmentedLine.
01:45This is almost identical to the addNewLine method except there is a second
01:49parameter, which is the number of segments.
01:51We are going to split that line up into-- let's call it 20 segments and let's do
01:56the same for the other two lines.
02:01Now you might not notice too much difference in this yet but if we started
02:05moving the camera around without doing this, you might see that the lines
02:09sometimes pop in front of the bat and the ball. Okay.
02:13So now we have sorted that out. Let's go back into our PingPong3D document class
02:18and add a new function that updates the camera position.
02:21We are going to call that method in the game loop just before we render the
02:25scene and of course, now we have to define that method.
02:34So what we are going to do now is use a very simple method for orbiting the
02:37camera around an object and I first heard of this method from John Gordon, one
02:42of the Papervision team members, and he is excellent at finding these little
02:45workarounds to make it a lot easier to do these kind of updates.
02:49So here is what we do.
02:51The first thing is we move the camera into the center of the Papervision
02:55coordinate system, which is right in the middle of the arena, at the origin 0, 0, 0.
02:59So camera.x = camera.y = camera.z which is all set at 0.
03:07So we have moved the camera into the middle of the screen.
03:11Now we are going to rotate the camera so it's looking slightly down.
03:15Rather than using the pitch method, we are now directly setting the rotationX
03:19property of our camera.
03:21This means that we can set that rotation value to an arbitrary value, rather
03:25than using pitch, which just rotates it from where it is at that time.
03:30So it's relative rotation.
03:31So we are going to set the rotationX to be 35 degrees.
03:35So it's looking slightly down.
03:36The next thing we do is add one to the rotationY.
03:41So we increment it there with that double plus and then we move the camera backwards.
03:46I am going to move it back 700 units.
03:50Now, as we are moving the camera's rotation around freely, we need to make sure
03:54that it's no longer acting as a target cam and the way to enable free movement
03:58in a camera is by setting its target to null.
04:02This means that we now have full control over our camera.
04:04So let's just explain what's happening here.
04:07So we are moving into the center of the arena.
04:09We are setting the rotationX.
04:09So we are looking slightly down.
04:12We are adding one to the rotationY.
04:14So we are rotating one degree around the Y-axis and then we are moving backwards.
04:20Now all of this happens before we call the Render command so you don't actually
04:24any of this camera movement.
04:25All you see is the view from the camera after it's finished, which means that
04:31we are going to move forward, rotate around, and then move backwards a little
04:34bit more every frame.
04:36Let's just take a look at that.
04:37So now you can see we are rotating freely around our game.
04:42Now of course, it actually makes the game pretty difficult to play but
04:45that does not matter.
04:46This is just a little demonstration of this technique and it can be really,
04:50really valuable not only for orbiting the cameras but also from arranging your
04:543-dimensional display objects.
Collapse this transcript
Placing the 3D game in an outer space environment
00:00So now we have got our 3D PingPong game all up and running, let's add a reflection to it.
00:05Because obviously, all projects are at least 25% better with a reflection, or at
00:11least that's what I think.
00:13So there is a really handy object in Papervision and it's a type of BasicView.
00:18But instead of rendering the scene once, it also renders the scene upside-down
00:22as though it was reflected off the surface of the ground.
00:25It couldn't be easier to use.
00:26You just literally replace BasicView with ReflectionView.
00:30Let's just take a quick look at this.
00:34Now obviously this doesn't quite look right.
00:38This is because by default the reflection is at Y-position of 0.
00:42As the arena lines are actually below 0, it means that the reflection is going
00:46upside-down and appearing on top of the reflection.
00:49This is an important thing to bear in mind.
00:51The ReflectionView isn't smart enough to know what's under the ground and what isn't.
00:56So you need to make sure that all of your objects are over the ground.
00:59Also, as the surface of the reflection is exactly half-way though the bat and
01:05the ball, you don't see any reflections on those either.
01:07The reflection is getting obscured by the actual object itself.
01:11So the way to fix this is to change the surface height of the reflection so that
01:15it's underneath those objects.
01:17I will show you how to do that.
01:18So, in the method that initializes the 3D I will scroll down and find it.
01:23We are going to move the surfaceHeight of this ReflectionView down to -16.
01:31That should be underneath those objects.
01:33So let's take a look at our reflection now.
01:35So you can see now that our reflection is the exactly where you want it to be
01:39and those objects look like they are skidding across an incredibly shiny surface.
01:45There are some other useful features of the ReflectionView.
01:47You can actually change how the reflection is adjusted and by default, it just
01:53automatically makes it a bit darker, but you can actually adjust that yourself
01:58using setReflectionColor.
02:00setReflectionColor takes redMultiplier, greenMultiplier, blueMultiplier,
02:04and the red, green, and blue Offsets.
02:06Those behave in exactly the same way as a traditional Flash colorTansform objecs.
02:11But we are not going to do that now.
02:13We are happy with the default setting. So let's move on.
02:14Now, just for fun, let's try something here.
02:18We are going to replace the ball with our Earth object from before.
02:21If we drill down into our package here, I have already made an object called
02:26Earth that's designed especially for this use.
02:28Notice that as Earth extends Ball, it means that we can freely replace it in our
02:34game and we won't get any problems there, because the Earth object will inherit
02:38all the functions of the Ball that we need.
02:40So here is the same stuff as we had before where we were making the Earth.
02:44It creates the shade and the light, it makes the sphere, maps the Earth
02:48bitmap material onto it.
02:50There is only one extra thing here from the Earth that we have before and it's
02:54this little bit of code here.
02:57What this does is it rotates the sphere around the Y-axis in the direction that
03:00it's moving and then it adds 24 degrees to the X rotation every frame.
03:06This means that no matter which direction the Earth is rolling, it will always
03:09look like it's rolling along properly rather than skidding across the floor.
03:14So now let's replace the ball in our game with the Earth.
03:16We need to find initObjects. Scroll down here.
03:22This is where we are creating the ball.
03:23So instead of the Ball, let's make it an Earth.
03:25Make sure that's imported.
03:29So now we have the Earth rolling around instead of a ball.
03:33But of course, the Earth doesn't entirely belong on a table tennis table.
03:36So let's go one step further and put it in space.
03:39Now I have created here an object called Skybox.
03:43Obviously, we covered Skyboxes in the earlier chapter, but this time we are
03:46creating a cube object that sets up the Skybox for me.
03:50The only difference with this and the Skybox that we used before is that in
03:54the constructor for the cube we are specifying that we don't want a bottom side to this cube.
03:59So the bottom of the cube is left open.
04:01We are also moving the cube up so that it doesn't go through the floor.
04:07Now what we need to do is add this into the game into the initObject method.
04:10And we will just add it into the scene here.
04:15I will now create a new Skybox.
04:19Let's take a look at that.
04:23So now we have learned how to add a reflection to our Papervision BasicView very easily.
04:29We have also looked at how we can replace the ball in our game with an Earth and
04:31add a Skybox into our scene.
Collapse this transcript
Controlling the orbit of the camera with the mouse
00:00In this movie, we're going to learn how we can click and drag the mouse to
00:04control how the camera orbits around our scene.
00:06So the first thing we'll do is actually edit an event listener to listen to the
00:10stage to see when it receives a MouseDown events.
00:13So let's just do that here, initListeners method.
00:17This time we're listening for a MouseEvent.
00:20It's a MOUSE_DOWN event that we want.
00:22We're going to call a method called mouseDown when we receive one of those.
00:27Likewise, we're going to now add a MOUSE_UP listener.
00:30We call a method called mouseUP when we get one of those.
00:36Before we define those functions, let's just add a few properties into
00:39our document class.
00:40First one is going to be a Boolean value to store whether the mouse is
00:47currently pressed down or not.
00:48We're going to set it by default to false.
00:51The next variable we're going to declare is the pitch and yaw for our camera.
00:56We're going to actually keep track of this in this example.
00:59We're also going to create a point object called lastMousePoint.
01:08This is going to be the Flash built-in point object.
01:11We're going to use this to store where the mouse was in the last frame.
01:17Now we set up these variables. Let's add those functions that are called when we
01:20receive the mouseDown and mouseUP.
01:21First one is mouseDown.
01:25Of course, it receives a MouthEvent.
01:27Although we're not using it. We still need to set it up.
01:30First thing we do in this method is set the isMouseDown Boolean to true.
01:34We are also going to store the current mouse position in the
01:40lastMousePoint object.
01:42So that's mouseX of this document, which is relative to the stage.
01:48So now we're going to define the mouseUP method.
01:53That's called when we receive a mouseUp on the stage.
01:54Again, just like before, add a parameter for the MouseEvent. This method is much
02:03simpler. All we need to do reset the isMouseDown Boolean to false.
02:08What this means is that at any time during our game loop, we can check to see
02:11whether the mouse button is pressed or whether it isn't, just by checking this
02:15isMouseDown variable.
02:16So now let's take a look at the code that updates the camera.
02:21So this is still as it was in the last exercise where we're just setting those
02:25camera.rotationX and Y values.
02:28But now we're going to use the mouse position to update those pitch and yaw
02:32values that we're storing and then we'll update the camera's rotation value
02:35dependent on those two variables.
02:37So the first thing is we set the camera's rotationX to be the pitch.
02:41Then we'll set the rotationY to be the yaw.
02:43But now we need to actually update those values, dependent on whether the mouse is
02:47currently clicked down.
02:48If it is clicked down, where the mouse is moving from?
02:51So let's check to see is the mouse down first?
02:57If it is, we're going to get the difference between where the mouse was in the
03:01last frame, and where it is now to adjust the rotation values.
03:05So we're going to add the difference between the mouse's last Y position and
03:10its current Y position.
03:11We're going to add that to the pitch, in other words, the rotation around the X axis.
03:16This means that if you click and drag your mouse up and down, the camera should
03:20orbit around the X axis.
03:22So how do we do that?
03:23It's just adding some code here. +=.
03:26The first thing we'd need to do is workout the difference between those two positions.
03:30So mouseY, the current mouse position, minus the last mouse y position.
03:37This value is in pixels and it could be that you move quite a few pixels between frames.
03:42That would represent quite a big rotation.
03:44So we need to reduce the effects of this rotation by multiplying that value by
03:49a small number, let's say 0.1, and add a couple of parentheses there, just to make
03:53it a little clearer.
03:55Now we're going to do the same thing for the yaw of the camera.
03:58But this time, dependent on the mouse's X position.
04:02Finally, we need to store the mouse's current position in the
04:06lastMousePoint object.
04:08So, lastMousePoint.x = mouseX, and lastMousePoint.y = mouseY.
04:17So let's see how that looks.
04:20So now you can see that we're side-on on the view.
04:22As I click and drag up and down, I rotate around the X axis.
04:26Actually, this doesn't seem to be working.
04:28I think we've maybe done something wrong.
04:29Let's just go back and check.
04:30We can't seem to rotate around the Y axis.
04:33Let's just check our code.
04:34Oh, yes, we didn't change that to yaw.
04:37So let's replace that and try again.
04:41So now you can see hopefully, as we click left and right and up and down,
04:45we can freely move the camera around the scene.
04:47So you can tell this is an incredibly powerful way to move the camera.
04:52Of course, most of your projects will be interactive.
04:54So any ways that you can think of to give the user more control overall 3D
04:58environment, the better.
05:00This is incredibly simple way to do that that.
05:02Now you might notice that as Papervision is rendering, some frames are harder to
05:06render than others, and the Flash Player might start it from time-to-time.
05:10This is a very subtle effect.
05:12But it means that as you're orbiting around the camera, it kind of digs this just a little bit.
05:17We found already sneaky technique to help with this.
05:20I'll show you it now.
05:21So in this version, we are just setting the camera's rotationX and rotationY
05:28directly to the pitch that we set it here.
05:31But what we want to do now is instead of moving straight to that point,
05:34we're actually going to move a percentage of the way towards it.
05:38This is a technique that I like to call real-time easing.
05:41I'll show how it works.
05:43As well as a pitch and yaw value that will be defined at the top, we're going to
05:47define a targetPitch and a targetYaw.
05:53So these will be the values that the camera wants to go to, and targetYaw.
06:01So the next step of this is if we go back to our updateCamera method, here where
06:07we're setting directly the pitch and yaw of where we want the camera to go.
06:10Instead, this time we're going to set the targetPitch and the targetYaw.
06:15So this is where the camera wants to be, but we're not going to move it straight
06:18there. We're going to move it a percentage of the way there.
06:21So how do we do that?
06:22Well, let's edit couple of lines of code here.
06:25We're going to subtract the pitch from the targetPitch.
06:28This gives us the difference between the two.
06:30Then we're going to multiply that by 0.2, which means that we get 20% of the
06:36difference between the two.
06:37Then finally, we're going to add that value to our current pitch.
06:40The way we do that is by adding the targetPitch-pitch multiplied by 0.2 and the
06:49same for the yaw. -yaw multiplied by 0.2.
06:55So now instead of directly going to that position, we should only go 20% of the way there.
07:01Now of course, you'll realize that that means that you will eventually get
07:04there, or at least very close to there.
07:06Let's just see what that looks like.
07:08So now when we click and drag, you can see the movement of the camera
07:12is completely smooth.
07:14This is a really, really useful technique, and we use it all the time.
07:17It just really helps to give you 3D projects that real sleek smooth feel.
07:20There is more information about real-time easing on my blog.
07:25It's probably worth checking that out.
07:26There is also some methods to get a kind of springy ease, which we're going to
07:30be looking at in later chapters.
Collapse this transcript
6. Viewport Layers
Introducing ViewportLayers
00:00In this chapter, we're going to be looking at viewport layers.
00:05Viewport layers are an incredibly useful feature of Papervision3D.
00:07They can solve all kinds of problems, and give you extra features that you
00:10wouldn't normally have.
00:11Now you might remember that Papervision3D uses a painter's algorithm to
00:15render its triangles.
00:17What this means is it calculates which triangles are in the back, and which
00:20triangles are in the front and then it draws them all one-by-one starting from
00:24the back, and going to the front.
00:27This means that all of the triangles are just draw and using Flash's 2D drawing
00:31API, which means that they are all bundled into one Flash container sprite.
00:36Now, this is obviously a very optimized way to render triangles.
00:39However, it does make things a little bit limiting, especially if you
00:42then want to add blend modes, alpha channels, or filters to specific groups of triangles.
00:48So that's where viewport layers come in.
00:49Let's take a look at this first example.
00:52We have two spheres, each with a slightly different color, and they're inside
00:56this sphereParent, which is an empty DisplayObject3D.
00:59These two spheres are set slightly apart.
01:02One with an x position of -300, and one at +300.
01:06We're adding those into the parent DisplayObject and then adding the parent into the scene.
01:11Every frame via then rotating that parent around the Y axis.
01:15Let's just take a quick look.
01:16So there you can see our two spheres.
01:20Now you might have noticed that all of Papervision's DisplayObject3Ds have
01:25properties much in the same way as Flash DisplayObjects movie clips and
01:29sprites. They have properties like alpha.
01:32Also they have blendMode, and also filters.
01:36Let's just try setting one of these.
01:38Let's try making our first sphere transparent by giving it an alpha value of 0.3.
01:44That's 30% opaque. Let's take a look.
01:47Now of course, this looks exactly the same as before.
01:50This might be a surprise, but remember what I said before.
01:53All of the triangles are rendered into the same container sprite.
01:56It's very difficult to change the alpha if groups of triangles drawn with
01:59the Flash 2D drawing API and it's actually impossible if you're using a Bitmap material.
02:04So let's go back to our code. Why isn't this alpha value working?
02:07Well, the reason is because those triangles are just drawn straight into the
02:10main container sprite.
02:12However, you can tell Papervision to use its own container sprite, or its own
02:16viewport layer by setting the useOwnContainer flag to be true.
02:21So now let's take a look at our image.
02:23Now you can see the second sphere is now fully transparent.
02:27Now you might also notice that that sphere is always getting rendered on top of
02:30the other sphere and that's an important thing to remember too.
02:33Imagine in Flash if you have lots of shapes drawn with the 2D drawing API and
02:38then you put a movie clip in with them,
02:39the movie clip is always going to be in front of those shapes.
02:43That's exactly what's happening here.
02:45One of the sphere's triangles are all being drawn into the main container
02:48sprite and the other sphere is getting drawn into its own container sprite or viewport layer.
02:53So that viewport layer is always going to appear above the other triangles in that container.
02:58So let's give the other sphere its own container sprite too.
03:06So now you can see those spheres are properly sorted.
03:08Viewport layers are always sorted dependent on their average Z position.
03:13So let's see what else we can do with viewport layers.
03:15There are other properties of DisplayObjects that only come into play when you
03:20start using viewport layers.
03:21As I said before, they are blendMode.
03:24So let's make these spheres and have an additive BlendMode.
03:32The same for thesecond sphere as well.
03:34Just Copy/Paste that. Save a bit of time.
03:39So let's take a look.
03:40So now both of these spheres have 80% opacity.
03:43They also are rendered with the additive BlendMode.
03:46So you can see how they're merging together.
03:49Just like Flash's 2D DisplayObjects, you can also add a filters array to a DispayObject3D.
03:58In this case, we're going to just add a single BlurFilter to that array.
04:02Let's make it a little bit blurrier than the default values.
04:07We're also going to add the same array of filters to the second sphere.
04:14So now you can see that both of our spheres' filter properties, alpha properties,
04:19and blendMode properties are all now enabled, because we've set the
04:22useOwnContainer flag to be true.
04:25Now bear in mind that the useOwncontainer flag will only create a viewport layer
04:29for that objects during the render cycle.
04:31So before you've rendered the scene, that object will not have a viewport
04:36layer assigned to it.
04:37But once you've rendered it, that shape will have its own viewport layer and you
04:40can access that viewport layer through the DisplayObject3D container property.
04:46So now you know how to give DisplayObject3Ds their viewport layer to enable the
04:51alpha, filters, and blendMode properties.
Collapse this transcript
Using ViewportLayers to fix z-sorting problems
00:00So now we're going to look at how we can use viewport layers to fix Z depth
00:04sorting problems, which can be quite tricky.
00:06But as soon as you understand how viewport layers work, this should fix most of your issues.
00:11Now, I'm just going to take a look at this exercise file and talk you
00:13through what happens.
00:15You can see here there is a couple of nested For loops.
00:17These arrange several spheres into a grid.
00:19Then if we scroll down, you can see here we're also creating a plane by
00:23rotating it around the X axis 90 degrees, so it's actually on the floor.
00:27So let's take a look at this.
00:29Now, if you've ever tried to render your objects on top of a floor, you might
00:32have encountered this sort of problem.
00:34Let me just take explain what's going on here.
00:36Remember that Papervision sorts all of its triangles dependent on the average Z
00:40position of each point in that triangle.
00:43As the plane is only made up of two triangles, you can imagine that the center
00:46points of each of those two triangles are in a position in the middle of those
00:50triangles, which means that sometimes they appear in front of the average center
00:54point of each of the triangles in the spheres.
00:57So you can see this triangle here.
00:59The center point of this triangle would be around here.
01:01You can imagine that the spheres that would be behind it. The triangles within
01:05that sphere would have average Z positions of all their points, which would
01:09appear behind this average Z point of this plane's triangle.
01:13So let's look at ways to fix this problem.
01:16Now, first the easy way to fix it is as we're creating each sphere, we're going
01:21to set the useOwnContainer property of that sphere to be true.
01:27This means that as it's rendered, it's given its own viewport layer. Excellent!
01:31So this seems to have fixed it.
01:33But you might be confused as to why that's fixed it.
01:35Now, remember that by default Papervision just renders all of its triangle into
01:40its own container sprite.
01:41That's where the plane currently is.
01:43So we're rendering the two triangles within the plane in the main container
01:47sprite for our Basic View.
01:49Then each of those spheres has its own viewport layer.
01:51As a viewport layer is a container sprite of its own, it's always going to
01:56appear above triangles drawn with the drawing API.
01:59So this solution would work for most things, but you might find that you want
02:02more control over the order in which your viewport layers and your objects are rendered.
02:07So now let's try putting that plane inside its own viewport layer.
02:09So here is where we create the plane.
02:12Let's set the useOwnContainer property of this plane to be true.
02:18So now, let's take a look. Okay.
02:19So this might not be exactly what you expected.
02:21But remember that viewport layers are sorted based on the average Z position of
02:27each of the triangles within that viewport layer.
02:29This means that the average Z position for this plane is going to be right in
02:33the middle, which is going to appear in front of the average Z position of each
02:37of these spheres that are past the center point of the plane.
02:40So now what we need to do is set a specific Z depth for this plane's viewport
02:45layer, so we can force it to be rendered behind the other spheres.
02:51Now, the first thing that we need is a reference to this plane's viewport layer.
02:55But remember that because we're using the useOwnContainer flag, this means that
02:59a viewport layer isn't created until we've rendered the scene at least once.
03:04So I'm going to show you another way to set up a viewport layer.
03:06That means that we can create a viewport layer at this point and then do the
03:09things that we need to it.
03:11Now, there is a property of the Basic View object called viewport.
03:16Viewport contains the sprite where all of your 3D triangles are drawn.
03:19Now, there is a method of the Viewport object called getChildLayer, and it takes
03:25a property, which is DisplayObject3D.
03:28So we are going to getChildLayer for the plane.
03:31Now, you might realize that there isn't currently a viewport layer already set
03:34up for this plane, but what getChildLayer will do by default is it will look to
03:38see if that object has a viewport layer already.
03:41If it does, it will give you that viewport layer.
03:43If it doesn't, it will create one for you and put that object inside it.
03:48It also returns a reference to that viewport layer.
03:50So it means that we can now store that in our variable here called vpl, which
03:54is the viewport layer.
03:55I am going to set the ChildLayer of that plane to that value.
03:59You can see that we have a warning here.
04:03This is because we are already defining a variable called viewport layer up here.
04:05So we don't need to redefine that.
04:08So I'm going to just go ahead and use that variable.
04:11So now we've created a viewport layer for this plane and we also have a
04:14reference to that plane.
04:15There is a property of a viewport layer object called forceDepth.
04:19It's a Boolean that you can set to true.
04:22If you set this value, it means that this viewport layer is no longer sorted
04:27dependent on the average Z position of all its triangles.
04:30It will be sorted on a screen depth value that you give it using the
04:34screenDepth property.
04:35We're going to just give this a high number for now so we can ensure it's
04:38always going to be behind our spheres.
04:40Let's take a look at that now. Excellent!
04:42So this has fixed our viewport layer sorting problem.
04:47The viewport layer for the plane is fixed at a depth of 2000, which is always
04:50going to appear behind those spheres.
04:52This can be an incredibly useful technique, particularly if you're building a
04:56room with walls or a ceiling.
04:57You're pretty much always going to want to make sure that those walls and
05:00ceilings and the floor all appear behind your other objects.
05:04By putting those in a viewport layer and forcing its depth to be a high number,
05:08you're going to ensure that that is always in the background.
05:11Now, another benefit of using viewport layers is that you can add traditional
05:15Flash MouseEvents to each one of those viewport layers.
05:18Remember that under the hood, a viewport layer extends a sprite object, which
05:22means we can add MouseEvents to those objects.
05:25If we scroll up here to see the part where we're creating those sphere objects,
05:28we're going to stop using the useOwnContainer flag, because we want a reference
05:32to its viewport layer.
05:33So again, we're going to call the getChildLayer method of the viewport and pass
05:38in a reference to that sphere.
05:39Remember that that's going to create a viewport layer for our sphere.
05:42Put this sphere inside the viewport layer and return a reference to
05:46that viewport layer.
05:47Now we have that viewport layer, we can add the standard Flash
05:51MouseEvent listener to it.
05:53So again, that will be a MouseEvent, make sure it's imported.
05:57We want to listen for a MOUSE_DOWN event.
05:59We're going to call a method mouseDown.
06:04But if we set the buttonMode property of this viewport layer,
06:08it means that we're going to get the hand cursor appear when we mouse over that object.
06:12Now, you can see down here, I've already created this mouseDown function.
06:16It doesn't do anything at the moment.
06:18It just literally traces out a HELLO.
06:20So we can see that we've clicked on it.
06:22Of course in your projects you'd probably want to do something a bit more
06:24meaningful at this stage.
06:25Let's just see what that does.
06:27So now you can see as we mouse over each one of these spheres, we get the hand cursor.
06:32Also, as we click on those, the mouseDown method is called and we can see that
06:37it's tracing out HELLO here in the console.
06:39But by using Flash's built-in MouseEvent you get the benefits of enabling
06:44accessibility functions within Flash, and certainly for the work that we do for
06:48the BBC, that is very important.
06:50By having these MouseEvent listeners, we can now tab through those objects using the Tab key.
06:55If those buttons did anything, hitting the space would work on them.
06:59Now we've learned how to use viewport layers to fix Z depth sorting conflicts.
07:03We've also learned how we can add MouseEvent Listeners to each of those
07:07viewport layers.
Collapse this transcript
Selectively rendering viewport layers to save processor time
00:00So now we are going to learn how we can use viewport layers to save processor
00:04time by only rendering objects that have changed.
00:07Of course, by default Papervision has to clear the whole entire containerSprite
00:11and we draw every triangle from scratch every frame.
00:14Now, if only certain objects within that scene have changed, then there is no
00:17point in redrawing the whole lot.
00:19However, because Parervision uses the painter's algorithm, all of those
00:22triangles are bundled into the same containerSprite.
00:25This means that it's impossible to erase only selected triangles and only redraw those.
00:29You either clear the whole scene or you leave them all there.
00:32However, remember that by using viewport layers we are actually creating
00:36separate container sprites for each 3D object.
00:39This means that we can tell Papervision to only rendered the objects that
00:42we wanted to render.
00:43Let's take a look at this example.
00:45We create a sphere, adding it to the scene like before.
00:48We are also making a viewport layer for that sphere using the
00:52viewport.getChildLayer.
00:53Then we are creating a plane.
00:54Notice that this plane has 100 horizontal subdivisions and 100
00:57vertical subdivisions.
00:59This means for a hell of lot of triangles and it's going to extremely slow
01:02to render this plane.
01:03I won't really recommend using this number of subdivisions, but it's to prove a point.
01:07So let's go with it.
01:07We are moving that plane's Z value back into the screen.
01:10So it's quite far into the distance.
01:12We are also creating a viewport layer for that plane using
01:15viewport.getChildLayer.
01:16We are setting the forceDepth property to true so it's set always to be rendered
01:21as though it had a screenDepth of 2000.
01:23Then we are adding back to the scene.
01:25Here is the camera setup stuff that we have seen before.
01:28On the enterFrame function we are rotating the sphere around the Y axis.
01:32Now, let's just take a look at that.
01:33As there are an awful lot of triangles in the scene, you can see that this is
01:38rendering very slowly, with a frame rate of something like 2 frames per second.
01:41But of course, there is no point in re- rendering all of those triangles every frame.
01:44It's only the sphere's triangles that are actually changing.
01:48So let's look at how we can only update that singleRender layer.
01:52To do that let's look at what normally happens within a singleRender command.
01:55I'm going to Command+Click on this function, Ctrl+Click on a PC, to delve into
02:01our AbstractView, which is where our BasicView object expends to see how a
02:06singleRender works.
02:07You can see here it's calling the method onRenderTick, which is here.
02:11onRendertick calls the renderScene method of the built-in renderer inside a
02:15BasicView. Notice that renderScene has three parameters.
02:19The scene with all those 3D objects inside, the camera which is the position
02:23which we are looking at Layers objects from, and the viewport which is what
02:26contains the sprite where all of our triangles rendered.
02:29So now, let's go back to our Exercise Files.
02:32So we've seen that singleRender calls the renderer method renderScene, but
02:35there's another method within the renderer that we can use to any render specific
02:41layers and that is the renderLayers method.
02:43If I uncomment this line of code here, you can see it.
02:46So we're accessing the built-in renderer within BasicView and calling the
02:50renderLayers method on that object.
02:52renderLayers is almost the same as renderScene and it takes the scene,
02:55camera and viewport.
02:56But this fourth parameter is actually an array of viewport layers and we're
03:01using this square bracket shorthand to create a new array there.
03:04What this means is that we're no longer rendering the viewport layers for
03:08the plane in the background; we are just rendering the viewport layers with this Sphere in it.
03:12So let's take a look at this.
03:13So you're seeing that now there is a slight problem in that we are not
03:17rendering out plane in the background at all.
03:19So instead what we need to do is actually render the whole scene once and then
03:24we'll continue to only update the viewport layer for the sphere.
03:27We'll do that in the constructor when we are setting everything up.
03:31At the end of the constructor we are just going to call singleRender.
03:34So that makes sure that the entire scene is rendered at least once.
03:38Now, you can see that as we're only re- rendering this sphere and not the massive
03:42place in the background, our frame rate is now at acceptable levels.
03:46So this great as long as the camera isn't moving, but what if the camera does move?
03:49Well, let's take a look at the next example and we'll find out.
03:52viewport layers2b.as.
03:55Now in this example it's identical to the previous one. We are creating this
03:59sphere viewport layer in the Planes viewport layers, rendering it once.
04:02But now let's look at out enterFrame loop.
04:05It's little bit more complicated than before.
04:07What we are doing is that we're updating the camera's X position dependent on
04:11the mouseX within the viewport's containerSprite.
04:15Now, the reason we're getting the mouseX out for our containerSprite rather
04:18than from a document is that the containerSprite is centered in the middle of the screen.
04:22This means that we'll get a mouseX value which is at 0 in the middle of the
04:26screen and negative as we go left and positive as we go right.
04:29So this condition out here checks to see if the camera's X position is different
04:33from where the current mouseX position is.
04:36If it is different, then what we do is we move the camera to be where that mouseX is.
04:41So what we were doing is moving the camera left and right dependent on the mouse position.
04:45If the mouse is moved, then we call singleRender, which renders the whole scene.
04:50However, if we haven't moved the mouse, then we call the renderLayers function,
04:53which specifies that we only render the sphere's viewport layer.
04:56So this means that as I move the mouse left and right, the camera moves left and
05:00right and the whole scene is being re- rendered while that mouse is moving.
05:04However, when we stop moving the mouse only this spheres viewport layer is
05:08now being rendered.
05:09Let's take a look at this.
05:10So you can see as I move the mouse left and right, the frame rate is pretty low
05:14as the whole scene needs to be re-rendered.
05:16But when I stop moving the mouse, we are now a new re-rendering the sphere and
05:21the performance goes right up and the frame rate is back to acceptable levels.
05:25This is a really, really useful technique.
05:27I can't emphasize that enough. It's so important.
05:30The Flash Player doesn't like it if you are constantly giving it lots and lots
05:33work to do, but by making sure we are only re-rendering the whole scene when
05:37it's absolutely necessary to do so, it means that we give the Flash Player a
05:41little break and I always find that the Flash Player performance much better
05:45under those circumstances.
05:47So now we have learned how we can selectively render viewport layers to
05:50save processor time.
Collapse this transcript
Using ViewportLayers to create a separate, moving cloud layer for the Earth model
00:00In our Hello World chapter we combined two different BitmapMaterials to create
00:04the effects of the Earth with the cloud layer on top of it.
00:07Now, we couldn't move those clouds separately from the Earth material
00:11underneath because they were both being combined within the same triangles and in the same way.
00:15In this example, we are going to create two spheres, one with the clouds and
00:18one with the Earth.
00:19Then we're going to use viewport layers to fix the Z depth conflicts that we
00:22find when we have two objects very close to each other.
00:25We're also going to use those to add some nice filter effects.
00:29So let's scroll-down our Class here.
00:30So you can see we're creating an Earth Bitmap and a BumpMap and an Earth's
00:34Bitmap just like before.
00:36And we're creating an Earth's Sphere here and we're also creating a clouds
00:40Sphere with the cloudMaterial.
00:42Notice that the cloud's Sphere is slightly larger than the Earth's Sphere.
00:45We are adding them both into the scene.
00:48On the enterFrame I am going to actually rotate the Earth around the Y axis by
00:52-0.05 so very slow rotation.
00:55Now, we are rotating the clouds around the Y axis by -0.07, which is a little faster.
01:00We're also rolling the clouds as well.
01:03Now these are very slight subtle rotations but they're actually quite
01:06effective in the scene.
01:07Let's take a quick look at it.
01:09Okay, so you can see straightaway that we're getting Z conflict errors.
01:12As each of those triangles pop in and out from in front of and behind each
01:17other, now remember from previous examples this is because each triangle is
01:21sorted from its average Z position.
01:23So how do we fix this?
01:25Well, the first thing we could do is give each of those spheres their own container.
01:29So let's do that.
01:30With useOwncontainer and also one for the clouds Sphere.
01:36So let's take a look now.
01:41Okay, so that's mostly good.
01:43However, keep an eye open.
01:45See there, it flicked out of visibility.
01:49Now this is because the viewport layers are sorted on the average Z position of
01:53every triangle inside that object.
01:56Now, as these spheres are based in the same position in 3D space, in fact
02:01they're both at the origin 0, 0, 0,
02:03this means that the average position of all of their triangles are going to be
02:07very, very close to each other, and you are going to find very slight
02:11differences in those values causes one to jump in front of the other.
02:15In this example, a very simple way to fix this would be by moving the clouds
02:19Sphere forward a little.
02:20Let's just set its Z position in front of the Earth by giving a value of -20. That's towards us.
02:28Although that's not very much you'll find that that's enough to get around those
02:31very subtle errors as those two objects pop in front of each other.
02:36So now we have fixed the Z-depth conflicts.
02:38Let's look at adding some more effects to our objects.
02:41Well, the first thing I want to do is make the clouds a little more transparent.
02:44Of course, remember that because we have a viewport layer for our clouds,
02:49it means the alpha property of our clouds object will work.
02:52Let set the alpha value to 50% or 0.5.
02:54So now our clouds are a little bit more transparent.
02:59Finally, to give it that extra polish, let's add a GlowFilter to the Earth.
03:03Do that by setting the Earth's filters array to be a new array containing a new GlowFilter.
03:09Okay, and set the color of the GlowFilter to be a light blue to be like the
03:15atmosphere, let's say 55aaff. That should be bluish.
03:21And then we're going to set the alpha transparency of that Glow to 50% or 0.5.
03:26Then we're going to set the X and Y blur distance to 32.
03:29Now you might not know that all of the filters are optimized to the values
03:34that are a power of two.
03:35So 32 is always going to work better as a blur value than 31. Just a very useful
03:41tip there, not that widely known.
03:42We're going to give it a strength of 2 and the quality of 1.
03:46That's the default values for the GlowFilter, I am going to put it in a
03:49dynamically generated array using the bracketing shortcut.
03:51Let's take a look at our Earth and clouds now with the atmosphere.
03:56So now by using viewport layers we've created a much nicer effect on our Earth
03:59including in atmosphere.
04:00We have also enabled it so that our clouds can rotate independently of the Earth.
Collapse this transcript
7. Creating an Interactive Carousel
Introducing interactive carousels
00:00In this chapter we are going to learn how to build an interactive carousel.
00:04It's really common use of the Papervision to actually layout your photos and
00:07interact with them in your projects.
00:09So, we'll start with this simple interactive carousel where you can mouse over
00:12and make these planes flip around.
00:14We'll also be learning about real -time easing along with spring.
00:17You can see also that as we click on those they change color.
00:19So this will be using Papervision's built-in interactivity.
00:23Then we'll be taking a whole bunch of photos and putting them in our Carousel.
00:27We'll be doing this by importing our images from an SWC file.
00:31This is a really useful way of getting our assets outside of Flash Pro and into
00:35Flash Builder. And then finally we'll learn how we can use our custom made video
00:39material to apply a real- time video onto our 3D objects.
00:44So we'll take it step-by-step and each time we'll get it gradually more
00:47complicated until we have the final results.
Collapse this transcript
Setting up blank planes in a carousel
00:00So in this movie we are going to look at how we can create our carousel of planes.
00:05So that's a big ring of planes all round evenly spaced in a big circle.
00:08But of course, if we wanted to work out the position of each of plane, we would
00:12have to use some trigonometry and we 'd prefer to avoid that kind of thing.
00:15So I will show you a much easier now.
00:17Here is a fairly empty document class.
00:19We have just literally declared a few variables at the top here, the number of
00:23planes that we want to make, in this case 60, and also an empty DisplayObject3D
00:27that we are going to put all those planes in and this is where we create that
00:30DisplayObject and add it into the scene.
00:32We also are listening to the enterFrame event.
00:36We are calling singleRender every frame.
00:38But of course, we haven't put anything in that planeContainer.
00:39So let's create our planes that we are going to need.
00:43First of all, I am just going to declare a variable that we can use for this and
00:46I am going to create a ColorMaterial that we can use for all of the planes.
00:54And it's going to be a dark red.
00:59Now because we are going to be seeing the inside of those planes as well as the
01:02outside, we need to set the doubleSided property to be true.
01:08So now let's make the planes.
01:10I am going to create a For loop here.
01:12It's writing through a value between 0 and 60, or the number of planes that we
01:17stored above, and every time around the loop we are going to create a new plane.
01:24Pass it through the ColorMaterial. Give it a width and height of 40.
01:30We are going to have just one subdivision in both horizontal and vertical axes.
01:34So here is the clever bit about how we arrange these planes.
01:38For each plane, we are going to rotate it around a little bit more than the
01:41previous one until by the time we've got through all the planes we will have
01:44done a full 360 degree rotation.
01:47So let's figure out how much we have to rotate each plane by.
01:51Well, firstly, we divide 360 by the number of planes, which in this case will be 6 degrees.
01:57And 6 degrees times 60 is 360.
01:59So, by the time we get to the last plane, we would have done a full 360 degree rotation.
02:06Of course, we need to multiply that 6 degrees by i which is the gradually
02:10incrementing variable.
02:11So the first time around, i will be 0, which means that we won't rotate the plane at all.
02:15The next time around, where i is 1, we will rotate the plane around 6 degrees
02:20and so on until we do a full rotation through all the planes.
02:24So now we have learned how much we should rotate it by, we are going to move
02:26that plane forwards.
02:27Do you remember we had moveBackward command on the camera and every
02:32DisplayObject3D has the moveForward and moveBackward methods on them?
02:36So we can use those to just move any object in the direction that it's facing.
02:40Finally, we will add that plane to the planeContainer so that we can have one
02:45main container that contains all the planes.
02:48So let's take a look at that.
02:49So you can see that we have a big ring or planes.
02:51They are all evenly spaced, but of course, because their Y position is 0 and so
02:55is the camera's Y-position at 0, it means that we are looking side on those
02:59planes and I know that's a bit strange.
03:00So, let's lift up our camera.
03:02We are going to raise it up 300 units and also we are just going to move it a
03:08little bit closer than normal.
03:10Camera default position is -1000.
03:11So we are just going to move it to -900, get it a little bit closer. Excellent!
03:16So now you can see exactly how those planes are arranged.
03:20Now we have lifted up the camera.
03:21Remember that as the camera has got a target by default of an empty
03:25DisplayObject, 0,0,0, that means that we are looking into the center of
03:29that ring of planes.
03:30So, the next step is to get that ring of planes to rotate dependent on our mouse position.
03:36So we are going to yaw the planeContainer and the amount we rotate that around
03:46is going to be dependent on the mouse's X position.
03:47But rather than just getting the mouseX property of this document class, we are
03:52going to get the mouseX property of the viewport's containerSprite. Now remember that
03:57that's where Papervision renders all of the triangles.
03:59The benefit of getting the mouseX property of this object is that it's centered
04:03in the middle of the stage.
04:04In this case, that mouseX value is going to be between -400 and +400, which is
04:10an awful lot degrees to rotate around every frame.
04:13So we are going to multiply that by a very small number.
04:16In this case, 0.005.
04:19So let's take a look. Excellent!
04:21So now our carousel spins around.
04:23As I move the mouse left, it spins around more in that direction.
04:26As I move it right, it spins around more in the opposite direction.
04:29Finally, and just because we can, let's add a reflection.
04:34So remember like before, we are extending ReflectionView instead of BasicView.
04:38And that automatically gives us a reflection.
04:40But of course, the default position for the reflective surface is at a Y value of 0.
04:45So we are going to need to move it down so we can actually see the reflection of our planes.
04:50So let's just set the surfaceHeight here.
04:54Remember the surfaceHeight is a property of the ReflectionView.
04:57We are going to set it to -40.
04:58So that moves the surface down which means that we should be able to properly
05:03see the reflections on our planes.
05:05So now we have learned a really quick way to arrange things in a big circle
05:08using the moveBackward command.
05:09We are also controlling that ring of planes using the mouse and just for good
05:14measure we have added a reflection.
Collapse this transcript
Setting up interactivity in the carousel
00:00Okay, in this movie we are going to look at Papervision's
00:03built-in interactivity.
00:05Now in previous chapters about viewport layers we looked at how we can create
00:10viewport layers and add traditional mouse events to those layers.
00:12However, Papervision has built-in interactivity, so if you don't want to put
00:16your objects in viewport layers.
00:18It's actually an incredibly clever system. Every frame it fires out array
00:22dependent on where the mouse position is and it finds which triangles it
00:25hits, then it generates special Papervision interactive scene events which
00:30you can then listen to.
00:31So let's look at how we go about setting that up.
00:34There are three things that you need to do in order to get interactive scene
00:37events to fire on Papervision objects.
00:40The first thing you need to do is set the interactive property of the basic view
00:45in the constructor. So you can see the third prompt we are going to leave is its
00:47default, move on to the fourth which is interactive, again set that's true.
00:52So that starts to trigger Papervision's interactivity system.
00:56Secondly, we need to set the interactive property in any materials that you want
01:01to have interactions on.
01:02So this would be the interactive property of this material here.
01:05Finally, you need to actually add the event listeners to those objects.
01:11In this case, we are not adding it to the material we are actually adding it
01:14into this plane object.
01:15So let's just do that here after we make the plane.
01:18So we just add an EventListener in the same way that we add normal mouse events
01:22to a normal Flash 2D sprite. But in this case we are listening to an
01:26InteractiveScene3DEvent.
01:27Let's listen for the object's over event.
01:35This will fire when your mouse goes over the plane.
01:39And we can call a method called planeOver at that point.
01:43Now we are getting an error because we need to define that method. Let's scroll
01:46down to the bottom and declare that function here, and of course it would get an
01:54interactive scene 3D event passed into it.
02:00Now all we are going to do when we get one of these is trace out a message to
02:04the Console. Let's just see if that works.
02:08So here we have our carousel.
02:10I am just going to shrink that a little so we can see the Console.
02:13As I mouse over each one of those planes you can see in our Console that
02:17trace message coming up.
02:19So we are receiving an InteractiveScene3DEvent for each one of those planes
02:23as we mouse over it.
02:24Let's also listen for Mouse Out and Mouse Down events. But with the
02:29InteractiveScene3DEvents those aren't called Mouse Down and Mouse Out.
02:33They're called Object Out and Object Click.
02:36So let's just set up those listeners. I am just doing some copy-pasting and
02:40we'll call different methods for each one of those, which we will then go to define
02:44subsequently at the bottom of our document.
02:47I am just going to copy-paste this one because it's a bit faster.
02:49So planeOut and planeClick.
02:59Let's just check how that looks.
03:00So just shrink that again, we can see the MOUSE OVER and the MOUSE OUT events happening.
03:06So let's click on a plane. We can see that those click events are firing
03:11properly, excellent!
03:12So now we have learned how to use Papervision's built-in interactive system to
03:16listen out from Mouse Events when they account on 3D objects.
Collapse this transcript
Animating planes in the carousel with real-time easing
00:00In this movie we are going to look at how we can extend the plane object and add
00:04additional functionality to it.
00:06In this case, we are going to make them flip over and change color and we are
00:11going to make it do this when it receives a mouse event.
00:12First of all, let's just take a look at this document. It's pretty much left as
00:15it was in the last exercise.
00:17Except we have tied it up a little bit.
00:19The part which now makes the plane is separated out into its own method here,
00:24makePlanes, and we are calling that in the constructor for our class.
00:27We've also created a planes array and as we are making each plane we are now
00:32pushing each one into that array.
00:34So we have an array that contains all of the planes.
00:37We have also made a function called updatePlanes. Now we are going to use that
00:40to actually update each one of these newly extended plane objects.
00:44So first things first. At the moment we are currently making an ordinary
00:48type of plane. We are going to stop that. We are going to actually make one
00:51of our special objects.
00:52It's here in the directory called FlipPlane.
00:55We'll take a look at that in a moment, but for now let's just replace this plane
00:58object here with a FlipPlane object and of course the declaration for the
01:03variable up there should also be FlipPlane.
01:05Let's look at the parameters in this object. Well, that's nice and easy. There aren't any.
01:15Now the FlipPlane also takes care of its own material.
01:18So we no longer need to make a color material for it to use.
01:21So now let's take a look at that object.
01:24Okay, so this extends Plane.
01:27So straightaway we know that this object also looks exactly like a plane. It has
01:31all the same geometry as a usual plane.
01:33But interestingly, it sets up its own color material before it calls its own
01:38constructor passing through that material into the parent object.
01:41Here is the update function, which updates the animation for this plane.
01:45We'll look at this in a moment, but let's just scroll down to these methods
01:49here: over, out, and click.
01:51Now these are the methods that we will call when we receive Mouse Over, Out and Click events.
01:57We'll look at the over, we are going to set the fill color of the material to
02:01white, then we are going to set this property targetPitch to 180.
02:05Now you might remember in previous chapters my talking about real-time
02:08easing and that's what we are doing here.
02:10But instead of position value, we are actually easing a pitch value, in other
02:14words a rotation around the X axis.
02:17So let's take a look at the targetPitch object. We are declaring it up the top.
02:21We have currentPitch and targetPitch.
02:23So let's see how that relates to our update function.
02:26There are some bits here about the resetCounter and we'll take a look at that in
02:31a moment, but here is the bits to do with currentPitch and targetPitch.
02:33First of all, we are taking to see if those two things are different. If they
02:37are different it means that the currentPitch isn't currently set to where it's
02:41aiming to be i.e. the targetPitch.
02:43Remember like before, we are calculating the difference between the target and
02:47the current by subtracting one from the other, and then we are multiplying that
02:50by 0.1, in other words that's 10% of the difference, and we are storing that in
02:55this variable diff. Then we are adding that to the currentPitch, and then
02:59finally we are setting the LocalRotationX to be that Pitch value.
03:02LocalRotationX is a bit of legacy code. It's used to do something slightly
03:07different from the RotationX property of Papervision, but now it seems that
03:11LocalRotationX and RotationX are pretty much the same.
03:16Let's just scroll down to see what happens on that out.
03:18Well, we have this resetCounter, which is set to 100.
03:22Now if you look at the update function up here, we are checking to see if
03:25the resetCounter is greater than 0, then we are going to subtract 1 from the resetCounter.
03:31If the resetCounter is 0, i.e. it's counted down to 0 already, then we reset
03:36the flip and set the resetCounter to be -1 so we no longer do any of these conditionals.
03:42So these conditionals no longer return True.
03:45resetFlip, if we just drill down into that, it resets the material color and
03:50resets the targetPitch to 0.
03:51So that means it makes it want to return back to its original rotation.
03:56And then finally, we have the separate function here for when you click on the
03:59object, which sets the fill color of that material to be blue.
04:02So let's look at how we set that up in the parent class.
04:04So as in the previous example, we are still adding these InteractiveScene3DEvent
04:09listeners to the plane and calling these methods down here.
04:13But instead of just tracing those values, let's actually do something.
04:17So the first thing we need to know is which plane was rolled over and we can
04:21extract that out of the event.
04:23And there is a property of the InteractiveScene3DEvent, which is
04:27displayObject3D, and that's the object that was broadcasting the event.
04:31And we need to strict type that as a FlipPlane because we know that the only
04:34objects that we are using are FlipPlanes.
04:38And we are going to store that in a local variable.
04:45So now we have extracted that flipPlane out of the event, we are going to call
04:50the over method of that flipPlane.
04:55So that will call the over method of the FlipPlane, which sets its target pitch
04:58to 180 and changes the color of that plane.
05:01So want to flip over 180 degrees.
05:03So then likewise, I can just copy-paste this code to extract the FlipPlane out
05:07of these plane out events, and to call the Out method on that plane, and of
05:13course for a click we can do the same thing. This time with the click method of the flipPlane.
05:18Let's just see how that works.
05:20So now you can see the planes are moving around.
05:23When I mouse over it actually changes color, but it doesn't animate.
05:28That's because we haven't actually implemented the update function of those planes yet.
05:32So let's do that now.
05:34If we scroll up here, we'll find the empty updatePlanes function.
05:37So now what we need to do is iterate through each of the planes, using the for
05:44each loop and then call the update function on each one.
05:52So we are iterating through each plane in our planes array and calling
05:55the update function.
05:56So let's see how that works.
05:58So now we've got our planes are rotating around. Ehen we mouse over it, it does
06:02the real-time ease towards its flipped position.
06:05And of course after a little while the counter resets to 0 and the plane gets
06:09reset back to its original position.
06:11So I can mouse over each one of those. Let's test the Mouse Click event.
06:16So now I have clicked on that plane. It turned blue.
06:19So that's how the planes look when they do a real-time ease out, but let's now
06:23add springiness to that easing.
06:26The concept behind adding springiness to real-time easing is that we remember a
06:30little bit of how far the object moved in the last frame and apply that to the
06:34current frame as well.
06:36This means that objects tend to overshoot their target positional rotation and
06:40spring back into place.
06:41Implementing this can be easier. As well as the current and targetPitch we now
06:46also have a pitchVelocity.
06:47So now if we scroll down to the update function we can see that here is the bit
06:52that adds the difference between those two targets to the currentPitch.
06:56But this time we don't want to add that difference to the currentPitch. We are
07:00going to add it to the velocity.
07:01So pitchVel+=diff, and then we add that pitchVelocity to the currentPitch value.
07:08So instead of adding the difference directly to the currentPitch we are
07:11adding that difference to the velocity and then adding the velocity to the currentPitch.
07:15Now you might notice that with this bit of code, the pitchVelocity is just going
07:21to increase and increase forever and we get some very unpredictable results.
07:26So instead we don't want to remember the entire velocity from the last frame; [00:07:30.0 ] we want to reduce it every time.
07:32So with this line of code here uncommented, we make sure that the velocity is
07:36only 70% of what it was in the last frame.
07:39That means that it shouldn't get too springing out of control, but it should
07:42be nice and bouncy.
07:43So let's take a look at that.
07:44So now you can see as it flips over it actually overshoots a little bit and
07:49comes back and the same for when it resets.
07:52Creating a springing effect using this real-time easing method is really, really
07:56powerful. We use it all the time.
07:58But in this movie, we have learned how to extend our plane object and add this
08:02springing real-time easing and also reset after a certain amount of frames.
Collapse this transcript
Loading pictures and videos into the carousel using SWC files
00:00Now, we are going to learn how we can use an SWC file to load in
00:07our photos and embed those into our SWF and then apply those photos onto each of our planes.
00:12We are also going to look how we can actually create video material to play
00:15videos back on to each file planes also.
00:18Okay, first off, this is a slightly simplified version of the interactive one.
00:22So it's more like the earlier exercise in this chapter where we just arranged
00:26one of our planes in the big circle.
00:29You can see the code for that here.
00:30So it's all identical as far as putting the planes in the scene and
00:33arranging them goes.
00:34However, we have a new bit of information here, which is actually getting our
00:38photo from the SWC file and adding it to the plane as a movie material.
00:43We'll come to that in a moment.
00:46Let's just scroll up a little to this line of code here.
00:47var allPhotos and its of type AllPhotos = new AllPhotos.
00:53Now where is that class defined? I'll show you.
00:55We'll open the FLA in the fla folder here, Photos.fla, double-click that and here it is.
01:01Now, on the stage, it's one big movie clip and if I'll look inside that, there
01:06is lots of other movie clips inside it, and each movie clip has a bitmap inside it,
01:11a photo of California.
01:13Now, if we double-click out of that and move into the Library, let's just take a
01:18look at the definition for that AllPhotos movie clip.
01:19If we right-click on that and choose Properties, you can see that we are
01:26exporting this for ActionScript and we are giving it a class name of
01:29AllPhotos, which is great.
01:31But how do we then get that into our Flash Builder project?
01:35If we look at the Publish Settings for this file and then into the Flash tab
01:41and scroll down, you can see that this check booked here, Export SWC, is checked.
01:46What this means is that it will compile all of its classes into a compiled SWF file.
01:50That's what a SWC is.
01:52Now, it will put that in the same folder as it puts the SWF file so when we
01:55check the Formats tab here and see where it saves the SWF file, we know that the
01:59SWC will also go in this folder.
02:02I find that it's always safest to put the SWC and the SWF in s separate
02:05folder from your FLA.
02:06There has been a known issue with the exporting of SWC files when they are
02:10in the same folder as the FLA. So it's always much safer to just do that in a separate folder.
02:15So let's close this out and we'll publish this movie by hitting Command+Enter on
02:19a Mac and Ctrl+Enter on a PC.
02:22So that will export the SWF but it will also export this SWC.
02:26If we go back to Flash Builder, you can see in that SWC folder we have both
02:29the SWC and the SWF.
02:32And the way we reference that within our project is if we right-click on the
02:35project, select Properties > ActionScript Build Path and in the Library path tab,
02:41you can see that this SWC has already been added. But if it hadn't, we'd add it
02:45using either Add SWC or Add SWC Folder.
02:48In this case, we are going to add the entire folder.
02:50So any SWC folder that was in that folder would be integrated into our project,
02:56and the folder that we are using is called SWC.
02:58So you can see it's gone into that folder and found the photos.swc there.
03:02So now any classes that's defined within that SWC will be available to us in our project.
03:07Now remember in Flash itself, we set the movie clip AllPhotos to be exported for ActionScript.
03:13So that means we can now access and create that movie clip within Flash Builder.
03:17Now remember that each one had a photo inside of that movie clip.
03:20So we are going to create a plane for every one of those photos.
03:24So, instead of setting the number of planes manually, we are going to actually
03:28see how many children are within that movie clip and set the number of planes so
03:31that we can make one plane of each child inside that photos movie clip.
03:36Now, if we look at the loop that sets up the planes, we get the child movie
03:39clip out of the allPhotos movie by calling getChildAt.
03:42So, this will return us the movie clip of the depth that we specified with the number.
03:48So, by using i we are iterating through each one of those children.
03:51So, now we are creating a MovieMaterial out of that movie clip.
03:55We haven't looked at MovieMaterials yet.
03:56What it does is it turns a movie clip into a material that Papervision can use.
04:01You can see there are two more parameters after the movie clip itself,
04:04transparent and animated.
04:07Set Transparent to True if it's in a regular shape. Otherwise you will get a big
04:10square with your movie clip inside it.
04:12What happens in Papervision is that it converts that movie into a bitmap.
04:16Because it can't stretch movies onto triangles, it has to first convert it into a bitmap.
04:22The third parameter is whether it's animated or not.
04:24Now, use this very sparingly. In fact this should be set at False.
04:28If that set to True, then it means that that bitmap for the movie is actually
04:32updated every frame.
04:34So, obviously this is desirable if you are using an animation for a
04:37MovieMaterial, but if your movie is static, then there is no point in updating
04:41that bitmap every frame. Like before we are setting the double-sided property of
04:45the material and then we are passing that into the plane.
04:47What we now have is a ring of planes with each one of those photos on.
04:51Let's just take a quick look.
04:53So, now you can see that we have got each one of those photos and we are
04:56creating a MovieMaterial out of each one and applying it to each plane.
05:00So, that's one way of getting a movie clip onto a material.
05:03So, now we know how to get photos onto our planes, let's look at how we can
05:06get videos onto them.
05:08So if we look at the next file here, CarouselPlanes video.
05:13Now, this is identical to the example before. It's that we have of course added
05:17a reflection and this time instead of iterating through all our movie clips,
05:20we are not bothering of any of that, we are just creating one material and it's of
05:24type VideoMaterial.
05:25Now believe it or not, this isn't actually included in the Papervision library.
05:29There is a VideoStreamingMaterial as part of Papervision and that's the
05:32setup of material that is actually a streaming video from an FMS server or equivalent.
05:37But here is just a very simple material that I have created and it's here.
05:43It extends MovieMaterial and it places a video object inside it and it
05:48updates every frame.
05:49Now, if you've ever worked with video before, you'll recognize all of this code
05:53for setting up a video.
05:54So, I won't explain how that works now.
05:57So, let's go back to our class here.
05:59We are creating that VideoMaterial and the only parameter in that is the file name.
06:03This is an FLV that's loaded at run time, so it has to be in the same folder as
06:08the compiled SWF, in bin- debug, and you can see it there.
06:11So, now we are applying that VideoMaterial onto each one of our planes.
06:16Let's just take a look.
06:17So, now you can see by using this custom made VideoMaterial, you can apply your
06:21videos to your 3D objects very easily.
06:24We have also learned in this movie how to iterate through all of the movie clips
06:28within across inside an SWC and make materials out of each one of those.
Collapse this transcript
8. Creating an Interactive Grid of Photos
Introducing an interactive plane grid
00:00So here's the effect that we are hoping to accomplish in this chapter.
00:03It's a grid of photographs that move towards the camera as you move your mouse over them.
00:08You'll also notice that they've got a bit of springiness, using the real-time
00:12easing method we've used in previous chapters, and also that they get a bit
00:15brighter as they move towards the camera.
00:18So we'll build up this effect gradually, starting with a very ordinary grid of red planes.
00:23Then we'll add a reflection and make them a move towards the camera as your
00:27mouse gets near them.
00:29And then they'll get a little brighter as they move towards the camera.
00:32And also see there's a bit of spring there in how they move.
00:35Until we reach the final conclusion, where we have the full grid of photos
00:40getting brighter and springing around as you mouse over them.
00:43So let's get started.
Collapse this transcript
Making a grid of planes and moving the camera
00:00So we will get started by creating a grid of red planes.
00:03Here is most of the code to do that already in place.
00:06You can see that we are extending BasicView like always, we are making an Array
00:10of planes, we'll also specifying a number of columns and rows of the planes, and
00:14also the overall Width and Heights of the grid.
00:16If you look at the constructor for our class, we are setting the
00:19camera.z position to -500.
00:20We are actually making the array of planes and then calling the method makePlanes.
00:25Let's take a look at makePlanes here.
00:27So, we have two nested For loops, one for the rows and one for the columns.
00:32Each time we are making a new plane, with the plane red color material.
00:36Now, we are setting the plane's X position with this little bit of
00:39complicated math here.
00:40It's not that complicated once you start to break it down.
00:43We have the overall width of the grid then we are multiplying that by the column
00:47number that we are currently on.
00:48We are also adding 0.5 to actually make sure that all of our planes are
00:52centered in the middle.
00:53Then we are subtracting half the grid width, so that we know that the grid will
00:56be centered in the middle also.
00:58And the same goes for the planes Y position.
01:01Then we are adding that plane into the array of planes and adding the
01:04planes into the scene.
01:05So, let's take a look.
01:06So far so good. We have our grid of red planes.
01:10The first step of the effect that we want is to actually move the camera left
01:14and right as we move the mouse left and right.
01:16So, let's just implement that in our enterFrame function here.
01:20So, we are simply going to set the camera's X position relative to the mouse X.
01:25But not the mouse X from the document class. We are going to get the mouse x
01:29from the containerSprite.
01:30So, remember that that's the sprite that all the triangles are drawn into, and
01:33it's centered in the middle.
01:35So, we will have a value for our mouseX between -400 and +400.
01:39In the middle of the screen, it will be set to zero, and that's exactly what we want.
01:42So, let's take a look at that.
01:43Now, you can see that the camera's X position is dependent on the mouse's x
01:47position. Because we are using the default target camera, we'll always be
01:51looking back at the origin.
01:53However, I am not very happy with the camera is rotating.
01:56I'd rather that we saw more of the grid as we moved left and right.
02:00So, instead of just relying on the target camera to point towards the middle
02:04of the plane, we are going to actually manually update the rotation of the camera ourselves.
02:08So, in the constructor for the BasicView, let's pass in the CameraType.FREE.
02:13I am going to keep those parameters to the defaults and pass through a CameraType.FREE.
02:20This will ensure that the camera doesn't have a target and we are free to move
02:23the camera however we want.
02:24So, let's a look at that.
02:26so, now you can see our camera just laterally moves left and right, a very lateral movement.
02:31But we also want to be able to look back slightly on our grid.
02:34So, we are going to update the rotation ourselves.
02:37If we move down the enterFrame function here, let's add a rotation around the Y
02:42axis also dependent on the mouse's X position.
02:44So, we'll adjust the camera.rotationY and we'll set it to be again the mouseX
02:50relative to the viewport's containerSprite.
02:53Of course, this value will be in pixels and that will quite a large number so
02:58the rotation is going to be much, much too big.
03:00So, let's multiply it by a small number to reduce the effects of that rotation. Let's try 0.05.
03:08Now, you can see that actually we are looking in the wrong direction.
03:11I wanted the camera to steer slightly towards the grid, instead of it steering
03:14slightly away from it.
03:15So, instead of multiplying it by .05, let's multiply it by -0.05.
03:22This means that it should counteract the effects of the lateral movement some what.
03:26So, now you can see we are always looking back at the grid.
03:30You can see at the ends that the center of the grid isn't quite in the middle.
03:34So, I am just going to adjust that value a little bit more to .06.
03:37Hopefully, that should be-- yes, that's much better.
03:40Now of course, what could be more important than our beloved ReflectionView to
03:46add a shiny reflection to our scene.
03:50But of course we need to move the SurfaceHeight down.
03:52We'll do that in the constructor here.
03:55And I will move it sufficiently down so that it should be below all the planes. Let's try -400. [00:04:012.47] So, now we've got our grid of planes along with the reflection.
04:07We are also moving the camera laterally dependent on the mouse position. We are
04:11also angling the camera towards the center of the grid.
04:14This is the first step in the effect that we want to achieve.
Collapse this transcript
Adjusting each plane's z-depth according to the mouse position
00:00So, now we are going to take the next step in creating this effect and that
00:03is adjusting Z position of each of our planes dependent on the position of the mouse.
00:08So, this is pretty much the same as the last example.
00:11However, we also have created this method at the bottom called updatePlanes.
00:17Now, at the moment it's just doing some calculations, but it's not actually
00:20affecting anything right now.
00:21This updatePlanes method is called every frame just before we render the scene.
00:25We pass in the containerSprite's mouseX and mouseY position.
00:29So, now within the updatePlanes function we iterate through each of our planes
00:34and extract its house array here.
00:36This line of code here is calculating the difference between the mouse's X
00:40position and the plane's x position.
00:42The next line calculates the difference between the mouseY and the plane's y position.
00:47Now, bear in mind that we are actually comparing two different
00:49coordinate systems.
00:50The plane's X and Y positions are actually three-dimensional coordinates.
00:54The mouse's X and Y positions are two- dimensional coordinates relative to the
00:58stage or at least relative to the viewport.containerSprites.
01:01Naturally, I wouldn't expect those two coordinate systems to match up, but we'll
01:05look at adjusting that later.
01:09The next line of code is actually calculating the distance between those two
01:10points using Pythagorean Theorem, A2+B2=C2.
01:15Now, you don't need to necessarily understand how that equation works, but just
01:19know that by getting the square root of the sum of these two value squared, we
01:23are left with the distance between those two points.
01:26Now, we have the distance between them.
01:27Let's actually do something with that distance.
01:30In fact, let's adjust the plane.z position.
01:32In fact, let's just set it to distance and see what happens.
01:35Okay, let's debug this movie.
01:35So you can see that it's getting to be what we want, but it's not quite right
01:42and it's not quite right for several reasons.
01:44The first reason is that the mouseY position actually affects planes at the
01:49both when we are at the top and when we move the mouse down it actually adjust
01:52the planes at the top.
01:54Also, really I want these planes to come forward as the mouse moves over
01:58them, so you can very clearly see right now the differences between those two
02:01coordinate systems.
02:03One is that they are just on a completely different scale and the other is that
02:07they are inverted in the Y axis.
02:09The Y axis is very, very simple to fix.
02:12We can just literally multiply mouseY by -1.
02:14So, let's see what difference that makes.
02:19So, although the two coordinate systems are still completely mismatched,
02:23at least the planes at the top move forward as you move the mouse up.
02:26So, we fixed the problem with the inverted Y axis.
02:29So, let's see if we can get these coordinate systems to match up a little better.
02:32But just before we do that we are going to limit the amount that the planes can
02:36move along the Z axis.
02:38That's very simple.
02:39We are just going to do a check on distance here.
02:41If distance>150 then distance = 150.
02:47That means that our distance will never be greater than 150 and our planes will
02:53never get too far away from the camera.
02:55Let's just check that.
02:56So, now you can see the movement of those planes is far reduced.
03:00Although it's still a lot, it still continues to refine those values.
03:04Currently, that distance calculation is returning quite a high number.
03:08Now, I want to reduce the distance value that we get from that calculation.
03:12The simplest way to do that is by multiplying it by a number.
03:15In this case, we are going to try 0.4, which means that we'll get 40% of the
03:19distance that we used to have.
03:21Let's just see how that looks. Ah!
03:22So that's getting a bit closer to what we want.
03:25However, the mouse position is still not entirely aligned with the
03:29three-dimensional X and Y position of the planes.
03:32So, let's just see if we can add a multiply to those two mouse X and Y values.
03:37Just from looking at it I would guess that we need to increase that mouseY and
03:41mouseX value by a small amount, maybe by half.
03:44Let try increasing it by half.
03:46The way we do that, well, we are already multiplying mouseY by -1.
03:49Now, we are also going to multiply mouseX by 1.5.
03:55So, that will mean that it's 50% larger than it used to be.
03:58Of course, because, we are already multiplying mouseY by -1, if we multiply it
04:02by -1.5, it will have the effect of inverting it and also enlarging it all in
04:07the same line of code.
04:08Let's take a look at that.
04:10So, now our two coordinate systems seem to be much more closely matched.
04:14So, we are adjusting the plane Z position dependent on the distance from the mouse.
04:20We are also limiting the extent of that effect.
04:23Finally, we have totally matched up the mouse's X and Y coordinate system with
04:27the planes three-dimensional X and Y system, and we are ready to move on.
Collapse this transcript
Extending the Plane class to add animation to color and position
00:00So, now we are going to refine this effect even further to introduce scaling,
00:04spring, and brightness to each plane as we move the mouse over it.
00:09So, this exercise file is pretty similar to the last one, except we've
00:12abstracted out the plane object itself into a new class called SpringyPlane.
00:18So, if you look at the makePlanes functions, now we go through and instead of
00:22just making a normal plane, we create one of these special SpringyPlanes.
00:26So, let's just take a look at the SpringyPlane object.
00:28You can see that it extends Plane and it also passes a new ColorMaterial to
00:35itself in its super constructor.
00:36It also has an update function.
00:38So, remember before we actually maintained the update within the main document
00:43class. Now we've brought that into our SpringyPlane class.
00:46So, now if we go back to a document class, you can see the method that
00:50updates the planes.
00:51No longer does it have to manage all of that stuff itself. It just literally cause the
00:56update method on the plane and pass this through mouseX and mouseY.
01:00Don't forget, of course, we've adjusted those mouseX and mouseY values to be
01:04closer to the three-dimensional x and y position of those planes.
01:08Now, there is lots of stuff in the SpringyPlane class.
01:10Most of it is disabled at the moment so I'll just talk you through the simple stuff.
01:14It's all in this update function here.
01:16Now, this is the same code that was in the previous example but at the
01:19document class level.
01:21So, we are working out the difference between the planes x and y position and
01:24the two-dimensional mouseX and mouseY position.
01:26We are getting the distance using the Pythag, multiplying it by 0.4 to make it less extreme.
01:33Then we are limiting it so that the planes can never get further away than 150 units.
01:39Then we are setting that z value for our plane to the distance of -100.
01:44This brings us to where we were in the last example, but this time we have an extended plane.
01:49There are some more calculations here but they are not brought into play yet.
01:52So, if we run this, we should see it's identical to the last example.
01:55If we go back to our SpringyPlane, let's start looking at some of these other values.
02:00Well, the first thing we are going to do is add spring.
02:03So, you might remember in the carousel example how we added a real-time
02:07ease with the spring.
02:08So, this time, rather than just going straight to the z position, we are going
02:12to set this targetZ value and also like before we have a zVel value.
02:16So, that is used to create a little bit of momentum so it overshoots its targets.
02:23If we scroll down, we'll see the bit that deals with that.
02:25So, here instead of setting the z value directly, let's set the targetZ.
02:31If we scroll down to the bottom of this, here is the code that actually
02:34influences that spring.
02:35So, like before, we are just multiplying the Z velocity by 0.6.
02:39So, it's now 60% of how fast it was moving in the last frame.
02:44We are calculating the difference between where it wants to be and where it
02:48currently is, multiplying that by 0.3.
02:50So, it's always going to move 30% of the way towards the target except of
02:55course now we are not adding that directly into the z position.
02:58We are adding that to the z velocity and then finally we are adding the z
03:03velocity to the z position.
03:03Let's just have a look at that spring in action.
03:06So, now you can see as I move my mouse around, not only do the planes move back
03:11and forth, but they also spring around rather pleasingly.
03:14Okay, so now let's move on to the next stage of this effect.
03:17If we uncomment this line of code here, we are now adjusting the scale of our
03:24plane depending on the distance.
03:27So, again here is quite a scary calculation, but don't worry too much.
03:30What this means is we are converting the distance from a number in
03:34Papervision units to a number that is more suitable for adjusting the scale value of our plane.
03:40So, this means as the plane comes towards us, it will also grow.
03:43Let's just take a look at that.
03:45So, it's quite a subtle effect.
03:47You don't really know it's sitting that that much.
03:49But you can see that the distance between each plane seems to reduce as it comes forward.
03:52That's the effect of the scale there that you can see in action.
03:57So, finally and perhaps most complicated is how we adjust the color of this plane.
04:02So, let me just try and talk you through this.
04:04First of all, we divide the distance by 150.
04:08As our distance generally is a number between 0-150, this means that we will now
04:14have a value between 0 and 1.
04:16Then we subtract this number from 1.
04:18So, whereas before if we had a value of 1, we would now have 0 and vice-versa.
04:23So, this is the scary bit here.
04:25We are calculating a color register depending on that value. By multiplying it by
04:30the hex values 0x60 and then adding 9f,
04:34it means that we now have a value between the hex value, 60 and ff.
04:39So, if you imagine that that is now the red value for our color, you'll
04:43know that we have a red color that is between kind of quite dark red and a very bright red.
04:50But if we use this as an RRGGBB color, this number will be on the right-hand
04:54side representing the blue color.
04:56But we need it on the left-hand side representing a red color.
04:59So, we are going to do a binary shift, 16 bits, which shoves our two blue color
05:06values from the right-hand side all the way over to the left, turning them into
05:10a color value that is red.
05:12So, after all of that, we now have a color value between 600000, which is dark red,
05:20and ff0000, which is bright red.
05:24Then finally, we just have to set the fillColor of that material to this new
05:28color that we've created.
05:29So that was pretty hard going.
05:32Well, let's see it in action.
05:33Okay, so now we are getting much closer to our finished effects.
05:37We have the scaling in place, the movement, the spring and also this very
05:41pleasing brightness.
05:43So, now we are ready to move on even further to adding the photos into this grid.
Collapse this transcript
Loading images onto the planes and adjusting the brightness with a CompositeMaterial
00:00So, now we have our planes moving back and forth depending on the mouse position
00:04with a really pleasing spring scale effect and also brightness. Let's look at
00:08how we can actually add photos on to those planes.
00:11So, you'll see in this example, PlaneGrid3b, it's pretty much identical to the
00:15last example except that instead of using our SpringyPlane, we are using one of
00:20these objects, these custom made objects I'll show you in a moment, called
00:23SpringyPlaneMovieClip.
00:26It's identical to our SpringyPlane except we pass in a movie clip to apply on to that plane.
00:32So, here you'll see that we are constructing an allPhotos object and we are
00:35getting that allPhotos object out of this SWC file.
00:40So, this is the method that we are using to get our photos out of Flash Pro
00:45and into Flash Builder.
00:46We covered this in more detail in our carousel chapter.
00:49So, refer back to that if you want a reminder of how we did this.
00:52But this allPhotos is a movie clip that contains lots of other movie clips,
00:57which have our photos inside it.
00:59This time we are keeping a counter, which starts at 0, and every time we make a
01:04new plane, we'll increment that counter.
01:06This is just solely so that we know which child to get out of that allPhotos object.
01:10So, by getting allPhotos.getChildAt( counter), we know that we are getting one of
01:16those movie clips inside allPhotos one at a time and applying them into our
01:20SpringyPlaneMovieClip.
01:21SpringyPlaneMovieClip has three parameters.
01:25The first is the width of that plane, the second is the height of that plane,
01:29and the third is the texture.
01:32Now, the texture for this is actually a Flash display object.
01:34As we are iterating through all the allPhotos object, we should get movie clips
01:39for each one of those things.
01:40Notice here that we are also setting the width and height of that plane
01:44depending on the width and height of the movie clip that we are loading.
01:47So, let's just go into our SpringyPlaneMovieClip to see what's happening there.
01:52Notice we have a movieMaterial object here defined as a member variable.
01:57We are constructing that in the constructor of our SpringyPlaneMovieClip.
01:59We are making a movie material out of the texture that's being passed in.
02:05In this case, it will be one of our photo images and then we are calling the
02:08super constructor of our plane.
02:09Apart from that, this class is identical to the last one except that obviously
02:14it doesn't adjust the color of that photo yet. Aaain, we'll look at how to replace
02:18the brightness shortly, but for now, it's just making a photo.
02:21You can see that the spring and the scale is still in place but not the brightness.
02:28Now, adjusting the brightness on a BitmapMaterial, which is what the
02:33movieMaterial becomes, is quite a challenge.
02:35That's because you can't change the brightness of a bitmap as you are drawing a
02:39bitmap fill with the Flash 2D Drawing API.
02:42That's all is going on on in the head of Papervision.
02:44It's just actually taking those movie materials, turning them into a bitmap and
02:50drawing bitmap fills with them.
02:52But of course, we can't actually change the brightness of that unless we
02:55change the original bitmap and doing that would be really, really costly and quite difficult.
02:59So, instead, we are going to find another way to affect the brightness of these
03:02photos using a composite material.
03:05The way we are going to do that is by combining a colorMaterial with
03:08this movieMaterial.
03:09So, we'll just declare at the top of our document here.
03:18Let me go into and make that in the constructor for our SpringyPlane.
03:23So, the colorMaterial and it's just going to be a totally black colorMaterial.
03:32It's going to also be completely opaque at least for now.
03:35So, then we are going to make a compositeMaterial out of those two materials.
03:43We are going to combine the movieMaterial and the colorMaterial into one.
03:49Now, we are going to make sure that we added the movieMaterial first to that
03:58compositeMaterial and then the colorMaterial, because that makes sure that we
04:05draw those in the right order.
04:06What we are going to do is actually adjust the transparency of that
04:12colorMaterial as it gets closer to the camera.
04:15That will give the effects of the bitmap underneath getting darker and lighter.
04:18So, now I am passing in the compositeMaterial instead of movieMaterial.
04:24So, that's all good so far but now we need to actually adjust the transparency of
04:30that colorMaterial depending on its distance from the camera.
04:32So, if we scroll down here, you can see that we are calculating the brightness
04:36there depending on the distance divided 150.
04:38As the distance is generally a value between 0-150, we can use that as
04:44a brightness value.
04:45Then finally, all we need to do is adjust the transparency of that colorMaterial
04:51depending on that brightness value.
04:52We do that by adjusting the fillAlpha property.
04:58Let's see how that looks.
05:01So, we are close to the effect that we want but of course, the extentsof that
05:04darkness is much too extreme.
05:07We just want it to fade out a little bit in the background not quite as much as
05:10that but we are very, very close to getting what we need.
05:13So, if we look back at the SpringyPlaneMovieClip, we need to just adjust that
05:17brightness value before we apply it to the colorMaterial.
05:20At the moment, it's going from an alpha value of 0 to 1, which is fully
05:24transparent to fully opaque, but if we multiply it by 0.5, then it means it will
05:28go from the value between 0 and 0.5.
05:31So, the black colorMaterial will never be more than 50% opaque.
05:36Let's check this out now. Excellent!
05:37So now we've got our finished effects.
05:40You can see that we've got our brightness on each of the photos using the
05:44combination of the movieMaterial and the colorMaterial.
05:47We'll also have our plane scaling off as they move towards the camera.
05:51Finally, we have these really pleasing springy effects as they come back and forth.
05:55So, you can see now how we've combined many different features into one fairly
06:00sophisticated looking effect.
Collapse this transcript
9. Particles and Billboards
Introducing particles
00:00Throughout this chapter, we are going to be looking at Papervision's built-in
00:03particle rendering system.
00:05Now, when we talk about particles in 3D, we don't mean the scientific particles
00:09like protons and electrons. We are just referring to a method of rendering.
00:13How it works is that we take a three- dimensional vertex or point in space,
00:17we convert it into 2D and then we draw an image at that point.
00:21We can see in this example, we are just literally drawing a single pixel.
00:25So there is no scaling involved whatsoever.
00:27However, if you are not rendering pixels, you can render shapes that get larger
00:31and smaller as they get closer and further away from the camera.
00:34With the standard particle material in Papervision, you can render circles as
00:38well as squares, and as in this earlier example from the Hello World chapter,
00:42you can also use the particle system to render bitmaps.
00:45So notice that those bitmaps are drawn in that three-dimensional position after
00:49it's been converted to 2D.
00:49So we take that point, work out where it appear on the screen, and draw the
00:55particle at that position, of course taking into account how big that particle
00:59would be depending on its distance from the camera.
01:01So we just saw how we can use an image of a star to create a star field, but
01:05here we have as spherical image as our particle bitmap.
01:08By using a flat image of a 3D object in this way, we can actually save an awful
01:12lot of processor time.
01:13If you imagine how difficult it would be to render this number of spheres in
01:17Papervision, we find that we use this particle system a lot to save process at time.
01:22And this method of using a 2D image of a three-dimensional shape is sometimes
01:27known as Billboarding.
01:28Likewise, this type of particle is sometimes known as a Point Sprite.
01:32Later on in this chapter we will learn how we can create a series of bitmaps,
01:36each slightly blurrier than the last, to create this really smart looking
01:40depth-of-field effect.
01:42And here is a three-dimensional snow effect where we are adding simple physics
01:45to each particle to create the image of falling snow.
01:47We are going to be using this snow field in our later augmented reality chapter.
01:52But we are going to look in this chapter about how we can add some physics to
01:56our particles to create this really cool bouncing particle effect.
02:01So now we understand what that Papervision particle rendering system is,
02:04let's get started and see how we can actually put those particles in our projects.
Collapse this transcript
Using the Particle object and ParticleMaterials
00:00Okay, so now we know what the Papervision particle rendering system looks like.
00:04Let's learn how we can actually create our own particles ourselves and place
00:08them in our project.
00:10So here is the exercise file. Just like normal,
00:12we are extending basic view.
00:13At the top we are declaring a view called Particles.
00:16So the Particles is a special type of display object 3D that's only used to
00:20render particles, and it's this that we add into our scene.
00:22Here, we are embedding a bitmap that we will use later, but this is
00:25the important bit here.
00:26We are actually creating that particles object there, and we are defining
00:30a ParticleMaterial.
00:32This is just the basic ParticleMaterial that draws a simple shape for our particle image.
00:37We are setting first parameter to be white, the second one is the opacity of
00:41that particle, and as it's one that's 100% opaque, and the third parameter is the
00:45shape that we are going to render our particle in.
00:48That can either be a square or a circle.
00:50Then this final parameter is actually the scale factor for this material.
00:54We will talk a little bit more about how this ParticleMaterial scale affects
00:57how our particles look.
00:58But for now, we are just going to set that to 1.
01:01Scrolling down, we see that this loop here is iterating through 100 times and
01:06making a new particle every time.
01:08So we are creating our actual particle object.
01:11Bear in mind that this isn't a DisplayObject3D.
01:14So we can't add that directly to the scene.
01:16It can only be contained within a particles object.
01:19Here is the constructs for our particle.
01:21The first parameter is the material that we are going to use.
01:23The second parameter is the scale or the size of this particle.
01:26By switching the size of the particle to 0, as long as we are using a simple
01:30particle material, this means that our particles would be rendered as a pixel.
01:34And subsequently we are setting the X, Y, and Z position for that particle here
01:38with these final three parameters.
01:40This bit of code here will return a random value between -150 and 150.
01:45What this means is that our particles would be randomly placed inside a cubic area.
01:51Now, we have got our particle. There is nothing to do except to add it into our
01:54particles DisplayObject3D.
01:57Some simple set up stuff here.
01:58You've seen this already many times now where we are adding an EnterFrame
02:01listener and we are updating the particle's rotation dependent on the mouse position.
02:06Let's take a quick look.
02:07So this is actually rendering a single pixel for every particle.
02:10You might not be able to see that very clearly, because they are very small, but
02:13it's a very optimized way to render things and can sometimes be good for you if
02:17you are creating a star field.
02:18So now let's look at how we can use bitmaps for our particle image.
02:23And I comment that code out and uncomment this.
02:25Now we are setting up a bitmap particle material instead of the
02:28standard particle material.
02:30The bitmap particle material takes this as its first parameter, a bitmap, and
02:34this is a bitmap that we have embedded into our document just like before, up
02:38here using the embed directive.
02:42Second parameter there is a scale factor.
02:44So we can use this to adjust the scale that our particles are rendered in.
02:48This is really useful for bitmap particle materials, because by default this
02:52particle would be rendered at one pixel per Papervision unit.
02:56Now, as you can imagine some of these bitmaps might be quite large, in which
02:59case our particles will appear very, very large also.
03:02So, we can use this value to scale out bitmap particles down.
03:06These final two parameters are an offset value, which means that we can adjust
03:09the center point of our particle into the middle.
03:12The bitmap that we are using in this case is 64x64.
03:14So, by specifying -32 in each axis, it means that it offsets the position of our
03:20particle image up so that the 3D point for that particle is in the center of the
03:25image of the particle.
03:27Now, when we specify a particle size of 0 when using bitmap particles,
03:31our particle will be infinitesimally small, and you can't see it.
03:34So, let's set this to 1 and see how that looks.
03:36So, you can see that our particles are really, really much too big now and this
03:41is because every pixel in our image is rendered at the scale of one Papervision unit,
03:45which is much too big.
03:46So, let's adjust this by using the scale value of our bitmap particle material,
03:51and it's here, the second parameter.
03:53Let's make it 10% of what it was.
03:55So, that's a bit better, you could argue that they're a little small, but that's fine.
03:58It's an effect.
03:59So now finally we are going to look at the MovieParticleMaterial.
04:02The MovieParticleMaterial takes a Flash display object and converts it into a
04:07bitmap for use with our particles.
04:09The MovieParticleMaterial takes a display object as its first parameter.
04:14In this case, we are extracting a movie clip out of a compiled SWC file, just as
04:19we did in our previous Photo Carousel chapter.
04:22Let's open Flash and have a quick look at that image.
04:24Here we have the timeline for that movie clip and it's just literally flashing
04:28along with timeline like this.
04:30So, now we know what that movie clip is let's look at the next two parameters
04:33for this MovieParticleMaterial constructor.
04:36So the second parameter is a Boolean, which defines whether we are going to
04:39convert this movie clip into a transparent or opaque bitmap.
04:43If our movie clip is in a regular shape, then we should really set that to
04:46transparent to avoid having a big rectangular area all around our image.
04:51The finally parameter is an animated flag.
04:53We are going to set that to false for now.
04:54So, let's take a look at that.
04:56So, again, you can see that our particles are really, really huge.
04:59Unfortunately, there is no ways to adjust the scale of a movie particle
05:03material, but we can adjust the size of the particle.
05:05So let's make that 10% of what it was.
05:08So, now our movie clip particles are much smaller.
05:11So the final thing is to turn on animation for this MovieParticleMaterial and
05:15take a look at that!
05:16So, now what's happening is that the movie itself is updating every frame and
05:21the Papervision particle system is re -rendering that image into a bitmap.
05:25Bear in mind that this can be very slow.
05:27In this case, because we are reusing the same movie particle material,
05:30Papervision is smart enough to know that it only needs to update the bitmap once.
05:35However, if we were using a different movie particle material for every particle,
05:38this could really slow the process down.
05:40So, just watch out with that.
05:41So, now we know how to create our own particles objects, add particles to
05:47it manually, and we also know about all of the different types of particle material.
05:52We are ready to find out more interesting ways to arrange our particles.
Collapse this transcript
Arranging the particles
00:00So now we're going to learn how to arrange our particles in several different ways.
00:05So here is our exercise file. Pretty much the same as it was before, just
00:08putting our particles in at random positions.
00:11Let's delete this line, and uncomment this line now and what this line of
00:15code does is just like before, it creates a new particle with the
00:18particlematerial we're giving it.
00:20It gives the scale of 0, and I'm going to just make that a little bit larger.
00:23Let's make it 1 so that we know that our pixels will match our units, but of course,
00:28 then it's divided by 5 with this scale factor here from the material.
00:32Now these two parameters here define the X and Y position of our particle.
00:36We're actually using some math here which takes our I value and converts it into a
00:43grid of X and Y. So as I increments, we'll find that our X position increments by
00:4850 every time, but then because we're guessing i%10 this means that this value
00:53be reset back to 0 once we get above 10.
00:56So this means that our X value will be going up to 10 and then back to 0 and
01:01then up to 10 again.
01:02So then this next part actually increases the Y position of our particle
01:07every 10 particles.
01:09So this has the effect of arranging our particles in a grid.
01:11There is some fairly complex stuff going on there.
01:13So I recommend that you take the time to just study that in more detail,
01:17if arranging things using math is something that you're interested in.
01:19So let's take a look at that.
01:21So now you can see our particles are arranged in a grid.
01:25So let's look at more interesting ways to arrange our particles.
01:28I'm going to delete this For loop and uncomment this one.
01:32Currently, this is doesn't actually do anything except add 1000 particles all
01:36at the same position.
01:37What I'm trying to do here is arrange the particles randomly around the outside
01:41of this sphere, and I'll show you exactly how we're doing this.
01:44So, the first thing. We want to know how wide that sphere should be.
01:48In this case, our sphere is going to have a radius of 200 units.
01:52So then we iterate amount of 1000 times this bit of code here.
01:56The first we do is we're going to create a Number3D.
01:59A Number3D is a three-dimensional point, and it's one of that built-in
02:03Papervision objects.
02:04So using the Number3D constructively we are setting the X value of this Number3D
02:09to be the radius and the Y and the Z values to be 0.
02:13This means that this position is over to the right.
02:16Now the next thing we're going to do is rotate that value around the Y axis.
02:21There is a built-in method of the Number3D, which is rotateY.
02:27So that will rotate our Number3D around the Y axis.
02:30We're going to do that by a random around between 0 and 360.
02:34Let's just take a look at that.
02:36So now you can see we've 1000 particles all arranged in a huge ring.
02:41That's probably too many particles to actually have within that small space, but
02:45this is just the first step of where we're going.
02:47So now we're rotating it randomly around the Y axis.
02:49We're subsequently then going to rotate randomly around the X axis.
02:54But we're not going to go all the way from 0-360.
02:56We're only going to go from between 0-180.
03:00So if you imagine what this is doing is it's rotating a random amount around the
03:07Y axis between 0 and 360.
03:08So that's a full circle.
03:11And then it's rotating a random amount around 180 around the X axis, which is half a circle.
03:17And if you can visualize that, that should produce an entire sphere of particles.
03:22Let's just take a look, and here you have it.
03:24So by using a Number3D we can actually reposition our particles around the
03:29surface of this sphere.
03:30Now let's move on to the next file, scrolling down to take a look at this.
03:35It's almost identical to the one before, but this time instead of randomly
03:40positioning our particles, we're firstly creating a sphere.
03:44So, this is the same as the spheres as we've used before.
03:47So we're not actually going to place this sphere inside our scene.
03:50We're just going to use the points within the sphere to arrange our particles.
03:54So now we're actually to iterate through every vertex within this sphere,
03:59find the geometry for all of the DisplayObjects3D are stored inside a geometry object.
04:05Inside of that geometry object is an array of vertices.
04:07These are all the points that are within our DisplayObject3D.
04:11So using this loop we can iterate through each one of the points in the sphere.
04:15So then when we create our particle, we assign it a position that is relative to
04:20that vertex position.
04:21So we give that an X value that not just the vertex's x value, and so on
04:26with the Y and Z. This means that we're arranging a single particle at every
04:30point where there is a vertex within the sphere.
04:33Let's take a look at that.
04:34So you can see what we have our sphere full of particles and of course in this
04:38example we've also added a reflection.
04:40So now you know how you can manually alter the position of our particles to make
04:45some really interesting and creative shapes.
Collapse this transcript
Adding depth-of-field blur
00:00So now in this movie, we're going to learn how to create a Depth-of-Field
00:04Blur for our particles.
00:05So you can see in this photo that the candies that are closer to the camera are all
00:10out of focus, as are the candies as they go further away from the camera.
00:13And you can see there is an area in the middle where they are in focus.
00:16So this is usually caused by macro lenses and also zooming in on camera lenses
00:21usually extenuates this effect.
00:23By adding this effect to our particles, it gives it a really nice kind of analog
00:27feel, making it look a lot less computerized.
00:30So how would we go about implementing an effect like this?
00:33Well, remember that all of our particles, they are just bitmap fills on the stage.
00:37So we can't apply filters to each individual particle.
00:40I guess we could make several particle containers all with one particle in
00:44each and then give that particle's container its own viewport layer and add a
00:48Blur filter to that.
00:49But that would be really, really processor intensive.
00:52So you can see that adding a Depth-of-Field Blur to our particles is quite a challenge.
00:56The approach I've decided to take is to pre-create an array of bitmaps.
01:01Each bitmap slightly blurrier than the last.
01:03So let's take a look at that first step in the code.
01:06So here we're looking at Particles3.as. Let's scroll down.
01:10So far it's all pretty much identical to what we've had before.
01:13We're creating a Sphere DisplayObject3D.
01:15We're using that to arrange our particles.
01:18We're not passing any bitmap material to start with. We're just passing in a
01:22normal standard particle material.
01:23We're going to quickly discard that, so it doesn't actually matter too much what
01:27that is at this stage.
01:27We're going to scroll down to the bottom of this file, to the bit that
01:31creates the bitmaps.
01:33So we have this function here called makeDOFBitmaps, or make
01:36Depth-of-Field bitmaps.
01:38So first of all we create an empty array to store our bitmapMaterials in, and
01:42then we make a bitmap data out of the embedded asset called particleBitmap, and
01:47if we just look in our assets folder, I'll show you that one. It's here.
01:51It's this bead.png.
01:53So now we have our source image. We can now go through and create several
01:56bitmaps, all with varying amounts of blur.
01:59So what we have here is a for loop, where i is between 0-1, incrementing in 0.5.
02:04We're going to use this to decide how much blur there is on each bitmap.
02:08First of all, we'll determine the strength of that blur by multiplying i by 32.
02:13So this will give us a number between 0 and 32, and we're going to use that for
02:18the strength of the blur.
02:19So now we create a BitmapData that's just slightly bigger than our original bitmap.
02:23You can see here we're adding the bluramount*2 to the width and the height.
02:27This is to make sure that we have enough space around the original image to
02:30draw the blur into.
02:32So these next lines of code here creates a matrix that is then translated by
02:36the bluramount to make sure that our particle image is drawn in the center of our new bitmap.
02:41And then finally, we apply the Blur filter to that bitmap.
02:45You can see here we're using the applyFilter method of any bitmap data that
02:49requires a source bitmap, a rectangle for that filter to be applied into, the
02:53topLeft point for the rectangle, and then of course the actual filter itself.
02:57In this case, it's a BlurFilter with the set amount of blur that we've decided
03:02and the quality set to 6.
03:03This is quite a high value for the quality, but seeing as we're only going
03:06through this loop once, it shouldn't matter that that's a little bit more
03:10processor heavy than some of the lower quality settings.
03:13So the final step is that we create a BitmapParticleMaterial with that newly
03:17rendered blurred bitmap and we add that BitmapParticleMaterial to our
03:22bitmapMaterials array.
03:24So now we have an array of BitmapParticleMaterial, and the first
03:28BitmapParticleMaterial in that Array is completely unblurred and the last
03:32BitmapParticleMaterial in that array is very blurred.
03:35So let's see how we update our particles with those newly
03:39blurred bitmapMaterials.
03:42If we look at the enterFrame function, you can see now we're calling a
03:46function every frame called updateParticlesDOF or Depth-of-Field, which is
03:50this function here.
03:51Before we look any closer at this function, let's take a look at the first
03:55four values in our function.
03:57Now we have nearFieldMax and nearFieldMin. These values determine how close the
04:01particle has to be to the camera before it starts getting blurry, and these two
04:05values determine how far away it has to be from the camera before it starts
04:08blurring in the other end.
04:11So this diagram explains exactly the limits of that blurriness.
04:15So you can see the particles in the middle are completely unblurred.
04:18So their Z position is greater than the Maximum nearField and less than
04:23the Minimum farField.
04:25So particles within this area are completely unblurred.
04:27Now, as we move between nearFieldMax and nearFieldMin, we go from the minimum
04:32amounts of blurriness to the maximum amounts of blurriness.
04:35And if the particles are closer than the Minimum nearField than these are all
04:39equally blurry, and that's the most blurry they can be.
04:42And likewise on the opposite side. As we reach farFieldMin, we start to get
04:47blurrier and blurrier, until we reach farFieldMax, at which point we're at
04:51the maximum blurriness.
04:52Any particles beyond this point will also be that blurry.
04:56So let's take a look at that in code.
04:57So for this function that updates the particle's Depth-of-Field, the first thing
05:02we do is store the length of that array.
05:04It's useful to store the array of lengths upfront, especially if you're going to
05:07be accessing it regularly, because accessing the array length is surprisingly
05:11processor intensive, especially if you're doing it hundreds of times.
05:15So now we iterate through every particle in our array of particles.
05:19This first conditional determines whether the particle is closer to the camera
05:22than the Maximum nearField value, in which case it works out exactly how
05:27blurry it should be.
05:28And likewise, for the second conditional, that this one checks to see whether the
05:32particle is further away than the farFieldMin.
05:35So then we're clamping those values to make sure that our bitmapnumber is within
05:39the range of the number of bitmapMaterials in our array.
05:42So then finally, we set that particle's material to the BitmapParticleMaterial
05:47that is the right blurriness for that particle's Z distance from the camera.
05:52The only other thing to check out is this bit of code here, which rotates the
05:56particle's container along the X-Z plane, dependent on the mouse position.
06:01So let's take a look at our Depth-of-Field particles.
06:04So you can see this is a really nice effect.
06:06So I move the mouse forwards and backwards, you can see how those particles come
06:10in and out of range.
06:11Before we move on, we're just going to finally show you those particles
06:15arranged in a cube pattern.
06:18So instead of applying the particles to the points in a sphere, we're going to
06:21apply them to the points in a cube.
06:23So now we've learned how you can pre- create an array of BitmapParticleMaterials,
06:28each with a varying amounts of blur, and then apply those to each particle,
06:32dependent on their distance from the camera.
Collapse this transcript
Animating particles with physics
00:00In this movie I am going to show you how you can create simple physics
00:03simulation and add those to your particles.
00:06Of course, if we wanted a very accurate physical simulation it would be incredibly
00:10complicated and very processor-intensive.
00:13I am going to show you a really simple way to add physics to all of your particles.
00:16We will take it step-by-step.
00:18Imagine this ball is one of out particles and it's moving along the X axis
00:22four units per frame.
00:23If you've done any kind of animation and programming, this should seem
00:26pretty familiar to you.
00:27So we have an X position for our ball and then it's updated by its
00:31velocity every frame.
00:33So if we wanted to simulate the effects of drag, a really, really simple way to
00:37do this would be because just to multiply our velocity value by a number close
00:41to 1. In this case, 0.9.
00:44So you'll understand that our X velocity is reduced by a small amount every
00:48frame and it gives the effect that our ball or our particle is slowing down.
00:52As well as just in one axis this also works in two dimensions.
00:56Here we have a velocity X and a velocity Y, and we are multiplying them both by .9.
01:01Notice that this doesn't change the direction of our ball.
01:05It just literally slows down in the direction that it's going.
01:08So the next thing we can add is some gravity and to recreate that it's just by
01:12adding a small amount of the Y velocity every frame.
01:15Now in this example the Y axis is down in much the same way as Flash's 2D
01:20Coordinate System, but remember that in Papervision the Y axis goes up.
01:23So if we wanted to recreate a downwards gravity in Papervision we'd add a
01:27negative value to our Y velocity.
01:29Here is how to detect very simple collisions with the ground.
01:33Now again this isn't a very accurate method of collision detection, but it's
01:36perfectly fine for our uses and it's extremely efficient on the processor.
01:39So here is what we do.
01:41We check to see is our particle below the ground, i.e. we are checking its Y position.
01:47So if our ground is at 0 we check to see if our particle has gone below 0.
01:51If it has gone below 0 we set it to be at 0.
01:54So it looks like it's hitting the floor.
01:55And then we reverse the Y velocity.
01:57If you look at this math at the top of the screen here, you will see that we are
02:01multiplying the Y velocity by -0.6. That means that it will be reversed, but only
02:06with 60% of the speed that it was going downwards at.
02:09So if our velocity was initially going down at 10 units per frame, it would now
02:14be going up at 6 units per frame.
02:16So that works in 2D, but it also works in 3D.
02:19The only difference is that we now have X, Y, and Z positions and we also have
02:24X, Y, and Z velocities.
02:26We are applying drag to all of those axes, X, Y, and Z and we are still only
02:30adding the gravity to the Y axis.
02:33So now we have learned to apply physics to an object in 3D, we can now go ahead
02:36and add physics to our particles.
02:38So let's look at our exercise file Particles4.as.
02:43This is pretty much the same as the previous example except we are going back to
02:47the original method where we are placing these particles in a random cubic area.
02:52You might also notice that instead of making the standard particles object we
02:56are creating a physicsParticles object.
02:58Now this is a custom made glass that's here in our project folder.
03:01I will take you through that in a minute, but let's just continue down to see
03:04what else we've changed.
03:06Now you will notice that in this for loop here instead of adding a normal
03:09particle to our particles object we are adding a special PhysicsParticle,
03:13and again this is a custom class that we've defined here in our project source folder.
03:17The only other difference that we've got from the last example is that we are
03:20calling the updatePhysics method of our particles object.
03:23Now this isn't a normal particles object anymore.
03:26It's our special PhysicsParticle's object.
03:27So let's first look at the changes we've made to our physicsParticle to make it
03:33have physical effects.
03:34So I am going to Command+Click or Ctrl+Click on the PC into our class to
03:38check its definition.
03:39So you can see that our physicsParticle extends particle.
03:42That means that we can now add it to a normal particle's object just as though
03:47it's a normal particle.
03:48Notice also that our physicsParticle has velocity, which is a Number3D.
03:52So remember that's a three-dimensional point.
03:55We can use that to store our velocity for the X axis, Y, and Z axis all in one object.
04:01Then we have this property bounce.
04:02Do you remember in this slide that I just showed you we multiplied the Y
04:06velocity with this value when we detect a collision with the floor?
04:09Then we have a gravity value here.
04:11So this number is added to our Y velocity every frame, and of course because the
04:16Papervision coordinate system is Y up, by having a negative number for gravity
04:20it means that our particles will be drawn towards the ground.
04:23Here is the damping value and this is used to apply drag.
04:26So every frame we multiply the velocityX, velocityY, and velocityZ by this
04:31number and it has the effect of reducing the velocity, in much the same way as
04:36though there was some kind of drag on those particles.
04:38In the constructor for our physicsParticle there is nothing really going on,
04:41which is actually calling the superconstructor.
04:44If we scroll down further you will see the update function of our particle.
04:47This method is called to every frame to update the velocity and position of our
04:51particle depending on its physical attributes.
04:52See here there are also a few lines there to check a collision with the floor.
04:57So now we know a bit more about how the physicsParticle works. Let's look at our
05:01special physicsParticle's container that can manage those types of particles.
05:06So you can see just like our physicsParticle extended a particle object,
05:10our physicsParticle's container extends the particles container object.
05:14So this is just like the Papervision particles object except we are going to add
05:17a few more attributes to it.
05:19We have this property here, which is the position of the floor that we are
05:22going to use for the collision detection and then we have the updatePhysics method here.
05:27Again, this is called every frame.
05:28What this does is it iterates through every one of its particles and checks to
05:32see if it's a physicsParticle.
05:34If it is a physicsParticle, then it calls the update function on that particle.
05:38So now we've created our physicsParticle's container, we've added a number of
05:42physicsParticle objects into that container, and we are calling the updatePhysics
05:46method on that particles' object every frame.
05:49So let's just take a look at how that works.
05:50Okay, we are not seeing an awful lot of stuff here.
05:53There is the particle.
05:54So we are actually moving the camera around with the mouse.
05:57It seems that the particles are much too close to the camera.
05:59So let's move the camera back a little.
06:00So let's set it back a little further than the default of -1000.
06:04Let's check that out.
06:08Excellent!
06:10So now we can see our particles and they are bouncing up and down now due to
06:13their physical properties.
06:14So you can see that this simple physics simulation is an incredibly powerful
06:18tool that we can use to make some really sophisticated effects.
06:22We've only really scratched the surface of what's possible with this kind of system.
06:26If you are interested in particle systems, it's probably worth checking out my
06:29particle presentation from the last Flashforward Conference and that's here in
06:33the archives on lynda.com, and maybe you will be able to work out how to apply
06:37some of those effects into our new Papervision 3D particle system.
06:42So now we've extended the particle object to create a physicsParticle.
06:45We've created a new special type of particles container that can update
06:49those physics properties to create some really dynamic and cool looking
06:53particle effects.
Collapse this transcript
10. Augmented Reality with FLARToolKit
Introducing Augmented Reality and FLARToolKit
00:00So now we are going to look at making an augmented reality project using the
00:05FLARToolKit, which is an open- source ActionScript library, made by a
00:09Japanese guy called Saqoosha.
00:11So augmented reality is where you have one of these square markers called a
00:16fiduciary marker, and the web cam image is passed into FLARToolKit.
00:22And FLARToolKit actually analyzes that image, looking for this big thick black square.
00:27Once it's found it, it finds the corner points, figures out where they are in 2D
00:32and where they would be in the corresponding 3D space.
00:35So it converts that 2D square into its 3D coordinates.
00:38Once it has that information it can pass it on to Papervision and then we can
00:42actually create an object that shares that same space.
00:45So if I move my fingers away from this marker, you will see how that works.
00:48So you can see now that FLARToolKit is analyzing that image.
00:54It's converting that two-dimensional square shape into a three-dimensional
00:58rotation and translation.
01:01Then we can actually add those images and the models inside that container.
01:06So we will talk about how that works a bit in details in the coming videos,
01:10but this is a really, really cool effect and we've used it quite a lot in
01:14certain entertainment projects like those ones for Pet Shelter here in the US through Draftfcb.
01:21We are also working on a few projects for children for the BBC.
01:24So it can be pretty useful for those sort of fun type of projects.
01:30So if you've run the setup video in the introductory chapter, then you will know
01:35how to actually get these files into your projects.
01:37But the only thing to bear in mind is that this is actually licensed under a
01:43Commercial ShareAlike License, which means that if you want to use it in a
01:47commercial project, you need to actually make all of your code for that
01:50project open-source.
01:53If you don't want to open-source your project then you need to get in touch with
01:55Saqoosha and arrange to use a license.
01:58So now you know what's FLARToolKit is and what it looks like. Let's learn about
02:04how we can put that into our projects.
Collapse this transcript
Exploring the AR base application
00:01So now that we know all about augmented reality and the FLARToolKit, we are going to
00:04learn actually how we can build one of these projects for ourselves.
00:06Now, naturally it's a very complex code library. FLARToolKit can be pretty
00:11fiddly at its set up.
00:12But don't worry we've taken care of most of the complexity with this Alchemy base app.
00:17So don't worry if you don't have the Exercise Files, because this base
00:21application will be available to download as a free exercise file on the course
00:25page and also on my web site.
00:27So let's start just talking through a little bit about how this base application works.
00:32So we will scroll down there and you will see that this extends BasicView like
00:36all of our other projects, and then this first couple of lines of code here
00:40within the class actually embed the data file for the pattern marker.
00:43So there are two files that you need for these pattern markers. The first is
00:48this data file, which is here within the Assets folder, and then there is also a
00:54PDF of this marker image that you will need to print out if you want to work
00:57along with these files.
00:59This PDF and the data file are also a part of the free exercise files on the course page.
01:04So is this marker image in the middle of it you want to use. These blank
01:07markers at the top and the bottom are for you to customize for a later video in this chapter.
01:13An important thing to know about these patterns is that they should really
01:16ideally be as rigid as possible.
01:18If there's any curve in the paper then FLARToolKit will struggle to
01:22recognize the shape.
01:23But don't worry if you don't have any curve to print this out on. I usually find
01:26that if you fold the paper into three along here and here, the marker usually
01:30has enough rigidity to work.
01:32So let's carry on down the base app.
01:36Here are some variables that FLARToolKit needs, various objects within the code
01:41itself that deal with setting up, and here are some variables that we will need
01:46to actually capture the web cam image and to draw it into a bitmap.
01:49We'll talk about OnImageFound and OnImageLost in a subsequent video.
01:54So I am going to skip on past that for now.
01:56We'll also be talking about the threshold adjustment system in the next movie.
02:01If we continue down, you can see where the constructor for this class is.
02:06So it calls this Super for the basic view.
02:08It creates this camera parameters file.
02:11So this is the default setting for the camera, which defines how wide or
02:15zoomed-in a lens that it is.
02:16Obviously, because we're distributing this FLARToolKit app on the web, we'll
02:21find that most people will have web cams and that it will be slightly different.
02:25However, I find that using the default parameters usually works fine for
02:29pretty much everyone.
02:31So let's quickly scan through the rest of this class.
02:34This is a bit that creates that marker from the data, ready for FLARToolKit to use,
02:39then we call the init function here.
02:41So there is lot going on here.
02:43This bit of code here sets up the webCam and the video, this creates a bitmap
02:48data to draw the video into every frame, and this bit creates a bitmap container
02:53for that bitmap data, so that we can see it on our stage and it's placed behind
02:58the Viewport values and addChildAt.
03:00The next three lines of code set up the FLARToolKit objects that we need and
03:05then this line of code here offsets the viewport for Papervision so that it
03:08matches up with the FLARToolKit data.
03:11Rather than use the standard Papervision camera, we need to use a special
03:15FLARCamera3D and set that as the camera property of our basic view.
03:20Then we create a FLARMarkerNode.
03:20So this is a Papervision DisplayObject3D and this is where we put all our 3D
03:26models and it's this object that has its position and rotation updated relative
03:31to the marker. And then of course we'll add that to the Papervision scene.
03:36Then we call addSceneObjects and in this case we're going to create a Wireframe
03:39plane and the cube with a FlatShader.
03:42Both of these objects get added into our FLAR DisplayObject3D, the container.
03:48So then if we scroll down we can see the main loop for our FLARToolKit base application.
03:54These first lines of code take the image from the web cam and draws into our camBitmapData.
04:00Then we tell FLARToolKit to look at that bitmap data to use that to try and find the pattern.
04:04There is some code here that deals with the automatic threshold system we'll
04:09discuss in the next movie and then if this line of code that does the core
04:13detection for FLARToolKit.
04:14Notice it's using this detector object and it's running the method of
04:19that detectMarkerLite.
04:20So this is where FLARToolKit actually analyzes that image and figures out
04:24whether it confined our marker or not.
04:27The next part of this conditional checks the getConfidence method of our
04:31detector to see how confident that it was that it found the marker.
04:35You can try adjusting this value if you find that your application has trouble
04:39detecting different types of markers.
04:40So if the image is found, then we call this getTransformationMatrix from the detector.
04:47This retains data about the orientation of our marker in 3D space.
04:51So then we set the transformation of our container object to match that marker.
04:55So we'll move on to this line here, singleRender, which renders the scene.
04:59So there is quite a lot of code in here.
05:02It's quite daunting, but the reason that this all is here is so that you don't
05:06have to worry about it.
05:07Let's just check and see how this works.
05:09So you will notice every time we run this we get this request popping up to ask
05:14us to allow the Flash Player to access our camera.
05:17It can get really troublesome actually continually clicking that.
05:21So if you don't want to be troubled by that again, go onto Settings and then
05:24check this Remember box here.
05:27If you find that it's not finding your camera, then click on this camera image
05:31here and choose your camera from the drop-down menu.
05:34So now we've got our base app working and you can see we have our cube and
05:39Wireframe plane on our marker.
Collapse this transcript
Adjusting the threshold to automatically improve the reliability of marker detection
00:01Now you'll find that for your augmented reality projects is that you will be working
00:04with a vast variety of different webcams of varying degrees of quality, plus
00:09also each of those webcams is going to be in a completely different environment.
00:12Some will be in daylight.
00:14Some will be at nighttime with room lighting.
00:16So we will see how to make our code as robust as possible.
00:20Now, I've built into the base application this automatic threshold adjustment system.
00:25But before I show you how it works, I am going to show you what happens if we disable it.
00:29We're taking advantage of the fact that FLARToolKit, before it does any
00:33processing of the image, is that it runs a threshold filter on it.
00:37That is it converts it into a completely black and white image.
00:40So I am going to disable the system by double-clicking this automatically
00:44adjusted threshold value currentThreshold, and setting that to a fixed value of let's say 50.
00:52This is what most FLARToolKit apps would be set at.
00:54But let's just see what happens when we run that.
00:56So actually the lighting in here is really, really good, and it's not a tool
01:02like how most people's cameras would be setup.
01:04But still, even with the slight amount of kind of brightness changing, there
01:08see where it's picking up the light on the marker and we release it there.
01:12That's because it's just using a fixed threshold and it's not properly
01:16distinguishing anymore between the light and the dark areas.
01:18So using this adjustment, this automatic adjusted version of the threshold will
01:24fix that problem,. Let's reinstate it.
01:26So now I am going to replace that with what it was before and instead of
01:30running this base app, I am going to save it and run this threshold demo instead.
01:36The threshold demo actually extracts out the bitmap and applies the threshold to
01:41it as it's running so we can see what's going on.
01:43So you can see in the top right-hand corner there that that is the version of
01:48the image after the threshold has been applied and you can see that it's
01:51flicking back and forth because it can't currently find the marker.
01:55I bring the marker up here though, now it's found the marker. It's happy and
01:59it's no longer adjusting the threshold.
02:01But if I just make it so that it gets a bit shinier, well it actually
02:04re-compensates so quickly that you can't even really notice that. Did you see it
02:08lost it then and then it flickered a bit?
02:11That's because it was adjusting that threshold value again until it found the marker.
02:14So let's just take a quick look at what's going on there.
02:18So if we go back to our Base class and this is the function that's called every frame.
02:26Now, there is a bit of complex logic there, but all it's really doing is taking
02:30a central threshold value and then if it can't find the marker, it will move up
02:35away from that value a certain amount.
02:38If it still can't find the marker, then in the next frame we'll go below the
02:42central point by the same amount.
02:45If at that point it still can't find the marker, then it increases the
02:48difference between the central point that goes back above the central point.
02:52So it's actually moving upwards and downwards around the middle point and the
02:56distance it moves from the middle point every frame is increasing as long as it
03:00can't find the marker.
03:02You will see down here, there's a bit of extra code here. If it finds the image,
03:06then it resets the threshold variance, that's the amount it moves every frame up and down,
03:11 back to 0 because it no longer has to scan up and down.
03:14And it also sets this threshold value to be where the threshold currently is
03:18and it's this threshold variable that is the central point that we're moving above and below.
03:24And here's the bit of code that actually increases those values should the marker
03:28not be found on any frame.
03:30So you can see that this is a very powerful system to improve the reliability of FLARToolKit.
03:34But because it's not doing any additional processing on the image, it's actually
03:38very easy on the processor.
03:39There are other ways of improving the reliability of the marker detection.
03:44In fact Saqoosha himself made a really clever filter that actually adjusts the
03:48image for areas of brightness and darkness.
03:51However, it is quite heavy on the processor, because it's actually processing
03:54that image every frame.
03:56By simply adjusting this threshold value, we're not actually manipulating that
04:00image at all, and it's really, really easy on the processor.
04:03So now we have got really solid base application that we can now use for our own
04:08augmented reality project.
Collapse this transcript
Placing a custom 3D model into an Augmented Reality scene
00:00So now we've looked at the complexity of the base app for our FLARToolKit and
00:04I expect you are probably a little bit daunted by that.
00:07There is an awful lot of different things that we have to get workings together.
00:10Not only the FLARToolKit, but also Papervision and also there is all the
00:14automatic threshold adjustment. There is a lot of code in there.
00:17But thankfully, you don't need to worry about that, because it's so easy to just
00:21extend that base app and leave all of that complexity in the base app and it
00:25means that our apps that we built can be very, very simple.
00:28I will show you an example of that here.
00:29So we are extending the base app there and what we are doing is creating a new
00:34DAE just like in previous chapters and then we are loading the knotted torus.
00:40These two lines of code here adjust the position of DAE so that it looks
00:44right on our marker.
00:46The FLARS base node display object that everything goes into can be rotated in
00:50a rather usual and an unexpected way.
00:52So you might find that you have to play with these ways until your object is
00:56correctly oriented on your marker.
00:58Then finally, rather than adding that DAE into our scene, we add it to the container.
01:04So the container is has its position and rotation updated it relative to the marker.
01:09So these lines are commented out.
01:11So actually ignore these lines for now.
01:13I'll come to those in a minute, but that is all the code that you need.
01:16Ignore these final functions.
01:18We'll talk about that in a moment, but all you really need are these lines here
01:22that actually create your 3D object and that means the container.
01:25Let's just see how that works.
01:26So now we have our DAE object loading and being placed relative to our marker.
01:33Now notice as it actually loses the marker that DAE then suddenly just stops still.
01:39It's because it can no longer find the marker to update its position.
01:43If I move my finger out of the way, you will see that it finds it again.
01:46Now obviously it can lose that marker for any number of reasons.
01:49Obviously, being obscured is the most obvious way that.
01:53that can happen, but also if the lighting, if the reflection gets just too shiny
01:57and it loses it, you can notice it sort of jitters around a little.
02:00So we need to actually handle that a little bit more effectively, rather than
02:06just have it freeze in space.
02:10Thankfully, there is this system built into our base app that we can take advantage of.
02:13There is a couple of properties of the base app called onImageFound and onImageLost.
02:20Now these are functions and I am just going to point them at the functions that
02:25I have declared below.
02:26If onImageFound is defined, then it will call this function every frame that it
02:31actually finds the marker and if onImageLost is defined, then it calls this
02:36function on every frame where the FLARToolKit can't find the marker.
02:40So we have defined these functions here.
02:42They are very, very simple.
02:44If fadeIn is getting called, it means that we found the marker and if the DAE's
02:49alpha value is less than 1, then we'll just increment it a bit.
02:52More importantly for the fadeOuts, this is called every time that we can't find
02:56the marker and if the DAE's alpha is greater than 0, then we are going to
03:00subtract the small amount from the DAE's alpha.
03:04So what this means is that instead of just sticking in its position, the model
03:08will slowly just fade in and out as it loses and finds that marker.
03:12Now of course remember that because we are adjusting the alpha property of the DAE,
03:15we also need to set the useOwnContainer property of that DAE to make sure
03:20that the DAE has a viewport layer.
03:22Let's just see that in action.
03:26So you can actually see that that's not working as it should be.
03:31Now the reason for that is although we set useOwnContainer on the DAE, because
03:36the DAE geometry isn't placed into that object until the DAE is loaded, it means
03:41that all of the geometry for DAE is not in that viewport layer.
03:45That's a really easy mistake to make.
03:47So let's just see how we can fix that.
03:48I am going to open this next file now AR_DAE2.
03:51Now this has got a lot more code in it, but it's essentially the same as last time.
03:56Here is the bit where the DAE is created and we are loading that file, adjusting
04:01its position and rotation relative to the marker container.
04:03Here is the important bit. We are now listening to see when that DAE is loaded.
04:09And it's not until the DAE is loaded that we are calling this method down here
04:14and it's at that point the DAE useOwnContainer is set.
04:17Now we are also doing some other stuff here.
04:20It's just like in the 3D Models chapter where we are creating an environment map
04:24and replacing the material in that DAE with the environment map.
04:29Remember that's the shiny texture.
04:30So now if we scroll up, you can see that we are again setting those onImageFound
04:35and onImageLost functions.
04:37So those functions will get called every time the marker is found or lost.
04:41Let's see how that works.
04:45So now you can see not only has our DAE got a really nice shiny reflective
04:49surface, but also as it loses that marker instead of just sticking in space it
04:54actually fades out and when I take my finger away, and it finds the marker
04:58again, the object fades back in.
05:01So there are other ways to handle when the marker is lost or found, but I find
05:05that by fading it in and out is quite a subtle of doing so.
05:08So now we know how easy it is to extend our FLARToolKit base app to put our own
05:13models inside our marker container.
Collapse this transcript
Adding a shadow effect to the 3D model
00:01So now we've got our 3D object placed on from the scene.
00:05Now I find that actually while that looks pretty cool and that is really exciting,
00:11because it's such a different style of objects to the rest of the scene,
00:14it looks very much like it's superimposed and I like to try to find as many
00:19different methods as I can to reduce that effect.
00:22So the first thing I am going to do is actually put a shadow onto -- which looks
00:27like it's actually on the marker itself.
00:29So let's take a look at how we are going to do that.
00:33So first off let's take a look at this shadow image that I have created.
00:37Let's scroll down here and go into our assets folder.
00:42It's here, torusshadow.jpg.
00:45How I created this was to import the 3D model into Photoshop and render it from
00:50the top down and then fill it in with black and give it a nice big blur.
00:52So the next step is to create a plane with the torusshadow on it.
00:58Here we have there, we are creating this plane.
01:01We are going to call it shadowPlane and then if we scroll down when the dae is
01:04loaded, we are actually placing that shadowPlane into the container.
01:09Before we do anything else, let's just check to see how that looks.
01:12So that's the first step.
01:15Obviously, it looks a little bit unsophisticated.
01:18Also, notice that the shadow actually isn't moving around along with the torus.
01:22So we've got a bit more refinement to do.
01:26So let's find the EnterFrame function.
01:27Here it is, and as we're rotating the dae around the Y axis,
01:32let's also rotate the shadow around the Y axis.
01:34Now because we don't want the big white areas in our image to appear, we are
01:37going to set the blendMode of that object to be Multiply.
01:40Of course, to set the blendMode of any 3D object, we also need to make sure that
01:45useOwnContainer is set to true.
01:48The Multiply blendMode basically means that white areas of our image are going
01:52to be invisible and it's only going to actually darken the image behind it where
01:57there are black parts of our shadow image.
01:59Let's just take a look at that.
02:01So we have a shadow, but it's pretty intense.
02:04It's a little bit over-the-top, and also it's not quite in the same position
02:08as the torus above it.
02:09But it's a good start. Let's carry on.
02:11So if we look up here at the top we are now going to fix the rotation of that
02:17shadowPlane so that it matches that off the torus dae.
02:21Let's again scroll back down here and add a bit of an alpha to that shadowPlane.
02:27Now of course, because we have now got a plane as well as the dae, we also need
02:30to make sure that the plane fades in and out as the dae fades in and out.
02:35Because the dae is alpha goes from 0 to 1, we can actually just literally
02:39copy that value for our shadowPlane but multiply it by 0.3.
02:43So when our dae is fully opaque, it has an alpha value of 1,
02:47it means our shadowPlane is always going to be 30% opaque.
02:51Let's see how that looks now. Excellent!
02:56So now we have a quite convincing looking shadow on our objects and it's really,
03:00really does help to place it in the scene.
03:03Now you might also notice that the torus itself is really, really sharp.
03:09Because it's obviously rendered in Papervision.
03:11It's just looks super-computerized.
03:15So I am just going to look it away to soften that affect to make it look a bit
03:18more like it's in our space.
03:20And that can be simpler.
03:23I am actually just going to add a BlurFilter into our dae object.
03:28So now you can see that by adding the BlurFilter, it just has the effect of
03:35softening that image a little bit and it makes it look a little bit more like
03:39it's actually in the space that I am in.
03:41We have learned now how to add a shadow and blur our objects and it really helps
03:47to place these objects inside the webcam image.
Collapse this transcript
Creating custom markers
00:00So now we've got FLARToolKit up and running, and we can now add in our own 3d
00:05models and place them over the webcam image.
00:07But of course I'm sure for your projects, you are most likely going to want to
00:11create own markers rather than just the default
00:14rather than plain looking markers we've been using so far. I expect you're
00:17probably going to want to put your company logo in there.
00:19But just a little word of advice, the simpler that these markers are, i.e. if
00:25they're very solid, thick, lots of color, it's going to run a lot better than
00:29if it's a very detailed image.
00:31But how do we create those markers?
00:33Well, first of all, let's just look inside our base app to see where we are
00:38actually importing that marker data.
00:40So as this line of code here and what we're doing is we're actually embedding that pattern sample 1.
00:47Now patt.sample1 is actually a data file, which represents the image in the PDF
00:52file in our main project folder here.
00:55So, if you want to print out one of the markers, you'd use this PDF file.
00:58Now you'll notice in this PDF file there're also a couple of blank markers for you to use.
01:04So I've printed this out, and I've actually drawn a picture inside the marker.
01:08You'll see in a moment.
01:08Now I'm going to convert that image into this data file that we need.
01:13So there are two ways to do this.
01:17The first one is by using this online pattern marker generator on this web site here.
01:22So you can click on that.
01:24And that should open up and you'll be able to do it.
01:26However, I prefer to use Saqooshas AIR for doing this and also because you can
01:32download it onto your computer. You can make patterns even when you're
01:35connected to the Internet.
01:37I always find this web page really hard to find, because it's actually got
01:41a spelling mistake in the title page.
01:43But don't worry the URL is onscreen so you can just go to this page and it's this
01:47Japanese line here, next to where it says Adobe AIR.
01:50So click on this, and you'll download the AIR app, and then double-click to install it.
01:55We're just going to put in our Application's folder.
01:59After this is installed, it just automatically run for you.
02:04So, now here I've got my image of the marker file I wanted to use.
02:09That's just a picture that I've drawn and you can see on the other side is
02:13the normal pattern.
02:14But as I hold up this new image, you can see that there's a red line around the
02:19marker, and that shows that it's actually found that marker.
02:22So, now I'm just going to click on Save Pattern and it will now allow me to
02:27save the data to that.
02:28So, I'm going to navigate into our workspace and into the AugmentedReality
02:33folder, assets, and I'm just going to call it custom_marker.
02:42So now we have that data file ready to use.
02:44So let's go back into our base app and change the name of this sample pattern to
02:48the one that we've just created.
02:50So now let's run this file.
02:53Okay, so now you can see that I am holding up the old marker that I had before
02:59and it doesn't work anymore.
03:00But if I use this newly generated marker file, you can see that it now works
03:04on my custom image.
03:09So, now I've edited that in our base app.
03:11It means that all of our classes that extend this up now use our custom_marker.
03:17So here's a class that I've made earlier.
03:20Now, of course, you don't have to just add 3D geometry into your
03:22augmented reality app.
03:24You can also use particles.
03:25And here is an example from one of the earlier chapters where we're actually
03:27putting the particle's object into our augmented reality container.
03:33Now, because this class actually extends the base class and we've just adjusted
03:36the pattern that that base class uses, let me run this.
03:40Again, this file should also use our new custom_marker, and there we have it.
03:51So, now we've learnt how to create our own custom markers and convert them into
03:55data files that we can then use in our FLARToolKit applications.
Collapse this transcript
Conclusion
Goodbye
00:00So this brings us to the end of the Papervision Essential Training course.
00:05I really hope you've enjoyed it.
00:06Now, obviously Papervision is huge, and there's no way I could have possibly
00:10covered absolutely everything in the entire library.
00:12But of course you are a good way there into it now, and hopefully you've got
00:15enough to actually start creating your own really exciting 3D Flash projects.
00:21So thank you so much for joining me on Papervision3D Essential Training.
Collapse this transcript


Suggested courses to watch next:

Flash Player 10 New Features (4h 0m)
Lee Brimelow


ActionScript 3.0: Working with XML (2h 27m)
Todd Perkins


Are you sure you want to delete this bookmark?

cancel

Bookmark this Tutorial

Name

Description

{0} characters left

Tags

Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading
cancel

bookmark this course

{0} characters left Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading

Error:

go to playlists »

Create new playlist

name:
description:
save cancel

You must be a lynda.com member to watch this video.

Every course in the lynda.com library contains free videos that let you assess the quality of our tutorials before you subscribe—just click on the blue links to watch them. Become a member to access all 98,466 instructional videos.

start free trial learn more

If you are already an active lynda.com member, please log in to access the lynda.com library.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Access to lynda.com videos

Your organization has a limited access membership to the lynda.com library that allows access to only a specific, limited selection of courses.

You don't have access to this video.

You're logged in as an account administrator, but your membership is not active.

Contact a Training Solutions Advisor at 1 (888) 335-9632.

How to access this video.

If this course is one of your five classes, then your class currently isn't in session.

If you want to watch this video and it is not part of your class, upgrade your membership for unlimited access to the full library of 1,893 courses anytime, anywhere.

learn more upgrade

You can always watch the free content included in every course.

Questions? Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com.

You don't have access to this video.

You're logged in as an account administrator, but your membership is no longer active. You can still access reports and account information.

To reactivate your account, contact a Training Solutions Advisor at 1 1 (888) 335-9632.

Need help accessing this video?

You can't access this video from your master administrator account.

Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com for help accessing this video.


site feedback

Thanks for signing up.

We’ll send you a confirmation email shortly.


By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

Keep up with news, tips, and latest courses with emails from lynda.com.

By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

   
submit Lightbox submit clicked