/// <summary> /// This returns a random ball, with some optional fixed values /// </summary> public static WeaponSpikeBallDNA GetRandomDNA(WeaponSpikeBallMaterial?material = null, double?radius = null) { WeaponSpikeBallDNA retVal = new WeaponSpikeBallDNA(); Random rand = StaticRandom.GetRandomForThread(); // Radius if (radius != null) { retVal.Radius = radius.Value; } else { retVal.Radius = rand.NextDouble(.2, .5); } // Material if (material == null) { retVal.Material = UtilityCore.GetRandomEnum <WeaponSpikeBallMaterial>(); } else { retVal.Material = material.Value; } return(retVal); }
public WeaponSpikeBall(WeaponMaterialCache materials, WeaponSpikeBallDNA dna) { _materials = materials; var model = GetModel(dna, materials); this.Model = model.Item1; this.DNA = model.Item2; }
private static Model3DGroup GetModel_IronSteel(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = WeaponDNA.GetKeyValue("spikeLen", from, to, dna.Radius * StaticRandom.NextDouble(1.3d, 1.8d)); double ballRadius = spikeLength * .6d; #region Spikes System.Windows.Media.Media3D.Material material = materials.Spike_Steel; // the property get returns a slightly random color GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; double[] radii = new double[] { spikeLength, ballRadius *WeaponDNA.GetKeyValue("spikeRadMult", from, to, StaticRandom.NextDouble(.7, .87)) }; TriangleIndexed[] triangles = UtilityWPF.GetIcosahedron(radii); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(triangles); retVal.Children.Add(geometry); #endregion #region Ball material = materials.Ball_Iron; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; triangles = UtilityWPF.GetIcosahedron(ballRadius, 1); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(triangles); retVal.Children.Add(geometry); #endregion return(retVal); }
//TODO: Have an explicit attach point private static Tuple <Model3DGroup, WeaponSpikeBallDNA> GetModel(WeaponSpikeBallDNA dna, WeaponMaterialCache materials) { WeaponSpikeBallDNA finalDNA = UtilityCore.Clone(dna); if (finalDNA.KeyValues == null) { finalDNA.KeyValues = new SortedList <string, double>(); } Model3DGroup model = null; switch (finalDNA.Material) { case WeaponSpikeBallMaterial.Wood: model = GetModel_WoodIron(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Bronze_Iron: model = GetModel_BronzeIron(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Iron_Steel: model = GetModel_IronSteel(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Composite: model = GetModel_Composite(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Klinth: model = GetModel_Klinth(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Moon: model = GetModel_Moon(dna, finalDNA, materials); break; default: throw new ApplicationException("Unknown WeaponSpikeBallMaterial: " + finalDNA.Material.ToString()); } return(Tuple.Create(model, finalDNA)); }
//TODO: Have an explicit attach point private static Tuple<Model3DGroup, WeaponSpikeBallDNA> GetModel(WeaponSpikeBallDNA dna, WeaponMaterialCache materials) { WeaponSpikeBallDNA finalDNA = UtilityCore.Clone(dna); if (finalDNA.KeyValues == null) { finalDNA.KeyValues = new SortedList<string, double>(); } Model3DGroup model = null; switch (finalDNA.Material) { case WeaponSpikeBallMaterial.Wood: model = GetModel_WoodIron(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Bronze_Iron: model = GetModel_BronzeIron(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Iron_Steel: model = GetModel_IronSteel(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Composite: model = GetModel_Composite(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Klinth: model = GetModel_Klinth(dna, finalDNA, materials); break; case WeaponSpikeBallMaterial.Moon: model = GetModel_Moon(dna, finalDNA, materials); break; default: throw new ApplicationException("Unknown WeaponSpikeBallMaterial: " + finalDNA.Material.ToString()); } return Tuple.Create(model, finalDNA); }
/// <summary> /// This returns a random ball that will fit well with the handle passed in /// </summary> public static WeaponSpikeBallDNA GetRandomDNA(WeaponHandleDNA handle) { WeaponSpikeBallDNA retVal = new WeaponSpikeBallDNA(); Random rand = StaticRandom.GetRandomForThread(); // Radius retVal.Radius = GetRandomRadius(handle.Radius, handle.Length); #region Material // Choose a ball material that goes with the handle's material //NOTE: This is assuming that the ball is an appropriate radius for the handle it will be attached to. //A large soft wood could safely handle a very small ball, etc WeaponSpikeBallMaterial[] ballMaterials = null; switch (handle.HandleMaterial) { case WeaponHandleMaterial.Soft_Wood: ballMaterials = new[] { WeaponSpikeBallMaterial.Wood, WeaponSpikeBallMaterial.Composite }; break; case WeaponHandleMaterial.Hard_Wood: ballMaterials = new[] { WeaponSpikeBallMaterial.Wood, WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Composite, WeaponSpikeBallMaterial.Klinth }; break; case WeaponHandleMaterial.Bronze: case WeaponHandleMaterial.Iron: case WeaponHandleMaterial.Steel: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Composite: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Composite, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Klinth: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Moon: ballMaterials = new[] { WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; default: throw new ApplicationException("Unknown WeaponHandleMaterial: " + handle.HandleMaterial.ToString()); } // Choose one from the filtered list retVal.Material = rand.NextItem(ballMaterials); #endregion #region Color ColorHSV? basedOn = null; if (handle.MaterialsForCustomizable != null && handle.MaterialsForCustomizable.Length > 0 && !string.IsNullOrEmpty(handle.MaterialsForCustomizable[0].DiffuseColor)) { basedOn = UtilityWPF.ColorFromHex(handle.MaterialsForCustomizable[0].DiffuseColor).ToHSV(); } switch (retVal.Material) { case WeaponSpikeBallMaterial.Composite: retVal.MaterialsForCustomizable = WeaponHandleDNA.GetRandomMaterials_Composite(null, basedOn); break; case WeaponSpikeBallMaterial.Klinth: retVal.MaterialsForCustomizable = WeaponHandleDNA.GetRandomMaterials_Klinth(null, basedOn); break; } #endregion return retVal; }
private static Model3DGroup GetModel_Moon(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { //TODO: Animate the spikes (shafts of light) by choosing one as the independently rotated spike, and the others run through one step of Math3D.GetRandomVectors_SphericalShell_EvenDist //TODO: Also animate each spike's radius and length (or at least length) //TODO: Also animate each spike's color opacity Model3DGroup retVal = new Model3DGroup(); double spikeLength = dna.Radius * 2d; double ballRadius = dna.Radius * 1d; double spikeRadius = dna.Radius * .033; System.Windows.Media.Media3D.Material material; GeometryModel3D geometry; #region Ball material = materials.Ball_Moon; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; geometry.Geometry = UtilityWPF.GetSphere_LatLon(5, ballRadius); retVal.Children.Add(geometry); #endregion #region Spikes foreach (Vector3D spikeLocation in Math3D.GetRandomVectors_SphericalShell_EvenDist(30, ballRadius, .03, 100)) { material = materials.Spike_Moon; geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation))); // the tube builds along z List<TubeRingBase> rings = new List<TubeRingBase>(); double spikeLengthMid = spikeLength * .75d; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingRegularPolygon(spikeLengthMid, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingDome(spikeLength - spikeLengthMid, false, 2)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, true, false, transform); retVal.Children.Add(geometry); } #endregion return retVal; }
private static Model3DGroup GetModel_Klinth(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = WeaponDNA.GetKeyValue("spikeLength", from, to, StaticRandom.NextPercent(dna.Radius * 1.1d, .05)); double ballRadius = dna.Radius; double spikeRadius = WeaponDNA.GetKeyValue("spikeRadius", from, to, StaticRandom.NextPercent(dna.Radius * .2, .1)); var color = WeaponMaterialCache.GetKlinth(dna.MaterialsForCustomizable); finalDNA.MaterialsForCustomizable = color.Item3; GeometryModel3D geometry; #region Ball geometry = new GeometryModel3D(); geometry.Material = color.Item1; geometry.BackMaterial = color.Item1; Icosidodecahedron ball = UtilityWPF.GetIcosidodecahedron(ballRadius); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(ball.AllTriangles); retVal.Children.Add(geometry); #endregion #region Spikes // Put a spike through the center of each pentagon foreach (Vector3D spikeLocation in ball.PentagonPolys.Select(o => Math3D.GetCenter(o.Select(p => ball.AllPoints[p])))) { geometry = new GeometryModel3D(); geometry.Material = color.Item2; geometry.BackMaterial = color.Item2; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation))); // the tube builds along z List<TubeRingBase> rings = new List<TubeRingBase>(); double spikeLengthMid = spikeLength * .8d; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingRegularPolygon(spikeLengthMid, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingDome(spikeLength - spikeLengthMid, false, 3)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, false, false, transform); retVal.Children.Add(geometry); } #endregion return retVal; }
private static Model3DGroup GetModel_Composite(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); Random rand = StaticRandom.GetRandomForThread(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeOrthLength = WeaponDNA.GetKeyValue("spikeOrthLength", from, to, rand.NextPercent(dna.Radius * 1.4d, .1)); double spikeDiagLength = WeaponDNA.GetKeyValue("spikeDiagLength", from, to, rand.NextPercent(dna.Radius * 1.15d, .05)); double ballRadius = dna.Radius; double spikeOrthRadius = WeaponDNA.GetKeyValue("spikeOrthRadius", from, to, rand.NextPercent(dna.Radius * .5, .1)); double spikeDiagRadius = WeaponDNA.GetKeyValue("spikeDiagRadius", from, to, rand.NextPercent(dna.Radius * .5, .1)); double ballRadiusDepth = ballRadius * .1; //this is how far the triangle parts of the ball sink in var color = WeaponMaterialCache.GetComposite(dna.MaterialsForCustomizable); finalDNA.MaterialsForCustomizable = color.Item4; GeometryModel3D geometry; #region Ball - outer geometry = new GeometryModel3D(); geometry.Material = color.Item1; geometry.BackMaterial = color.Item1; Rhombicuboctahedron ball = UtilityWPF.GetRhombicuboctahedron(ballRadius * 2, ballRadius * 2, ballRadius * 2); TriangleIndexed[] usedTriangles = UtilityCore.Iterate( ball.Squares_Orth.SelectMany(o => o), ball.Squares_Diag.SelectMany(o => o), GetModel_Composite_SquareSides(ball, ballRadiusDepth * 1.1) // this builds plates that go toward the center of the ball, because the triangles are indented ).ToArray(); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(usedTriangles); retVal.Children.Add(geometry); #endregion #region Ball - inner geometry = new GeometryModel3D(); geometry.Material = color.Item2; geometry.BackMaterial = color.Item2; // Use the triangles, but suck them in a bit geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(GetModel_Composite_IndentedTriangles(ball, ballRadiusDepth)); retVal.Children.Add(geometry); #endregion #region Spikes var spikeLocations = UtilityCore.Iterate(ball.SquarePolys_Orth.Select(o => Tuple.Create(true, o)), ball.SquarePolys_Diag.Select(o => Tuple.Create(false, o))). Select(o => new { IsOrth = o.Item1, Center = Math3D.GetCenter(o.Item2.Select(p => ball.AllPoints[p])).ToVector() }); // Put a spike through the center of each square foreach (var spikeLocation in spikeLocations) { geometry = new GeometryModel3D(); geometry.Material = color.Item3; geometry.BackMaterial = color.Item3; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation.Center))); // the tube builds along z List<TubeRingBase> rings = new List<TubeRingBase>(); double spikeLengthActual = spikeLocation.IsOrth ? spikeOrthLength : spikeDiagLength; double spikeRadiusActual = spikeLocation.IsOrth ? spikeOrthRadius : spikeDiagRadius; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadiusActual, spikeRadiusActual, false)); rings.Add(new TubeRingPoint(spikeLengthActual, false)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, true, false, transform); retVal.Children.Add(geometry); } #endregion return retVal; }
private static Model3DGroup GetModel_IronSteel(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = WeaponDNA.GetKeyValue("spikeLen", from, to, dna.Radius * StaticRandom.NextDouble(1.3d, 1.8d)); double ballRadius = spikeLength * .6d; #region Spikes System.Windows.Media.Media3D.Material material = materials.Spike_Steel; // the property get returns a slightly random color GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; double[] radii = new double[] { spikeLength, ballRadius * WeaponDNA.GetKeyValue("spikeRadMult", from, to, StaticRandom.NextDouble(.7, .87)) }; TriangleIndexed[] triangles = UtilityWPF.GetIcosahedron(radii); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(triangles); retVal.Children.Add(geometry); #endregion #region Ball material = materials.Ball_Iron; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; triangles = UtilityWPF.GetIcosahedron(ballRadius, 1); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(triangles); retVal.Children.Add(geometry); #endregion return retVal; }
private static Model3DGroup GetModel_Composite(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); Random rand = StaticRandom.GetRandomForThread(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeOrthLength = WeaponDNA.GetKeyValue("spikeOrthLength", from, to, rand.NextPercent(dna.Radius * 1.4d, .1)); double spikeDiagLength = WeaponDNA.GetKeyValue("spikeDiagLength", from, to, rand.NextPercent(dna.Radius * 1.15d, .05)); double ballRadius = dna.Radius; double spikeOrthRadius = WeaponDNA.GetKeyValue("spikeOrthRadius", from, to, rand.NextPercent(dna.Radius * .5, .1)); double spikeDiagRadius = WeaponDNA.GetKeyValue("spikeDiagRadius", from, to, rand.NextPercent(dna.Radius * .5, .1)); double ballRadiusDepth = ballRadius * .1; //this is how far the triangle parts of the ball sink in var color = WeaponMaterialCache.GetComposite(dna.MaterialsForCustomizable); finalDNA.MaterialsForCustomizable = color.Item4; GeometryModel3D geometry; #region Ball - outer geometry = new GeometryModel3D(); geometry.Material = color.Item1; geometry.BackMaterial = color.Item1; Rhombicuboctahedron ball = UtilityWPF.GetRhombicuboctahedron(ballRadius * 2, ballRadius * 2, ballRadius * 2); TriangleIndexed[] usedTriangles = UtilityCore.Iterate( ball.Squares_Orth.SelectMany(o => o), ball.Squares_Diag.SelectMany(o => o), GetModel_Composite_SquareSides(ball, ballRadiusDepth * 1.1) // this builds plates that go toward the center of the ball, because the triangles are indented ).ToArray(); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(usedTriangles); retVal.Children.Add(geometry); #endregion #region Ball - inner geometry = new GeometryModel3D(); geometry.Material = color.Item2; geometry.BackMaterial = color.Item2; // Use the triangles, but suck them in a bit geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(GetModel_Composite_IndentedTriangles(ball, ballRadiusDepth)); retVal.Children.Add(geometry); #endregion #region Spikes var spikeLocations = UtilityCore.Iterate(ball.SquarePolys_Orth.Select(o => Tuple.Create(true, o)), ball.SquarePolys_Diag.Select(o => Tuple.Create(false, o))). Select(o => new { IsOrth = o.Item1, Center = Math3D.GetCenter(o.Item2.Select(p => ball.AllPoints[p])).ToVector() }); // Put a spike through the center of each square foreach (var spikeLocation in spikeLocations) { geometry = new GeometryModel3D(); geometry.Material = color.Item3; geometry.BackMaterial = color.Item3; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation.Center))); // the tube builds along z List <TubeRingBase> rings = new List <TubeRingBase>(); double spikeLengthActual = spikeLocation.IsOrth ? spikeOrthLength : spikeDiagLength; double spikeRadiusActual = spikeLocation.IsOrth ? spikeOrthRadius : spikeDiagRadius; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadiusActual, spikeRadiusActual, false)); rings.Add(new TubeRingPoint(spikeLengthActual, false)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, true, false, transform); retVal.Children.Add(geometry); } #endregion return(retVal); }
private static Model3DGroup GetModel_WoodIron(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); Random rand = StaticRandom.GetRandomForThread(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = dna.Radius * 1.4d; double ballRadius = dna.Radius * 1d; double spikeRadius = dna.Radius * .2; #region Ball System.Windows.Media.Media3D.Material material = materials.Ball_Wood; // the property get returns a slightly random color GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; // Create a convex hull out of semi evenly distibuted points int numHullPoints = Convert.ToInt32(WeaponDNA.GetKeyValue("numHullPoints", from, to, rand.Next(20, 50))); TriangleIndexed[] ball = Math3D.GetConvexHull(Math3D.GetRandomVectors_SphericalShell_EvenDist(numHullPoints, ballRadius, .03, 10).Select(o => o.ToPoint()).ToArray()); geometry.Geometry = UtilityWPF.GetMeshFromTriangles(ball); retVal.Children.Add(geometry); #endregion // These are placed where the rings are, to push spikes away (so that spikes don't poke through the rings) List<Vector3D> staticPoints = new List<Vector3D>(); #region Rings material = materials.Spike_Iron; // the property get returns a slightly random color // 0, 1 or 2 rings. Higher chance of 0 than 2 int numRings = Convert.ToInt32(WeaponDNA.GetKeyValue("numRings", from, to, Math.Floor(rand.NextPow(2, 2.3)))); double[] zs = new double[0]; switch (numRings) { case 0: break; case 1: zs = new double[] { WeaponDNA.GetKeyValue("ringZ1", from, to, Math1D.GetNearZeroValue(ballRadius * .75)) }; break; case 2: double z1 = WeaponDNA.GetKeyValue("ringZ1", from, to, Math1D.GetNearZeroValue(ballRadius * .75)); double z2 = 0; if (from == null || !from.TryGetValue("ringZ2", out z2)) { do { z2 = Math1D.GetNearZeroValue(ballRadius * .75); } while (Math.Abs(z1 - z2) < ballRadius * .4); to.Add("ringZ2", z2); } zs = new double[] { z1, z2 }; break; default: throw new ApplicationException("Unexpected number of rings: " + numRings.ToString()); } // Build the rings at the z offsets that were calculated above for (int cntr = 0; cntr < zs.Length; cntr++) { retVal.Children.Add(GetModel_WoodIron_Ring_Band(ballRadius, zs[cntr], material, ball, from, to, "ringZ" + cntr.ToString())); // Store points at the rings double ringRadiusAvg = Math.Sqrt((ballRadius * ballRadius) - (zs[cntr] * zs[cntr])); staticPoints.AddRange(Math2D.GetCircle_Cached(7).Select(o => (o.ToVector() * ringRadiusAvg).ToVector3D(zs[cntr]))); } #endregion #region Spikes Vector3D[] staticPointsArr = staticPoints.Count == 0 ? null : staticPoints.ToArray(); double[] staticRepulse = staticPoints.Count == 0 ? null : Enumerable.Range(0, staticPoints.Count).Select(o => .005d).ToArray(); int numSpikes = Convert.ToInt32(WeaponDNA.GetKeyValue("numSpikes", from, to, rand.Next(8, 14))); Vector3D[] spikeLocations; if (from != null && from.ContainsKey("spikeLoc0X")) { spikeLocations = new Vector3D[numSpikes]; for (int cntr = 0; cntr < numSpikes; cntr++) { string prefix = "spikeLoc" + cntr.ToString(); spikeLocations[cntr] = new Vector3D(to[prefix + "X"], to[prefix + "Y"], to[prefix + "Z"]); } } else { spikeLocations = Math3D.GetRandomVectors_SphericalShell_EvenDist(numSpikes, ballRadius, .03, 10, null, staticPointsArr, staticRepulse); for (int cntr = 0; cntr < numSpikes; cntr++) { string prefix = "spikeLoc" + cntr.ToString(); to.Add(prefix + "X", spikeLocations[cntr].X); to.Add(prefix + "Y", spikeLocations[cntr].Y); to.Add(prefix + "Z", spikeLocations[cntr].Z); } } for (int cntr = 0; cntr < spikeLocations.Length; cntr++) { material = materials.Spike_Iron; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocations[cntr]))); // the tube builds along z List<TubeRingBase> rings = new List<TubeRingBase>(); double spikeRadiusA = WeaponDNA.GetKeyValue("spikeRad" + cntr.ToString(), from, to, rand.NextPercent(spikeRadius, .33)); rings.Add(new TubeRingRegularPolygon(0, false, spikeRadiusA, spikeRadiusA, false)); rings.Add(new TubeRingPoint(WeaponDNA.GetKeyValue("spikeLen" + cntr.ToString(), from, to, rand.NextDouble(spikeLength * .9, spikeLength * 1.1)), false)); int numSegments = Convert.ToInt32(WeaponDNA.GetKeyValue("spikeSegs" + cntr.ToString(), from, to, rand.Next(3, 6))); bool isSoft = Math1D.IsNearZero(WeaponDNA.GetKeyValue("spikeSoft" + cntr.ToString(), from, to, rand.Next(2))); geometry.Geometry = UtilityWPF.GetMultiRingedTube(numSegments, rings, isSoft, false, transform); retVal.Children.Add(geometry); } #endregion return retVal; }
private static Model3DGroup GetModel_WoodIron(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); Random rand = StaticRandom.GetRandomForThread(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = dna.Radius * 1.4d; double ballRadius = dna.Radius * 1d; double spikeRadius = dna.Radius * .2; #region Ball System.Windows.Media.Media3D.Material material = materials.Ball_Wood; // the property get returns a slightly random color GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; // Create a convex hull out of semi evenly distibuted points int numHullPoints = Convert.ToInt32(WeaponDNA.GetKeyValue("numHullPoints", from, to, rand.Next(20, 50))); TriangleIndexed[] ball = Math3D.GetConvexHull(Math3D.GetRandomVectors_SphericalShell_EvenDist(numHullPoints, ballRadius, .03, 10).Select(o => o.ToPoint()).ToArray()); geometry.Geometry = UtilityWPF.GetMeshFromTriangles(ball); retVal.Children.Add(geometry); #endregion // These are placed where the rings are, to push spikes away (so that spikes don't poke through the rings) List <Vector3D> staticPoints = new List <Vector3D>(); #region Rings material = materials.Spike_Iron; // the property get returns a slightly random color // 0, 1 or 2 rings. Higher chance of 0 than 2 int numRings = Convert.ToInt32(WeaponDNA.GetKeyValue("numRings", from, to, Math.Floor(rand.NextPow(2, 2.3)))); double[] zs = new double[0]; switch (numRings) { case 0: break; case 1: zs = new double[] { WeaponDNA.GetKeyValue("ringZ1", from, to, Math1D.GetNearZeroValue(ballRadius * .75)) }; break; case 2: double z1 = WeaponDNA.GetKeyValue("ringZ1", from, to, Math1D.GetNearZeroValue(ballRadius * .75)); double z2 = 0; if (from == null || !from.TryGetValue("ringZ2", out z2)) { do { z2 = Math1D.GetNearZeroValue(ballRadius * .75); } while (Math.Abs(z1 - z2) < ballRadius * .4); to.Add("ringZ2", z2); } zs = new double[] { z1, z2 }; break; default: throw new ApplicationException("Unexpected number of rings: " + numRings.ToString()); } // Build the rings at the z offsets that were calculated above for (int cntr = 0; cntr < zs.Length; cntr++) { retVal.Children.Add(GetModel_WoodIron_Ring_Band(ballRadius, zs[cntr], material, ball, from, to, "ringZ" + cntr.ToString())); // Store points at the rings double ringRadiusAvg = Math.Sqrt((ballRadius * ballRadius) - (zs[cntr] * zs[cntr])); staticPoints.AddRange(Math2D.GetCircle_Cached(7).Select(o => (o.ToVector() * ringRadiusAvg).ToVector3D(zs[cntr]))); } #endregion #region Spikes Vector3D[] staticPointsArr = staticPoints.Count == 0 ? null : staticPoints.ToArray(); double[] staticRepulse = staticPoints.Count == 0 ? null : Enumerable.Range(0, staticPoints.Count).Select(o => .005d).ToArray(); int numSpikes = Convert.ToInt32(WeaponDNA.GetKeyValue("numSpikes", from, to, rand.Next(8, 14))); Vector3D[] spikeLocations; if (from != null && from.ContainsKey("spikeLoc0X")) { spikeLocations = new Vector3D[numSpikes]; for (int cntr = 0; cntr < numSpikes; cntr++) { string prefix = "spikeLoc" + cntr.ToString(); spikeLocations[cntr] = new Vector3D(to[prefix + "X"], to[prefix + "Y"], to[prefix + "Z"]); } } else { spikeLocations = Math3D.GetRandomVectors_SphericalShell_EvenDist(numSpikes, ballRadius, .03, 10, null, staticPointsArr, staticRepulse); for (int cntr = 0; cntr < numSpikes; cntr++) { string prefix = "spikeLoc" + cntr.ToString(); to.Add(prefix + "X", spikeLocations[cntr].X); to.Add(prefix + "Y", spikeLocations[cntr].Y); to.Add(prefix + "Z", spikeLocations[cntr].Z); } } for (int cntr = 0; cntr < spikeLocations.Length; cntr++) { material = materials.Spike_Iron; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocations[cntr]))); // the tube builds along z List <TubeRingBase> rings = new List <TubeRingBase>(); double spikeRadiusA = WeaponDNA.GetKeyValue("spikeRad" + cntr.ToString(), from, to, rand.NextPercent(spikeRadius, .33)); rings.Add(new TubeRingRegularPolygon(0, false, spikeRadiusA, spikeRadiusA, false)); rings.Add(new TubeRingPoint(WeaponDNA.GetKeyValue("spikeLen" + cntr.ToString(), from, to, rand.NextDouble(spikeLength * .9, spikeLength * 1.1)), false)); int numSegments = Convert.ToInt32(WeaponDNA.GetKeyValue("spikeSegs" + cntr.ToString(), from, to, rand.Next(3, 6))); bool isSoft = Math1D.IsNearZero(WeaponDNA.GetKeyValue("spikeSoft" + cntr.ToString(), from, to, rand.Next(2))); geometry.Geometry = UtilityWPF.GetMultiRingedTube(numSegments, rings, isSoft, false, transform); retVal.Children.Add(geometry); } #endregion return(retVal); }
/// <summary> /// This returns a random ball that will fit well with the handle passed in /// </summary> public static WeaponSpikeBallDNA GetRandomDNA(WeaponHandleDNA handle) { WeaponSpikeBallDNA retVal = new WeaponSpikeBallDNA(); Random rand = StaticRandom.GetRandomForThread(); // Radius retVal.Radius = GetRandomRadius(handle.Radius, handle.Length); #region Material // Choose a ball material that goes with the handle's material //NOTE: This is assuming that the ball is an appropriate radius for the handle it will be attached to. //A large soft wood could safely handle a very small ball, etc WeaponSpikeBallMaterial[] ballMaterials = null; switch (handle.HandleMaterial) { case WeaponHandleMaterial.Soft_Wood: ballMaterials = new[] { WeaponSpikeBallMaterial.Wood, WeaponSpikeBallMaterial.Composite }; break; case WeaponHandleMaterial.Hard_Wood: ballMaterials = new[] { WeaponSpikeBallMaterial.Wood, WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Composite, WeaponSpikeBallMaterial.Klinth }; break; case WeaponHandleMaterial.Bronze: case WeaponHandleMaterial.Iron: case WeaponHandleMaterial.Steel: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Composite: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Composite, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Klinth: ballMaterials = new[] { WeaponSpikeBallMaterial.Bronze_Iron, WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; case WeaponHandleMaterial.Moon: ballMaterials = new[] { WeaponSpikeBallMaterial.Iron_Steel, WeaponSpikeBallMaterial.Klinth, WeaponSpikeBallMaterial.Moon }; break; default: throw new ApplicationException("Unknown WeaponHandleMaterial: " + handle.HandleMaterial.ToString()); } // Choose one from the filtered list retVal.Material = rand.NextItem(ballMaterials); #endregion #region Color ColorHSV?basedOn = null; if (handle.MaterialsForCustomizable != null && handle.MaterialsForCustomizable.Length > 0 && !string.IsNullOrEmpty(handle.MaterialsForCustomizable[0].DiffuseColor)) { basedOn = UtilityWPF.ColorFromHex(handle.MaterialsForCustomizable[0].DiffuseColor).ToHSV(); } switch (retVal.Material) { case WeaponSpikeBallMaterial.Composite: retVal.MaterialsForCustomizable = WeaponHandleDNA.GetRandomMaterials_Composite(null, basedOn); break; case WeaponSpikeBallMaterial.Klinth: retVal.MaterialsForCustomizable = WeaponHandleDNA.GetRandomMaterials_Klinth(null, basedOn); break; } #endregion return(retVal); }
private static Model3DGroup GetModel_Moon(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { //TODO: Animate the spikes (shafts of light) by choosing one as the independently rotated spike, and the others run through one step of Math3D.GetRandomVectors_SphericalShell_EvenDist //TODO: Also animate each spike's radius and length (or at least length) //TODO: Also animate each spike's color opacity Model3DGroup retVal = new Model3DGroup(); double spikeLength = dna.Radius * 2d; double ballRadius = dna.Radius * 1d; double spikeRadius = dna.Radius * .033; System.Windows.Media.Media3D.Material material; GeometryModel3D geometry; #region Ball material = materials.Ball_Moon; // the property get returns a slightly random color geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; geometry.Geometry = UtilityWPF.GetSphere_LatLon(5, ballRadius); retVal.Children.Add(geometry); #endregion #region Spikes foreach (Vector3D spikeLocation in Math3D.GetRandomVectors_SphericalShell_EvenDist(30, ballRadius, .03, 100)) { material = materials.Spike_Moon; geometry = new GeometryModel3D(); geometry.Material = material; geometry.BackMaterial = material; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation))); // the tube builds along z List <TubeRingBase> rings = new List <TubeRingBase>(); double spikeLengthMid = spikeLength * .75d; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingRegularPolygon(spikeLengthMid, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingDome(spikeLength - spikeLengthMid, false, 2)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, true, false, transform); retVal.Children.Add(geometry); } #endregion return(retVal); }
private static Model3DGroup GetModel_Klinth(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials) { Model3DGroup retVal = new Model3DGroup(); var from = dna.KeyValues; var to = finalDNA.KeyValues; double spikeLength = WeaponDNA.GetKeyValue("spikeLength", from, to, StaticRandom.NextPercent(dna.Radius * 1.1d, .05)); double ballRadius = dna.Radius; double spikeRadius = WeaponDNA.GetKeyValue("spikeRadius", from, to, StaticRandom.NextPercent(dna.Radius * .2, .1)); var color = WeaponMaterialCache.GetKlinth(dna.MaterialsForCustomizable); finalDNA.MaterialsForCustomizable = color.Item3; GeometryModel3D geometry; #region Ball geometry = new GeometryModel3D(); geometry.Material = color.Item1; geometry.BackMaterial = color.Item1; Icosidodecahedron ball = UtilityWPF.GetIcosidodecahedron(ballRadius); geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(ball.AllTriangles); retVal.Children.Add(geometry); #endregion #region Spikes // Put a spike through the center of each pentagon foreach (Vector3D spikeLocation in ball.PentagonPolys.Select(o => Math3D.GetCenter(o.Select(p => ball.AllPoints[p])))) { geometry = new GeometryModel3D(); geometry.Material = color.Item2; geometry.BackMaterial = color.Item2; RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation))); // the tube builds along z List <TubeRingBase> rings = new List <TubeRingBase>(); double spikeLengthMid = spikeLength * .8d; rings.Add(new TubeRingRegularPolygon(0, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingRegularPolygon(spikeLengthMid, false, spikeRadius, spikeRadius, false)); rings.Add(new TubeRingDome(spikeLength - spikeLengthMid, false, 3)); geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, false, false, transform); retVal.Children.Add(geometry); } #endregion return(retVal); }
/// <summary> /// This returns a random ball, with some optional fixed values /// </summary> public static WeaponSpikeBallDNA GetRandomDNA(WeaponSpikeBallMaterial? material = null, double? radius = null) { WeaponSpikeBallDNA retVal = new WeaponSpikeBallDNA(); Random rand = StaticRandom.GetRandomForThread(); // Radius if (radius != null) { retVal.Radius = radius.Value; } else { retVal.Radius = rand.NextDouble(.2, .5); } // Material if (material == null) { retVal.Material = UtilityCore.GetRandomEnum<WeaponSpikeBallMaterial>(); } else { retVal.Material = material.Value; } return retVal; }
private void btnGenerateSpikeBall_Click(object sender, RoutedEventArgs e) { try { _viewport.Children.RemoveAll(_visuals); string selectedItem = cboMaterial.SelectedItem as string; WeaponSpikeBallMaterial material; if (selectedItem == null || !Enum.TryParse(selectedItem, out material)) { MessageBox.Show("Unrecognized material", "CharacterStatsPanel", MessageBoxButton.OK, MessageBoxImage.Warning); return; } WeaponSpikeBallDNA dna = new WeaponSpikeBallDNA() { Radius = 1d, Material = material }; ModelVisual3D visual = new ModelVisual3D(); visual.Content = new WeaponSpikeBall(new WeaponMaterialCache(), dna).Model; _visuals.Add(visual); _viewport.Children.Add(visual); } catch (Exception ex) { MessageBox.Show(ex.ToString(), "CharacterStatsPanel", MessageBoxButton.OK, MessageBoxImage.Error); } }