Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007
MileStone 6: 3D graphics and API redesign
Milestone 6 case study.
Author: Nate Weimer.
Greetings and welcome to Pimpsqueak's Milestone 6 case study! Undoubtedly you've been following team Pimpsqueak's ongoing struggle to design the perfect adventure game creation engine. Milestone 6 was the assignment in which we were to implement 3D graphics using Wonderland in squeak. In addition to this we were left with the oppurtunity to completely redesign any portion of the project we didn't like. For more information see Fall 2001 Milestone 6.
Unfortunately, due to time constraits, team Pimpsqueak was unable to implement the redesign that we originally had planned. For a detailed look at our design plans, please see our power point presentation on the Cases page. The rest of this study will focus on 3D graphics in Wonderland.
Designing a 3D engine
Modularity: A necessity
The first step in making our 3D engine was to create a seperate class called AG3D. This seemed to be an obvious choice because we didn't want to tie in 3D graphics into fundamental code. In certain situations, such as running the game from a web server, the user would not have seen the graphical feature of our adventure game. Because Wonderland is so hardware intensive, we didn't want it to be started in such an event, thus modularity was important.
Our original design plan for Wonderland was a bit ambitious. Our vision was to create all rooms in the adventure game at once, so we would have an actual 3D world. If there was a door in the room, the user would be able to see into the next room. Once this had been accompolised, we could simply add a new camera that looked down upon all the rooms at once, thus acting as an aerial map of the game world. With Wonderland's built-in makePlaneName: method, we figured that building 3 planes into a wall with an open space for a door would be a piece of cake. However, making this proved to be rather difficult. After several hours of attempting to move, resize, place, and curse the namespace of planes in Wonderland, we realized 2 things. First, it would take several hours more of tweaking with sizes and placement to allign the planes exactly how we wanted it. Second, and most important, it became evident that having that many objects at once in Wonderland would slow down preformance to the point at which it would compromise the desired effect. The allignement also became a problem when we tried to apply a ceiling to the top of the room. Again, through trial and error, a simple three-walled room, without a ceiling became the solution.
Now that we had a room, we needed to put something in the room. Rooms needed to be distinct, and objects needed some sort of 3D representation. Well, since the class provided us with all sorts of nifty .mdl files to go along with Wonderland's makeActorFrom: method, it seemed logical to use them as our 3D models, though other formats were considered as we shall discuss later.
The color of a room, the texture of a wall, the look of an object were all attributes of the room or object. Thinking from an OO design perspective, we thought that rooms and objects would know their own attributes, which is why we created instance variables in AGRoom that would represent wall color, floor color, and wall texture. In AGObject we created a variable that holds the .mdl file that shall represent the 3D version of that object. The only variable left to put in AG3D was the one I called "lookingGlass", which was the instance of Wonderland we were dealing with. This design seemed to make building rooms very easy. We wrote a method in the AG3D class that takes AGRoom as an argument. It builds three walls, then set's all the attributes according to that room's variables. Then it cycles through the contents of the room and, provided that a model has been set, creates an actor of each object.
Tying Events to Wonderland
This was perhaps the most difficult portion of the assignment. As certain events happened in the game, such as entering a new room, dying, or taking objects, Woderland was supposed to react graphically. The main difficulty in working with Wonderland without the Wonderland editor is accessing actors. One must use getNameSpace at: in order to do so. Instead of parsing the .mdl file path to retrieve what might have been the model's name (if a model didn't have a unique name, Wonderland would change the name for you), I retreived the namespace as an actor was being made in wonderland with this piece of code that makes me very happy:
agobject modelNamespace: ((lookingGlass makeActorFrom: agobject model) getName).
Above modelNamespace is another instance variable added to AGObject ( you can never have too many :).
From here accessing actors in Wonderland was no more difficult than typing fifteen characters. Now we simply modified the processCommand method in AGWorld to make the proper calls to AG3D when events occured. In retrospect, this was probabaly poor OO design for not taking advantage of the model-view-controller paradigm. Instead of having AGWorld use AG3D methods, AGWorld could have signaled a change each time an event occured, and AG3D had it been a dependant, could've asked AGWorld for updates. But perhaps this is a flaw in our overall design, and not just the 3D aspect.
Alternatives we didn't use.
In addition to our ambitious first design for 3D (see above), we had other ideas thrown out.
We didn't want to be constrained by the .mdl files provided. Unfortunately after an extensive internet search, we found very few public .mdl files. What was worse is that Wonderland didn't seem to recognize files other than the ones provided.
In the search for .mdl files we found that 3DS files were fairly abundant on the web. Unfortunately wonderland seemed to not recognize all 3DS files either. Also many 3DS files were just of rediculous size, including a pine tree that rendered each branch individually. I thought that squeak had just frozen again until I noticed a huge list of actors in the Wonderland editor.
Another morbid idea that crossed our minds was to create a new method in Wonderland called makeActorFrom:Named:. This was one solution to the problem of retrieving actor's namespace. This way AG3D could create its own names for all of its actors. But when I discovered that makeActorFrom: actually returned the name, we decided it was much simpler to grab it from there rather than to hack Wonderland.
Advice For Working in Wonderland
- When working with Wonderland and with squeak in general save often!
- Take the time to do the Wonderland bunny demo. Simply reading or watching a lecture about Wonderland doesn't really help you remember the large variety of Wonderland methods. It doesn't take that much time, and it's worth it.
- Copy/Paste is your Friend. I can't tell you how many times I used (w getNamespace at: actor).
- Keep the editor handy. Our project involved having the editor hidden, but the editor's quick reference is just too useful to not have it available during development.
- Don't be afraid to look at the source code. This should probably go without saying, but it's a good reminder anyway.
- When not working with the editor, be aware of one method more than any other: w release. This quits wonderland. And no one wants 50 Wonderland morphs stacked on top of each other on the screen. Closing cameraWindow morphs manually can be a pain, especially since every actor in Wonderland is also a morph. Finding the morph that is the actual cameraWindow can take time.
Link to this Page