internal static UtilityNewt.IObjectMassBreakdown GetMassBreakdown(Vector3D scale, double cellSize) { // Convert this.Scale into a size that the mass breakdown will use Vector3D size = new Vector3D(scale.X, scale.Y, scale.Z); return(UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Sphere, UtilityNewt.MassDistribution.Uniform, size, cellSize)); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X, and scale is for radius, but the mass breakdown wants diameter // Reducing Z a bit, because the energy tank has a rounded cap Vector3D size = new Vector3D(this.Scale.Z * HEIGHTPERCENTOFSCALE, this.Scale.X * RADIUSPERCENTOFSCALE * 2d, this.Scale.Y * RADIUSPERCENTOFSCALE * 2d); // Cylinder UtilityNewt.ObjectMassBreakdown cylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, size, cellSize); Transform3D transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 90)); // the physics hull is along x, but dna is along z // Rotated UtilityNewt.ObjectMassBreakdownSet combined = new UtilityNewt.ObjectMassBreakdownSet( new UtilityNewt.ObjectMassBreakdown[] { cylinder }, new Transform3D[] { transform }); // Store this _massBreakdown = new MassBreakdownCache(combined, Scale, cellSize); return(_massBreakdown.Breakdown); }
internal static UtilityNewt.IObjectMassBreakdown GetSensorMassBreakdown(ref MassBreakdownCache existing, Vector3D scale, double cellSize) { if (existing != null && existing.Scale == scale && existing.CellSize == cellSize) { // This has already been built for this size return(existing.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X, and scale is for radius, but the mass breakdown wants diameter) Vector3D size = new Vector3D(scale.Z * SIZEPERCENTOFSCALE_Z, scale.X * SIZEPERCENTOFSCALE_XY * 2, scale.Y * SIZEPERCENTOFSCALE_XY * 2); var cylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, size, cellSize); Transform3D transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 90)); // the physics hull is along x, but dna is along z // Rotated UtilityNewt.ObjectMassBreakdownSet combined = new UtilityNewt.ObjectMassBreakdownSet( new UtilityNewt.ObjectMassBreakdown[] { cylinder }, new Transform3D[] { transform }); // Store this existing = new MassBreakdownCache(combined, scale, cellSize); return(existing.Breakdown); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } var breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, this.Scale, cellSize); // Store this _massBreakdown = new MassBreakdownCache(breakdown, Scale, cellSize); return(_massBreakdown.Breakdown); }
private static UtilityNewt.ObjectMassBreakdownSet GetMassBreakdown_Trapazoid(Point[] verticies, Vector3D size, double cellSize, bool isRight) { if (verticies.Length != 4) { throw new ApplicationException("There should be exactly 4 verticies passed in: " + verticies.Length.ToString()); } double base1 = (verticies[2].X - verticies[3].X) * size.X; // the verticies are built counter clockwise, starting at the lower left corner double base2 = (verticies[1].X - verticies[0].X) * size.X; double height = (verticies[2].Y - verticies[1].Y) * size.Y; List <Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double> > items = new List <Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double> >(); if (isRight) { // Rectangle double rectBase = base1; var rectangle = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, new Vector3D(rectBase, height, size.Z), cellSize); items.Add(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(rectangle, new Vector3D((base1 * .5d) - (base2 * .5d), 0d, 0d).ToPoint(), Quaternion.Identity, rectBase * height)); // Triangle double triangleBase = base2 - base1; var triangle = GetMassBreakdown_Triangle(new Vector3D(triangleBase, height, size.Z), cellSize, true); items.Add(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(triangle.Item1, new Vector3D(base1 * .5d, 0d, 0d) + triangle.Item2.ToPoint(), Quaternion.Identity, triangleBase * height * .5d)); } else { // Rectangle double rectBase = base1; var rectangle = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, new Vector3D(rectBase, height, size.Z), cellSize); items.Add(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(rectangle, new Vector3D(0d, 0d, 0d).ToPoint(), Quaternion.Identity, rectBase * height)); // Triangle - right double triangleBase = (base2 - base1) * .5d; var triangle = GetMassBreakdown_Triangle(new Vector3D(triangleBase, height, size.Z), cellSize, true); Vector3D triangleOffset = new Vector3D((rectBase * .5d) + (triangleBase * .5d), 0d, 0d) + triangle.Item2; double triangleArea = triangleBase * height * .5d; items.Add(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(triangle.Item1, triangleOffset.ToPoint(), Quaternion.Identity, triangleArea)); // Triangle - left triangleOffset = new Vector3D(triangleOffset.X * -1d, triangleOffset.Y, triangleOffset.Z); Quaternion triangleOrientation = new Quaternion(new Vector3D(0, 1, 0), 180d); items.Add(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(triangle.Item1, triangleOffset.ToPoint(), triangleOrientation, triangleArea)); } return(UtilityNewt.Combine(items.ToArray())); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X) //DNA plays with X and Z as the 2D axis and height is along Y //Vector3D size = new Vector3D(Scale.X, Scale.Y, Scale.Z * THICKNESS); //Vector3D size = new Vector3D(Scale.Z * THICKNESS, Scale.X, Scale.Y); //Vector3D size = new Vector3D(Scale.X, Scale.Z * THICKNESS, Scale.Y); Vector3D size = new Vector3D(Scale.X, Scale.Y * THICKNESS, Scale.Z); //Vector3D size = new Vector3D(Scale.Z, Scale.X, Scale.Y); UtilityNewt.IObjectMassBreakdown breakdown = null; switch (this.Shape) { case SolarPanelShape.Square: breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, size, cellSize); break; case SolarPanelShape.Right_Triangle: case SolarPanelShape.Triangle: var triangleBreakdown = GetMassBreakdown_Triangle(size, cellSize, this.Shape == SolarPanelShape.Right_Triangle); breakdown = UtilityNewt.Combine(new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>[] { new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(triangleBreakdown.Item1, triangleBreakdown.Item2.ToPoint(), Quaternion.Identity, 1d) }); break; case SolarPanelShape.Right_Trapazoid: case SolarPanelShape.Trapazoid: breakdown = GetMassBreakdown_Trapazoid(this.Vertices.ToArray(), size, cellSize, this.Shape == SolarPanelShape.Right_Trapazoid); break; default: throw new ApplicationException("Unknown SolarPanelShape: " + this.Shape.ToString()); } // Store this _massBreakdown = new MassBreakdownCache(breakdown, Scale, cellSize); return(_massBreakdown.Breakdown); }
internal static UtilityNewt.IObjectMassBreakdown GetCameraMassBreakdown(ref MassBreakdownCache existing, Vector3D scale, double cellSize) { if (existing != null && existing.Scale == scale && existing.CellSize == cellSize) { // This has already been built for this size return(existing.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use Vector3D size = new Vector3D(scale.X * SCALE, scale.Y * SCALE, scale.Z * SCALE); var breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Sphere, UtilityNewt.MassDistribution.Uniform, size, cellSize); // Store this existing = new MassBreakdownCache(breakdown, scale, cellSize); return(existing.Breakdown); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use Vector3D size = new Vector3D(this.Scale.X, this.Scale.Y * RATIOY, this.Scale.Z * RATIOZ); var breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, size, cellSize); // Store this _massBreakdown = new MassBreakdownCache(breakdown, Scale, cellSize); return(_massBreakdown.Breakdown); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use Vector3D size = new Vector3D(this.Scale.X * DirectionControllerRingDesign.SIZEPERCENTOFSCALE, this.Scale.Y * DirectionControllerRingDesign.SIZEPERCENTOFSCALE, this.Scale.Z * DirectionControllerRingDesign.SIZEPERCENTOFSCALE); var breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Sphere, UtilityNewt.MassDistribution.Uniform, size, cellSize); // Store this _massBreakdown = new MassBreakdownCache(breakdown, Scale, cellSize); return(_massBreakdown.Breakdown); }
internal static UtilityNewt.IObjectMassBreakdown GetMassBreakdown(Vector3D scale, double cellSize) { // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X, and scale is for radius, but the mass breakdown wants diameter Vector3D size = new Vector3D(scale.Z * HEIGHTPERCENTOFSCALE, scale.X * RADIUSPERCENTOFSCALE * 2d, scale.Y * RADIUSPERCENTOFSCALE * 2d); // Center Vector3D centerSize = new Vector3D(size.X * .4d, size.Y * .65d, size.Z * .65d); double centerVolume = Math.Pow((centerSize.Y + centerSize.Z) / 4d, 2d) * Math.PI * centerSize.X; // dividing by 4, because div 2 is the average, then another 2 is to convert diameter to radius var centerCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, centerSize, cellSize); // Bulb Vector3D bulbSize = new Vector3D(size.X * .18d, size.Y, size.Z); double bulbVolume = Math.Pow((bulbSize.Y + bulbSize.Z) / 4d, 2d) * Math.PI * bulbSize.X; var bulbCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, bulbSize, cellSize); // Tip Vector3D tipSize = new Vector3D(size.X * .12d, size.Y * .5d, size.Z * .5d); double tipVolume = Math.Pow((tipSize.Y + tipSize.Z) / 4d, 2d) * Math.PI * tipSize.X; var tipCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, tipSize, cellSize); // Combined shape double offsetXBulb = (centerSize.X * .5d) + (bulbSize.X * .5d); double offsetXTip = (centerSize.X * .5d) + bulbSize.X + (tipSize.X * .5d); Quaternion rotate = new Quaternion(new Vector3D(0, 1, 0), 90); var objects = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double> [5]; objects[0] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(centerCylinder, new Point3D(0, 0, 0), rotate, centerVolume); objects[1] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(bulbCylinder, new Point3D(0, 0, offsetXBulb), rotate, bulbVolume); // the breakdowns were build along X, but now putting them back along Z objects[2] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(bulbCylinder, new Point3D(0, 0, -offsetXBulb), rotate, bulbVolume); objects[3] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(tipCylinder, new Point3D(0, 0, offsetXTip), rotate, tipVolume); objects[4] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(tipCylinder, new Point3D(0, 0, -offsetXTip), rotate, tipVolume); var combined = UtilityNewt.Combine(objects); return(combined); }
private static Tuple <UtilityNewt.ObjectMassBreakdown, Vector3D> GetMassBreakdown_Triangle(Vector3D size, double cellSize, bool isRight) { // This is just a hack, because I'm too lazy to make the breakdown calculate a triangle. // I figure if the area of the breakdown is the same as the area of the triangle, and if the breakdown is offset, it should be pretty close // (actually, probably not, because distance counts more than mass: mr^2, so this rectangle approach will probably give a lower inertia // than it should) Vector sizeExtended = new Vector(size.X * 1.1, size.Y * 1.1); // compensating for the lower inertia of the hack rectangle by assuming the triangle is larger double area = sizeExtended.X * sizeExtended.Y * .5d; // cache the area of this triangle double areaRoot = Math.Sqrt(area); // take the square root to see what the average width/height should be double x = sizeExtended.X / sizeExtended.Y * areaRoot; // use the ratio of x to y to see how much of that square root should be double y = sizeExtended.Y / sizeExtended.X * areaRoot; // When the ratio of x to y is too great, the derived x and y become larger than the original, so cap them if (x > sizeExtended.X) { x = sizeExtended.X; y = 2d * area / x; // since x was capped, make y take up the slack } else if (y > sizeExtended.Y) { y = sizeExtended.Y; x = 2d * area / y; } // Now shift the hack rectangle so that it's more over the triangle portion double offsetX = 0d; if (isRight) { offsetX = size.X * -.12d; } double offsetY = size.Y * -.12d; // Build the breakdown and return the breakdown along with the offset var breakdown = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Box, UtilityNewt.MassDistribution.Uniform, new Vector3D(x, y, size.Z), cellSize); return(new Tuple <UtilityNewt.ObjectMassBreakdown, Vector3D>(breakdown, new Vector3D(offsetX, offsetY, 0d))); }
public override UtilityNewt.IObjectMassBreakdown GetMassBreakdown(double cellSize) { if (_massBreakdown != null && _massBreakdown.Scale == Scale && _massBreakdown.CellSize == cellSize) { // This has already been built for this size return(_massBreakdown.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X, and scale is for radius, but the mass breakdown wants diameter Vector3D size = new Vector3D(this.Scale.Z * HEIGHTPERCENTOFSCALE * 2d, this.Scale.X * RADIUSPERCENTOFSCALE * 2d, this.Scale.Y * RADIUSPERCENTOFSCALE * 2d); // HEIGHTPERCENTOFSCALE is a radius, so it needs to be doubled too // Center Vector3D centerSize = new Vector3D(size.X * .5d, size.Y, size.Z); double centerVolume = Math.Pow((centerSize.Y + centerSize.Z) / 4d, 2d) * Math.PI * centerSize.X; // dividing by 4, because div 2 is the average, then another 2 is to convert diameter to radius var centerCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, centerSize, cellSize); // Cap Vector3D capSize = new Vector3D(size.X * .25d, size.Y * .6d, size.Z * .6d); double capVolume = Math.Pow((capSize.Y + capSize.Z) / 4d, 2d) * Math.PI * capSize.X; var capCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, capSize, cellSize); // Combined shape double offsetX = (centerSize.X * .5d) + (capSize.X * .5d); Quaternion rotate = new Quaternion(new Vector3D(0, 1, 0), 90); var objects = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double> [3]; objects[0] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(centerCylinder, new Point3D(0, 0, 0), rotate, centerVolume); objects[1] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(capCylinder, new Point3D(0, 0, offsetX), rotate, capVolume); // the breakdowns were build along X, but now putting them back along Z objects[2] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(capCylinder, new Point3D(0, 0, -offsetX), rotate, capVolume); var combined = UtilityNewt.Combine(objects); // Store this _massBreakdown = new MassBreakdownCache(combined, Scale, cellSize); return(_massBreakdown.Breakdown); }
internal static UtilityNewt.IObjectMassBreakdown GetTankMassBreakdown(ref MassBreakdownCache existing, Vector3D scale, double cellSize) { if (existing != null && existing.Scale == scale && existing.CellSize == cellSize) { // This has already been built for this size return(existing.Breakdown); } // Convert this.Scale into a size that the mass breakdown will use (mass breakdown wants height along X, and scale is for radius, but the mass breakdown wants diameter Vector3D size = new Vector3D(scale.Z, scale.X * RADIUSPERCENTOFSCALE * 2d, scale.Y * RADIUSPERCENTOFSCALE * 2d); // Main Cylinder Vector3D mainSize = new Vector3D(size.X * .75d, size.Y, size.Z); double mainVolume = Math.Pow((mainSize.Y + mainSize.Z) / 4d, 2d) * Math.PI * mainSize.X; // dividing by 4, because div 2 is the average, then another 2 is to convert diameter to radius var mainCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, mainSize, cellSize); // End Caps Vector3D capSize = new Vector3D(size.X * .125d, size.Y * .5d, size.Z * .5d); double capVolume = Math.Pow((capSize.Y + capSize.Z) / 4d, 2d) * Math.PI * capSize.X; var capCylinder = UtilityNewt.GetMassBreakdown(UtilityNewt.ObjectBreakdownType.Cylinder, UtilityNewt.MassDistribution.Uniform, capSize, cellSize); // Combined shape double offsetX = (mainSize.X * .5d) + (capSize.X * .5d); Quaternion rotate = new Quaternion(new Vector3D(0, 1, 0), 90); var objects = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double> [3]; objects[0] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(mainCylinder, new Point3D(0, 0, 0), rotate, mainVolume); objects[1] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(capCylinder, new Point3D(0, 0, offsetX), rotate, capVolume); // the breakdowns were build along X, but now putting them back along Z objects[2] = new Tuple <UtilityNewt.ObjectMassBreakdown, Point3D, Quaternion, double>(capCylinder, new Point3D(0, 0, -offsetX), rotate, capVolume); var combined = UtilityNewt.Combine(objects); // Store this existing = new MassBreakdownCache(combined, scale, cellSize); return(existing.Breakdown); }
private void DrawMassBreakdown(UtilityNewt.IObjectMassBreakdown breakdown, double cellSize) { #region Draw masses as cubes double radMult = (cellSize * .75d) / breakdown.Max(o => o.Item2); DoubleVector dirFacing = new DoubleVector(1, 0, 0, 0, 1, 0); Model3DGroup geometries = new Model3DGroup(); foreach (var pointMass in breakdown) { double radius = pointMass.Item2 * radMult; CollisionHull dummy1; Transform3DGroup dummy2; Quaternion dummy3; DiffuseMaterial dummy4; geometries.Children.Add(GetWPFGeometry(out dummy1, out dummy2, out dummy3, out dummy4, CollisionShapeType.Box, _colors.MassBall, _colors.MassBallReflect, _colors.MassBallReflectIntensity, new Vector3D(radius, radius, radius), pointMass.Item1, dirFacing, false)); } ModelVisual3D visual = new ModelVisual3D(); visual.Content = geometries; _viewport.Children.Add(visual); _currentVisuals.Add(visual); #endregion #region Draw Axiis ScreenSpaceLines3D line = new ScreenSpaceLines3D(); line.Color = Colors.DimGray; line.Thickness = 2d; line.AddLine(new Point3D(0, 0, 0), new Point3D(10, 0, 0)); _viewport.Children.Add(line); _currentVisuals.Add(line); line = new ScreenSpaceLines3D(); line.Color = Colors.Silver; line.Thickness = 2d; line.AddLine(new Point3D(0, 0, 0), new Point3D(0, 10, 0)); _viewport.Children.Add(line); _currentVisuals.Add(line); line = new ScreenSpaceLines3D(); line.Color = Colors.White; line.Thickness = 2d; line.AddLine(new Point3D(0, 0, 0), new Point3D(0, 0, 10)); _viewport.Children.Add(line); _currentVisuals.Add(line); #endregion }