A few months ago, I was approached by the president of the company I’m currently working for.
He needed a game; more precisely, one of our clients needed a game. The president approached me for two reasons: I’m the flash guru in this joint and he knew I wanted to work in games. We sat down with the client and talked more about the game, how it’ll play and more importantly, how it’ll look.
Without a doubt, I pitched the idea that we use Papervision 3D to render the game. It’ll add the extra wow factor to the project when combining it with a proper 2D physics engine to create something that should look and feel like the real thing. After showing a few examples of what Papervision 3D can do, they were both sold that we should use this technology. Only problem was, I never used it before and I needed to learn it quickly to get a working prototype up.
Being an open source project, it was lacking what open source projects lack the most; proper documentation. A lot of my questions could not be answered through the internet since this project is still very new and not a whole lot of people have dabbled in it. However, luckily for me, there was an irc chan with some really helpful people that saved my ass on several occasions.
For our purposes, we needed two different viewports with two cameras (a shot cam and an overview cam) and because of this, we could only go with the very latest version of Papervision (Great White). For the physics engine, we needed something that’s fast, easy to use and easy to modify. I personally selected the APE engine since it was one of the least complex, yet it was fast and did it’s job properly. I needed something not too complex since I’m no physics major and furthermore, I needed to modify the engine to have ‘z friction’ since this is a 2D engine. I decided to go with a 2D engine because a 3D engine would be too complex and slow for something which is essentially 2D with a deceleration of speed when moving which I call ‘z friction’.
The learning curve wasn’t too steep, which is good since we had a tight deadline for this project. The beginning tutorial on papervision is easy to follow, but the more advanced topics aren’t exactly talked about and that’s where things became a hassle. With our engines chosen, it was off to the races to get this out.
Modeling
When I was in my teens, I did some 3D modeling using Lightwave which was self-taught using online resources. I wasn’t an expert, but it gave me some basic concepts on how to model and texture. Thankfully, this knowledge was enough to get me by on this project.
However, there is one important question to ask yourself before you do anything else: Do I really need a model of that?
Simple question, but I noticed that just a few polygons removed can make a significant difference in processing speed. Sometimes it’s the model that’s too complex, sometimes the texture. Either way, we needed this game to be able to run on most computers, so performance was the utmost priority.
At first, I used a plane to have the ice surface on. After trying this out for a while, I decided against it because it was hogging resources to render it. Instead, I made the background static (both the overview background and shot background), this gave the game a 35% performance increase. So, before you start modeling, ask yourself if a model is really required, or you could get away with a simple image or some other ingenious solution.
The first obstacle was to import a model into Papervision that was modeled with 3dsmax. Since Papervision uses the Collada file format to import their models, I decided to use that. Luckily enough, there’s a free plugin to export Collada files with 3dsmax (don’t use the native collada exporter) called ColladaMax. After installing the plugin, we need to create our model; let’s create a box for example sake. Next, click the modify tab and make sure our box is selected. We are now going to create a UVW Map for the box so to texture our model. Drop down the modifier list and add ‘Unwrap UVW’ from the list. Now, find the ‘Parameters’ box and click on the ‘Edit’ button. This will pop up a window with a mesh (a square if you made a box). Normally, the mesh is a lot more complex when it isn’t a primitive object and we would need to turn this mesh into a human understandable map. To simplify it, click the ‘Face Sub – Object Mode’ button at the bottom then click on the ‘Mapping’ menu bar item and click on ‘Flatten Mapping’. Keep the numbers in the popup box as default and click ‘ok’.
You should now see each face of your object in 2D. Now remove the checkerboard texture from the dropdown box at the top right by clicking on ‘Remove Texture’. Then click the ‘Tools’ menu bar item and select ‘Render UVW Template’. Keep the defaults and click on the ‘Render UV Template’ button. A new window should appear with all your faces outlined. Click the top-left button to save your template as an image where you can then open it using your favorite image editing software and add whichever texture you want to each face then save your changes while removing the actual template.
Now we’re going to add the texture to our object. Open the Material Editor window (under Rendering -> Material Editor), and change the name of the material in the combobox to whatever you want or just keep it as default. Then we will add the image map to this material by pressing the button on the right of the ‘Diffuse’ box. A window should appear with a list and in that list, click on ‘Bitmap’. You can now choose the texture you want to add to it. You then just need to click the ‘Assign Material to Selection’ button located near the top of the Material Editor window. That’s it, our map is now complete. Now you can see the object with the current applied map to it and you can modify the texture and the changes will be applied to the object in real time.
The last step is to export the model in Collada file format. Select ‘Export Selected’ from the File menu item and select the file type to be ‘COLLADA(*.DAE)’ and choose a filename. A window should appear, make sure that ‘Relative Paths’ and ‘Triangulate’ option is selected. The relative paths is so that the texture is in a relative directory from the file you’re saving (ie. ../../images/texture.jpg). And that’s it, you’re now ready to load your model within papervision!
Importing Model
My prefered way to import a model is to create a subclass of the Collada class to load the model and then you can modify it from within the class as you want. It’s also useful to have all the physics related to the model within this subclass. Here’s an example class:
package { import flash.events.*; import org.papervision3d.events.FileLoadEvent; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.parsers.Collada; import org.papervision3d.materials.utils.MaterialsList; /** * Creates the different rocks to be displayed in the game * * @see org.papervision3d.objects.parsers.Collada * @see org.papervision3d.objects.DisplayObject3D */ public class SomeModel extends Collada { private var modelLoaded:Boolean = false; // loaded flag /** * Constructor * * @param matList:MaterialList the material list to be added to the model * @param name:String name of this specific rock */ public function SomeModel(matList:MaterialsList, name:String = null) { super('modelPath.dae', matList, name); // listen for when it's done this.addEventListener(FileLoadEvent.LOAD_COMPLETE, handleLoadComplete); } /** * Handles the event when the broom finishs loading the material and model. * Certain properties cannot be accessed until model is fully loaded * * @param e:Event event handler object * @return void */ private function handleLoadComplete(e:Event):void { this.modelLoaded = true; } } }
This will load the model, but will not add it to the scene, you need to use the ‘scene.addChild’ function to add the model to your scene. The material list that needs to be provided is the texture that was used on your model in 3dsmax. So, to instantiate the class to add it to the stage, you’d do something like this:
var mat:BitmapFileMaterial = new BitmapFileMaterial("boxMaterial.jpg"); var model:SomeModel = new SomeModel(mat, 'someBox'); scene.addChild(model);
Rendering
A problem I’ve noticed early on is how the rendering engine works. Apparently, it uses a painter’s algorithm which isn’t exactly perfect and when it comes to displaying objects that are close to each other, it can create some flickering. After a lot of searching, some people on the irc chan helped out. I needed to change the rendering order of the object manually using a z sort. To do this, you need to access your viewport and change the sortMode property like so:
import org.papervision3d.view.layer.util.ViewportLayerSortMode; viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
After that, the rest was easy. I placed all rendered objects in a 2D array consisting of the object itself then it’s z coordinate. Since the camera was at (0, 0, 0), we can sort the array using the z index in descending order and add the proper layerIndex to each model.
Conclusion
This game was quite an experience and has gotten quite a good amount of attention. Throughout the whole project, creating the model, adding the texture and the z sorting was the biggest challenges because of lack of information. Hopefully this will help anyone out there. Please be free to ask any questions or come visit on the irc chan.
Copyright © Thinking in Code. All Rights Reserved. Powered by Wordpress
Michel,
I saw your article on PV3D and figured maybe you had encountered the same issue I’m currently having. I am working on a project for my employer and have had an issue where I’m simulating the flipping of a page. I would greatly appreciate any help I can get.
The page, while flipping, is a collada object given the correct page front and page to show. The problem occurs when I start flipping the object. I’ll use the cover page for the book as an example. I need to effectively take the 2d sprite representation, place the 3D sprite object over it, place the revealed page over the cover, drop the 2d version of the cover page out. So the 3d looks like the cover page folding away to reveal the first page of the book.
The problem is that this fast switching causes flicker. You don’t see it if you don’t put the first page there, if you’re just folding open to nothing. I tried to remedy the problem with the following solution. I start flipping the 3d object before I even add it to the stage. What this does is make a call in the 3d object to render. I thought this might help to ensure that the object has drawn before I’m dropping things out from under it… No such luck as far as solving the problem goes.
I thought maybe since you had mentioned some things about z-sorting in your 3d space you had perhaps encountered some interference between 2d and 3d objects.
Thanks again for hearing my plea. This project is due on Monday. While the flicker is a pretty big aesthetic issue, I do have bigger fish to fry. I’ll email you if I can figure it out. I’ve probably already spent 6 hours just trying to solve the flicker.
Take care -Burton
p.s. someone suggested I maybe utilize viewport layers.. the 2d objects are not ever added to the display list that constructs the page flip (3d) but I suppose I could use them in there until the flip is done and add them where they’re supposed to be.
Hi Burton, Thanks for posting.
I’m not too sure I understand the whole thing, particularly the part about the ’2d sprite representation’ and ‘place the 3D sprite object over it’.
2 things would help: an demo of the product and some source code. I also highly suggest that you come visit the papervision irc channel (#papervision3d on irc.freenode.net); I’m always on there plus there’s quite a few papervision gurus that are eager to help. From the sounds of it, I don’t think that z-sorting would solve the problem, but I may be mistaken since I’m not exactly sure what the problem is to begin with.
Please, come visit the channel so we can have a realtime conversation with other helpful people and hopefully get this figured out.