Exemplo n.º 1
0
        /// <summary>
        /// Converts the screen coordinates to world coordiantes using the specified attitude matrix.
        /// </summary>
        /// <param name="pointOnScreen">
        /// The point in screen coordinates to translate.
        /// </param>
        /// <param name="attitude">
        /// The attitude matrix to use for translations.
        /// </param>
        /// <returns>
        /// A <see cref="Vector3"/> in world space.
        /// </returns>
        public Vector3 ScreenToWorld(Point pointOnScreen, Matrix attitude)
        {
            // Ensure that the viewport has been created
            EnsureViewport();

            // Use the attitude Matrix saved in the OnMouseLeftButtonUp handler.
            // Rotate it 90 degrees around the X axis to put it in the XNA Framework coordinate system.
            attitude = Matrix.CreateRotationX(MathHelper.PiOver2) * attitude;


            // for the near point we specified zero as the z component of the point which means this point is as close as
            // possible to the camera, while one for the second point means it’s as far as possible from the camera
            Vector3 nearPoint = new Vector3((float)pointOnScreen.X, (float)pointOnScreen.Y, 0);
            Vector3 farPoint  = new Vector3((float)pointOnScreen.X, (float)pointOnScreen.Y, 1);

            // Convert the near and far points from mouse space to 3D space
            nearPoint = viewport.Unproject(nearPoint, projection, view, attitude);
            farPoint  = viewport.Unproject(farPoint, projection, view, attitude);

            // Now that we have the near and far points in 3D space, create a directional vector between the two points
            // and normalize it. Normalizing makes the vector only one unit in length but still pointing in the same
            // direction.
            Vector3 direction = farPoint - nearPoint;

            direction.Normalize();

            // Now we take our direction and multiply it by 10, which essentially just moves it out almost to the edge of
            // our sceeen (our edge is 12 as defined by FarClippingPlane above). 10 units is also where all the labels like
            // 'front', 'back', 'left', etc. are positioned. This way if the user taps on one of the labels, their new label
            // will be at the same location and will move in sync.
            Vector3 unprojected = direction * 10;

            // Return the unprojected location
            return(unprojected);
        }
Exemplo n.º 2
0
        private void EnsureViewport()
        {
            // Only do this once
            if (viewport.Width == 0 || previousOrientation != currentOrientation || viewPortNeedsRebuilding)
            {
                // Initialize the viewport and matrixes for 3d projection.
                // Create the ViewPort based on the size of ourselves (the view) and not the screen. That's
                // becase the View should be sized to the camera preview, which is not the same size as
                // the Page or Window.
                viewport = new Viewport(0, 0, (int)this.ActualWidth, (int)this.ActualHeight);
                viewPortNeedsRebuilding = false;

                float aspect = viewport.AspectRatio;
                projection = Matrix.CreatePerspectiveFieldOfView(1, aspect, (float)NearClippingPlane, (float)FarClippingPlane);

                // Rotate items by adjusting camera's up vector
                Vector3 cameraUpVector = Vector3.Up;
                switch (currentOrientation)
                {
                case ControlOrientation.Clockwise270Degrees:
                    cameraUpVector = Vector3.Right;
                    break;

                case ControlOrientation.Clockwise90Degrees:
                    cameraUpVector = Vector3.Left;
                    break;

                    #if WIN_RT
                case ControlOrientation.Clockwise180Degrees:
                    cameraUpVector = Vector3.Down;
                    break;
                    #endif
                }

                view = Matrix.CreateLookAt(new Vector3(0, 0, 1), Vector3.Zero, cameraUpVector);

                previousOrientation = currentOrientation;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Occurs when the value of the <see cref="Attitude"/> property has changed.
        /// </summary>
        /// <param name="e">
        /// A <see cref="DependencyPropertyChangedEventArgs"/> containing event information.
        /// </param>
        protected override void OnAttitudeChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnAttitudeChanged(e);

            // Ensure that the viewport has been created
            EnsureViewport();

            // Get the RotationMatrix from the MotionReading.
            // Rotate it 90 degrees around the X axis to put it in the XNA Framework coordinate system.
            Matrix xnaAttitude = Matrix.CreateRotationX(MathHelper.PiOver2) * Attitude;

            // Loop through our items
            for (int i = 0; i < Items.Count; i++)
            {
                // Get the WorldVIewItem that matches the index
                WorldViewItem wvItem = ItemContainerGenerator.ContainerFromIndex(i) as WorldViewItem;

                // If we couldn't get a WorldViewItem for the index, skip
                if (wvItem == null)
                {
                    continue;
                }

                // Get the ARItem that the WorldViewItem represents
                ARItem arItem = (ARItem)wvItem.DataContext;

                // Create a World matrix for the ARItems WorldLocation
                Matrix world = Matrix.CreateWorld(arItem.WorldLocation, new Vector3(0, 0, 1), new Vector3(0, 1, 0));

                // Use Viewport.Project to project the ARItems location in 3D space into screen coordinates
                Vector3 projected = viewport.Project(Vector3.Zero, projection, view, world * xnaAttitude);

                // If the point is outside of this range, it is behind the camera
                if (projected.Z > 1 || projected.Z < 0)
                {
                    // Out of range, just hide
                    wvItem.Visibility = Visibility.Collapsed;
                }
                else
                {
                    // In range so show
                    wvItem.Visibility = Visibility.Visible;

                    /*
                     * // Create a TranslateTransform to position the WorldViewItem
                     * TranslateTransform tt = new TranslateTransform();
                     *
                     * // Offset by half of the WorldViewItems size to center it on the point
                     * tt.X = projected.X - (wvItem.ActualWidth / 2);
                     * tt.Y = projected.Y - (wvItem.ActualHeight / 2);
                     *
                     * // Set the transform, which moves the item
                     * wvItem.RenderTransform = tt;
                     */

                    // Create a CompositeTransform to position and scale the WorldViewItem
                    CompositeTransform ct = new CompositeTransform();

                    // Offset by half of the WorldViewItems size to center it on the point

                    // TODO: Expose vertical limit property
                                        #if WIN_RT
                    ct.TranslateX = projected.X - (wvItem.ActualWidth / 2) - (this.ActualWidth / 2);

                    // Ricky; Keep the y value within the screen
                    double y  = projected.Y - (wvItem.ActualHeight / 2);
                    double h2 = this.Height / 2;
                    y             = (y < -h2) ? -h2 : ((y > h2) ? h2 : y);
                    ct.TranslateY = y;
                                        #endif

                                        #if WINDOWS_PHONE
                    ct.TranslateX = projected.X - (wvItem.ActualWidth / 2);
                    ct.TranslateY = projected.Y - (wvItem.ActualHeight / 2);
                                        #endif


                    #if WP7
                    double scale = MathHelper.Lerp((float)MinItemScale, (float)MaxItemScale, ((float)FarClippingPlane - Math.Abs(arItem.WorldLocation.Z)) / (float)FarClippingPlane);
                    #else
                    double scale = MathHelper.Lerp(MinItemScale, MaxItemScale, (FarClippingPlane - Math.Abs(arItem.WorldLocation.Z)) / FarClippingPlane);
                    #endif
                    ct.ScaleX = scale;
                    ct.ScaleY = scale;

                    // Set the transform, which moves the item
                    wvItem.RenderTransform = ct;

                    // Set the items z-index so that the closest item is always rendered on top
                    Canvas.SetZIndex(wvItem, (int)(scale * 255));
                }
            }
        }