private ChangeInstruction(Asteroid[] remove_Asteroids, Mineral[] remove_Minerals)
            {
                this.InstructionType = MapPopulationManager.InstructionType.Remove;

                this.Remove_Asteroids = remove_Asteroids;
                this.Remove_Minerals = remove_Minerals;

                this.Add_Position = new Point3D();
                this.Add_Velocity = new Vector3D();
                this.Add_AngVel = new Vector3D();
                this.Asteroid = null;
                this.Mineral = null;
            }
            private ChangeInstruction(Point3D add_Position, Vector3D add_Velocity, Vector3D add_AngVel, AsteroidDNA asteroid, MineralDNA mineral, Asteroid[] remove_Asteroids, Mineral[] remove_Minerals)
            {
                this.InstructionType = MapPopulationManager.InstructionType.Merge;

                this.Add_Position = add_Position;
                this.Add_Velocity = add_Velocity;
                this.Add_AngVel = add_AngVel;

                this.Asteroid = asteroid;
                this.Mineral = mineral;

                this.Remove_Asteroids = remove_Asteroids;
                this.Remove_Minerals = remove_Minerals;
            }
        private void ShowAsteroid_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                RemoveItem_Click(this, new RoutedEventArgs());

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

                Asteroid asteroid = new Asteroid(5, (r, t) => r * 600, position, _world, _map, _material_Item);

                asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVector_Spherical(2d);

                _map.AddItem(asteroid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
예제 #4
0
        private void PhysicsAsteroids()
        {
            const double ONETHIRD = 1d / 3d;
            const double DENSITY = 10;

            if (_explosion == null || _explosion.Shards == null)
            {
                return;
            }

            var getMass = new Func<double, ITriangleIndexed[], double>((rad, tris) =>
            {
                double volume = 4d * ONETHIRD * Math.PI * rad * rad * rad;
                return DENSITY * volume;
            });

            _asteroidShards = new Asteroid[_explosion.Shards.Length];

            for (int cntr = 0; cntr < _explosion.Shards.Length; cntr++)
            {
                AsteroidExtra extra = new AsteroidExtra()
                {
                    Triangles = _explosion.Shards[cntr].Hull_Centered,
                    RandomRotation = false,
                    GetVisual = GetAsteroid,
                };

                _asteroidShards[cntr] = new Asteroid(_explosion.Shards[cntr].Radius, getMass, _explosion.Shards[cntr].Center_ParentCoords, _world, _map, _material_Asteroid, extra);

                if (_explosion.Velocities != null && _explosion.Velocities.Length == _explosion.Shards.Length)
                {
                    _asteroidShards[cntr].PhysicsBody.Velocity = _explosion.Velocities[cntr];
                }

                _map.AddItem(_asteroidShards[cntr]);
            }
        }
예제 #5
0
        private void PhysicsAsteroids_ORIG(Tuple<int, ITriangleIndexed[]>[] asteroidShards, Tuple<Point3D, Vector3D, double>[] shots, double asteroidRadius)
        {
            const double ONETHIRD = 1d / 3d;
            const double DENSITY = 10;

            var subAsteroidProps = asteroidShards.
                Select(o =>
                {
                    #region examine shard

                    var aabb = Math3D.GetAABB(o.Item2);

                    double radius = Math.Sqrt((aabb.Item2 - aabb.Item1).Length / 2);

                    Point3D center = Math3D.GetCenter(TriangleIndexed.GetUsedPoints(o.Item2));
                    Vector3D centerVect = center.ToVector();

                    Point3D[] allPoints = o.Item2[0].AllPoints.
                        Select(p => p - centerVect).
                        ToArray();

                    TriangleIndexed[] shiftedTriangles = o.Item2.
                        Select(p => new TriangleIndexed(p.Index0, p.Index1, p.Index2, allPoints)).
                        ToArray();

                    return new
                    {
                        Index = o.Item1,
                        Triangles = shiftedTriangles,
                        Radius = radius,
                        Center = center,
                    };

                    #endregion
                }).
                ToArray();


            //TODO: When the asteroid shards are resmoothed, the velocities are very small
            //
            //Maybe add more orth velocity
            //
            //Maybe pull the hit source slightly into the asteroid
            //
            //Maybe add some random velocity (size proportional to the velocity)

            Vector3D[] veclocites = CalculateVelocites(subAsteroidProps.Select(o => o.Center).ToArray(), shots, asteroidRadius);

            veclocites = veclocites.
                Select(o => o + Math3D.GetRandomVector_Spherical(o.Length * .25)).
                ToArray();



            var getMass = new Func<double, ITriangleIndexed[], double>((rad, tris) =>
            {
                double volume = 4d * ONETHIRD * Math.PI * rad * rad * rad;
                return DENSITY * volume;
            });

            _asteroidShards = new Asteroid[asteroidShards.Length];

            for (int cntr = 0; cntr < asteroidShards.Length; cntr++)
            {
                AsteroidExtra extra = new AsteroidExtra()
                {
                    Triangles = subAsteroidProps[cntr].Triangles,
                    RandomRotation = false,
                    GetVisual = GetAsteroid,
                };

                _asteroidShards[cntr] = new Asteroid(subAsteroidProps[cntr].Radius, getMass, subAsteroidProps[cntr].Center, _world, _map, _material_Asteroid, extra);

                _asteroidShards[cntr].PhysicsBody.Velocity = veclocites[cntr];

                _map.AddItem(_asteroidShards[cntr]);
            }
        }
        private void AddAsteroid_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Point3D position = Math3D.GetRandomVector_Spherical(BOUNDRYSIZEHALF * .75d).ToPoint();

                Asteroid asteroid = new Asteroid(StaticRandom.NextPercent(ASTEROIDRADIUS, .5), GetAsteroidMass, position, _world, _map, _material_Asteroid);

                asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVector_Spherical(1d);
                asteroid.PhysicsBody.Velocity = Math3D.GetRandomVector_Spherical(4d);

                _map.AddItem(asteroid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
예제 #7
0
        private void CreateAsteroids_Build(double radius, Point3D position)
        {
            AsteroidExtra extra = new AsteroidExtra()
            {
                GetMineralsByDestroyedMass = GetMineralsFromDestroyedAsteroid,
                MineralMaterialID = _material_Mineral,
                MinChildRadius = ItemOptionsAstMin2D.MINASTEROIDRADIUS,
            };

            Asteroid asteroid = new Asteroid(radius, GetAsteroidMassByRadius, position, _world, _map, _material_Asteroid, extra);

            asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVector_Spherical(1d);
            asteroid.PhysicsBody.Velocity = Math3D.GetRandomVector_Circular(6d);
            //asteroid.PhysicsBody.Velocity = asteroid.PhysicsBody.Position.ToVector().ToUnit() * -10d;		// makes all the asteroids come toward the origin (this is just here for testing)
            //asteroid.PhysicsBody.Velocity = asteroid.PhysicsBody.Position.ToVector().ToUnit().GetRotatedVector(new Vector3D(0, 0, 1), -90) * (StaticRandom.NextDouble() * 10d);


            //asteroid.PhysicsBody.ApplyForceAndTorque += new EventHandler<BodyApplyForceAndTorqueArgs>(Asteroid_ApplyForceAndTorque);


            _map.AddItem(asteroid);

            // This works, but the asteroids end up being added after the space stations, and the transparency makes them invisible
            #region Multithread

            //// Come up with the hull on a separate thread (this should speed up the perceived load time a bit)
            //var task = Task.Factory.StartNew(() =>
            //{
            //    return Asteroid.GetHullTriangles(radius);
            //});

            //// Run this on the UI thread once the hull is built
            ////NOTE: This is not the same as a wait.  Execution will go out of this method, and this code will fire like an event later
            //task.ContinueWith(resultTask =>
            //    {
            //        double mass = 10d + (radius * 100d);		// this isn't as realistic as 4/3 pi r^3, but is more fun and stable

            //        Asteroid asteroid = new Asteroid(radius, mass, position, _world, _material_Asteroid, task.Result);

            //        asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVectorSpherical(1d);
            //        asteroid.PhysicsBody.Velocity = Math3D.GetRandomVectorSpherical(6d);
            //        //asteroid.PhysicsBody.Velocity = asteroid.PhysicsBody.Position.ToVector().ToUnit() * -10d;		// makes all the asteroids come toward the origin (this is just here for testing)

            //        asteroid.PhysicsBody.ApplyForceAndTorque += new EventHandler<BodyApplyForceAndTorqueArgs>(Body_ApplyForceAndTorque);

            //        _map.AddItem(asteroid);
            //    }, TaskScheduler.FromCurrentSynchronizationContext());

            #endregion
        }
        private void CreateAsteroids_Build(double radius)
        {
            var getMass = new Func<double, ITriangleIndexed[], double>((rad, tris) => 10d + (rad * 100d));      // this isn't as realistic as 4/3 pi r^3, but is more fun and stable

            Asteroid asteroid = new Asteroid(radius, getMass, new Point3D(0, 0, 0), _world, _map, _material_Asteroid);

            var posVel = GetPositionVelocity(asteroid.PhysicsBody.Mass);

            asteroid.PhysicsBody.Position = posVel.Item1;

            asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVector_Spherical(1d);
            //asteroid.PhysicsBody.Velocity = asteroid.PhysicsBody.Position.ToVector().ToUnit() * -10d;		// makes all the asteroids come toward the origin (this is just here for testing)
            asteroid.PhysicsBody.Velocity = posVel.Item2;


            asteroid.PhysicsBody.ApplyForceAndTorque += new EventHandler<BodyApplyForceAndTorqueArgs>(Asteroid_ApplyForceAndTorque);

            _map.AddItem(asteroid);

            // This works, but the asteroids end up being added after the space stations, and the transparency makes them invisible
            #region Multithread

            //// Come up with the hull on a separate thread (this should speed up the perceived load time a bit)
            //var task = Task.Factory.StartNew(() =>
            //{
            //    return Asteroid.GetHullTriangles(radius);
            //});

            //// Run this on the UI thread once the hull is built
            ////NOTE: This is not the same as a wait.  Execution will go out of this method, and this code will fire like an event later
            //task.ContinueWith(resultTask =>
            //    {
            //        double mass = 10d + (radius * 100d);		// this isn't as realistic as 4/3 pi r^3, but is more fun and stable

            //        Asteroid asteroid = new Asteroid(radius, mass, position, _world, _material_Asteroid, task.Result);

            //        asteroid.PhysicsBody.AngularVelocity = Math3D.GetRandomVectorSpherical(1d);
            //        asteroid.PhysicsBody.Velocity = Math3D.GetRandomVectorSpherical(6d);
            //        //asteroid.PhysicsBody.Velocity = asteroid.PhysicsBody.Position.ToVector().ToUnit() * -10d;		// makes all the asteroids come toward the origin (this is just here for testing)

            //        asteroid.PhysicsBody.ApplyForceAndTorque += new EventHandler<BodyApplyForceAndTorqueArgs>(Body_ApplyForceAndTorque);

            //        _map.AddItem(asteroid);
            //    }, TaskScheduler.FromCurrentSynchronizationContext());

            #endregion
        }
 // Merge
 public ChangeInstruction(Point3D add_Position, Vector3D add_Velocity, Vector3D add_AngVel, AsteroidDNA asteroid, Asteroid[] remove_Asteroids)
     : this(add_Position, add_Velocity, add_AngVel, asteroid, null, remove_Asteroids, null) { }
 // Remove
 public ChangeInstruction(Asteroid[] remove_Asteroids)
     : this(remove_Asteroids, (Mineral[])null) { }
        private void AddAsteroid(ChangeInstruction instr)
        {
            //NOTE: The dna only holds radius, no triangles
            AsteroidExtra extra = new AsteroidExtra()
            {
                GetMineralsByDestroyedMass = _getMineralsByDestroyedMass,
                MineralMaterialID = _material_Mineral,
                MinChildRadius = _minChildAsteroidRadius,
            };

            Asteroid asteroid = new Asteroid(instr.Asteroid.Radius, _getAsteroidMassByRadius, instr.Add_Position, _world, _map, _material_Asteroid, extra);

            asteroid.PhysicsBody.AngularVelocity = instr.Add_AngVel;
            asteroid.PhysicsBody.Velocity = instr.Add_Velocity;

            _map.AddItem(asteroid);
        }
예제 #12
0
        private Visual3D GetAsteroidBlip(Asteroid asteroid)
        {
            if (asteroid.Radius < 2)
            {
                // No need to flood the map with tiny asteroids
                return null;
            }

            // Material
            MaterialGroup materials = new MaterialGroup();
            materials.Children.Add(new DiffuseMaterial(Brushes.DimGray));
            //materials.Children.Add(new SpecularMaterial(Brushes.White, 20d));

            // Geometry Model
            GeometryModel3D geometry = new GeometryModel3D();
            geometry.Material = materials;
            geometry.BackMaterial = materials;
            geometry.Geometry = _blipGeometry_Circle.Value;

            double[] astRad = new[] { asteroid.RadiusVect.X, asteroid.RadiusVect.Y, asteroid.RadiusVect.Z }.OrderByDescending(o => o).ToArray();
            double avgRad = Math1D.Avg(asteroid.RadiusVect.X, asteroid.RadiusVect.Y, asteroid.RadiusVect.Z);

            Transform3DGroup transform = new Transform3DGroup();
            transform.Children.Add(new ScaleTransform3D(astRad[0] * 2.2, astRad[2] * 2.2, astRad[1] * .5));
            transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), StaticRandom.NextDouble(360))));
            geometry.Transform = transform;

            // Model Visual
            ModelVisual3D retVal = new ModelVisual3D();
            retVal.Content = geometry;

            // Exit Function
            return retVal;
        }
예제 #13
0
            public HitTracker2(World world, Map map, int materialID, Asteroid parent, Vector3D radius, double minChildRadius, Func<double, ITriangleIndexed[], double> getMassByRadius, Func<double, MineralDNA[]> getMineralsByDestroyedMass, int mineralMaterialID)
            {
                _world = world;
                _map = map;
                _materialID = materialID;
                _parent = parent;
                _minChildRadius = minChildRadius;
                _getMassByRadius = getMassByRadius;
                _getMineralsByDestroyedMass = getMineralsByDestroyedMass;
                _mineralMaterialID = mineralMaterialID;

                _radius = radius;
                _radiusMin = Math1D.Min(_radius.X, _radius.Y, _radius.Z);
            }
예제 #14
0
            // This also creates minerals
            private IMapObject[] GetChildAsteroids(double overDamage, Point3D parentPos, Vector3D parentVel)
            {
                const double MAXOVERDMG = 13;       // overdamage of 1 is the smallest value (the asteroid was barely destroyed).  Larger values are overkill, and the asteroid becomes more fully destroyed
                const int MAXCHILDREN = 5;

                #region Child asteroid sizes

                // Figure out the radius of the child asteroids
                double radius = GetTotalChildRadius(_radius, overDamage, MAXOVERDMG);

                // Get the volumes of the child asteroids
                double[] asteroidVolumes = null;
                if (radius > _minChildRadius)
                {
                    double totalVolume = 4d / 3d * Math.PI * radius * radius * radius;
                    double minVolume = 4d / 3d * Math.PI * _minChildRadius * _minChildRadius * _minChildRadius;

                    int numChildren = GetNumChildren(radius, MAXCHILDREN, totalVolume, minVolume, overDamage, MAXOVERDMG);
                    asteroidVolumes = GetChildVolumes(numChildren, totalVolume, minVolume);
                }
                else
                {
                    // Not enough left, don't create any child asteroids
                    radius = 0;
                    asteroidVolumes = new double[0];
                }

                #endregion
                #region Mineral sizes

                MineralDNA[] mineralDefinitions = null;
                if (_getMineralsByDestroyedMass != null)
                {
                    //double destroyedMass = GetDestroyedMass(Math3D.Avg(_radius.X, _radius.Y, _radius.Z), radius, _getMassByRadius);       // using avg had too many cases where the returned mass was negative
                    double destroyedMass = GetDestroyedMass(Math1D.Max(_radius.X, _radius.Y, _radius.Z), radius, _getMassByRadius);
                    if (destroyedMass > 0)      // child radius is calculated using max of _radius, but avg was passed to the getmass method.  So there's a chance that getmass returns negative
                    {
                        mineralDefinitions = _getMineralsByDestroyedMass(destroyedMass);
                    }
                }

                if (mineralDefinitions == null)
                {
                    mineralDefinitions = new MineralDNA[0];
                }

                #endregion

                if (asteroidVolumes.Length == 0 && mineralDefinitions.Length == 0)
                {
                    // Nothing to spawn
                    return null;
                }

                // Figure out positions
                AsteroidOrMineralDefinition[] children = PositionChildAsteroidsAndMinerals(asteroidVolumes, mineralDefinitions);

                #region Create IMapObjects

                IMapObject[] retVal = new IMapObject[children.Length];

                for (int cntr = 0; cntr < retVal.Length; cntr++)
                {
                    Point3D position = parentPos + children[cntr].Part.Position.ToVector();

                    if (children[cntr].IsAsteroid)
                    {
                        // Asteroid
                        AsteroidExtra extra = new AsteroidExtra()
                        {
                            Triangles = children[cntr].AsteroidTriangles,
                            GetMineralsByDestroyedMass = _getMineralsByDestroyedMass,
                            MineralMaterialID = _mineralMaterialID,
                            MinChildRadius = _minChildRadius,
                        };

                        retVal[cntr] = new Asteroid(children[cntr].AsteroidRadius, _getMassByRadius, position, _world, _map, _materialID, extra);
                    }
                    else
                    {
                        // Mineral
                        MineralDNA mindef = children[cntr].MineralDefinition;
                        double densityMult = mindef.Density / Mineral.GetSettingsForMineralType(mindef.MineralType).Density;
                        retVal[cntr] = new Mineral(mindef.MineralType, position, mindef.Volume, _world, _mineralMaterialID, _sharedVisuals.Value, densityMult, mindef.Scale);
                    }

                    retVal[cntr].PhysicsBody.Rotation = children[cntr].Part.Orientation;

                    Vector3D velFromCenter = children[cntr].Part.Position.ToVector().ToUnit(false);
                    velFromCenter *= UtilityCore.GetScaledValue(1, 4, 1, MAXOVERDMG, overDamage);

                    retVal[cntr].PhysicsBody.Velocity = parentVel + velFromCenter;

                    retVal[cntr].PhysicsBody.AngularVelocity = Math3D.GetRandomVector_Spherical(UtilityCore.GetScaledValue(.5, 8, 1, MAXOVERDMG, overDamage));
                }

                #endregion

                return retVal;
            }
예제 #15
0
            private IMapObject[] ConvertToMapObjects(AsteroidOrMineralDefinition[] items, Point3D parentPos, Vector3D parentVel, Quaternion parentRot)
            {
                IMapObject[] retVal = new IMapObject[items.Length];

                RotateTransform3D rotate = new RotateTransform3D(new QuaternionRotation3D(parentRot));

                for (int cntr = 0; cntr < retVal.Length; cntr++)
                {
                    Point3D position = parentPos + rotate.Transform(items[cntr].Part.Position.ToVector());

                    if (items[cntr].IsAsteroid)
                    {
                        // Asteroid
                        AsteroidExtra extra = new AsteroidExtra()
                        {
                            Triangles = TriangleIndexed.Clone_Transformed(items[cntr].AsteroidTriangles, rotate),
                            GetMineralsByDestroyedMass = _getMineralsByDestroyedMass,
                            MineralMaterialID = _mineralMaterialID,
                            MinChildRadius = _minChildRadius,
                            RandomRotation = false,
                            SelfDestructAfterElapse = items[cntr].ShouldAsteroidSelfDestruct ? StaticRandom.NextPercent(SELFDESTRUCTTIME, .5) : (double?)null,
                            MineralsWhenSelfDestruct = items[cntr].MineralsAfterSelfDestruct,
                        };

                        retVal[cntr] = new Asteroid(items[cntr].AsteroidRadius, _getMassByRadius, position, _world, _map, _materialID, extra);
                    }
                    else
                    {
                        // Mineral
                        MineralDNA mindef = items[cntr].MineralDefinition;
                        double densityMult = mindef.Density / Mineral.GetSettingsForMineralType(mindef.MineralType).Density;
                        retVal[cntr] = new Mineral(mindef.MineralType, position, mindef.Volume, _world, _mineralMaterialID, _sharedVisuals.Value, densityMult, mindef.Scale);
                    }

                    retVal[cntr].PhysicsBody.Velocity = parentVel + rotate.Transform(items[cntr].Velocity);

                    // Need to be careful if setting this.  Too much, and it will come apart unnaturally
                    //retVal[cntr].PhysicsBody.AngularVelocity = ;
                }

                return retVal;
            }