Dracula is a Virtual Environment that allows the user to experience what it would feel like to be Jonathan Harker. We wanted the user to be immersed in a dark and scary environment.
The user assumes the role of Jonathan Harker. After his intimidating experience in count Dracula's castle that could have cost him his life, he is now determined to take revenge by going back to the count's castle and killing him. Throughout the experience
the user is confronted with obstacles and puzzles. This all leads up to the final battle with Dracula.
The user begins in the courtyard. In the courtyard the user is confronted by the castle entrance. The entrance is locked so the user must find another way in. The courtyard includes some arches and a “blood” fountain.
It is a cold winter night, and Harker can barely see his finger in the darkness. Before proceeding, the user has to find a light source. Fortunately, there happens to be a burning torch at the east side of the castle.
The user discovers a graveled path leading from the courtyard which leads to dense dark woods. The path seems to go away from the castle, but having no other options, the user follows this path. The howling of hungry wolves can be heard from the dense wood on the sides of the path. A flock of bats suddenly appears from out of the darkness. Being curious, the bats are attracted to the user. The user however uses his torch to scare them away and continues following the path. The howling of wolves get louder and closer, but the user has no other option but to continue.
Finally, count Dracula's huge castle can be seen again through the woods again, and the path seems to be leading to the back of the castle.
User sees a door. Fortunately, the door is unlocked. Harker opens the door and steps it. It looks like a wine cellar with lots of old empty wooden shelves. There is a big table in the middle. There is also a large wooden wine rack with few bottles. A portrait for count Dracula can be seen hanging on the wall. There is no other door or window.
Harker notices two big lampstands. on the sides of the portrait. He decide to light these with his torch so he can better search for a secret hidden door. After lighting both lampstands, to his surprise, count Dracula's portrait opens and reveals a hand drawn sketch. The user tries to immitate this patern on the wine rack using the bottles. The wine rack opens revealing a secret passage!
Harker proceeds through the secret passage towards the main castle room. There are two levels to this room. The user can walk up the stairs to get to the second level. The user will find out that most of the room doors are locked except one. The user also first encounters Dracula in this room. Count Dracula courteously greets Harker welcoming him to his castle and disappears into green smoke.
Harker remembers that Dracula is intimidated by crosses, and he remembers that he left a cross in his bedroom. He rushes towards his bedroom in the second floor. Fortunately, the door is unlocked. The room consists of the bed, a bookshelf, and a fireplace in the corner. The user can check the two other doors in this room but they are locked. The only place left is the window.
Harker remembers the last time he scaled the castle's wall, walking on the narrow ledge extending from below his room's window to count Dracula's window. The user has to guide Harker to step out of the window, walk on the narrow ledge towards Dracula's room. After successfully making it to Dracula's room, user ducks and step into the count's room. A pile of gold sits next to Dracula's bed.
The spiral stairs leads the user down to the Cathedral. Here the user sees several coffins and is confronted by Dracula.
The torch is the user's main source of light. Without it the world would look very dark and almost impossible to see. The user must first find the torch before proceeding to the woods. The torch also serves as a weapon against bats and can burn various objects in the environment.
The cross can be found in Harker's Room. When button 2 is pressed, a dagger comes out from the bottom. The dagger is needed to kill Dracula.
Our doors do not need to be pressed to open. The user can just push on them to open.
User has to move bottles from one slot to another in the wine rack so that they match the puzzle guide.
The user fights against Dracula in the Cathedral. Dracula mocks you by laughing and saying things like “is that the best you can do?” When the user gets close to him, he turns into a bat a flees. While in bat mode Dracula will try to attack you and if successful will bite your neck. The user can use the fire to strike at the bat and turn Dracula into his normal form again. Dracula will be dazed and be on the floor. At that moment the user must stab Dracula with the dagger or else Dracula will wake up and fly away.
Ambient sounds are critical component of our VR experience. The ambient sounds change as the use progresses through the environment. Additionally, their volume increases/decreases gradually in real-time so the transition is natural. The following is a list of ambient sounds in the different portions of the environment.
A simple particle system is used for all the water, fire, and smoke effect. By changing the parameters of the particles we were able to make several different effects. The fire plays a big role in giving the environment a source of light. While the smoke allowed the transition of Dracula from human to bat. The blood fountain gives a nice scary effect.
The Boid's algorithm was used to animate the flock of bats in the woods. The bats use cohesion, seperation, and alignment calculations to make a believable flock of bats. By adding the fire into the avoid list, the bats will try to avoid any fire particle. On the other hand, adding the user to the cohesion list, the bats tend to attract to the user giving an “attack” effect.
Dracula has two forms. A human form and a bat form. When he is in the human form, he will make comments and laugh at the user. He will always face the user and if the user comes to close he turns into a bat and a puff of smoke appears. The bat form was kind of challenging to make. We gave the bat the same collision method as the user so it would not go through walls. We made it goal based so that it doesn't stay in one place all the time.
The height map and terrain navigation component has been re-written. The new method guarantees much higher resolution, and is many times more efficient as the previous method. Instead of representing the height map as veritices in Electro (using Lua's associate arrays), the height map pixel corresponding to the user's position is calculated, read directly from the original height map bitmap that was used to generate the terrain, and its colored is scaled to calculate the height of the current point.
Our virtual environment is massive both in terms of size and complexity. Therefore, an optimized execution was crucial to our experience. In fact, without optimization, the refresh rate would be extremely low (even on advanced machines, such as the C-Wall). Optimization has been done on multiple levels:
1. Object level: large objects were broken into smaller objects that are positioned in the loading stage. For example, the castle structure consists of hundreds of objects that are loaded separately. This technique exploits Electro's object culling mechanism, keeping the number of rendered object to minimum.
2. Real-time object rendering control: even when the size of objects is small and their number is big, frame rate still suffers a hit due to limitation in Electro's occlusion testing (Electro does not exclude occluded objects from being rendered). To overcome this limitation, we divided the environment into non-overlapping regions, and associated Electro entities with these regions so that only entities that the user actually see will get rendered. All other entities are marked with Electro's invisible flag, preventing them from being rendered, and saving us a huge burden. The trick of course is to ensure seamless transition between these regions. We were successfully able to tweak all the regions and parameters so that this feature is completely unnoticeable by the user – except for the achieved performance improvement :)
3. Particle system: particle system take a significant amount of CPU time to compute the position/scale/orientation of individual particles. By making use of the regions described above, we make sure that only the particle system that are seen by the user get updated.
4. Lua optimization: we rely heavily on Lua's efficient tables.
In our object-oriented style to coding this project, we implemented an eventing system. In our system an event can be created and “bound” to any number of event triggers. When these triggers have their state changed it notifies the event and the event notifies any registered “event listeners.” In this way we had a very general solution for doing all the events in our project. From “puzzle solved” to “user entered courtyard” any module in our system could be notified of the events it was curious about. This was the backbone of our optimization code. Turning on/off particle systems and hide/showing electro entities.
Shaders were a terrible animal to tackle. A basic bump map shader with both directional and point lighting was used. All lighting calculations were performed at the pixel level. Although it was very difficult to put together and get it running correctly. For starters, there are no vertex attributes that can be passed into a shader through electro. That is, you can't get per-vertex data from the electro into the shader. Bump maps typically use per-vertex “tangent” and “bitangent” values to convert the entire world into “tangent” space. Tangent space is mentioned in regards to bump shading in the following wiki: http://gpwiki.org/index.php/OpenGL:Tutorials:GLSL_Bump_Mapping. This was solved by using a serious of calculated “approximations” of tangent space in the shader itself.
Additionally, getting the torch positions and moon direction vectors into the correct coordinate spaces proved very challenging. Every tick of the clock the camera position and torch positions are updated and sent to the shaders. In this way the shader can compute all the needed values.
We didn't have the time or the resources to bump map everything. So we set up the electro lighting to “mimic” the shader lighting. Namely, a single directional light that is the same color as the moon light color in the shader exists and additionally a point light that is torch color follows the torch around. The result is pretty effective.