コード例 #1
0
ファイル: Bezier.cs プロジェクト: charlierix/AsteroidMiner
        private static Vector3D? GetControlPoints_Middle_ControlLine(Vector3D dir21, Vector3D dir23)
        {
            // Get the angle between the two directions
            double angle = Vector3D.AngleBetween(dir21, dir23);
            if (Double.IsNaN(angle))
            {
                return null;
            }

            Vector3D axis = Vector3D.CrossProduct(dir21, dir23);
            if (axis.IsNearZero())
            {
                return null;
            }

            // Get the vector directly between the two directions
            Vector3D between = dir21.GetRotatedVector(axis, angle / 2d);

            // Now get the vector that is orthogonal to that between vector.  This is the line that
            // the control points will be along
            return Vector3D.CrossProduct(between, axis);        // length doesn't really matter for this.  It could also point in the exact opposite direction, and that wouldn't matter
        }
コード例 #2
0
        public static MeshGeometry3D GetCone_AlongX(int numSegments, double radius, double height)
        {
            // This is a copy of GetCylinder_AlongX
            //TODO: This is so close to GetMultiRingedTube, the only difference is the multi ring tube has "hard" faces, and this has "soft" faces (this one shares points and normals, so the lighting is smoother)

            if (numSegments < 3)
            {
                throw new ArgumentException("numSegments must be at least 3: " + numSegments.ToString(), "numSegments");
            }

            MeshGeometry3D retVal = new MeshGeometry3D();

            #region Initial calculations

            Transform3D transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 90d));

            double halfHeight = height / 2d;

            Point[] points = Math2D.GetCircle_Cached(numSegments);

            double rotateAngleForPerp = Vector3D.AngleBetween(new Vector3D(1, 0, 0), new Vector3D(radius, 0, height));		// the 2nd vector is perpendicular to line formed from the edge of the cone to the tip

            #endregion

            #region Side

            for (int cntr = 0; cntr < numSegments; cntr++)
            {
                retVal.Positions.Add(transform.Transform(new Point3D(points[cntr].X * radius, points[cntr].Y * radius, -halfHeight)));
                retVal.Positions.Add(transform.Transform(new Point3D(0, 0, halfHeight)));		// creating a unique point for each face so that the lighting will be correct

                // The normal points straight out for a cylinder, but for a cone, it needs to be perpendicular to the slope of the cone
                Vector3D normal = new Vector3D(points[cntr].X, points[cntr].Y, 0d);
                Vector3D rotateAxis = new Vector3D(-points[cntr].Y, points[cntr].X, 0d);
                normal = normal.GetRotatedVector(rotateAxis, rotateAngleForPerp);

                retVal.Normals.Add(transform.Transform(normal));

                // This one just points straight up
                retVal.Normals.Add(transform.Transform(new Vector3D(0, 0, 1d)));
            }

            for (int cntr = 0; cntr < numSegments - 1; cntr++)
            {
                // 0,2,3
                retVal.TriangleIndices.Add((cntr * 2) + 0);
                retVal.TriangleIndices.Add((cntr * 2) + 2);
                retVal.TriangleIndices.Add((cntr * 2) + 3);

                // The cylinder has two triangles per face, but the cone only has one
                //// 0,3,1
                //retVal.TriangleIndices.Add((cntr * 2) + 0);
                //retVal.TriangleIndices.Add((cntr * 2) + 3);
                //retVal.TriangleIndices.Add((cntr * 2) + 1);
            }

            // Connecting the last 2 points to the first 2
            // last,0,1
            int offset = (numSegments - 1) * 2;
            retVal.TriangleIndices.Add(offset + 0);
            retVal.TriangleIndices.Add(0);
            retVal.TriangleIndices.Add(1);

            //// last,1,last+1
            //retVal.TriangleIndices.Add(offset + 0);
            //retVal.TriangleIndices.Add(1);
            //retVal.TriangleIndices.Add(offset + 1);

            #endregion

            // Caps
            int pointOffset = retVal.Positions.Count;

            //NOTE: The normals are backward from what you'd think

            GetCylinder_AlongXSprtEndCap(ref pointOffset, retVal, points, new Vector3D(0, 0, 1), radius, radius, -halfHeight, transform);
            //GetCylinder_AlongXSprtEndCap(ref pointOffset, retVal, points, new Vector3D(0, 0, -1), radius, halfHeight, transform);

            // Exit Function
            //retVal.Freeze();
            return retVal;
        }
コード例 #3
0
        private void LinearDotProduct_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Vector3D vector = new Vector3D(1, 0, 0);
                Vector3D axis = new Vector3D(0, 0, 1);

                var test = Enumerable.Range(0, 360).
                    Select(o =>
                        {
                            double angle = o;
                            Vector3D rotated = vector.GetRotatedVector(axis, angle);
                            double dot = Vector3D.DotProduct(vector, rotated);
                            double linear = Math3D.GetLinearDotProduct(vector, rotated);
                            double distance = Math.Abs(dot - linear);

                            return new
                            {
                                Angle = angle,
                                Dot = dot,
                                Linear = linear,
                                Distance = distance,
                            };
                        }).
                    ToArray();

                Point3D[] allPoints = test.
                    SelectMany(o => new[] { new Point3D(o.Angle, o.Dot * 90, 0), new Point3D(o.Angle, o.Linear * 90, 0) }).
                    ToArray();

                IEnumerable<Tuple<int, int>> indicesGap = test.
                    Select((o, i) => Tuple.Create(i * 2, (i * 2) + 1));

                IEnumerable<Tuple<int, int>> indices1 = Enumerable.Range(0, test.Length - 1).
                    Select(o => Tuple.Create(o * 2, (o + 1) * 2));

                IEnumerable<Tuple<int, int>> indices2 = Enumerable.Range(0, test.Length - 1).
                    Select(o => Tuple.Create((o * 2) + 1, ((o + 1) * 2) + 1));

                double thickness = LINETHICKNESS_SCREENSPACE;

                ClearAll();
                AddLines_ScreenSpace(indicesGap, allPoints, thickness, Colors.White);
                AddLines_ScreenSpace(indices1, allPoints, thickness, Colors.Red);
                AddLines_ScreenSpace(indices2, allPoints, thickness, Colors.Blue);

                _camera.Position = new Point3D(180, 0, -500);
                _camera.LookDirection = new Vector3D(0, 0, 1);
                _camera.UpDirection = new Vector3D(0, 1, 0);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
コード例 #4
0
ファイル: Ship.cs プロジェクト: charlierix/AsteroidMiner
        private void ChangeSwarmBots(SwarmFormation formation)
        {
            ChangeSwarmBotsSprtRemoveAll();

            if (formation == SwarmFormation.None)
            {
                _swarmbotFormation = SwarmFormation.None;
                return;
            }

            double startAngle, stepAngle;       // 0 is straight in front of the ship
            int numBots;
            double distanceMult;

            switch (formation)
            {
                case SwarmFormation.AllFront:
                    #region AllFront

                    startAngle = 0d;
                    stepAngle = 360d;

                    //numBots = 20;
                    numBots = _numSwarmbots;

                    distanceMult = 8d;

                    #endregion
                    break;

                case SwarmFormation.AllRear:
                    #region AllRear

                    startAngle = 180d;
                    stepAngle = 360d;

                    //numBots = 20;
                    numBots = _numSwarmbots;

                    distanceMult = 8d;

                    #endregion
                    break;

                case SwarmFormation.Triangle:
                    #region Triangle

                    startAngle = 0d;
                    stepAngle = 120d;

                    //numBots = 10;
                    numBots = _numSwarmbots / 3;
                    if (numBots % 3 != 0 || numBots == 0)
                    {
                        numBots++;
                    }

                    distanceMult = 9d;

                    #endregion
                    break;

                case SwarmFormation.ReverseTriangle:
                    #region ReverseTriangle

                    startAngle = 180d;
                    stepAngle = 120d;

                    //numBots = 10;
                    numBots = _numSwarmbots / 3;
                    if (numBots % 3 != 0 || numBots == 0)
                    {
                        numBots++;
                    }

                    distanceMult = 9d;

                    #endregion
                    break;

                case SwarmFormation.Pentagon:
                    #region Pentagon

                    startAngle = 0d;
                    stepAngle = 72d;

                    //numBots = 7;
                    numBots = _numSwarmbots / 5;
                    if (numBots % 5 != 0 || numBots == 0)
                    {
                        numBots++;
                    }

                    distanceMult = 9d;

                    #endregion
                    break;

                case SwarmFormation.ReversePentagon:
                    #region ReversePentagon

                    startAngle = 180d;
                    stepAngle = 72d;

                    //numBots = 7;
                    numBots = _numSwarmbots / 5;
                    if (numBots % 5 != 0 || numBots == 0)
                    {
                        numBots++;
                    }

                    distanceMult = 9d;

                    #endregion
                    break;

                case SwarmFormation.SurroundShip:
                    #region SurroundShip

                    startAngle = 0d;
                    stepAngle = 360d;

                    //numBots = 30;
                    numBots = _numSwarmbots;

                    distanceMult = 0d;

                    #endregion
                    break;

                default:
                    throw new ApplicationException("Unknown SwarmFormation: " + formation.ToString());
            }

            // Figure out how far away from the ship the bots should be
            double chaseOffsetDistance = (_radiusX + _radiusY) / 2d;
            chaseOffsetDistance *= distanceMult;

            // Build the swarms
            double angle = startAngle;
            while (angle < startAngle + 360d)
            {
                Vector3D chasePoint = new Vector3D(0, chaseOffsetDistance, 0);
                chasePoint = chasePoint.GetRotatedVector(new Vector3D(0, 0, 1), angle);

                _swarmBots.Add(ChangeSwarmBotsSprtSwarm(numBots, chasePoint));
                _swarmbotChasePoints.Add(chasePoint.ToPoint());

                PointVisualizer chasePointSprite = new PointVisualizer(_map.Viewport, _sharedVisuals);
                chasePointSprite.PositionRadius = .1d;
                chasePointSprite.VelocityAccelerationLengthMultiplier = .05d;
                chasePointSprite.ShowPosition = _showDebugVisuals;
                chasePointSprite.ShowVelocity = _showDebugVisuals;
                chasePointSprite.ShowAcceleration = _showDebugVisuals && DEBUGSHOWSACCELERATION;
                _swarmbotChasePointSprites.Add(chasePointSprite);

                angle += stepAngle;
            }

            _swarmbotFormation = formation;
        }
コード例 #5
0
        private static ShipPartDNA[] GetRandomThrusters(int count, bool randomOrientations, ThrusterTypeValues thrustType)
        {
            const double MINRADIUS = 1.5;
            const double MAXRADIUS = 3;
            const double MINSIZE = .5;
            const double MAXSIZE = 1.5;

            if (count < 2)
            {
                throw new ApplicationException("Must have at least two thrusters");
            }

            List<ShipPartDNA> retVal = new List<ShipPartDNA>();

            Random rand = StaticRandom.GetRandomForThread();

            double stepAngle = 360d / count;
            double rangeAngle = 120d / count;       // the sum of these pie slices should cover 2/3 of the area

            Vector3D axis = new Vector3D(0, 0, 1);
            double startAngle = rand.NextDouble(360);

            for (int cntr = 0; cntr < count; cntr++)
            {
                double angle = startAngle + (cntr * stepAngle);
                angle += rand.NextDouble(-rangeAngle, rangeAngle);

                Vector3D position = new Vector3D(rand.NextDouble(MINRADIUS, MAXRADIUS), 0, 0);
                position = position.GetRotatedVector(axis, angle);

                double size = rand.NextDouble(MINSIZE, MAXSIZE);

                //Random direction
                Quaternion orientation = Quaternion.Identity;
                if (randomOrientations)
                {
                    Vector3D standardVect = new Vector3D(0, 0, 1);
                    Vector3D rotatedVect = Math3D.GetRandomVector_Cone(axis, 90);
                    orientation = Math3D.GetRotation(standardVect, rotatedVect);
                }

                ThrusterType type;
                switch (thrustType)
                {
                    case ThrusterTypeValues.Single:
                        type = ThrusterType.One;
                        break;

                    case ThrusterTypeValues.Dual:
                        type = ThrusterType.Two;
                        break;

                    case ThrusterTypeValues.Six:
                        type = ThrusterType.Two_Two_Two;
                        break;

                    case ThrusterTypeValues.Random:
                        type = UtilityCore.GetRandomEnum<ThrusterType>(ThrusterType.Custom);
                        break;

                    default:
                        throw new ApplicationException("Unknown ThrusterTypeValues: " + thrustType.ToString());
                }

                retVal.Add(new ThrusterDNA() { PartType = Thruster.PARTTYPE, Orientation = orientation, Position = position.ToPoint(), Scale = new Vector3D(size, size, size), ThrusterType = type });
            }

            return retVal.ToArray();
        }
コード例 #6
0
        private void CreateSpaceStations()
        {
            double xyCoord = _boundryMax.X * .7;
            double zCoord = _boundryMin.Z - 3;
            double minDistanceBetweenStations = 200d;

            #region Home Station

            // Make one right next to the player at startup (always a distance of 10*sqrt(2), but at a random angle, just so it's not boring)
            Vector3D homeLocation = new Vector3D(14.142, 0, 0);
            homeLocation = homeLocation.GetRotatedVector(new Vector3D(0, 0, 1), Math1D.GetNearZeroValue(360d));

            CreateSpaceStationsSprtBuild(new Point3D(homeLocation.X, homeLocation.Y, zCoord));

            #endregion

            // Make a few more
            for (int cntr = 0; cntr < 4; cntr++)
            {
                // Come up with a position that isn't too close to any other station
                Vector3D position = new Vector3D();
                while (true)
                {
                    #region Figure out position

                    position = Math3D.GetRandomVector_Circular(xyCoord);
                    position.Z = zCoord;

                    // See if this is too close to an existing station
                    bool isTooClose = false;
                    foreach (SpaceStation station in _spaceStations)
                    {
                        Vector3D offset = position - station.PositionWorld.ToVector();
                        if (offset.Length < minDistanceBetweenStations)
                        {
                            isTooClose = true;
                            break;
                        }
                    }

                    if (!isTooClose)
                    {
                        break;
                    }

                    #endregion
                }

                CreateSpaceStationsSprtBuild(position.ToPoint());
            }
        }