Beispiel #1
0
        private void RandomCamera_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Position
                Vector3D position = Math3D.GetRandomVector_Spherical(CAMERADISTANCE / 2, CAMERADISTANCE * 2);

                // Look Direction
                Vector3D lookDirection = position * -1;

                Vector3D   rotateAxis = Math3D.GetRandomVector_Cone(Math3D.GetArbitraryOrhonganal(lookDirection), 0, 20, 1, 1);
                Quaternion rotate     = new Quaternion(rotateAxis, Math1D.GetNearZeroValue(20));

                lookDirection = rotate.GetRotatedVector(lookDirection);

                // Up Vector
                Vector3D up = Math3D.GetArbitraryOrhonganal(lookDirection);

                // Commit
                _camera.Position      = position.ToPoint();
                _camera.LookDirection = lookDirection;
                _camera.UpDirection   = up;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Beispiel #2
0
        private void ChangeDragPlane(RayHitTestParameters clickRay)
        {
            _dragHistory.Clear();

            if (_selectedItem == null)
            {
                _dragPlane = null;
                return;
            }

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

            Point3D point = _selectedItem.Item.PositionWorld;

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

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

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

            _dragMouseDownClickRay  = clickRay;
            _dragMouseDownCenterRay = new RayHitTestParameters(point, clickRay.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)
        }
Beispiel #3
0
        /// <summary>
        /// This is used to rotate a 2D icon onto 4 evenly distributed points around a sphere
        /// </summary>
        private static Transform3D[] GetRotations_Tetrahedron(double radius)
        {
            List <Transform3D> retVal = new List <Transform3D>();

            Vector3D position = new Vector3D(radius, 0, 0);
            Vector3D right    = new Vector3D(0, 1, 0);
            Vector3D up       = new Vector3D(0, 0, 1);

            Tetrahedron tetra = UtilityWPF.GetTetrahedron(1);

            foreach (Point3D dir in tetra.AllPoints)
            {
                Quaternion randRot  = Math3D.GetRotation(right, Math3D.GetArbitraryOrhonganal(position));       // give it a random spin so that the final icons aren't semi lined up
                Quaternion majorRot = Math3D.GetRotation(position, dir.ToVector());

                Transform3DGroup transform = new Transform3DGroup();
                transform.Children.Add(new RotateTransform3D(new QuaternionRotation3D(randRot)));
                transform.Children.Add(new RotateTransform3D(new QuaternionRotation3D(majorRot)));

                retVal.Add(transform);
            }

            return(retVal.ToArray());
        }
Beispiel #4
0
        private void grdViewPort_MouseDown(object sender, MouseButtonEventArgs e)
        {
            const double CLICKDISTANCE = BOUNDRYSIZE / 8;

            try
            {
                if (e.ChangedButton != MouseButton.Left)
                {
                    // All the special logic in this method is for the left button
                    return;
                }

                // Fire a ray at the mouse point
                Point clickPoint2D = e.GetPosition(grdViewPort);

                RayHitTestParameters   clickRay;
                List <MyHitTestResult> hits = UtilityWPF.CastRay(out clickRay, clickPoint2D, _viewport, _camera, _viewport, false);

                // Figure out where to place the point
                Point3D   clickPoint3D;
                ITriangle clickPlane = null;
                if (hits != null && hits.Count > 0)
                {
                    // They clicked on something, so use that
                    clickPoint3D = hits[0].Point;
                }
                else
                {
                    //TODO: If there is a mothership, choose a point in a plane that goes through it (orth to the click ray)
                    //
                    // If there isn't, but they click near a swarm, use that plane
                    //
                    // Or if they click near something (like an asteroid)

                    double?clickDistNearSwarm = GetClickDistanceNearSwarm(clickRay);

                    double clickDist;
                    if (clickDistNearSwarm == null)
                    {
                        clickDist = Math.Max(CLICKDISTANCE, _camera.Position.ToVector().Length / 1.1);
                    }
                    else
                    {
                        clickDist = clickDistNearSwarm.Value;
                    }

                    clickPoint3D = clickRay.Origin + clickRay.Direction.ToUnit() * clickDist;
                }

                // Update the click plane
                if (clickPlane == null)
                {
                    Vector3D standard = Math3D.GetArbitraryOrhonganal(clickRay.Direction);
                    Vector3D orth     = Vector3D.CrossProduct(standard, clickRay.Direction);
                    clickPlane = new Triangle(clickPoint3D, clickPoint3D + standard, clickPoint3D + orth);
                }

                // Store the point and plane
                _strokes.AddPointToStroke(clickPoint3D);
                _clickPlane = clickPlane;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Beispiel #5
0
        /// <summary>
        /// This overload is the same as the previous, but if the camera is looking along the plane/cylinder wall, then the output will be
        /// constrained to a line/circle
        /// NOTE: Sphere and circle will never be constrained, the lesser overload will be used instead
        /// </summary>
        public Point3D?CastRay(RayHitTestParameters mouseDownClickRay, RayHitTestParameters mouseDownCenterRay, RayHitTestParameters currentClickRay, PerspectiveCamera camera, Viewport3D viewport)
        {
            if (_shape == ShapeType.None)
            {
                return(null);
            }
            else if (_shape == ShapeType.Sphere || _shape == ShapeType.Circle || _shape == ShapeType.Circles)
            {
                return(CastRay(mouseDownClickRay, mouseDownCenterRay, currentClickRay));
            }

            #region Get dot product

            //NOTE: _camera.LookDirection and _camera.UpDirection are really screwed up (I think that the trackball messed them up), so fire a ray instead
            // I'm not using the mouse click point, because that can change as they drag, and the inconsistency would be jarring
            RayHitTestParameters cameraLook = UtilityWPF.RayFromViewportPoint(camera, viewport, new Point(viewport.ActualWidth / 2d, viewport.ActualHeight / 2d));

            double   dot  = 0;
            double[] dots = null;

            Vector3D cameraLookUnit = cameraLook.Direction.ToUnit();

            switch (_shape)
            {
            case ShapeType.Plane:
                dot = Vector3D.DotProduct(_plane.NormalUnit, cameraLookUnit);                   // the dot is against the normal
                break;

            case ShapeType.Line:
            case ShapeType.Cylinder:
                //NOTE: They cylinder only limits movement if they are looking along the line.
                dot = Vector3D.DotProduct(_direction.ToUnit(), cameraLookUnit);                 // the dot is along the drag line
                break;

            case ShapeType.Lines:
            case ShapeType.LinesCircles:                // I don't care about the dot product for the circles, they aren't limited
                dots = _lines.Select(o => Vector3D.DotProduct(o.Direction.ToUnit(), cameraLookUnit)).ToArray();
                break;

            default:
                throw new ApplicationException("finish this");
            }

            #endregion

            Point3D?retVal = null;

            switch (_shape)
            {
            case ShapeType.Line:
                #region Line

                if (Math.Abs(dot) > _constrainMaxDotProduct)
                {
                    retVal = null;
                }
                else
                {
                    double dummy1;
                    retVal = CastRay_Line(out dummy1, _point, _direction, mouseDownClickRay, mouseDownCenterRay, currentClickRay);
                }

                #endregion
                break;

            case ShapeType.Lines:
            case ShapeType.Circles:
            case ShapeType.LinesCircles:
                #region Lines/Circles

                //NOTE: These have to look at _shape instead of null checks, because the values may be non null from a previous use

                List <RayHitTestParameters> usableLines = new List <RayHitTestParameters>();
                if (_shape == ShapeType.Lines || _shape == ShapeType.LinesCircles)
                {
                    for (int cntr = 0; cntr < _lines.Length; cntr++)
                    {
                        if (Math.Abs(dots[cntr]) <= _constrainMaxDotProduct)
                        {
                            usableLines.Add(_lines[cntr]);
                        }
                    }
                }

                CircleDefinition[] usableCircles = null;
                if (_shape == ShapeType.Circles || _shape == ShapeType.LinesCircles)
                {
                    usableCircles = _circles;                   // all circles are always used
                }

                retVal = CastRay_LinesCircles(usableLines, usableCircles, mouseDownClickRay, mouseDownCenterRay, currentClickRay);

                #endregion
                break;

            case ShapeType.Plane:
                #region Plane

                if (Math.Abs(dot) < 1d - _constrainMaxDotProduct)
                {
                    retVal = CastRay_PlaneLimited(_plane, mouseDownClickRay, mouseDownCenterRay, currentClickRay, cameraLook);
                }
                else
                {
                    retVal = CastRay_Plane(_plane, mouseDownClickRay, mouseDownCenterRay, currentClickRay);
                }

                #endregion
                break;

            case ShapeType.Cylinder:
                #region Cylinder

                if (Math.Abs(dot) > _constrainMaxDotProduct)
                {
                    // Constrain to a circle
                    Vector3D circleVector1 = Math3D.GetArbitraryOrhonganal(_direction);
                    Vector3D circleVector2 = Vector3D.CrossProduct(circleVector1, _direction);
                    Triangle plane         = new Triangle(_point, _point + circleVector1, _point + circleVector2);

                    double dummy1;
                    retVal = CastRay_Circle(out dummy1, plane, _point, _radius, mouseDownClickRay, mouseDownCenterRay, currentClickRay);
                }
                else
                {
                    retVal = CastRay_Cylinder(_point, _direction, _radius, mouseDownClickRay, mouseDownCenterRay, currentClickRay);
                }

                #endregion
                break;

            case ShapeType.Mesh:
                throw new ApplicationException("finish this");

            case ShapeType.None:
                retVal = null;
                break;

            default:
                throw new ApplicationException("Unknown ShapeType: " + _shape.ToString());
            }

            return(retVal);
        }
Beispiel #6
0
        private static MeshGeometry3D GetArrowMesh(Point3D from, Point3D to, double thickness)
        {
            double half = thickness / 2d;

            Vector3D line = to - from;

            if (line.X == 0 && line.Y == 0 && line.Z == 0)
            {
                line.X = 0.000000001d;
            }

            Vector3D orth1 = Math3D.GetArbitraryOrhonganal(line);

            orth1 = Math3D.RotateAroundAxis(orth1, line, StaticRandom.NextDouble() * Math.PI * 2d);             // give it a random rotation so that if many lines are created by this method, they won't all be oriented the same
            orth1 = orth1.ToUnit() * half;

            Vector3D orth2 = Vector3D.CrossProduct(line, orth1);

            orth2 = orth2.ToUnit() * half;

            // Define 3D mesh object
            MeshGeometry3D retVal = new MeshGeometry3D();

            // Arrow Base
            retVal.Positions.Add(from - orth1);     // 0
            retVal.Positions.Add(from + orth1);     // 1
            retVal.Positions.Add(from - orth2);     // 2
            retVal.Positions.Add(from + orth2);     // 3

            // Arrow Tip
            retVal.Positions.Add(to);       // 4

            // Tip Faces
            retVal.TriangleIndices.Add(0);
            retVal.TriangleIndices.Add(3);
            retVal.TriangleIndices.Add(4);

            retVal.TriangleIndices.Add(3);
            retVal.TriangleIndices.Add(1);
            retVal.TriangleIndices.Add(4);

            retVal.TriangleIndices.Add(1);
            retVal.TriangleIndices.Add(2);
            retVal.TriangleIndices.Add(4);

            retVal.TriangleIndices.Add(2);
            retVal.TriangleIndices.Add(0);
            retVal.TriangleIndices.Add(4);

            // Base Faces
            //NOTE: These lines need to use as few triangles as possible, and they will almost certainly leave IsShiny false.  So a backplate isn't really needed
            //retVal.TriangleIndices.Add(0);
            //retVal.TriangleIndices.Add(2);
            //retVal.TriangleIndices.Add(1);

            //retVal.TriangleIndices.Add(1);
            //retVal.TriangleIndices.Add(3);
            //retVal.TriangleIndices.Add(0);

            // shouldn't I set normals?
            //retVal.Normals

            //retVal.Freeze();
            return(retVal);
        }
Beispiel #7
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();
        }