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个蓝色的点光源,按-键移除这个光源。程序截图如下:

单元测试

文件下载(已下载 1332 次)

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

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号