#region File Description //----------------------------------------------------------------------------- // NormalMappingEffect.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; #endregion namespace NormalMappingEffect { /// /// Sample shows how to render a model using a custom effect. /// public class NormalMappingEffectGame : Microsoft.Xna.Framework.Game { #region Fields GraphicsDeviceManager graphics; KeyboardState lastKeyboardState = new KeyboardState(); GamePadState lastGamePadState = new GamePadState(); KeyboardState currentKeyboardState = new KeyboardState(); GamePadState currentGamePadState = new GamePadState(); Model model; // the next 4 fields are inputs to the normal mapping effect, and will be set // at load time. change these to change the light properties to modify // the appearance of the model. Vector4 lightColor = new Vector4(1, 1, 1, 1); Vector4 ambientLightColor = new Vector4(.2f, .2f, .2f, 1); float shininess = .3f; float specularPower = 4.0f; // the sample arc ball camera values float cameraArc = 0; float cameraRotation = 45; float cameraDistance = 1500; // the light rotates around the origin using these 3 constants. the light // position is set in the draw function. const float LightHeight = 600; const float LightRotationRadius = 800; const float LightRotationSpeed = .5f; bool rotateLight = true; float lightRotation; #endregion #region Initialization public NormalMappingEffectGame() { Content.RootDirectory = "Content"; graphics = new GraphicsDeviceManager(this); } /// /// Load your graphics content. /// protected override void LoadContent() { model = Content.Load("lizard"); foreach (ModelMesh mesh in model.Meshes) { foreach (Effect effect in mesh.Effects) { effect.Parameters["LightColor"].SetValue(lightColor); effect.Parameters["AmbientLightColor"].SetValue (ambientLightColor); effect.Parameters["Shininess"].SetValue(shininess); effect.Parameters["SpecularPower"].SetValue(specularPower); } } } #endregion #region Update and Draw /// /// Allows the game to run logic. /// protected override void Update(GameTime gameTime) { HandleInput(); UpdateCamera(gameTime); // Turn on the rotating light if ((currentGamePadState.Buttons.A == ButtonState.Pressed && lastGamePadState.Buttons.A != ButtonState.Pressed) || (currentKeyboardState.IsKeyUp(Keys.Space) && lastKeyboardState.IsKeyDown(Keys.Space))) { rotateLight = !rotateLight; } base.Update(gameTime); } /// /// This is called when the game should draw itself. /// protected override void Draw(GameTime gameTime) { GraphicsDevice device = graphics.GraphicsDevice; device.Clear(Color.CornflowerBlue); // Compute camera matrices. Matrix unrotatedView = Matrix.CreateLookAt( new Vector3(0, 0, -cameraDistance), Vector3.Zero, Vector3.Up); Matrix view = Matrix.CreateRotationY(MathHelper.ToRadians(cameraRotation)) * Matrix.CreateRotationX(MathHelper.ToRadians(cameraArc)) * unrotatedView; Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1, 10000); if (rotateLight) { lightRotation += (float)gameTime.ElapsedGameTime.TotalSeconds * LightRotationSpeed; } Matrix lightRotationMatrix = Matrix.CreateRotationY(lightRotation); Vector3 lightPosition = new Vector3(LightRotationRadius, LightHeight, 0); lightPosition = Vector3.Transform(lightPosition, lightRotationMatrix); // Draw the model. Matrix[] transforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(transforms); foreach (ModelMesh mesh in model.Meshes) { foreach (Effect effect in mesh.Effects) { Matrix world = transforms[mesh.ParentBone.Index]; effect.Parameters["World"].SetValue(world); effect.Parameters["View"].SetValue(view); effect.Parameters["Projection"].SetValue(projection); effect.Parameters["LightPosition"].SetValue(lightPosition); } mesh.Draw(); } base.Draw(gameTime); } #endregion #region Handle Input /// /// Handles input for quitting the game. /// private void HandleInput() { lastKeyboardState = currentKeyboardState; lastGamePadState = currentGamePadState; currentKeyboardState = Keyboard.GetState(); currentGamePadState = GamePad.GetState(PlayerIndex.One); // Check for exit. if (currentKeyboardState.IsKeyDown(Keys.Escape) || currentGamePadState.Buttons.Back == ButtonState.Pressed) { Exit(); } } /// /// Handles camera input. /// private void UpdateCamera(GameTime gameTime) { float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds; // Check for input to rotate the camera up and down around the model. if (currentKeyboardState.IsKeyDown(Keys.Up) || currentKeyboardState.IsKeyDown(Keys.W)) { cameraArc += time * 0.1f; } if (currentKeyboardState.IsKeyDown(Keys.Down) || currentKeyboardState.IsKeyDown(Keys.S)) { cameraArc -= time * 0.1f; } cameraArc += currentGamePadState.ThumbSticks.Right.Y * time * 0.25f; // Limit the arc movement. if (cameraArc > 90.0f) cameraArc = 90.0f; else if (cameraArc < -90.0f) cameraArc = -90.0f; // Check for input to rotate the camera around the model. if (currentKeyboardState.IsKeyDown(Keys.Right) || currentKeyboardState.IsKeyDown(Keys.D)) { cameraRotation += time * 0.1f; } if (currentKeyboardState.IsKeyDown(Keys.Left) || currentKeyboardState.IsKeyDown(Keys.A)) { cameraRotation -= time * 0.1f; } cameraRotation += currentGamePadState.ThumbSticks.Right.X * time * 0.25f; // Check for input to zoom camera in and out. if (currentKeyboardState.IsKeyDown(Keys.Z)) cameraDistance += time * 0.5f; if (currentKeyboardState.IsKeyDown(Keys.X)) cameraDistance -= time * 0.5f; cameraDistance += currentGamePadState.Triggers.Left * time; cameraDistance -= currentGamePadState.Triggers.Right * time; // Limit the camera distance. if (cameraDistance > 5000.0f) cameraDistance = 5000.0f; else if (cameraDistance < 350.0f) cameraDistance = 350.0f; if (currentGamePadState.Buttons.RightStick == ButtonState.Pressed || currentKeyboardState.IsKeyDown(Keys.R)) { cameraArc = 0; cameraRotation = 45; cameraDistance = 1500; } } #endregion } #region Entry Point /// /// The main entry point for the application. /// static class Program { static void Main() { using (NormalMappingEffectGame game = new NormalMappingEffectGame()) { game.Run(); } } } #endregion }