예제 #1
0
        public override void StartDrag(RayHitTestParameters ray)
        {
            if (_sphereCenter == null || _sphereOrientation == null)
            {
                throw new InvalidOperationException("SphereCenter and SphereOrientation need to be set before calling this method");
            }

            if (_dragHitShape == null)
            {
                _dragHitShape = new DragHitShape();
            }
            _dragHitShape.SetShape_Sphere(this.SphereCenter, this.Radius);

            _dragMouseDownClickRay  = ray;
            _dragMouseDownCenterRay = ray;
            //_dragMouseDownCenterRay = new RayHitTestParameters(this.DragAxis.Origin, ray.Direction);		//TODO: the ray through the center of the part really isn't parallel to the click ray (since the perspective camera sees in a cone)

            // Remember where they clicked (to be able to calculate the rotation in DragItem)
            Point3D?hitPoint = _dragHitShape.CastRay(ray);

            if (hitPoint == null)
            {
                // This will never happen for sphere
                _mouseDownHitPoint = new Point3D(0, 0, 0);
            }
            else
            {
                _mouseDownHitPoint = hitPoint.Value;
            }

            _mouseDownOrientation = this.SphereOrientation.ToUnit();
        }
예제 #2
0
        public override void DragItem(RayHitTestParameters ray)
        {
            if (this.DragAxis == null)
            {
                throw new InvalidOperationException("DragAxis needs to be set before calling this method");
            }

            // Compare the ray with the drag axis to see where on the axis they clicked
            // If the method comes back false, then the click ray is parallel to the axis, so just don't drag the arrow
            Point3D?hitPoint = _dragHitShape.CastRay(_dragMouseDownClickRay, _dragMouseDownCenterRay, ray);

            if (hitPoint != null)
            {
                this.DragAxis = new RayHitTestParameters(hitPoint.Value, this.DragAxis.Direction);
            }
        }
예제 #3
0
        //TODO: This functionality should be part of MapObjectChaseVelocity
        private static Point3D?AdjustIfOffPlane(Point3D itemPos, double itemRadius, DragHitShape dragPlane, Point3D?chasePoint)
        {
            const double MAXOFFSET    = 1.5;
            const double PERCENTATMAX = .01;        // even if they are really far off the plane, don't completely chase the plane, some percent needs to go toward the chase point passed in

            Point3D?pointOnPlane = dragPlane.CastRay(itemPos);

            if (pointOnPlane == null)
            {
                // Don't know where they are relative to the plane (this should never happen)
                return(chasePoint);
            }
            else if (Math3D.IsNearValue(pointOnPlane.Value, itemPos))
            {
                // They're position is the same as the point on the plane (they are already on the plane)
                return(chasePoint);
            }

            Vector3D vectToPlane = (itemPos - pointOnPlane.Value);
            double   distToPlane = vectToPlane.Length;

            if (distToPlane < itemRadius * .01)
            {
                // They are less than a percent of their body size off the plane, just return the point passed in
                return(chasePoint);
            }

            if (chasePoint == null)
            {
                // Null was passed in, just go straight for the plane (this should never happen)
                return(pointOnPlane);
            }

            // Figure out how much to dive for the plane vs go for the chase point
            double offset  = distToPlane / itemRadius;
            double percent = PERCENTATMAX;

            if (offset < MAXOFFSET)
            {
                // They are less than the max allowable distance from the plane
                percent = UtilityCore.GetScaledValue_Capped(PERCENTATMAX, 1d, 0, MAXOFFSET, MAXOFFSET - offset);
            }

            Vector3D direction = chasePoint.Value - pointOnPlane.Value;

            return(pointOnPlane.Value + (direction * percent));
        }
예제 #4
0
        public Point3D?ProjectTo3D()
        {
            //TODO: Cache this
            Vector3D orth = Vector3D.CrossProduct(Look, Up);

            //TODO: Cache Up as a unit vector

            // Project the X part of the 2D along orth
            Vector3D x = orth.ToUnit(true) * (CurrentPoint2D.X / Scale);

            // Project the Y part along up
            Vector3D y = Up.ToUnit(true) * (CurrentPoint2D.Y / Scale);

            if (Math3D.IsInvalid(x) || Math3D.IsInvalid(y))
            {
                return(null);
            }

            // Fire a ray along look toward the drag plane
            return(_dragPlane.CastRay(new RayHitTestParameters(Position + x + y, Look)));
        }
예제 #5
0
        private void DrawLines_Plate(int numSamples, double half, double lineThickness, AxisFor axisX, AxisFor axisY, AxisFor axisZ)
        {
            const double ELAPSEDURATIONSECONDS = 1;

            // Figure out how wide to make the plate
            int totalSamples  = numSamples * numSamples * numSamples;       // numsamples is per axis, so cube it
            int cellsPerSlice = _field.Size * _field.Size;
            int numSlices     = Convert.ToInt32(Math.Round(Convert.ToDouble(totalSamples) / Convert.ToDouble(cellsPerSlice)));

            if (numSlices == 0)
            {
                numSlices = 1;
            }

            int toOffset   = numSlices / 2;
            int fromOffset = numSlices - toOffset - 1;

            DateTime now = DateTime.UtcNow;

            bool isOverField = false;

            if (_mousePoint != null)
            {
                #region Snap to mouse

                // Cast a ray (Copied this from ItemSelectDragLogic.ChangeDragPlane, DragItem)

                Point3D point = new Point3D(0, 0, 0);

                RayHitTestParameters cameraLookCenter = UtilityWPF.RayFromViewportPoint(_camera, _viewport, new Point(_viewport.ActualWidth * .5d, _viewport.ActualHeight * .5d));

                // Come up with a snap plane
                Vector3D  standard = Math3D.GetArbitraryOrhonganal(cameraLookCenter.Direction);
                Vector3D  orth     = Vector3D.CrossProduct(standard, cameraLookCenter.Direction);
                ITriangle plane    = new Triangle(point, point + standard, point + orth);

                DragHitShape dragPlane = new DragHitShape();
                dragPlane.SetShape_Plane(plane);

                // Cast a ray onto that plane from the current mouse position
                RayHitTestParameters mouseRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, _mousePoint.Value);
                Point3D?hitPoint = dragPlane.CastRay(mouseRay);

                if (hitPoint != null)
                {
                    // Find the nearest Z cell
                    double halfSize = (_field.Size * _sizeMult) / 2d;
                    double cellSize = (_field.Size * _sizeMult) / _field.Size;

                    int zIndex = Convert.ToInt32((halfSize - axisZ.GetValue(hitPoint.Value)) / cellSize);

                    if (zIndex >= 0 && zIndex < _field.Size)
                    {
                        isOverField = true;

                        // Cap to field
                        _plateCurrentIndex = _field.Size - zIndex;        // it's actually the opposite
                        if (_plateCurrentIndex - fromOffset < 0)
                        {
                            _plateCurrentIndex = fromOffset;
                        }
                        else if (_plateCurrentIndex + toOffset > _field.Size - 1)
                        {
                            _plateCurrentIndex = _field.Size - toOffset - 1;
                        }

                        _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                    }
                }

                #endregion
            }

            if (!isOverField)
            {
                #region Shift the plate

                if (_plateCurrentIndex + toOffset > _field.Size - 1)
                {
                    _plateCurrentIndex = _field.Size - toOffset - 1;
                    _sceneRemaining    = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                }
                else if (now > _sceneRemaining)
                {
                    _plateCurrentIndex--;

                    if (_plateCurrentIndex - fromOffset <= 0)
                    {
                        _plateCurrentIndex = _field.Size - toOffset - 1;
                    }

                    _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS);
                }

                #endregion
            }

            double[] velX = _field.VelocityX;
            double[] velY = _field.VelocityY;
            double[] velZ = _field.VelocityZ;

            bool[] blocked = _field.Blocked;

            _velocityLines.BeginAddingLines();

            for (int z = _plateCurrentIndex - fromOffset; z <= _plateCurrentIndex + toOffset; z++)
            {
                for (int x = 0; x < _field.Size; x++)
                {
                    for (int y = 0; y < _field.Size; y++)
                    {
                        int xRef = -1;
                        int yRef = -1;
                        int zRef = -1;

                        axisX.Set3DIndex(ref xRef, ref yRef, ref zRef, x);
                        axisY.Set3DIndex(ref xRef, ref yRef, ref zRef, y);
                        axisZ.Set3DIndex(ref xRef, ref yRef, ref zRef, z);

                        int index1D = _field.Get1DIndex(xRef, yRef, zRef);

                        if (blocked[index1D])
                        {
                            continue;
                        }

                        DrawLinesSprtAddLine(xRef, yRef, zRef, index1D, half, lineThickness, velX, velY, velZ);
                    }
                }
            }

            _velocityLines.EndAddingLines();
        }
예제 #6
0
        private void DragItem(Point clickPoint)
        {
            bool usingAdaptive = this.UseAdaptiveDragPlane && !Keyboard.IsKeyDown(Key.LeftShift);

            // Don't do this here
            //if (usingAdaptive)
            //{
            //    // Refresh the plane before casting a ray onto it.
            //    // (mousemove will only fire when they actually move the mouse, so the item could be off the plane that _dragPlane knows
            //    // about)
            //    // When not using adaptive, the item needs to be dragged strictly onto the plane from when they first started dragging.  But
            //    // adaptive tries to drag the item into other items that are off the plane


            //    //TODO: I think this is a bit flawed.  It can cause the drag plane to move perpendicular to itself too easily at times

            //    ChangeDragPlane();
            //}

            #region Fire Ray

            //NOTE: This was copied from Game.Newt.v2.GameItems.ShipEditor.Editor.ChangeDragHitShape()

            RayHitTestParameters mouseRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, clickPoint);
            Point3D?hitPoint;
            if (_selectedItem.IsUsingSpring)
            {
                hitPoint = _dragPlane.CastRay(mouseRay);
            }
            else
            {
                hitPoint = _dragPlane.CastRay(_dragMouseDownClickRay, _dragMouseDownCenterRay, mouseRay, _camera, _viewport);
            }

            #endregion

            if (hitPoint == null)
            {
                return;
            }

            Point3D adjustedHitPoint = hitPoint.Value;

            if (usingAdaptive)
            {
                adjustedHitPoint = DragItem_Adaptive(hitPoint.Value);
            }

            _dragHistory.Add(adjustedHitPoint);

            //NOTE: SelectedItem may set the position directly, or apply a spring force toward this point passed in
            _selectedItem.SetPosition(adjustedHitPoint);

            #region NOT USED

            //There is no rotation for a plane
            //Quaternion? rotationDelta = _dragPlane.GetRotation(clickPoint, hitPoint.Value);
            //if (rotationDelta != null)
            //{
            //    Quaternion newRotation = Quaternion.Multiply(rotationDelta.Value.ToUnit(), _mouseDownDragOrientation);
            //    _selectedItem.Orientation = newRotation;
            //}

            #endregion
        }