Title: OGRE Tutorial Three
1OGRE Tutorial Three
- Terrain
- Sky
- Fog
- The Root object
2Choose a SceneManager
- To render terrain, set the SceneManager to the
TerrainSceneManager In ExampleApplicationchoo
seSceneManager mSceneMgr mRoot -gtcreateScene
Manager(ST_EXTERIOR_CLOSE) - The Root object
(mRoot is an instance of Root) is the "core" Ogre
object. (To see UML diagram of the relationships
between Ogre objects here.) - After invoking
the function, the Root object then queries the
SceneManagerEnumerator to find the SceneManager
of the requested type and returns it.
3SceneManager
- SceneManagers are not Singletons.
- Allow multiple SceneManagers
- Display multiple SceneManagers at the same time
using multiple Viewports. - The OctreeSceneManager registers itself as
ST_GENERIC and overrides the base SceneManager
class if the OctreeSceneManager plugin is used. - (The OctreeSceneManager uses a system of culling
objects that are not visible and thus it's
generally faster than the default SceneManager.) - Remove OctreeSceneManager plugin from plugins.cfg
?
4SceneManager
- - Use a Root object to create SceneManagers.
- -OGRE is flexible?
- install a plugin for creating SceneManagers
called MySceneManager". - To create a SceneManager of the type, call
- mSceneMgr mRoot-gtcreateSceneManager(
- MySceneManager,
- SCENE_MANAGER_NAME)
- - RootdestroySceneManager clean up a
SceneManager -
5Terrain
- SceneManagersetWorldGeometry create scene
- - By using the TerrainSceneManager, it is able
to load a terrain configuration which is stored
in a file. - Code
- Derive a new class DemoApp from
ExampleApplication. - In DemoAppcreateScene
- mSceneMgr-gtsetWorldGeometry("terrain.cfg")
- Problems
- (1) Standard lighting not work properly in
terrain - (2) Not easy to get Shadows to work
6Options for Terrain Generation
- The TerrainSceneManager uses Heightmaps to
generate terrain. - - Specify the heightmap (gray level image)
- Heightmap.imageimageName
- Set the texture
- WorldTextureimageName
-
- Set detail Texture (which is interlaced with the
- WorldTexture to make the terrain look more
realistic. - DetailTextureimageName
- A more detailed explanation of the terrain config
file can be found here.
7Terrain texture
Height Map
Detail texture
82x2 Tilings of Detail texture
9Terrain
With detail texture
Without detail texture
10About TerrainSceneManager
- Designed with paging functionality. Paging
terrain system (1) the terrain is broken into
chunks (2) display the portion which can be
seen Advantages -gt (1) Be able to use a huge
world (2) Maintain framerate For details, read
Paging Scene Manager.
10
11 Three types of sky (1) SkyBoxes (2) SkyDomes (3
) SkyPlanes To use the Example/ textures for
sky, add the following line to the
ExampleApplicationchooseSceneManager ResourceG
roupManager getSingleton() .initialiseAllRes
ourceGroups()
Sky
12SkyBoxes
- A giant cube that surrounds all of the objects
in the scene In createScene()
mSceneMgr-gtsetSkyBox( true,
"Examples/SpaceSkyBox")
12
13SkyDomes
- A giant cube is created around the Camera and
rendered onto - the texture is "projected" onto the SkyBox in a
spherical manner. - It looks as if the texture is wrapped around the
surface of a sphere. - Drawback the bottom of the cube will be
untextured - gthave some type of terrain that hides the base.
- In ExampleApplicationcreateScene
- mSceneMgr-gtsetSkyDome(true, "Examples/CloudySky",
5, 8)
13
13
14SkyPlanes
- A single plane. - Best position be somewhere
towards the middle of the terrain and close to
the ground. In ExampleApplicationcreateScene.
Plane plane plane.d 1000 plane.normal
Vector3NEGATIVE_UNIT_Y mSceneMgr-gtsetSkyPlane
( true, plane, "Examples/SpaceSkyPlane",
1500, 75)
14
15Fog
- When use the TerrainSceneManager
- - call the setFog function before the
setWorldGeometry function - - depending on which is called first,
a different vertex program will be chosen to
create the fog and terrain. - When creating fog, it doesn't create a fog
entity in empty space. - Fog is a filter applied to whatever objects are
rendered - When nothing is seen -gt no fog only see the
background color. - To have fog look correct, set the background to
the fog color.
16setFog
void OgreSceneManagersetFog ( FogMode mode FOG_NONE,
const ColourValue colour ColourValueWhite,
Real expDensity 0.001,
Real linearStart 0.0,
Real linearEnd 1.0
)
1st parameter set the type of fog 2nd
parameter set the color of the fog 3rd
parameter fog density (not used in linear
fog) 4th , 5th parameters specify the range
where the fog gets thicker.
16
17Steps to create fog
- set the background color
- (2) create the fog
- (3) If necessary, use the getNumViewports member
function to get the number of viewports and
iterate through them - ColourValue fadeColour(0.9, 0.9, 0.9)
- mWindow
- -gtgetViewport(0)
- -gtsetBackgroundColour(fadeColour)
18Types of fog
Two types of fog (1) Linear fog (2) Exponential
fog To create a linear fog mSceneMgr-gtsetFog(FO
G_LINEAR, fadeColour, 0.0, 50, 500) (Remember,
this code must appear before the setWorldGeometry
call)
18
19Exponential Fog
- Two types of exponential fog
- (1) FOG_EXP
- (2) FOG_EXP2 IE fog gets much thicker each unit
compared to FOG_EXP - - set a density for the fog
- mSceneMgr-gtsetFog(FOG_EXP, fadeColour, 0.0005)
- mSceneMgr-gtsetFog(FOG_EXP2, fadeColour, 0.0005)
- Using DirectX Renderer, it completely fogged out
- calling setFog after setWorldGeometry fixes this.
- The OpenGL Renderer behaves as documented.
19
19
20OpenGL Fog
mSceneMgr-gtsetFog( FOG_LINEAR, fadeColour, 0.0,
50, 500)
mSceneMgr-gtsetFog( FOG_EXP, fadeColour, 0.0005)
mSceneMgr-gtsetFog( FOG_EXP2, fadeColour, 0.0005)
mSceneMgr-gtsetFog( FOG_LINEAR, fadeColour, 0.0,
50, 5000)
Any problems? There is no fog when theres no
object. (see at the back)
21Problem when Using SkyBox and SkyDome with Fog
- - The problem unnatural fog
- - SkyDomes and SkyBoxes are cubes
- fog works in a spherical manner
- Lets try this.
- -Problem one if the skyboxs setting too small.
- ColourValue fadeColour(0.9, 0.9, 0.9)
- mSceneMgr-gtsetFog(FOG_LINEAR, fadeColour, 0.0,
50, 5000) - mWindow-gtgetViewport(0)-gtsetBackgroundColour(fade
Colour) - mSceneMgr-gtsetWorldGeometry("terrain.cfg")
- mSceneMgr-gtsetSkyDome(true, "Examples/CloudySky",
5, 8, 1000) - -Problem two move the camera aroundnotice the
blue coming through on the sides, but not in the
middle) - Question How to solve the problem ?
22(No Transcript)
23Correct settings
24Fog as Darkness
- Not use sky at all when you set fog, - set the
fog to be thick enough so that the sky cannot be
seen. - Set the fog to be very dark ColourValue
fadeColour(0.1, 0.1, 0.1) mWindow-gtgetViewport(0
) -gtsetBackgroundColour( fadeColour )
mSceneMgr-gtsetFog( FOG_LINEAR, fadeColour,
0.0, 10, 2000) mSceneMgr-gtsetWorldGeometry( "t
errain.cfg )
25Tutorial FourFrame Listeners and Unbuffered
Input
- Use FrameListeners to do things that require
updates every frame - Use Ogre's unbuffered input system
26FrameLiseners
- - Use FrameListeners to receive notification
before and after a frame is rendered to the
screen. - Two functions
- bool frameStarted(const FrameEvent evt)
- bool frameEnded(const FrameEvent evt)
27Major part of call graph
GameApplicationgo()
GameApplicationsetup()
RootstartRendering()
RootrenderOneFrame()
Root_fireFrameStarted()
Root_fireFrameEnded()
Root_updateAllRenderTargets()
27
27
28FrameLiseners
- An Application may have two or more
FrameListeners. - - Cannot determine which FrameListener is called
first, second, third...and so on. - To ensure that FrameListeners are called in a
certain order - -gt register only one FrameListener and have it
call all of the objects in the proper order.
29Example for Constructing a FrameLisener
Derive a new framelistener from
ExampleFrameListerner Class DemoFrameListener
public ExampleFrameListener public
DemoFrameListener( RenderWindow win,
Camera cam, SceneManager sceneMgr)
ExampleFrameListener(win, cam, false, false)
bool frameStarted(const FrameEvent evt)
return ExampleFrameListenerframeStarted(evt)
30Registering a FrameListener
- Create an instance of our DemoFrameListener and
register it with the Root object - In ExampleApplicationcreateFrameListener
method, and add this code to it - mFrameListener new DemoFrameListener(
- mWindow, mCamera, mSceneMgr)
- mRoot-gtaddFrameListener(mFrameListener)
- - The mRoot and mFrameListener variables are
defined in the ExampleApplication class.
31FrameLiseners
RootaddFrameListener add a FrameListener,
Root removeFrameListener remove a
FrameListener Note addremoveFrameListener
methods only take in a pointer to a
FrameListener - FrameListeners do not have
names -gtNeed to hold a pointer to each
FrameListener
32(No Transcript)
33- Unbuffered" mouse and key input call methods in
frame listener to query the state of the keyboard
and mouse. - A problem
- If a key is down, action can be taken on this
information. However, what happens in the next
frame? - Is the same key down and do the same thing again?
- (1) Keep track of whether or not the mouse was
also - down the previous frame
- (2) Define a variable mToggle for indicating the
state of - an action
- (3) Allow actions to happen after a certain
amount of time - has elapsed
Unbuffered input
34Specifying unbuffered input mode
Class DemoFrameListener public
ExampleFrameListener public
DemoFrameListener( RenderWindow win,
Camera cam, SceneManager sceneMgr)
ExampleFrameListener(win, cam, false,
false) .. ExampleFrameListener's
constructor ExampleFrameListener(win, cam,
false, false) -3rd variable specify whether
using buffered key input -4th variable specify
whether using buffered mouse input
35Specifying unbuffered input mode
mKeyboard static_castltOISKeyboardgt (mInputMa
nager-gtcreateInputObject( OISOISKeyboard,
false )) mMouse static_castltOISMousegt
(mInputManager-gtcreateInputObject(
OISOISMouse, false ))
36Open Input System (OSI)
- - OSI povides three primary classes to retrieve
input - Keyboard, (2) Mouse, and (3) Joystick.
- - OSI key codes OSIKC_ (More details read
KeyCode) - - To use the Keyboard and Mouse objects.
- Steps
- (1) Capture the current state of the keyboard
and mouse. - ? In DemoFrameListenerframeStarted
- mMouse-gtcapture()
- mKeyboard-gtcapture()
- Implement methods to handle key and mouse events.
- For example,
- if(mKeyboard-gtisKeyDown(OISKC_ESCAPE))
return false
36
37An Example Control the movement of a camera
Code mCamNode-gttranslate( transVector
evt.timeSinceLastFrame, NodeTS_LOCAL)
Note the magnitude of the translation should
be depended on the amount of time since the last
frame. Otherwise, how fast the movement of the
camera would be dependent on the framerate of the
application.
37
37
37
37
38Control the rotation of the camera
- use Quaternions for all rotation operations.
- use a Quaternion to rotate a vector
- apply all of the rotations done to the SceneNode
to the translation vector.
39Transformation Space
- Specify which Transformation Space to use to
move the object. - TS_PARENT In parent node
- TS_LOCAL In object node
- TS_WORLD In world coordinate system
- mCamNode-gttranslate(
- transVector evt.timeSinceLastFrame,
NodeTS_LOCAL)
40Transformation Space
To move a SceneNode along the direction specified
by the orientation Method one mCamNode-gttransl
ate( mCamNode-gtgetOrientation()
transVector evt.timeSinceLastFrame,
NodeTS_WORLD) Method Two mCamNode-gttra
nslate( transVector evt.timeSinceLastFrame,
NodeTS_LOCAL)
41Tutorial Five Buffered input
- Use OIS's buffered input
- Handle keyboard and mouse events
- by using Listeners.
- For more information about OSI, read Using OIS
article.
42Buffered input
- - Unbuffered input every frame the state of
OISKeyboard and OISMouse instances is queried
to see what keys and mouse buttons were being
held down. - Buffered input use listener interfaces to inform
the program that events have occurred. - When a key is pressed, a KeyListenerkeyPressed
event is fired. - When the button is released (no longer being
pressed) a KeyListenerkeyReleased event is
fired to all registered KeyListener classes.
43OSI
- OIS's listener system allow one listener per
Keyboard, Mouse, or Joystick object. - call the setEventCallback function (which we
will cover later) multiple times will result in
only the last registered listener getting events. - If two or more objects have to get Key, Mouse,
or Joystick events, write a message dispatch
yourself. - call the Keyboardcapture and Mousecapture in
the frameStarted method. - (OIS does not use threads (or magic) to determine
the keyboard and mouse states.)
44The KeyListener Interface
OIS's KeyListener interface provides two pure
virtual functions. (1) keyPressed function
(which is called every time a key is pressed)
(2) keyReleased (which is called every time a
key is released). The parameter passed to these
functions is a KeyEvent, which contains the key
code of what is being pressed/released.
45The MouseListener Interface
- MouseListenermousePressed
- MouseListenermouseReleased
- MouseListenermouseMoved
- Each receives a MouseEvent object the current
state of the mouse - The MouseState (const OISMouseEvent arg)
object contains - (1) the relative X and Y coordinates of the mouse
move, - i.e. ( arg.state.X.rel, arg.state.Y.rel )
- (2) the absolute X and Y coordinates (that is,
where exactly on the screen they are). - i.e. ( arg.state.X.abs, arg.state.Y.abs )
46Registering keyboard callback and mouse callback
- The OIS mMouse and mKeyboard objects are already
obtained in the ExampleFrameListener constructor.
- To register the DemoFrameListener as the
listener by calling the setEventCallback method
on these input objects -
- mMouse-gtsetEventCallback(this)
- mKeyboard-gtsetEventCallback(this)
47FrameListener for buffered input
class DemoFrameListener public
ExampleFrameListener, public
OISMouseListener, public OISKeyListener
public DemoFrameListener( RenderWindow
win, Camera cam, SceneManager
sceneMgr) ExampleFrameListener(win, cam,
true, true) bool
frameStarted(const FrameEvent evt)
if(mMouse) mMouse-gtcapture() if(mKeyboard)
mKeyboard-gtcapture() return mContinue
in ExampleFrameListenerExampleFrameListener
mKeyboard-gtsetEventCallback(this) mMouse-gtsetEv
entCallback(this)
47
48Example for Key Bindings
In DemoFrameListenerkeyPressed It is called
with a KeyEvent object when a button of the
keyboard is pressed. bool keyPressed(const
OISKeyEvent e) switch (e.key) case
OISKC_ESCAPE mContinue false break
default break return mContinue
48
49Example for Mouse Bindings
- Find the mousePressed function
- - Access to both a MouseEvent and a
MouseButtonID. - Switch on the MouseButtonID to determine the
button that was pressed in mousePressed - Mouse key code OISMB_
50Other Input System SDL
- Cross platform windowing/input systems
- Support joystick/gamepad input
51Tutorial SixCEGUI
52CEGUI
- - Use CEGUI (an embedded GUI system) with Ogre.
- - Add basic CEGUI functionality
- Require two libraries (1) CEGUIBase_d.lib
- (2) OgreGUIRenderer_d.lib
- - add them to the input of the linker
(debug_mode) - - for release mode, remove the _d on them
- See CEGUI home page for more information.
53Introduction to CEGUI
- A fully featured GUI library
- Can be embedded in 3D applications such as Ogre
(it also supports pure DirectX and OpenGL as
well). - Highly customizable -gt allow to define the look
and feel of the application by changing its skin. - Only a GUI library -gt not do its own rendering
nor do it hook into any mouse or keyboard events.
- (1) To render the content of CEGUI
- provide a renderer for it (which is the
OgreGUIRenderer library included in the SDK), - (2) To let it receive mouse and keyboard events
- manually inject the events into the CEGUI
system. - (3) Advantage
- have full control over the rendering and the
input
54Initializing CEGUI
- To initialize CEGUI, (1) get a renderer and (2)
create a CEGUI system. - In createScene
- mRenderer new CEGUIOgreCEGUIRenderer(
- mWindow, OgreRENDER_QUEUE_OVERLAY,
false, 3000, mSceneMgr) - mSystem new CEGUISystem(mRenderer)
- - Select the skin (to download CEGUI skin from
their website) - CEGUISchemeManagergetSingleton()
- .loadScheme((CEGUIutf8)"TaharezLookSkin.schem
e") -
- Set the default mouse cursor image and the
default font - mSystem-gtsetDefaultMouseCursor(
- (CEGUIutf8)"TaharezLook", (CEGUIutf8)"Mou
seArrow") - mSystem-gtsetDefaultFont((CEGUIutf8)"BlueHighwa
y-12")
55Mouse Cursor
Two ways to display a mouse cursor (1) use
CEGUI to display the mouse cursor (2) create the
mouse cursor using Ogre directly To set the
default mouse cursor, call MouseCursorsetImage
56Injecting Key Events
- - CEGUI does not handle input in any way.
- It does not read mouse movements or keyboard
input. - -gt the user should inject key and mouse events
into the - system
- -gt both the keyPressed and keyReleased functions
should be modified. - Work with CEGUI,
- set the mouse and keyboard as buffered mode
- -gt receive the events directly and inject them as
they happen. - Both OIS and CEGUI use the same key codes for
keyboard input -gt not necessary to convert the
key
57keyPressed
- In keyPressed
- CEGUISystem sys CEGUISystemgetSingletonP
tr() - sys-gtinjectKeyDown(arg.key) // (1) inject
down event - sys-gtinjectChar(arg.text) // (2) actual
character - After getting the system object,
- Do two things
- Inject the key down event into CEGUI.
- Inject the actual character that was pressed.
- Injecting the key down will not always bring
about the desired result when using a non-English
keyboard. - The injectChar was designed with Unicode support.
58keyReleased
- Inject the key up event into the system.
- In keyReleased
- CEGUISystemgetSingleton().injectKeyUp(arg.key
) - Note do not need to inject a character up
event, only the key up event is required.
59Converting and Injecting Mouse Events
- Different mouse button codes between OIS and
CEGUI. - Three steps - (1) convert OIS button IDs into
CEGUI button IDs - - (2) inject mouse button presses into CEGUI
- - (3) inject mouse movement into CEGUI
- (1) Convertion function
- CEGUIMouseButton convertButton(OISMouseButtonI
D buttonID) - switch (buttonID)
- case OISMB_Left return CEGUILeftButton
- case OISMB_Right return CEGUIRightButton
- case OISMB_Middle return CEGUIMiddleButton
- default return CEGUILeftButton
-
-
- (2) Injecting inject mouse events. In
mousePressed - CEGUISystemgetSingleton().
- injectMouseButtonDown(convertButton(id))
60Injecting Mouse Movement Events
(3) injecting mouse motion into CEGUI. In
mouseMoved CEGUISystemgetSingleton() .injec
tMouseMove(arg.state.X.rel, arg.state.Y.rel)
The OISmouseMoved handler gives those
relative movements in the state.X.rel variable
and the state.Y.rel variables. After the three
steps CEGUI is fully setup and receiving mouse
and keyboard events.
61Windows, Sheets, and Widgets
(1) In CEGUI, everything that is displayed is a
subclass of the CEGUIWindow class (2) A window
can have any number of children windows. -gtThis
means that when you create a frame to contain
multiple buttons, that frame is a Window.
-gt Can place a button inside another button,
(3) Not necessary to create each individual
object through code. (4) Create a GUI layout for
the application in an editor such as the CEGUI
Layout Editor. After placing all of the windows,
buttons, and other widgets onto the screen, the
editor saves the layout into a text file. -
Load the layout into what CEGUI calls a GUI sheet
(which is a subclass of CEGUIWindow).
Remark read CEGUI website for more
information.
62Loading a Sheet
- The WindowManagerloadWindowLayout
- load the sheet and puts it into a CEGUIWindow
object. - (2) call CEGUISystemsetGUISheet to display
it. - CEGUIWindow sheet CEGUIWindowManager
- getSingleton()
- .loadWindowLayout((CEGUIutf8)"ogregui.layout")
- mSystem-gtsetGUISheet(sheet)
- - To retrieve this sheet, call SystemgetGUISheet
. - To swap the GUI sheet, call SystemsetGUISheet
- Have to maintain the sheet pointer(s)
63Mannually Creating an Object
Example, adding a Quit button (1) Create a
default CEGUIWindow containing all of the
widgets. (2) Add code to createScene
CEGUIWindowManager win CEGUIWindow
ManagergetSingletonPtr() CEGUIWindow
sheet win-gtcreateWindow( "DefaultGUISheet",
"CEGUIDemo/Sheet") - Create a
"DefaultGUISheet" called "CEGUIDemo/Sheet". -
Common (and encouraged) to name the widget in a
hierarchical manner such as "SomeApp/MainMenu/S
ubmenu3/CancelButton". (3) Create the Quit
button and set its size CEGUIWindow quit
win-gtcreateWindow( "TaharezLook/Button",
"CEGUIDemo/QuitButton") quit-gtsetText("Quit")
quit-gtsetSize(CEGUIUVector2( CEGUIUDim(0.1
5, 0), CEGUIUDim(0.05, 0)))
64Mannually Creating an Object
- CEGUI uses a "unified dimension" system for its
sizes and positions. - Create a UDim object to tell it what size it
should be. - 1st parameter the relative size of the object
in relation to its parent. - 2nd parameter the absolute size of the object
(in pixels). - - only supposed to set one of the two parameters
to UDim. - - The other parameter must be 0.
-
- - Attach the Quit button to the sheet we have
created - Set the current GUI sheet for the system to be
that sheet - sheet-gtaddChildWindow(quit)
- mSystem-gtsetGUISheet(sheet)
15
5
65Handling Events
- CEGUI uses a callback mechanism which binds any
public function to be the event handler. For
example register Quit button's click event to
exit the program when it is pressed. (1) need a
pointer to the Quit button (2) subscribe to the
clicked event CEGUIWindowManager wmgr
CEGUIWindowManagergetSingletonPtr()
CEGUIWindow quit wmgr-gtgetWindow( (CEGUI
utf8)"CEGUIDemo/QuitButton")
quit-gtsubscribeEvent( CEGUIPushButton
EventClicked, CEGUIEventSubscriber(Dem
oListenerquit, this))
66Handling Events
- Every widget in CEGUI has a set of events that
it supports, and they all begin with "Event".
To subscribe to the event quit-gtsubscribeEvent
( CEGUIPushButtonEventClicked, //
(1) CEGUIEventSubscriber(DemoListenerquit,
this)) // (2) 1st parameter the event
itself. 2nd parameter an EventSubscriber
object. Remark Which event and which handler
to handle the event? The subsriber answer these
two questions.
66
67Render to Texture
- Purpose Create a render to texture window.
- Allow to create a second Viewport which can be
rendered directly into a CEGUI widget. - Eight Steps
- (1) Setup a scene for us to look at.
- (2) Create the RenderTexture. The RenderSystem
object provides the functionality to render to a
texture. - (3) Create a texture with the RenderSystemcreate
RenderTexture function. - (4) create camera
- (5) create a viewport using RenderTextureaddView
port - (6) Use renderSystemcreateTexture to render the
scene onto a texture - (7) Setup CEGUI image set to store the texture in
CEGUI system - (8) create StaticImage widget for rendering the
texture stored in the image set - See http//www.ogre3d.org/wiki/index.php/Basic_Tut
orial_7 for more information.
68References Terrain, Sky, Fog http//www.ogre3d.o
rg/wiki/index.php/Basic_Tutorial_3 FrameListener
and Unbuffered Input http//www.ogre3d.org/wiki/in
dex.php/Basic_Tutorial_4 Buffered
Input http//www.ogre3d.org/wiki/index.php/Basic_T
utorial_5 CEGUI http//www.ogre3d.org/wiki/index.
php/Basic_Tutorial_7