#region Copyright
/*
--------------------------------------------------------------------------------
This source file is part of Xenocide
by Project Xenocide Team
For the latest info on Xenocide, see http://www.projectxenocide.com/
This work is licensed under the Creative Commons
Attribution-NonCommercial-ShareAlike 2.5 License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/2.5/
or send a letter to Creative Commons, 543 Howard Street, 5th Floor,
San Francisco, California, 94105, USA.
--------------------------------------------------------------------------------
*/
/*
* @file XNetScene.cs
* @date Created: 2007/04/01
* @author File creator: dteviot
* @author Credits: none
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using ProjectXenocide.Utils;
using ProjectXenocide.UI.Scenes.Common;
using ProjectXenocide.Model;
using ProjectXenocide.Model.Geoscape;
#endregion
namespace ProjectXenocide.UI.Scenes.XNet
{
///
/// This is the 3D scene that appears on the X-Net screen
///
public class XNetScene : PolarScene
{
///
/// Constructor
///
public XNetScene()
:
base(defaultCameraDistance)
{
}
///
/// Load the graphic content of the scene
///
/// content manager that fetches the content
/// the display
public override void LoadContent(ContentManager content, GraphicsDevice device)
{
contentManger = content;
{
LoadModel(Matrix.Identity);
}
}
///
/// Render scene
///
/// time increment to use for updating scene
/// Device to use for render
/// Where to draw the scene on the display
public override void Draw(GameTime gameTime, GraphicsDevice device, CeGui.Rect sceneWindow)
{
// only draw in area we've been told to
Viewport oldview = device.Viewport;
device.Viewport = CalcViewportForSceneWindow(sceneWindow, device.Viewport);
Matrix projection = GetProjectionMatrix(AspectRatio);
// set up camera's position
Matrix viewMatrix = rotationMatrix * Matrix.CreateTranslation(0.0f, 0.0f, -CameraPosition.Z);
device.RenderState.DepthBufferEnable = true;
device.RenderState.DepthBufferWriteEnable = true;
device.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
// draw the model
//...Copy any parent transforms
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
//...Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set, as well as our camera and projection
foreach (BasicEffect effect in mesh.Effects)
{
effect.LightingEnabled = false;
effect.World = transforms[mesh.ParentBone.Index] * scalingMatrix;
effect.View = viewMatrix;
effect.Projection = projection;
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
// restore viewport
device.Viewport = oldview;
}
///
/// Compute matrix to scale the model, to fit it inside a bounding sphere of radius 1 centered at origin
///
/// The scaling matrix
private Matrix CalculateScalingMatrix()
{
BoundingSphere sphere = Util.CalcBoundingSphere(model);
// now figure out scale and displacement so fits inside sphere of radius 1 centered on origin
return Matrix.CreateTranslation(-sphere.Center) * Matrix.CreateScale((float)(1.0f / sphere.Radius));
}
///
/// Set the 3D model to show
///
/// Name of model to show
/// Rotation to apply to X-Net model, to set to inital orientation
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
Justification = "method performs a time-consuming operation")]
public void SetModel(string newModelName, Matrix initialRotation)
{
modelName = newModelName;
LoadModel(initialRotation);
ResetCamera();
}
///
/// Load the model from its resource file
///
/// The initial orientation of the model
private void LoadModel(Matrix initialRotation)
{
// "Light" version of Xenocide has most models removed
try
{
model = contentManger.Load("Content\\Models\\" + modelName);
}
catch (ContentLoadException)
{
// probably model isn't present, so fallback to default model
model = contentManger.Load("Content\\Models\\" + defaultModel);
initialRotation = Matrix.Identity;
}
scalingMatrix = CalculateScalingMatrix() * initialRotation;
}
///
/// Rotate the camera around the model.
///
/// Number of radians to rotate the camera around Y axis
/// Number of radians to rotate the camera around X axis
public override void RotateCamera(float longitude, float latitude)
{
rotationMatrix *= Matrix.CreateFromYawPitchRoll(longitude, latitude, 0.0f);
}
///
/// Applies a roll to the camera.
///
/// Number of radians to rotate the camera around Z axis
public void RollCamera(float roll)
{
rotationMatrix *= Matrix.CreateRotationZ(roll);
}
///
/// Move camera to it's default position
///
private void ResetCamera()
{
CameraPosition = new Vector3(0.0f, 0.0f, defaultCameraDistance);
rotationMatrix = Matrix.Identity;
}
#region Fields
///
/// Content manager that handles loading the model
///
private ContentManager contentManger;
///
/// 3D Model to show
///
private Microsoft.Xna.Framework.Graphics.Model model;
///
/// Factor we need to scale the model by, to get it to fit into a sphere of radius 1.0
///
private Matrix scalingMatrix;
///
/// Model to show on X-Net when we don't have a model
///
private const string defaultModel = "XCorps";
///
/// Name of the model to show in the 3D scene
///
/// default is the X-Corps logo
private string modelName = defaultModel;
///
/// Default distance for camera from model
///
private const float defaultCameraDistance = 3.5f;
///
/// Matrix storing the rotation of the camera.
///
private Matrix rotationMatrix = Matrix.Identity;
#endregion Fields
}
}