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); } }
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]); } }
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); } }
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); }
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; }
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); }
// 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; }
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; }