private void ShootTwoShots_Click(object sender, RoutedEventArgs e) { try { if (_asteroid == null) { MessageBox.Show("Need to make an asteroid first", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning); return; } ClearShots(); // Work backward to make sure the shots don't miss Point3D pointInside1 = Math3D.GetRandomVector_Spherical(MAXRADIUS / 3).ToPoint(); Point3D pointInside2 = Math3D.GetRandomVector_Spherical(MAXRADIUS / 3).ToPoint(); Vector3D directionOut1 = Math3D.GetRandomVector_Spherical_Shell(MAXRADIUS * 3); Vector3D directionOut2 = Math3D.RotateAroundAxis(directionOut1, Math3D.GetRandomVector_Spherical_Shell(1), Math1D.DegreesToRadians(Math1D.GetNearZeroValue(30))); _shots = new[] { Tuple.Create(pointInside1 + directionOut1, -directionOut1, 1d), Tuple.Create(pointInside2 + directionOut2, -directionOut2, 1d), }; // Find the deepest point of intersection var hits = _shots. Select(o => Math3D.GetIntersection_Hull_Ray(_asteroid, o.Item1, o.Item2)). ToArray(); if (hits.Length != 2 || hits.Any(o => o.Length != 2)) { MessageBox.Show("Expected two hits: " + hits.Length.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); return; } // Voronoi Point3D[] controlPoints = GetVoronoiCtrlPoints_TwoLines(hits, _asteroid); _voronoi = Math3D.GetVoronoi(controlPoints, true); DrawShatteredAsteroid_ORIG(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
private static Tuple <HullVoronoiExploder_Response, bool> SplitHull(ITriangleIndexed[] convexHull, Tuple <Point3D, Vector3D, double>[] shots, HullVoronoiExploder_Options options, double aabbLen) { #region intersect with the hull var hits = shots. Select(o => new HullVoronoiExploder_ShotHit() { Shot = o, Hit = GetHit(convexHull, o.Item1, o.Item2, o.Item3), }). Where(o => o.Hit != null). ToArray(); if (hits.Length == 0) { return(null); } #endregion #region voronoi Point3D[] controlPoints = GetVoronoiCtrlPoints(hits, convexHull, options.MinCount, options.MaxCount, aabbLen); VoronoiResult3D voronoi = Math3D.GetVoronoi(controlPoints, true); if (voronoi == null) { return(null); } #endregion // There is enough to start populating the response HullVoronoiExploder_Response retVal = new HullVoronoiExploder_Response() { Hits = hits, ControlPoints = controlPoints, Voronoi = voronoi, }; #region intersect voronoi and hull // Intersect Tuple <int, ITriangleIndexed[]>[] shards = null; try { shards = Math3D.GetIntersection_Hull_Voronoi_full(convexHull, voronoi); } catch (Exception) { return(Tuple.Create(retVal, false)); } if (shards == null) { return(Tuple.Create(retVal, false)); } // Smooth if (options.ShouldSmoothShards) { shards = shards. Select(o => Tuple.Create(o.Item1, Asteroid.SmoothTriangles(o.Item2))). ToArray(); } // Validate shards = shards. Where(o => o.Item2 != null && o.Item2.Length >= 3). Where(o => { Vector3D firstNormal = o.Item2[0].NormalUnit; return(o.Item2.Skip(1).Any(p => !Math.Abs(Vector3D.DotProduct(firstNormal, p.NormalUnit)).IsNearValue(1))); }). ToArray(); if (shards.Length == 0) { return(Tuple.Create(retVal, false)); } #endregion #region populate shards retVal.Shards = shards. Select(o => { 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 HullVoronoiExploder_Shard() { VoronoiControlPointIndex = o.Item1, Hull_ParentCoords = o.Item2, Hull_Centered = shiftedTriangles, Radius = radius, Center_ParentCoords = center, }); }). Where(o => o != null). ToArray(); #endregion return(Tuple.Create(retVal, true)); }
private void ShootOneShot_Click(object sender, RoutedEventArgs e) { try { if (_asteroid == null) { MessageBox.Show("Need to make an asteroid first", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning); return; } ClearShots(); // Work backward to make sure the shot doesn't miss Point3D pointInside = Math3D.GetRandomVector_Spherical(MAXRADIUS / 3).ToPoint(); Vector3D directionOut = Math3D.GetRandomVector_Spherical_Shell(MAXRADIUS * 3); _shots = new[] { Tuple.Create(pointInside + directionOut, -directionOut, 1d), }; // Find the deepest point of intersection var hits = Math3D.GetIntersection_Hull_Ray(_asteroid, _shots[0].Item1, _shots[0].Item2); if (hits.Length != 2) { MessageBox.Show("Expected two hits: " + hits.Length.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); return; } //TODO: Put a point in front, then remove that subhull. This will look like exploded material //or, put it on the same plane, and a cylinder will get cored out //Point3D[] controlPoints = GetVoronoiCtrlPoints_AroundLine_Simple(hits[0].Item1, hits[1].Item1, StaticRandom.Next(2, 7)); Point3D[] controlPoints = GetVoronoiCtrlPoints_AroundLine(hits[0].Item1, hits[1].Item1); _voronoi = Math3D.GetVoronoi(controlPoints, true); DrawShatteredAsteroid_ORIG(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
private void ProcessShots_ORIG() { // Intersect with the asteroid #region ORIG //var hits = _shots. // Select(o => // { // var intersections = Math3D.GetIntersection_Hull_Ray(_asteroid, o.Item1, o.Item2); // if (intersections.Length != 2) // { // return (Tuple<Point3D, Point3D>)null; // } // Vector3D penetrate = (intersections[1].Item1 - intersections[0].Item1) * o.Item3; // return Tuple.Create(intersections[0].Item1, intersections[0].Item1 + penetrate); // }). // Where(o => o != null). // ToArray(); #endregion var hits = _shots. Select(o => new ShotHit() { Shot = o, Hit = ExplosionForceWorker.GetHit(_asteroid, o.Item1, o.Item2, o.Item3), }). Where(o => o != null). ToArray(); if (hits.Length == 0) { if (_shots != null) { foreach (var shot in _shots) { DrawShot(shot.Item1, shot.Item2 * 2); } } _voronoi = null; DrawAsteroid(_asteroid); return; } // Voronoi Point3D[] controlPoints = ExplosionForceWorker.GetVoronoiCtrlPoints(hits, _asteroid); _voronoi = Math3D.GetVoronoi(controlPoints, true); DrawShatteredAsteroid_ORIG(); }
private void ClearShots() { _shots = null; _voronoi = null; _explosion = null; ClearVisuals(); }
private void ClearClickRayData() { _voronoi2NeighborRayStarts.Clear(); _voronoiResult = null; _viewportFull.Children.RemoveAll(_clickRays3D.Select(o => o.Visual)); _clickRays3D.Clear(); }
private void btn3DVoronoiDelaunay_Click(object sender, RoutedEventArgs e) { const double DELAUNAYRADIUS = .008; const double VORONOIRADIUS = .015; try { PrepFor3D(); ClearTempVisuals(); _voronoiResult = Math3D.GetVoronoi(_dots3D.SelectMany(o => o.Positions).ToArray(), true); // Delaunay _misc3D.Add(new Item3D(AddLines(_viewportFull, Tetrahedron.GetUniqueLines(_voronoiResult.Delaunay), _voronoiResult.ControlPoints, UtilityWPF.ColorFromHex("40000000"), DELAUNAYRADIUS))); // Voronoi Interior Edges var interiorEdges = _voronoiResult.Edges. Where(o => o.EdgeType == EdgeType.Segment). Select(o => Tuple.Create(o.Index0, o.Index1.Value)); _misc3D.Add(new Item3D(AddLines(_viewportFull, interiorEdges, _voronoiResult.EdgePoints, Colors.White, VORONOIRADIUS))); // Voronoi Rays #region all same color //var rays = _voronoiResult.Edges. // Where(o => o.EdgeType == EdgeType.Ray). // Select(o => Tuple.Create(o.Point0, o.Point0 + (o.Direction.Value * RAYLENGTH))); //_misc3D.Add(new Item3D(AddLines(_viewportFull, rays, Colors.Cornsilk, VORONOIRADIUS))); #endregion #region color by count var raysByIndex = _voronoiResult.Edges. Where(o => o.EdgeType == EdgeType.Ray). ToLookup(o => o.Index0); var raysByCount = raysByIndex. Select(o => new { Count = o.Count(), Rays = o }). ToLookup(o => o.Count); foreach (var raySet in raysByCount) { var rayTuples = raySet. SelectMany(o => o.Rays). Select(o => Tuple.Create(o.Point0, o.Point0 + (o.Direction.Value * RAYLENGTH))); Color color; switch (raySet.Key) { case 1: color = Colors.Cornsilk; break; case 2: color = Colors.Honeydew; break; default: color = Colors.Violet; break; } _misc3D.Add(new Item3D(AddLines(_viewportFull, rayTuples, color, VORONOIRADIUS))); } #endregion } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }