private Point3D GetWorldCenterMass(Body body) { ConvexBody3D bodyCast = body as ConvexBody3D; if (bodyCast == null) { throw new ApplicationException("Couldn't cast body as a ConvexBody3D: " + body.ToString()); } //TODO: Put this in a property off of convexbody //// Get the center of mass in model coords //Point3D centerMass = bodyCast.CenterOfMass; //Vector3D retVal = new Vector3D(centerMass.X, centerMass.Y, centerMass.Z); //// Transform that into world coords //body.VisualMatrix.Transform(retVal); return(body.VisualMatrix.Transform(bodyCast.CenterOfMass)); // Exit Function //return retVal; }
/// <summary> /// Set the properties, then call create /// NOTE: This adds itself to the viewport and world. In the future, that should be handled by the caller /// </summary> public void CreateAsteroid(MaterialManager materialManager, Map map, SharedVisuals sharedVisuals, Vector3D position) { _map = map; #region WPF Model // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(Brushes.Gray)); materials.Children.Add(new SpecularMaterial(Brushes.Silver, 100d)); // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; geometry.Geometry = sharedVisuals.AsteroidMesh; geometry.Transform = new ScaleTransform3D(_radius, _radius, _radius); // Model Visual ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; model.Transform = new TranslateTransform3D(position); // Add to the viewport _visuals.Add(model); _map.Viewport.Children.Add(model); #endregion #region Physics Body // Make a physics body that represents this shape _physicsBody = new ConvexBody3D(_map.World, model); //_physicsBody = new ConvexBody3D(_map.World, model, ConvexBody3D.CollisionShape.Sphere, _radius, _radius, _radius); // for some reason, this is throwing an exception. debug it _physicsBody.MaterialGroupID = materialManager.AsteroidMaterialID; _physicsBody.NewtonBody.UserData = this; _physicsBody.Mass = Convert.ToSingle(_mass); _physicsBody.LinearDamping = .01f; _physicsBody.AngularDamping = new Vector3D(.01f, .01f, .01f); _physicsBody.Override2DEnforcement_Rotation = true; _physicsBody.ApplyForce += new BodyForceEventHandler(Body_ApplyForce); #endregion // Add to the map _map.AddItem(this); }
private void CreateCube(Color color, Point3D location) { #region WPF Model // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(color))); materials.Children.Add(new SpecularMaterial(Brushes.White, 100d)); // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.Geometry = UtilityWPF.GetCube(1d); //geometry.Geometry = UtilityWPF.GetRectangle3D() // Transform Transform3DGroup transform = new Transform3DGroup(); // rotate needs to be added before translate //transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(Math3D.GetRandomVectorSpherical(_rand, 10), Math3D.GetNearZeroValue(_rand, 360d)))); transform.Children.Add(new TranslateTransform3D(location.ToVector())); // Model Visual ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; model.Transform = transform; #endregion // Add to the viewport _viewport.Children.Add(model); // Make a physics body that represents this cube ConvexBody3D body = new ConvexBody3D(_world, model); body.Mass = 1f; _cubes.Add(body); }
public void CreateMineral(MaterialManager materialManager, Map map, SharedVisuals sharedVisuals, Vector3D position, bool randomOrientation, double volumeInCubicMeters) { _map = map; _sharedVisuals = sharedVisuals; if (_mineralType == MineralType.Custom) { #region Validate if (_numSides < 3) { throw new ApplicationException("The number of sides must at least be 3"); } if (_rings.Count == 0) { throw new ApplicationException("Need at least one ring"); } #endregion } else { // Overwrite my public properties based on the mineral type StoreSettingsForMineralType(volumeInCubicMeters); } RotateTransform3D randomRotation = null; if (randomOrientation) { randomRotation = new RotateTransform3D(new AxisAngleRotation3D(Math3D.GetRandomVector_Spherical(1d), Math1D.GetNearZeroValue(360d))); } if (_mineralType == MineralType.Rixium) { #region Rixium Visuals Model3DGroup ringModels = new Model3DGroup(); ringModels.Children.Add(GetRixiumTorusVisual(new Vector3D(0, 0, -.6), .38, .5, randomRotation)); ringModels.Children.Add(GetRixiumTorusVisual(new Vector3D(0, 0, -.3), .44, .75, randomRotation)); ringModels.Children.Add(GetRixiumTorusVisual(new Vector3D(0, 0, 0), .5, 1, randomRotation)); ringModels.Children.Add(GetRixiumTorusVisual(new Vector3D(0, 0, .3), .44, .75, randomRotation)); ringModels.Children.Add(GetRixiumTorusVisual(new Vector3D(0, 0, .6), .38, .5, randomRotation)); //TODO: Look at the global lighting options PointLight pointLight = new PointLight(); pointLight.Color = Color.FromArgb(255, 54, 147, 168); pointLight.Range = 20; pointLight.LinearAttenuation = .33; ringModels.Children.Add(pointLight); ModelVisual3D ringModel = new ModelVisual3D(); // this is the expensive one, so as few of these should be made as possible ringModel.Content = ringModels; _visuals.Add(ringModel); _map.Viewport.Children.Add(ringModel); #endregion } #region WPF Model // Material MaterialGroup materials = new MaterialGroup(); if (_diffuseColor.A > 0) { materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(_diffuseColor))); } if (_specularColor.A > 0) { materials.Children.Add(new SpecularMaterial(new SolidColorBrush(_specularColor), _specularPower)); } if (_emissiveColor.A > 0) { materials.Children.Add(new EmissiveMaterial(new SolidColorBrush(_emissiveColor))); } // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; if (_mineralType == MineralType.Custom) { geometry.Geometry = UtilityWPF.GetMultiRingedTube_ORIG(_numSides, _rings, false, true); } else { geometry.Geometry = _sharedVisuals.GetMineralMesh(_mineralType); } if (randomOrientation) { geometry.Transform = randomRotation; } // Model Visual ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; model.Transform = new TranslateTransform3D(position); // Add to the viewport _visuals.Add(model); _map.Viewport.Children.Add(model); #endregion #region Physics Body // Make a physics body that represents this shape _physicsBody = new ConvexBody3D(_map.World, model); _physicsBody.MaterialGroupID = materialManager.MineralMaterialID; _physicsBody.NewtonBody.UserData = this; _physicsBody.Mass = Convert.ToSingle(_mass); _physicsBody.LinearDamping = .01f; _physicsBody.AngularDamping = new Vector3D(.01f, .01f, .01f); _physicsBody.Override2DEnforcement_Rotation = true; _physicsBody.ApplyForce += new BodyForceEventHandler(Body_ApplyForce); #endregion // Add to the map _map.AddItem(this); }
public PointVisualizer(Viewport3D viewport, SharedVisuals sharedVisuals, ConvexBody3D physicsBody) : this(viewport, sharedVisuals) { _physicsBody = physicsBody; }
private void Body_ApplyForce(Body sender, BodyForceEventArgs e) { ConvexBody3D senderCast = sender as ConvexBody3D; if (senderCast == null) { return; } #region Boundry Force Vector3D positionWorld = senderCast.PositionToWorld(senderCast.CenterOfMass).ToVector(); // Just using one property from boundry assumes the boundry is square, and max is positive double boundryMax = _boundryMax.X; double maxDistance = _boundryMax.X * .85d; if (positionWorld.LengthSquared > maxDistance * maxDistance) { // Get the distance from the max distance double distFromMax = positionWorld.Length - maxDistance; // wait till now to do the expensive operation. // I want an acceleration of zero when distFromMax is 1, but an accel of 10 when it's boundryMax //NOTE: _boundryMax.X is to the edge of the box. If they are in the corner the distance will be greater, so the accel will be greater double accel = UtilityCore.GetScaledValue(0, 30, 0, boundryMax - maxDistance, distFromMax); // Apply a force Vector3D force = positionWorld; force.Normalize(); force *= accel * senderCast.Mass * -1d; e.AddForce(force); } #endregion #region Gravity if (_hasGravity) { //TODO: Attract all other objects to the asteroids if (senderCast.MaterialGroupID == _materialManager.AsteroidMaterialID && _asteroidGravityForces.ContainsKey(senderCast)) { e.AddForce(_asteroidGravityForces[senderCast]); } else if (senderCast.MaterialGroupID == _materialManager.ShipMaterialID && _asteroidGravityForces.Keys.Count > 0) // the asteroids only attract every few frames. If I attract every frame, the forces are unbalanced, and the ship ends up propelling the asteroid around { #region Ship to asteroids Point3D shipPos = senderCast.PositionToWorld(senderCast.CenterOfMass); double shipMass = senderCast.Mass; Vector3D gravityForce = new Vector3D(0, 0, 0); foreach (Asteroid asteroid in _asteroids) { #region Apply Gravity Vector3D gravityLink = shipPos - asteroid.PositionWorld; double force = GRAVITATIONALCONSTANT * (asteroid.Mass * shipMass) / gravityLink.LengthSquared; gravityLink.Normalize(); gravityLink *= force; //_asteroidGravityForces[_asteroids[innerCntr].PhysicsBody] += gravityLink; gravityForce -= gravityLink; #endregion } e.AddForce(gravityForce); #endregion } } #endregion #region Set Velocities if (_setVelocityArgs != null) { _hasSetVelocities = true; // See if the velocity should be set for this type of object bool shouldSetVelocity = false; if (_setVelocityArgs.Asteroids && senderCast.MaterialGroupID == _materialManager.AsteroidMaterialID) { shouldSetVelocity = true; } else if (_setVelocityArgs.Minerals && senderCast.MaterialGroupID == _materialManager.MineralMaterialID) { shouldSetVelocity = true; } if (shouldSetVelocity) { // Figure out the velocity Vector3D velocity = new Vector3D(0, 0, 0); Vector3D angularVelocity = new Vector3D(0, 0, 0); if (_setVelocityArgs.Speed > 0d) { velocity = Math3D.GetRandomVector_Spherical(_setVelocityArgs.Speed); angularVelocity = Math3D.GetRandomVector_Spherical(_setVelocityArgs.Speed / 10d); if (_setVelocityArgs.IsRandom) { double halfSpeed = _setVelocityArgs.Speed / 2d; if (velocity.Length < halfSpeed) { // It's going too slow, choose a new speed between half and full velocity.Normalize(); double newSpeed = halfSpeed + (StaticRandom.NextDouble() * halfSpeed); velocity *= newSpeed; } } else { // GetRandomVectorSpherical returns random, but this should be fixed velocity.Normalize(); velocity *= _setVelocityArgs.Speed; } } // Set it (and clear rotation) senderCast.Omega = angularVelocity; senderCast.Velocity = velocity; } } #endregion }
private void btnAdd_Click(object sender, RoutedEventArgs e) { const double MINRATIO = .25d; const double MAXRATIO = 2d; const double MINMASS = .9d; const double MAXMASS = 5d; try { double ratioX, ratioY, ratioZ; if (chkRandomRatios.IsChecked.Value) { ratioX = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, 0d, 1d, StaticRandom.NextDouble()); ratioY = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, 0d, 1d, StaticRandom.NextDouble()); ratioZ = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, 0d, 1d, StaticRandom.NextDouble()); } else { ratioX = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, trkX.Minimum, trkX.Maximum, trkX.Value); ratioY = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, trkY.Minimum, trkY.Maximum, trkY.Value); ratioZ = UtilityCore.GetScaledValue(MINRATIO, MAXRATIO, trkZ.Minimum, trkZ.Maximum, trkZ.Value); } #region WPF Model // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(UtilityWPF.GetRandomColor(64, 192)))); materials.Children.Add(new SpecularMaterial(Brushes.White, 100d)); // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; geometry.Geometry = UtilityWPF.GetCube(new Point3D(-ratioX, -ratioY, -ratioZ), new Point3D(ratioX, ratioY, ratioZ)); //geometry.Geometry = UtilityWPF.GetRectangle3D() // Transform Transform3DGroup transform = new Transform3DGroup(); // rotate needs to be added before translate transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(Math3D.GetRandomVector_Spherical(10), Math1D.GetNearZeroValue(360d)))); transform.Children.Add(new TranslateTransform3D(Math3D.GetRandomVector(_boundryMin, _boundryMax))); // Model Visual ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; model.Transform = transform; #endregion // Add to the viewport _viewport.Children.Add(model); // Make a physics body that represents this cube ConvexBody3D body = new ConvexBody3D(_world, model); if (chkConstantMass.IsChecked.Value) { body.Mass = 1f; } else { // If I try to be realistic, then it's boring, so I'll scale the result. (density shrinks a bit as things get larger) double mass = ratioX * ratioY * ratioZ; mass = UtilityCore.GetScaledValue(MINMASS, MAXMASS, Math.Pow(MINRATIO, 3), Math.Pow(MAXRATIO, 3), mass); body.Mass = Convert.ToSingle(mass); } body.LinearDamping = .01f; body.AngularDamping = new Vector3D(.01f, .01f, .01f); //TODO: Make this work //body.Velocity = //needed? //_world.AddBody(body); body.ApplyForce += new BodyForceEventHandler(Body_ApplyForce); _cubes.Add(body); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// Set the properties, then call create /// NOTE: This adds itself to the viewport and world. In the future, that should be handled by the caller /// </summary> public void CreateShip(MaterialManager materialManager, SharedVisuals sharedVisuals, Map map, ProgressBarGame progressBarCargo, ProgressBarGame progressBarFuel) { const double THRUSTLINELENGTH = .5d; const double THRUSTLINELENGTH_EXTRA = .75d; const double THRUSTLINELENGTH_TURN = .3; _sharedVisuals = sharedVisuals; _map = map; _progressBarCargo = progressBarCargo; _progressBarFuel = progressBarFuel; #region Thrusters // These need to be definded before the visuals are created double radians = Math1D.DegreesToRadians(225); _thrusterOffset_BottomLeft = new Vector3D(this.RadiusX * Math.Cos(radians), this.RadiusY * Math.Sin(radians), 0); radians = Math1D.DegreesToRadians(135); _thrusterOffset_TopLeft = new Vector3D(this.RadiusX * Math.Cos(radians), this.RadiusY * Math.Sin(radians), 0); radians = Math1D.DegreesToRadians(315); _thrusterOffset_BottomRight = new Vector3D(this.RadiusX * Math.Cos(radians), this.RadiusY * Math.Sin(radians), 0); radians = Math1D.DegreesToRadians(45); _thrusterOffset_TopRight = new Vector3D(this.RadiusX * Math.Cos(radians), this.RadiusY * Math.Sin(radians), 0); _thrustForce = 100d; _torqueballLeftRightThrusterForce = -10d; #region Define ThrustLines //NOTE: The ThrustLine class will add/remove visuals directly from the viewport. There's no need for the map to get involved // The reference to the fuel tank will be made when I create the tank ThrustLine thrustLine; // Up _thrustLines.Add(Key.Up, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * _thrustForce, _thrusterOffset_BottomRight); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.Up].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * _thrustForce, _thrusterOffset_BottomLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.Up].Add(thrustLine); // W _thrustLines.Add(Key.W, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * (_thrustForce * 2d), _thrusterOffset_BottomRight); thrustLine.LineMaxLength = THRUSTLINELENGTH_EXTRA; _thrustLines[Key.W].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * (_thrustForce * 2d), _thrusterOffset_BottomLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH_EXTRA; _thrustLines[Key.W].Add(thrustLine); // Down _thrustLines.Add(Key.Down, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * _thrustForce, _thrusterOffset_TopRight); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.Down].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * _thrustForce, _thrusterOffset_TopLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.Down].Add(thrustLine); // S _thrustLines.Add(Key.S, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * (_thrustForce * 2d), _thrusterOffset_TopRight); thrustLine.LineMaxLength = THRUSTLINELENGTH_EXTRA; _thrustLines[Key.S].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * (_thrustForce * 2d), _thrusterOffset_TopLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH_EXTRA; _thrustLines[Key.S].Add(thrustLine); // Left _thrustLines.Add(Key.Left, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * _torqueballLeftRightThrusterForce, _thrusterOffset_BottomRight); thrustLine.LineMaxLength = THRUSTLINELENGTH_TURN; _thrustLines[Key.Left].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * _torqueballLeftRightThrusterForce, _thrusterOffset_TopLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH_TURN; _thrustLines[Key.Left].Add(thrustLine); // Right _thrustLines.Add(Key.Right, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, 1, 0) * _torqueballLeftRightThrusterForce, _thrusterOffset_TopRight); thrustLine.LineMaxLength = THRUSTLINELENGTH_TURN; _thrustLines[Key.Right].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(0, -1, 0) * _torqueballLeftRightThrusterForce, _thrusterOffset_BottomLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH_TURN; _thrustLines[Key.Right].Add(thrustLine); // A _thrustLines.Add(Key.A, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(-1, 0, 0) * _thrustForce, _thrusterOffset_TopRight); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.A].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(-1, 0, 0) * _thrustForce, _thrusterOffset_BottomRight); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.A].Add(thrustLine); // D _thrustLines.Add(Key.D, new List <ThrustLine>()); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(1, 0, 0) * _thrustForce, _thrusterOffset_TopLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.D].Add(thrustLine); thrustLine = new ThrustLine(_map.Viewport, _sharedVisuals, new Vector3D(1, 0, 0) * _thrustForce, _thrusterOffset_BottomLeft); thrustLine.LineMaxLength = THRUSTLINELENGTH; _thrustLines[Key.D].Add(thrustLine); #endregion #endregion MaterialGroup material = null; GeometryModel3D geometry = null; Model3DGroup models = new Model3DGroup(); ModelVisual3D model = null; #region Interior Extra Visuals // These are visuals that will stay oriented to the ship, but don't count in collision calculations #region Thrusters // These are the little balls, not the thrust lines double thrusterLocScale = 1d; models.Children.Add(GetThrusterVisual(_thrusterOffset_BottomLeft * thrusterLocScale)); models.Children.Add(GetThrusterVisual(_thrusterOffset_BottomRight * thrusterLocScale)); models.Children.Add(GetThrusterVisual(_thrusterOffset_TopLeft * thrusterLocScale)); models.Children.Add(GetThrusterVisual(_thrusterOffset_TopRight * thrusterLocScale)); #endregion #region Cargo Bay //TODO: Make a visual for this (probably pretty cube like) _cargoBay = new CargoBay(_cargoBayMass, _cargoBayVolume); _progressBarCargo.Minimum = 0d; _progressBarCargo.Maximum = _cargoBay.MaxVolume; _progressBarCargo.Value = 0d; #endregion #region Fuel Tank //TODO: This visual should be a pill _fuelTank = new FuelTank(); _fuelTank.DryMass = _fuelTankMass; _fuelTank.QuantityMax = _fuelTankCapacity; _fuelTank.QuantityCurrent = _fuelTank.QuantityMax; // a full tank with the purchace of a new ship!!! _fuelTank.FuelDensity = _fuelDensity; _progressBarFuel.Minimum = 0d; _progressBarFuel.Maximum = _fuelTank.QuantityMax; _progressBarFuel.Value = _fuelTank.QuantityCurrent; // Link to the thrusters foreach (List <ThrustLine> thrustLines in _thrustLines.Values) { foreach (ThrustLine thrustLine1 in thrustLines) { thrustLine1.FuelToThrustRatio = _fuelThrustRatio; thrustLine1.FuelTank = _fuelTank; } } #endregion #region Core // This just looks stupid. The idea is that you would see the various components (which would also be point masses). But until // the user can modify their ship, it's just an arbitrary ellipse that is ugly //// Material //material = new MaterialGroup(); //material.Children.Add(new DiffuseMaterial(Brushes.DimGray)); //material.Children.Add(new SpecularMaterial(Brushes.DimGray, 100d)); //// Geometry Model //geometry = new GeometryModel3D(); //geometry.Material = material; //geometry.BackMaterial = material; //geometry.Geometry = UtilityWPF.GetSphere(5, .45, .25, .05); //geometry.Transform = new TranslateTransform3D(0, this.RadiusY * -.25, 0); //// Model Visual //model = new ModelVisual3D(); //model.Content = geometry; ////NOTE: model.Transform is set to the physics body's transform every frame //// Add to the viewport //_viewport.Children.Add(model); //_visuals.Add(model); #endregion // Make a model visual for what I have so far model = new ModelVisual3D(); // this is the expensive one, so as few of these should be made as possible model.Content = models; _visuals.Add(model); _map.Viewport.Children.Add(model); #endregion #region WPF Collision Model // Material //NOTE: There seems to be an issue with drawing objects inside a semitransparent object - I think they have to be added in a certain order or something //Brush skinBrush = new SolidColorBrush(Color.FromArgb(50, _hullColor.R, _hullColor.G, _hullColor.B)); // making the skin semitransparent, so you can see the components inside Brush skinBrush = new SolidColorBrush(_hullColor); // decided to make it opaque, since I'm not showing anything inside material = new MaterialGroup(); material.Children.Add(new DiffuseMaterial(skinBrush)); material.Children.Add(new SpecularMaterial(Brushes.White, 75d)); // more reflective (and white light) MaterialGroup backMaterial = new MaterialGroup(); backMaterial.Children.Add(new DiffuseMaterial(skinBrush)); backMaterial.Children.Add(new SpecularMaterial(new SolidColorBrush(Color.FromArgb(255, 20, 20, 20)), 10d)); // dark light, and not very reflective // Geometry Model geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = backMaterial; geometry.Geometry = UtilityWPF.GetSphere_LatLon(5, this.RadiusX, this.RadiusY, this.RadiusZ); // Transform Transform3DGroup transform = new Transform3DGroup(); // rotate needs to be added before translate transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0))); transform.Children.Add(new TranslateTransform3D(new Vector3D(0, 0, 0))); // Model Visual model = new ModelVisual3D(); model.Content = geometry; model.Transform = transform; _physicsModel = model; // remember this, so I don't set its transform _visuals.Add(model); // Add to the viewport (the physics body constructor requires it to be added) _map.Viewport.Children.Add(model); #endregion #region Physics Body // Make a physics body that represents this shape _physicsBody = new ConvexBody3D(_map.World, model); _physicsBody.MaterialGroupID = materialManager.ShipMaterialID; _physicsBody.NewtonBody.UserData = this; _physicsBody.Mass = Convert.ToSingle(this.TotalMass); _physicsBody.LinearDamping = .01f; //_physicsBody.AngularDamping = new Vector3D(.01f, .01f, .01f); //_physicsBody.AngularDamping = new Vector3D(10f, 10f, 10f); _physicsBody.AngularDamping = new Vector3D(1f, 1f, 1f); _physicsBody.ApplyForce += new BodyForceEventHandler(Body_ApplyForce); #endregion #region Exterior Extra Visuals // There is a bug in WPF where visuals added after a semitransparent one won't show inside. The cockpit looks stupid when you can see // it inside the skin #region Cockpit // Material material = new MaterialGroup(); material.Children.Add(new DiffuseMaterial(new SolidColorBrush(UtilityWPF.AlphaBlend(Colors.Teal, Colors.DimGray, .2d)))); material.Children.Add(new SpecularMaterial(Brushes.White, 100d)); // Geometry Model geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; //geometry.Geometry = UtilityWPF.GetSphere(3, .4, .2, .3); geometry.Geometry = UtilityWPF.GetSphere_LatLon(3, .45, .25, .25); geometry.Transform = new TranslateTransform3D(0, this.RadiusY * .5, 0); // Model Visual model = new ModelVisual3D(); model.Content = geometry; // Add to the viewport _visuals.Add(model); _map.Viewport.Children.Add(model); #endregion #region Headlight SpotLight spotLight = new SpotLight(); //spotLight.Color = Color.FromArgb(255, 50, 170, 50); spotLight.Color = UtilityWPF.AlphaBlend(Colors.White, _hullColor, .25d); spotLight.Direction = new Vector3D(0, 1, 0); spotLight.OuterConeAngle = 25; spotLight.InnerConeAngle = 5; //spotLight.LinearAttenuation = .1; spotLight.QuadraticAttenuation = .0001; spotLight.Range = 1000; model = new ModelVisual3D(); model.Content = spotLight; _visuals.Add(model); _map.Viewport.Children.Add(model); #endregion #endregion // Add to the map _map.AddItem(this); }
private void btnAdd_Click(object sender, RoutedEventArgs e) { try { // Figure out the ratios and mass of this body ConvexBody3D.CollisionShape shape; double ratioX, ratioY, ratioZ, mass; GetRatiosMass(out shape, out ratioX, out ratioY, out ratioZ, out mass); #region WPF Model // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(UtilityWPF.GetRandomColor(64, 192)))); materials.Children.Add(new SpecularMaterial(Brushes.White, 100d)); // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; switch (shape) { case ConvexBody3D.CollisionShape.Cube: geometry.Geometry = UtilityWPF.GetCube(new Point3D(-ratioX, -ratioY, -ratioZ), new Point3D(ratioX, ratioY, ratioZ)); break; case ConvexBody3D.CollisionShape.Sphere: geometry.Geometry = UtilityWPF.GetSphere_LatLon(5, ratioX, ratioY, ratioZ); //geometry.Geometry = UtilityWPF.GetTorus(30, 10, ratioX * .2, ratioX); // break; case ConvexBody3D.CollisionShape.Capsule: case ConvexBody3D.CollisionShape.ChamferCylinder: case ConvexBody3D.CollisionShape.Cone: case ConvexBody3D.CollisionShape.Cylinder: default: throw new ApplicationException("Unknown ConvexBody3D.CollisionShape: " + shape.ToString()); } // Transform Transform3DGroup transform = new Transform3DGroup(); // rotate needs to be added before translate transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(Math3D.GetRandomVector_Spherical(10), Math1D.GetNearZeroValue(360d)))); transform.Children.Add(new TranslateTransform3D(Math3D.GetRandomVector(CREATEOBJECTBOUNDRY))); // Model Visual ModelVisual3D model = new ModelVisual3D(); model.Content = geometry; model.Transform = transform; #endregion // Add to the viewport _viewport.Children.Add(model); // Make a physics body that represents this shape ConvexBody3D body = new ConvexBody3D(_world, model); body.Mass = Convert.ToSingle(mass); body.LinearDamping = .01f; body.AngularDamping = new Vector3D(.01f, .01f, .01f); body.ApplyForce += new BodyForceEventHandler(Body_ApplyForce); _bodies.Add(body); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }