====== Lab 3 - Camera, Text, Environment and Sound ======
===== Before Coming to Class =====
* Bring your work from last week
===== Useful Links =====
* [[http://www.ru.is/kennarar/hannes/useful/PQR2.3.html|Python Quick Reference (LOCAL)]]
* [[http://www.ru.is/kennarar/hannes/useful/Python-Docs-2.5|Complete Python Documentation (LOCAL)]] //This is the latest 2.5 release, but new 2.5 features are well marked//
* [[http://www.ru.is/kennarar/hannes/useful/PandaManual|Panda 3D Manual (LOCAL)]]
* [[http://www.ru.is/kennarar/hannes/useful/PandaReference|Panda 3D Reference(LOCAL)]]
* [[http://www.ru.is/kennarar/hannes/useful/BlenderManual/htmlI|Blender Manual (LOCAL)]]
* [[http://www.ru.is/kennarar/hannes/useful/BlenderManual/htmlII/p2.html|Blender Reference (LOCAL)]]
* [[http://www.ru.is/kennarar/hannes/share/chicken_export1.0.zip|Chicken 1.0 EGG Exporter for Blender 3D (LOCAL)]]
===== In-Class Excercises =====
==== Before You Start ====
* Download and unzip the [[http://www.ru.is/kennarar/hannes/classes/ve2007/Lab3Assets.zip|Lab 3 Asset File]] into your working directory (same directory you used last week)
==== Continuing with your Virtual Room ====
* You can continue working where you left off last week on the [[Lab 2 Materials|Making a Virtual Room in Panda 3D]] exercise.
==== Improving the Virtual Room ====
- **Camera View:** Adjust your camera's //field of view// (FOV) and //near clipping distance// so that you see a bit more of the room as you move around in it. A field of view of **50** seems pretty good and a near clipping plane of **0.01**.
base.camLens.setFov(99)
base.camLens.setNear(1.0)
- **Onscreen Text:** Add a dynamic text label on your heads-up-display (HUD) simply by creating an **OnscreenText** object like this:
from direct.gui.OnscreenText import OnscreenText
textobject = OnscreenText(pos = (0, -0.9), fg = (1,1,1,1), bg = (0.3, 0.3, 0.3, 0.5),
align = TextNode.ACenter, scale = 0.07, mayChange = True)
You can look up the [[http://www.ru.is/kennarar/hannes/useful/PandaManual/OnscreenText.1.html|various creation parameters]] for **OnscreenText**. And then any time you want to display some text, just set the text property for this object. The following code sets the text to the current camera location values using a [[http://www.ibiblio.org/obp/pyBiblio/tips/wilson/stringFormat.php|python formatted string]]
textobject.setText("Your location is (%2.2f,%2.2f,%2.2f)" % (base.camera.getX(), base.camera.getY(), base.camera.getZ()))
- **Improved Spotlights:** The spotlights in Lab 2 sometimes don't produce any visual effect on the walls or the floors, even if they should according to their location. The reason is that the panels used in Lab 2 only have 4 vertices each and the amount of light hitting the panel is only calculated in those vertices, and then interpolated across the panel surface. If the cone of light misses the corners, none of the panel gets lit up, even if the light is shining right through its center. This situation can be improved by increasing the number of vertices in each panel. Instead of using a **CardMaker** to produce this simple kind of polygon, you should load in the model **Models/grid.egg**, which is a panel made out of 32x32 square polygons. Since this is a model you use again and again for each panel type (wall, floor, ceiling), you should only load this model once (in the constructor of your **Room**) and then //instance// it to a new (but empty) panel node you create to hold each panel. You then translate and orient the panel node as before. Do this and see how much your light changes!
# HINT - Loading a model
model = loader.loadModel("model.egg")
# HINT - Instancing it to a new pathnode
mypanel = root.attachNewNode("some panel")
model.instanceTo(mypanel)
- **Localized Sound:** Add some sound to the television broadcast which grows louder as you approach the television set and softer as you move away from it. First you need to create an instance of an **Audio3DManager** inside the **World**. You can use the **camera** object as the reference point for calculating how far the sound is traveling and therefore how much the volume should drop. Set the drop off factor to **10**. Then load the sound **glenn_launch.wav** and attach it to the television screen. Set the min distance of the sound to **1.2**. Make sure to start the sound playing. Play with different drop off factors and min distance values and see how it affects the sound in the room as you move around.
# HINT - Creating a 3D audio manager
# Note that 'reference_point' could be the pathnode of a listener's location
audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0], reference_point)
audio3d.setDropOffFactor(99)
# HINT - Loading a 3D sound and attaching it to an object
sound = audio3d.loadSfx('mysound.wav')
sound.setVolume(0.5)
audio3d.attachSoundToObject(sound, object )
audio3d.setSoundMinDistance(sound, 1.0)
sound.play()
- **Skybox:** Some of the wall panels have windows on them (namely the window and door panels). It would be nice to see through those windows to the outside! First let's create an outside view. Surround your entire scene with a box with the textures on the inside. A box like that, with textures depicting mountains and a sky already applied, can be found with the name **"Models/skybox.egg"**. As you can see, this sort of an object is called a //skybox//. Just load it as the member variable **self.skybox** in your **World**, attach it to **render** and scale it up 20 times. A //skybox// represents a horizon that the user should never be able to reach and pass through, and therefore it needs to move with the user, always keeping the user at its center. This is easy to do since **World** already has a **move** method that updates the camera position. Once the camera position has been updated in that method, give **self.skybox** the same position as the camera. Try moving outside of the room and notice how the horizon seems to stay put.
- **Fog:** To add a little bit of an atmosphere, add some fog to your skybox and play with the values. Don't make the fog too dense or you won't see much through the windows in the next step.
# HINT - Adding fog to a sub-tree starting at 'root' (could also be a node to a single model)
fog = Fog("Fog")
fog.setColor(0.6,0.6,0.8)
fog.setExpDensity(0.02)
root.setFog(fog)
- **Transparent Windows:** To make the glass see-through in your panels, you need to use textures that store a transparency value for each pixel, as well as the Red/Green/Blue (RGB) information. This transparency information is stored in an image layer called an //alpha channel//. In this layer, the color white (maximum value) means a opaque surface but the color black (minimum value or 0) means fully transparent. Not all image formats can store an alpha channel along with RGB. A new version of the **wall_tanned_door** and **wall_tanned_window** with an alpha channel, has been created in the **tiff** format (extension *.tif). Load this version of those textures into your **Room** instead of the old *.png ones. One more step is needed though. You will need to enable the transparency effect on the actual model that receives the texture. In this case the model is your **grid.egg** model (if you completed the second step above). Make the following call after you have loaded the model for the first time:
model.setTransparency(TransparencyAttrib.MAlpha)