23.在单元测试中添加光源
为了在单元测试中显示光照效果,现将引擎中单元测试使用的场景类defaultScene.cs的代码修改为以下内容:
namespace StunEngine
{
class defaultScene:Scene
{
public FpsCameraController fpsCamCtrl;
//一个长方体构成的地板作为参照物
private CubeSceneNode floor = null;
//单向光源
Light sunLight;
// 切换单向光源的移动
bool sunLightMove = false;
// 点光源
Light pointLight;
// 切换点光源的移动
bool pointLightMove = false;
//聚光灯
Light spotLight;
// 切换聚光灯的移动
bool spotLightMove = false;
// 第二个点光源
Light pointLight2;
//代表光源的模型
ModelSceneNode sunModel = null;
ModelSceneNode pointLightModel = null;
ModelSceneNode pointLightModel2 = null;
ModelSceneNode spotLightModel = null;
Vector3 position;
Vector3 scale;
Vector3 color;
Quaternion rotation;
float rotationAngle;
///
/// 构造函数
///
public defaultScene(StunXnaGE engine)
: base(engine, "default")
{
}
public override void Initialize()
{
base.Initialize();
//添加一个长方体代表地面作为参照物
floor = new CubeSceneNode(engine, this, "Textures//Grid", new Vector2(4f, 4f), null, Vector2.Zero);
AddNode(floor);
scale = new Vector3(20f, 0.5f, 20f);
floor.Pose.SetScale(ref scale);
//-----------------------------------
// 创建单向光
//-----------------------------------
//单向光源颜色设置为灰白色,位置为(0, 5, 10),单向光的位置是无意义的,实际设置的是它的光线方向,但设置位置比较符合习惯
color = new Vector3(0.8f, 0.8f, 0.8f);
position = new Vector3(0, 5, 10);
// 添加单向光源
sunLight = new Light(engine, color, -position);
AddLight(sunLight);
//添加一个代表带单向光源的箭头模型
sunModel = new ModelSceneNode(engine, this, "Models//arrow");
AddNode(sunModel);
sunModel.Material.CurrentTechniqueName = "SimpleTextured";
sunModel.Material.DiffuseTextureName = null;
sunModel.Material.DiffuseColor = color;
sunModel.Pose.SetPosition(ref position);
//将箭头放大2倍
scale = new Vector3(2.0f, 2.0f, 2.0f);
sunModel.Pose.SetScale(ref scale);
rotation = Quaternion.CreateFromYawPitchRoll(0, 3 * MathHelper.PiOver4, 0);
sunModel.Pose.SetRotation(ref rotation);
//-----------------------------------
// 创建点光源
//-----------------------------------
//点光源颜色设置为红色,位置为(-8, 5, 0)
color = new Vector3(1.0f, 0.0f, 0f);
position = new Vector3(-8, 5, 0);
//添加点光源
pointLight = new Light(engine, color, position, 20.0f, 2.0f);
AddLight(pointLight);
//添加一个代表点光源的球体模型
pointLightModel = new ModelSceneNode(engine, this, "Models//SphereLowPoly");
AddNode(pointLightModel);
pointLightModel.Pose.SetPosition(ref position);
pointLightModel.Material.CurrentTechniqueName = "SimpleTextured";
pointLightModel.Material.DiffuseTextureName = null;
pointLightModel.Material.DiffuseColor = color;
//将球缩小到0.3倍
scale = new Vector3(0.3f, 0.3f, 0.3f);
pointLightModel.Pose.SetScale(ref scale);
//-----------------------------------
// 创建聚光灯
//-----------------------------------
//将聚光灯的颜色设置为蓝色,位置为(0, 8, 0)
color = new Vector3(0.0f, 0.0f, 1.0f);
position = new Vector3(0, 8, 0);
//添加一个聚光灯光源,光线方向竖直向下
spotLight = new Light(engine, color, position, new Vector3(0, -1, 0), 15f, 1f, MathHelper.Pi /6.0f, MathHelper.Pi/3.0f);
AddLight(spotLight);
//添加一个代表聚光灯的圆锥体模型
spotLightModel = new ModelSceneNode(engine, this, "Models//Cone");
AddNode(spotLightModel);
spotLightModel.Material.CurrentTechniqueName = "SimpleTextured";
spotLightModel.Material.DiffuseTextureName = null;
spotLightModel.Material.DiffuseColor = color;
spotLightModel.Pose.SetPosition(ref position);
spotLightModel.Pose.SetScale(ref scale);
rotation = Quaternion.CreateFromYawPitchRoll(0, MathHelper.PiOver2, 0);
spotLightModel.Pose.SetRotation(ref rotation);
//-----------------------------------
// 创建相机
//-----------------------------------
Vector3 cameraPosition = new Vector3(0, 5, 20);
CameraSceneNode Camera = new CameraSceneNode(engine, this, cameraPosition, cameraPosition + Vector3.Forward);
Camera.Initialize();
Camera.FOV = MathHelper.PiOver4;
this.Camera = Camera;
//-----------------------------------
// 创建fps相机控制器
//-----------------------------------
fpsCamCtrl = new FpsCameraController(engine);
fpsCamCtrl.Elevation = 90;
Camera.AttachController(fpsCamCtrl);
//设置环境光颜色
this.AmbientColor = new Vector3(0.1f, 0.1f, 0.1f);
//设置雾化参数
this.FogEnabled = true;
this.FogStart = 50.0f;
this.FogEnd = 100.0f;
this.FogColor = new Color(1.0f, 1.0f, 1.0f).ToVector4();
}
public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
{
float time = (float)gameTime.TotalGameTime.TotalMilliseconds / 1000.0f;
//即一秒种转动的角度为45度
rotationAngle = time* 45 % 360;
float rotationRadians = MathHelper.ToRadians(rotationAngle);
//在高度为5的XZ平面上做半径为10的顺时针圆周运动
position = new Vector3(10 * (float)Math.Sin(-rotationRadians), 5.0f, 10 * (float)Math.Cos(-rotationRadians));
if (sunLightMove)
{
//设置单向光源位置
sunLight.Position = position;
//设置箭头模型位置
sunModel.Pose.SetPosition(ref position);
//设置箭头模型旋转
rotation = Quaternion.CreateFromYawPitchRoll(-(float)Math.Sin(rotationRadians), 3 * MathHelper.PiOver4, 0);
sunModel.Pose.SetRotation(ref rotation);
}
//在高度为5的XZ平面上做半径为8的逆时针圆周运动
position = new Vector3(8 * (float)Math.Sin(rotationRadians), 5.0f, 8 * (float)Math.Cos(rotationRadians));
if (pointLightMove)
{
//设置点光源位置
pointLight.Position = position;
//设置球模型位置
pointLightModel.Pose.SetPosition(ref position);
}
//让聚光灯光照方向左右旋转
Matrix lightRotation = Matrix.CreateRotationZ((float)Math.Sin(rotationRadians));
Vector3 lightDirection = Vector3.Transform(new Vector3(0, -1, 0), lightRotation);
if (spotLightMove)
{
//设置聚光灯光线旋转
spotLight.Direction = lightDirection;
//圆锥模型也随着旋转
Quaternion qu = Quaternion.CreateFromAxisAngle(Vector3.Right, MathHelper.PiOver2) * Quaternion.CreateFromAxisAngle(Vector3.Up, (float)Math.Sin(rotationRadians));
spotLightModel.Pose.SetRotation(ref qu);
}
//按数字键盘1键切换单向光的开关
if ((!(Input.Keyboard.IsKeyDown(Keys.LeftControl) || Input.Keyboard.IsKeyDown(Keys.RightControl)))&&Input.KeyboardKeyJustPressed(Keys.NumPad1))
{
sunLight.Enabled = !sunLight.Enabled;
sunModel.Visible = !sunModel.Visible;
}
//按住Control+数字键盘1键切换单向光源的移动
if ((Input.Keyboard.IsKeyDown(Keys.LeftControl) || Input.Keyboard.IsKeyDown(Keys.RightControl)) && Input.KeyboardKeyJustPressed(Keys.NumPad1))
{
sunLightMove = !sunLightMove;
}
//按数字键盘2键切换点光源的开关
if ((!(Input.Keyboard.IsKeyDown(Keys.LeftControl) || Input.Keyboard.IsKeyDown(Keys.RightControl)))&&Input.KeyboardKeyJustPressed(Keys.NumPad2 ))
{
pointLight.Enabled = !pointLight.Enabled;
pointLightModel.Visible = !pointLightModel.Visible;
}
//按住Control+数字键盘2键切换点光源的移动
if ((Input.Keyboard .IsKeyDown(Keys.LeftControl ) || Input.Keyboard.IsKeyDown(Keys.RightControl)) && Input.KeyboardKeyJustPressed(Keys.NumPad2))
{
pointLightMove = !pointLightMove;
}
//按数字键盘3键切换聚光灯的开关
if ((!(Input.Keyboard.IsKeyDown(Keys.LeftControl) || Input.Keyboard.IsKeyDown(Keys.RightControl))) && Input.KeyboardKeyJustPressed(Keys.NumPad3))
{
spotLight.Enabled = !spotLight.Enabled;
spotLightModel.Visible = !spotLightModel.Visible;
}
//按住Control+数字键盘3键切换聚光灯的移动
if ((Input.Keyboard.IsKeyDown(Keys.LeftControl) || Input.Keyboard.IsKeyDown(Keys.RightControl)) && Input.KeyboardKeyJustPressed(Keys.NumPad3))
{
spotLightMove = !spotLightMove ;
}
//按+键添加一个点光源
if (Input.KeyboardKeyJustPressed(Keys.Add ))
{
if (pointLight2 == null)
{
//点光源颜色设置为绿色,位置为(-4, 5, 0)
color = new Vector3(0.0f, 1.0f, 0.0f);
position = new Vector3(4, 5, 0);
//添加点光源
pointLight2 = new Light(engine, color, position, 25.0f, 1.0f);
AddLight(pointLight2);
//添加一个代表点光源的球体模型
pointLightModel2 = new ModelSceneNode(engine, this, "Models//SphereLowPoly");
AddNode(pointLightModel2);
pointLightModel2.Pose.SetPosition(ref position);
pointLightModel2.Material.CurrentTechniqueName = "SimpleTextured";
pointLightModel2.Material.DiffuseTextureName = null;
pointLightModel2.Material.DiffuseColor = color;
//将球缩小到0.2倍
scale = new Vector3(0.2f, 0.2f, 0.2f);
pointLightModel2.Pose.SetScale(ref scale);
}
}
//按-键移除一个点光源
if (Input.KeyboardKeyJustPressed(Keys.Subtract ))
{
if (pointLight2 != null)
{
RemoveLastLight();
RemoveNode(pointLightModel2);
pointLight2 = null;
}
}
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
}
}
}具体解释请看代码中的注释。上述代码在场景中添加了3个光源,分别是单向光源、点光源和聚光灯。实现的效果是按数字键盘1键切换单向光的开关,按Control+1键切换单向光源的运动,单向光源在5个单位的高度上做半径为10的顺时针旋转。按数字键盘2键切换点光源的开关,按Control+2键切换点光源的运动,点光源在5个单位的高度上做半径为8的逆时针旋转。按数字键盘3键切换聚光灯的开关,按Control+3键切换聚光灯光照方向的移动,聚光灯光照方向左右旋转。按+键在场景中添加第4个蓝色的点光源,按-键移除这个光源。程序截图如下:

发布时间:2010/4/23 下午12:56:49 阅读次数:6423
