public CustomUpAxisWithGlobalTransform()
        {
            InitializeComponent();

            // See XAML for more comments

            // Set the axes so they show left handed coordinate system such Autocad (with z up)
            // Note: WPF uses right handed coordinate system (such as OpenGL)
            //       DirectX also uses left handed coordinate system with y up
            CustomCameraAxisPanel1.CustomizeAxes(new Vector3D(1, 0, 0), "X", Colors.Red,
                                                 new Vector3D(0, 1, 0), "Z", Colors.Blue,
                                                 new Vector3D(0, 0, -1), "Y", Colors.Green);
        }
        public CameraPanelsSample()
        {
            InitializeComponent();

            // Set the axes so they show left handed coordinate system such Autocad (with z up)
            // Note: WPF uses right handed coordinate system (such as OpenGL)
            //       DirectX also uses left handed coordinate system with y up
            CustomCameraAxisPanel1.CustomizeAxes(new Vector3D(1, 0, 0), "X", Colors.Red,
                                                 new Vector3D(0, 1, 0), "Z", Colors.Green,
                                                 new Vector3D(0, 0, -1), "Y", Colors.Blue);

            this.Loaded += OnLoaded;
        }
        public ModelMoverOverlayWithZUpAxisSample()
        {
            // To use custom axes in ModelMoverVisual3D we could also change the default axes direction with the changing the following static fields:
            // This way we could define the ModelMoverVisual3D in XAML.
            // But here we will rather use a ModelMoverVisual3D constructor that takes custom axes as parameters.
            //ModelMoverVisual3D.DefaultXAxis = new Vector3D(1, 0, 0);
            //ModelMoverVisual3D.DefaultYAxis = new Vector3D(0, 0, -1);
            //ModelMoverVisual3D.DefaultZAxis = new Vector3D(0, 1, 0);


            InitializeComponent();


            // Calculate the inverted matrix at startup (used to convert from standard Y up to our Z up coordinate system)
            var invertedZUpMatrix = ZUpMatrix;

            invertedZUpMatrix.Invert();

            _zUpTransform3D         = new MatrixTransform3D(ZUpMatrix);
            _invertedZUpTransform3D = new MatrixTransform3D(invertedZUpMatrix);



            // To define custom axes directions for ModelMoverVisual3D, use the constructor that takes axes direction (note that this cannot be done in XAML)
            _modelMover = new ModelMoverVisual3D(xAxisVector3D: new Vector3D(ZUpMatrix.M11, ZUpMatrix.M12, ZUpMatrix.M13),
                                                 yAxisVector3D: new Vector3D(ZUpMatrix.M21, ZUpMatrix.M22, ZUpMatrix.M23),
                                                 zAxisVector3D: new Vector3D(ZUpMatrix.M31, ZUpMatrix.M32, ZUpMatrix.M33))
            {
                AxisLength      = 50,
                AxisRadius      = 1.5,
                AxisArrowRadius = 5
            };


            // Setup event handlers on ModelMoverVisual3D
            _modelMover.ModelMoveStarted += delegate(object o, EventArgs eventArgs)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                _startMovePosition = _selectedBoxModel.CenterPosition;
            };

            _modelMover.ModelMoved += delegate(object o, Ab3d.Common.ModelMovedEventArgs e)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }


                // When using custom coordinate system we need to transform the e.MoveVector3D.
                // Because the e.MoveVector3D is defined in standard Y up WPF 3D coordinate system,
                // we need to convert that into out Z up coordinate system.
                // This is done with using the inverted YUpMatrix:
                var transformedMoveVector3D = _invertedZUpTransform3D.Transform(e.MoveVector3D);

                var newCenterPosition = _startMovePosition + transformedMoveVector3D;

                if (Math.Abs(newCenterPosition.X) > 2000 ||
                    Math.Abs(newCenterPosition.Y) > 2000 ||
                    Math.Abs(newCenterPosition.Z) > 2000)
                {
                    InfoTextBlock.Text = "Move out of range";
                    return;
                }

                _selectedBoxModel.CenterPosition = newCenterPosition;


                var position = GetSelectedModelWorldPosition(); // GetSelectedModelPosition gets the _selectedBoxModel.CenterPosition and transforms it with the transformations of parent ModelVisual3D objects

                // Because ModelMoverVisual3D is in a separate Viewport3D that does not use the ZUpMatrix transformation,
                // we need to transform the position from z up coordinate system into the standard WPF 3D coordinate system:
                _modelMover.Position = _zUpTransform3D.Transform(position);


                InfoTextBlock.Text = string.Format("MoveVector3D: {0:0}", e.MoveVector3D);
            };

            _modelMover.ModelMoveEnded += delegate(object sender, EventArgs args)
            {
                InfoTextBlock.Text = "";
            };

            RootOverlayModelVisual3D.Children.Add(_modelMover);



            // Update the axes for CameraAxisPanel
            CustomCameraAxisPanel1.CustomizeAxes(new Vector3D(1, 0, 0), "X", Colors.Red,
                                                 new Vector3D(0, 1, 0), "Z", Colors.Blue,
                                                 new Vector3D(0, 0, -1), "Y", Colors.Green);



            // Set the ZUpMatrix to transform all the shown objects.
            // This way the objects will use the Z up matrix, but before rendering this will be transformed into the standard WPF 3D y up coordinate system.
            ZUpRootVisual.Transform = _zUpTransform3D;


            // We need to synchronize the Camera and Lights in OverlayViewport with the camera in the MainViewport
            Camera1.CameraChanged += delegate(object s, CameraChangedRoutedEventArgs args)
            {
                OverlayViewport.Camera         = MainViewport.Camera;
                OverlayViewportLight.Direction = ((DirectionalLight)Camera1.CameraLight).Direction;
            };


            _normalMaterial = new DiffuseMaterial(Brushes.Silver);
            _eventManager   = new Ab3d.Utilities.EventManager3D(MainViewport);

            CreateRandomScene();
        }