PSSMDemo.BasicLightCameraBuilder.BuildCore C# (CSharp) Method

BuildCore() protected method

protected BuildCore ( Matrix &lightView, Matrix &lightProjection ) : void
lightView Matrix
lightProjection Matrix
return void
        protected override void BuildCore(out Matrix lightView, out Matrix lightProjection)
        {
            // ライトの仮位置と仮 UP ベクトル。
            var position = Vector3.Zero;
            var up = Vector3.Up;

            const float zeroTolerance = 1e-6f;

            // ライト方向と仮 UP ベクトルが並行な場合、他の軸を利用。
            float dot;
            Vector3.Dot(ref up, ref lightDirection, out dot);
            if ((1 - Math.Abs(dot) < zeroTolerance))
            {
                up = Vector3.Forward;
            }

            // 仮ライト ビュー行列。
            MatrixHelper.CreateLook(ref position, ref lightDirection, ref up, out lightView);

            // ライト位置へ向かうレイ。
            //var ray = new Ray();
            //Vector3.Negate(ref lightDirection, out ray.Direction);

            // 仮ライト ビュー空間における表示カメラの境界錐台を包む境界ボックス。
            var boxLV = BoundingBoxHelper.Empty;
            eyeFrustum.GetCorners(corners);
            for (int i = 0; i < corners.Length; i++)
            {
                Vector3 cornerLV;
                Vector3.Transform(ref corners[i], ref lightView, out cornerLV);

                BoundingBoxHelper.Merge(ref boxLV, ref cornerLV);
            }

            // 境界ボックスのサイズを算出。
            Vector3 boxSizeLV;
            BoundingBoxHelper.GetSize(ref boxLV, out boxSizeLV);

            Vector3 halfBoxSizeLV;
            BoundingBoxHelper.GetHalfSize(ref boxLV, out halfBoxSizeLV);

            // 境界ボックスの近平面の中心へライト カメラの位置を合わせる。
            var positionLV = new Vector3(
                boxLV.Min.X + halfBoxSizeLV.X,
                boxLV.Min.Y + halfBoxSizeLV.Y,
                boxLV.Min.Z);

            // 仮ビュー行列の逆行列。
            Matrix invLightView;
            Matrix.Invert(ref lightView, out invLightView);

            // 仮ビュー行列の逆行列を掛ける事で仮ビュー空間におけるライト カメラ位置をワールド空間へ。
            Vector3.Transform(ref positionLV, ref invLightView, out position);

            // 決定したライト カメラ位置によりライトのビュー行列を決定。
            MatrixHelper.CreateLook(ref position, ref lightDirection, ref up, out lightView);

            // ビュー空間における表示カメラの境界錐台を包む境界ボックス。
            boxLV = BoundingBoxHelper.Empty;
            for (int i = 0; i < corners.Length; i++)
            {
                // ビュー空間へ頂点を変換してマージ。
                Vector3 cornerLV;
                Vector3.Transform(ref corners[i], ref lightView, out cornerLV);

                BoundingBoxHelper.Merge(ref boxLV, ref cornerLV);
            }

            // 境界ボックスのある範囲で正射影。
            // ただし、SceneExtrudeDistance に応じて near を後退させておく。
            Matrix.CreateOrthographicOffCenter(
                boxLV.Min.X, boxLV.Max.X,
                boxLV.Min.Y, boxLV.Max.Y,
                -boxLV.Max.Z - SceneExtrudeDistance, -boxLV.Min.Z,
                out lightProjection);
        }