private static void MyCurrentCamPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ViewFrustumFunctions vf = d as ViewFrustumFunctions;
            object newVal           = e.NewValue;

            HelixToolkit.SharpDX.ProjectionCamera cam = newVal as HelixToolkit.SharpDX.ProjectionCamera;

            if (vf != null && cam != null && vf.SynchrCam)
            {
                // clear children list
                vf.Children.Clear();
                // get the size of the viewport
                double      parentH = 0;
                double      parentW = 0;
                Viewport3DX parent  = vf.Parent as Viewport3DX;
                if (parent != null)
                {
                    vf.CurrentPos = parent.CurrentPosition;
                    parentH       = parent.ActualHeight;
                    parentW       = parent.ActualWidth;
                    //var test = parent.Parent;
                }

                // add new View Frustum
                vf.DefineViewFrustum(cam, parentH, parentW);
                vf.BuildViewFrustumModel();
            }
        }
        private void DefineViewFrustum(HelixToolkit.SharpDX.ProjectionCamera _cam, double _vpH, double _vpW)
        {
            if (_cam == null)
            {
                return;
            }

            // check for orthographic projection
            HelixToolkit.SharpDX.OrthographicCamera camOrtho = _cam as HelixToolkit.SharpDX.OrthographicCamera;

            // calculate CAMERA CS
            Point3D  camPos       = _cam.Position;
            Vector3D camViewDir   = _cam.LookDirection;
            double   distToTarget = camViewDir.Length;

            Utils.CommonExtensions.NormalizeVector3D(ref camViewDir);
            Vector3D camUpDir = _cam.UpDirection;

            Utils.CommonExtensions.NormalizeVector3D(ref camUpDir);

            // turn to orthogonal CS
            Vector3D camXDir = Vector3D.CrossProduct(camViewDir, camUpDir);

            Utils.CommonExtensions.NormalizeVector3D(ref camXDir);
            camUpDir = Vector3D.CrossProduct(camViewDir, camXDir);
            Utils.CommonExtensions.NormalizeVector3D(ref camUpDir);

            float zFar  = (float)_cam.FarPlaneDistance;
            float zNear = (float)_cam.NearPlaneDistance;

            // calculate base of frustum pyramid
            // perspective projection
            float nHalfH = (float)((zNear / zFar) * _vpH);
            float nHalfW = (float)((zNear / zFar) * _vpW);

            if (camOrtho != null)
            {
                // orthographic projection
                nHalfH = (float)((zNear / zFar) * distToTarget * _vpH);
                nHalfW = (float)((zNear / zFar) * distToTarget * _vpW);
            }
            this.nearBL = camPos + zNear * camViewDir - nHalfW * camXDir
                          - nHalfH * camUpDir;
            this.nearBR = camPos + zNear * camViewDir + nHalfW * camXDir
                          - nHalfH * camUpDir;
            this.nearTL = camPos + zNear * camViewDir - nHalfW * camXDir
                          + nHalfH * camUpDir;
            this.nearTR = camPos + zNear * camViewDir + nHalfW * camXDir
                          + nHalfH * camUpDir;
            // perspective projection
            float fHalfH = nHalfH * zFar / zNear;
            float fHalfW = nHalfW * zFar / zNear;

            if (camOrtho != null)
            {
                // orthographic projection
                fHalfH = nHalfH;
                fHalfW = nHalfW;
            }
            this.farBL = camPos + zFar * camViewDir - fHalfW * camXDir
                         - fHalfH * camUpDir;
            this.farBR = camPos + zFar * camViewDir + fHalfW * camXDir
                         - fHalfH * camUpDir;
            this.farTL = camPos + zFar * camViewDir - fHalfW * camXDir
                         + fHalfH * camUpDir;
            this.farTR = camPos + zFar * camViewDir + fHalfW * camXDir
                         + fHalfH * camUpDir;

            // calculate normals

            // near
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_NEAR] = new Point3D(this.nearBL.X * 0.5 + this.nearTR.X * 0.5,
                                                                                  this.nearBL.Y * 0.5 + this.nearTR.Y * 0.5,
                                                                                  this.nearBL.Z * 0.5 + this.nearTR.Z * 0.5);
            this.normals[(int)ViewFrustumOrientation.VF_NEAR] = camViewDir;
            // far
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_FAR] = new Point3D(this.farBL.X * 0.5 + this.farTR.X * 0.5,
                                                                                 this.farBL.Y * 0.5 + this.farTR.Y * 0.5,
                                                                                 this.farBL.Z * 0.5 + this.farTR.Z * 0.5);
            this.normals[(int)ViewFrustumOrientation.VF_FAR] = -camViewDir;
            // left
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_LEFT] = new Point3D(this.nearBL.X * 0.499 + this.nearTL.X * 0.499 + this.farBL.X * 0.001 + this.farTL.X * 0.001,
                                                                                  this.nearBL.Y * 0.499 + this.nearTL.Y * 0.499 + this.farBL.Y * 0.001 + this.farTL.Y * 0.001,
                                                                                  this.nearBL.Z * 0.499 + this.nearTL.Z * 0.499 + this.farBL.Z * 0.001 + this.farTL.Z * 0.001);
            Vector3D normalL = Vector3D.CrossProduct((this.farBL - this.nearBL), (this.nearBL - this.nearTL));

            Utils.CommonExtensions.NormalizeVector3D(ref normalL);
            this.normals[(int)ViewFrustumOrientation.VF_LEFT] = normalL;
            // right
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_RIGHT] = new Point3D(this.nearBR.X * 0.499 + this.nearTR.X * 0.499 + this.farBR.X * 0.001 + this.farTR.X * 0.001,
                                                                                   this.nearBR.Y * 0.499 + this.nearTR.Y * 0.499 + this.farBR.Y * 0.001 + this.farTR.Y * 0.001,
                                                                                   this.nearBR.Z * 0.499 + this.nearTR.Z * 0.499 + this.farBR.Z * 0.001 + this.farTR.Z * 0.001);
            Vector3D normalR = Vector3D.CrossProduct((this.farBR - this.nearBR), (this.nearTR - this.nearBR));

            Utils.CommonExtensions.NormalizeVector3D(ref normalR);
            this.normals[(int)ViewFrustumOrientation.VF_RIGHT] = normalR;
            // top
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_TOP] = new Point3D(this.nearTR.X * 0.499 + this.nearTL.X * 0.499 + this.farTR.X * 0.001 + this.farTL.X * 0.001,
                                                                                 this.nearTR.Y * 0.499 + this.nearTL.Y * 0.499 + this.farTR.Y * 0.001 + this.farTL.Y * 0.001,
                                                                                 this.nearTR.Z * 0.499 + this.nearTL.Z * 0.499 + this.farTR.Z * 0.001 + this.farTL.Z * 0.001);
            Vector3D normalT = Vector3D.CrossProduct((this.farTR - this.nearTR), (this.nearTL - this.nearTR));

            Utils.CommonExtensions.NormalizeVector3D(ref normalT);
            this.normals[(int)ViewFrustumOrientation.VF_TOP] = normalT;
            // bottom
            this.posOnBoundary[(int)ViewFrustumOrientation.VF_BOTTOM] = new Point3D(this.nearBR.X * 0.499 + this.nearBL.X * 0.499 + this.farBR.X * 0.001 + this.farBL.X * 0.001,
                                                                                    this.nearBR.Y * 0.499 + this.nearBL.Y * 0.499 + this.farBR.Y * 0.001 + this.farBL.Y * 0.001,
                                                                                    this.nearBR.Z * 0.499 + this.nearBL.Z * 0.499 + this.farBR.Z * 0.001 + this.farBL.Z * 0.001);
            Vector3D normalB = Vector3D.CrossProduct((this.farBR - this.nearBR), (this.nearBR - this.nearBL));

            Utils.CommonExtensions.NormalizeVector3D(ref normalB);
            this.normals[(int)ViewFrustumOrientation.VF_BOTTOM] = normalB;
        }