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