Assignment 1

3 downloads 94221 Views 119KB Size Report
In this first assignment you will familiarize yourselves with either Ogre3D or Irrlicht rendering engines or the XNA framework. Requirements. For this assignment ...
CS134 – Innovating Game Development Project 1: Rendering warm-up (5%) Out: Jan 28th, Mon Due: Feb 8th, Friday @11:59pm

Introduction During implementation of your game ideas it’s possible to get stuck in details that may not be apparent in the beginning. Some of these things might be related to: -

Handling user input Moving around in the scene Importing a models/scenes/levels Programming the GUI Loading textures Loading and playing sound files (3D sound!) Playing animated characters Handling physics and collision Programming for multiplayers over the network Use special effects such as fire, smoke, snow, parallax mapping, water surfaces, skyboxes, billboards, shadows, reflections, shaders…

Any one of these and possible many other details may halt your production pipeline. One of the things you will learn about game development in this class is to be able to comfortably work with existing software tools and libraries. We will expose you to some of the popular open source rendering, physics, sound, and networking APIs so that you will be able to focus on the innovative aspects of your games while making them entertaining and look good. In this first assignment you will familiarize yourselves with either Ogre3D or Irrlicht rendering engines or the XNA framework.

Requirements For this assignment you need to setup a 3D scene and create a ground plane, add light sources, 3D objects, skybox, camera navigation, and create a rigid body animation by using either Ogre, Irrlicht or XNA. You should find plenty of information and examples at the tutorials, wiki, and API pages of the engines. Irrlicht tutorials, wiki, forums, and API can be found at: http://irrlicht.sourceforge.net/tutorials.html http://www.irrlicht3d.org/wiki/ http://irrlicht.sourceforge.net/phpBB2/index.php http://irrlicht.sourceforge.net/docu/index.html

1

Ogre3D tutorials, wiki, forums, manual, and API can be found at: http://www.ogre3d.org/wiki/index.php/Ogre_Tutorials http://www.ogre3d.org/wiki/index.php/Main_Page http://www.ogre3d.org/phpBB2/ http://www.ogre3d.org/docs/manual/ http://www.ogre3d.org/docs/api/html/ XNA API and lots of useful information is available through Visual Studio’s help documentation. Programming guide, tutorials, samples, starter kits, and forum can be found at: http://msdn2.microsoft.com/en-us/library/bb198548.aspx http://creators.xna.com/Education/Tutorials.aspx http://creators.xna.com/Education/Samples.aspx http://creators.xna.com/Education/StarterKits.aspx http://forums.xna.com/ You may find it helpful to go through the demos that come with the engines. You can alternatively refer to the Ogre.ppt and Irrlicht.ppt help session slides for pointers.

Ogre Create a ground plane and texture map it. In Ogre you can use Ogre::MeshManager::createPlane() to define a plane mesh. You need to create an entity with it and attach it to a child of the root node. You can use Ogre::Entity::setMaterialName() to assign an already existing material to an entity. If you want to create a new material you need to create a .material script under the $ (OGRE_HOME)\media\materials\scripts\ directory and put the texture under $ (OGRE_HOME)\media\materials\textures directory. Details about creating materials can be found at Ogre manual. Create at least one light source by calling Ogre::SceneManager::createLight(). Ogre::Light has helper functions to change the light type, color, direction, and position. You can turn on shadows by calling Ogre::SceneManager::setShadowTechnique(). By default entities cast shadows. Add objects to the scene. Ogre has a proprietary 3D model format. Most common 3D formats can be converted to Ogre .mesh format using user-community-created plugins. You can find sample modes under the $(OGRE_HOME)\models directory. A model is loaded by the Ogre::Entity constructor. An entity needs to be attached to a scene node using Ogre::SceneNode::attachObject() to be displayed. You can use Ogre::SceneNode helper functions to change the position, orientation, and scale of your scene nodes.

2

Create a sky box and assign a sky texture to it by using Ogre::SceneManager::setSkyDome() and passing either a predefined or new material to it. Create a camera using Ogre::SceneManager::createCamera() and set its properties such as the position, the lookAt vector, near and far clipping plane distances. You need to assign control keys to the camera and process keyboard and mouse input to move it. You can use the ExampleFrameListener for these tasks. You can animate objects in a number of ways. One way would be to set up a keyframe animation if the scene node is a rigid body. If the scene node is an animated skeleton character, there will be a set of keyframe poses and the positions of the joints and bones will be interpolated in between the keyframes. Set up a camera track so that when the ‘c’ key is pressed the camera flies around your scene in a predefined track. You can create an Ogre:Animation object using the Ogre::SceneManager::createAnimation(), choose the interpolation method (linear or spline) by Ogre::Animation::setInterpolationMode(). Create a scene node object and attach your camera to it. Now create a Ogre::NodeAnimationTrack object to animate this camera scene node. Setup a Ogre::TransformKeyFrame object. Specify where your camera scene node will be at what time interval using Ogre::NodeAnimationTrack::createNodeKeyFrame() and Ogre::NodeAnimationTrack::setTranslate(). Once you are done create an AnimationState object using your Animation object. In your frame listener class’s frameStarted() method you need to notify the AnimationState object of the elapsed time since last frame so that it can do the interpolation calculations and position your camera correctly in each frame.

Irrlicht Create a ground plane and texture map it. You can simply create a cube scene node using irr::scene::ISceneManager::addCubeSceneNode() and scale it in the x and z directions using irr::scene::ISceneNode helper functions. Simply passing the name of your image file to Irr::scene::ISceneNode::setMaterialTexture() will texture map the scene node. Create at least one light source by calling scene::ILightSceneNode::addLightSceneNode(). Use irr::video::Slight helper functions to change the light type, color, direction, and position. Add objects to the scene. Irrlicht directly supports well know 3D object formats such as . 3ds, .x, .obj, and even Ogre .mesh. scene::IAnimatedMesh constructor loads the model. You need to create an IMesh object using irr::scene::MeshManipulator::createMeshWithTangents() and assign it to an irr::scene::ISceneNode. You can You can use ISceneNode helper functions to change the position, orientation, and scale of your scene nodes. Create a sky box and assign a sky texture to it by using irr::scene::ISceneManager::addSkyBoxSceneNode().

3

Create a camera using irr::scene::ISceneManager::addCameraSceneNodeFPS() and set its properties such as rotation, translation, and jump speeds, mapped keys, target vector, near and far clipping plane distances using irr::scene::ICameraSceneNode helper functions. In order to animate skeleton models, such as a Quake .md2 model, you need to create IAnimatedMeshSceneNode, choose an animation, set properties such as animation speed and the set of predefined keyframes. To animate a rigid body, such as the camera, you need to create an irr::scene::ISceneNodeAnimator object using irr::scene::ISceneManager::createFollowSplineAnimator() and pass to it a core::array of core::vector3df positions and the desired time interval between the keyframes. Set up an animation so that when the ‘c’ key is pressed the camera flies around your scene in a predefined track. In order to process keyboard events you need to inherit your own event receiver class from IEventReceiver and implement the OnEvent() method.

XNA Create a “Windows Game” project. In the LoadGraphicsContent() function you can load an .x model using the Load() function. You can find sample .x models under cs134/lib/xna/content directory. A Model can be made of multiple ModelMesh’es. In order to draw the model you need to loop through these ModelMesh’es. For each BasicEffect in a ModelMesh’s effects, you need to enable lighting by EnableDefaultLighting(), and set the BasicEffect’s World, View, and Projection matrices. In the Draw() function draw your model mesh like the following: foreach (ModelMesh mesh in myModel.Meshes) { //This is where the mesh orientation is set, as well as our camera // and projection foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.World = myWorldMatrix; effect.View = myViewMatrix; effect.Projection = myProjectionMatrix; } //Draw the mesh, will use the effects set above. mesh.Draw(); }

You can change the scale, rotation, and position of your models by adjusting your world matrix. You can use Matrix helper functions eg.: effect.World = Matrix.CreateScale(scaleVector3) * Matrix.CreateRotationY(rotationAngleFloat) * Matrix.CreateTranslation(translationVec3); Your view matrix may look like the following: myViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, cameraUp);

4

We will talk more about the camera paramaters shortly. Your projection matrix may look like the following: myProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip); where you can use values such as: float float float float

viewAngle = MathHelper.PiOver4; aspectRatio = (float)viewport.Width / (float)viewport.Height; nearClip = 1.0f; farClip = 10000.0f;

Add a ground plane using the ground.x model. You cannot explicitly add a camera so you will have to add some functionality yourself. You need to get keyboard input to get the camera position and orientation and then update you view matrix. You can get keyboard input such as the following in the Update() function: KeyboardState keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Left)) { // Rotate left cameraRotation += rotationSpeed; }

To move forwards and backwards you need to take into consideration the camera orientation and find which direction forwards is such as: if (keyboardState.IsKeyDown(Keys.Up)) { // move forwards Matrix forwardMovement = Matrix.CreateRotationY(cameraRotation); Vector3 v = new Vector3(0, 0, forwardSpeed); v = Vector3.Transform(v, forwardMovement); cameraPosition.Z += v.Z; cameraPosition.X += v.X; }

Now you can update the view matrix: // create a vector pointing the direction the camera is facing. Matrix rotationMatrix = Matrix.CreateRotationY(cameraRotation); Vector3 transformedReference = Vector3.Transform(new Vector3(0.0f, 0.0f, 1.0f), rotationMatrix); // calculate the direction the camera is looking at Vector3 cameraLookat = cameraPosition + transformedReference; // update view matrix myViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat,

5

cameraUp);

To add a skybox you will need a sphere model, a skybox cube map, and a custom shader effect which you can find under cs134/lib/xna/content directory. The shader applies a skybox style cube map to a sphere. In LoadGraphicsContent() function load the skybox.fx and load a cube map into a TextureCube object then set the following parameters: // load the effect, the texture, and the model used for drawing it Effect skySphereEffect = content.Load("skybox"); TextureCube skyboxTexture = content.Load("uffizi_cross"); sphereModel = content.Load("sphere"); // set the parameters of the effect skySphereEffect.Parameters["ViewMatrix"].SetValue(myViewMatrix); skySphereEffect.Parameters["ProjectionMatrix"].SetValue(myProjectionMat rix); skySphereEffect.Parameters["SkyboxTexture"].SetValue(skyboxTexture); // set the sky sphere effect to each part of the sphere model foreach (ModelMesh mesh in sphereModel.Meshes) { foreach (ModelMeshPart part in mesh.MeshParts) { part.Effect = skySphereEffect; } }

In Draw() function update the view and projection matrix values we send to the shader: // set the View and Projection matrix for the effect skySphereEffect.Parameters["ViewMatrix"].SetValue(myViewMatrix); skySphereEffect.Parameters["ProjectionMatrix"].SetValue(myProjectionMat rix);

Since we set the BasicEffect’s of the sphere model we don’t need the inner looop when drawing: // draw the sphere model that the effect projects onto foreach (ModelMesh mesh in sphereModel.Meshes) { mesh.Draw(); }

Because this shader sets some render states before it runs, you must reset the affected render states to the values we want to use for further rendering: // undo the renderstate settings from the shader graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace; graphics.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;

In order to script the camera to follow a curve you can use the Curve and CurveKey classes. Using Curves allows a path to be defined by a small number of control points with the Curves calculating the points on the path between the control points. Add Curve3D.cs 6

(found under cs134/lib/xna/content) to your project. Create two instances of this class, one for the position of the camera and the other for the lookAt vector. Also add variable to keep track of time: Curve3D cameraCurvePosition = new Curve3D(); Curve3D cameraCurveLookat = new Curve3D(); double time;

Define a function called InitCurve() and specify the points that the camera will pass throught and the points that the camera will be looking at. The number of points on the position and the lookAt curves don’t need to match, but the first and the last points on the curves should have the same time values if the curves oscillate: void InitCurve() { float time = 0; cameraCurvePosition.AddPoint(new Vector3(7.5f, 0, -45), time); cameraCurveLookat.AddPoint(new Vector3(9, 0, 9), time); time += 2000; cameraCurvePosition.AddPoint(new Vector3(3f, 0, -36), time); time += 2000; cameraCurvePosition.AddPoint(new Vector3(12f, 0, -30), time); time += 2000; … }

You can initialize your curve in Game1 constructor. Create a function called UpdateCameraCurve() to calculate the camera’s current position and orientation and update the view matrix: void UpdateCameraCurve() { Vector3 cameraPosition = cameraCurvePosition.GetPointOnCurve((float)time); Vector3 cameraLookat = cameraCurveLookat.GetPointOnCurve((float)time);

}

animatedCameraViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat,new Vector3(0.0f, 1.0f, 0.0f));

You can call this function from Update() function. In order to start the animation you need to update the time inside Update(): time += gameTime.ElapsedGameTime.TotalMilliseconds;

Don’t forget to alternate between your other view matrix and the animatedCameraViewMatrix when drawing your models.

7

Extra Credit -

Print out a message when an object is clicked in. Even better, translate the selected object. Create an environment mapped scene node Create a popup window or any other GUI component Create a cel shaded scene node Create a bump mapped scene node Create a transparent scene node that refracts light Use post-processing effects such as blur, bloom, edge detection, high dynamic range rendering, heat vision etc. Create a water surface. Create a burning scene node Create a scene node with smokes coming out of it Shatter a 3D model into pieces Deform a 3D model Load and play a skeleton animation Render your scene to a polygon Come up with something creative

8