private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                // Init World
                _world = new World();
                _world.Updating += new EventHandler<WorldUpdatingArgs>(World_Updating);
                _world.SetWorldSize(new Point3D(-100, -100, -100), new Point3D(100, 100, 100));
                _world.UnPause();

                // Camera Trackball
                _trackball = new TrackBallRoam(_camera);
                //_trackball.ShouldHitTestOnOrbit = true;
                _trackball.EventSource = grdViewPort;		//NOTE:  If this control doesn't have a background color set, the trackball won't see events (I think transparent is ok, just not null)
                _trackball.AllowZoomOnMouseWheel = true;
                _trackball.Mappings.AddRange(TrackBallMapping.GetPrebuilt(TrackBallMapping.PrebuiltMapping.MouseComplete));
                //_trackball.GetOrbitRadius += new GetOrbitRadiusHandler(Trackball_GetOrbitRadius);

                // Trackball Controls
                SetupModelTrackball();
                SetupFlowTrackball();

                // Fluid lines
                AddFluidVisuals(Convert.ToInt32(NUMFLUIDVISUALS * _flowViscosity));

                // Force lines
                _fluidHullForceLines = new ScreenSpaceLines3D(true);
                _fluidHullForceLines.Color = _colors.ForceLine;
                _fluidHullForceLines.Thickness = 2d;

                _viewport.Children.Add(_fluidHullForceLines);

                // Field - may want to only add this when a body is added
                _field = new FluidField3D(20);
                _field.Diffusion = 0;
                _field.Damping = 0; //GetFluidViscocity();        // this stays zero (see comments in VelocityViscocityChanged)

                _field.BoundryType = FluidFieldBoundryType3D.Open_Slaved;
                _fieldUniform = new FluidFieldUniform();
                _field.OpenBoundryParent = _fieldUniform;
                _field.SizeWorld = 10d;     // This changes whenever a body is swapped out

                _fieldCells = _field.GetCells();

                _fieldField = new FluidFieldField(_field);
                _fieldField.Viscosity = GetFluidViscocity();

                _isInitialized = true;

                ShowHideFluidBoundry();
                ShowHideBlockedCells();

                VelocityViscocityChanged();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
            public static int[] GetBlockedCells(FluidField3D field, IEnumerable<ITriangleIndexed[]> hulls)
            {
                //NOTE: The hulls need to be in model coords

                // Get populated hulls
                ITriangleIndexed[][] hulls1 = hulls.Where(o => o.Length > 0).ToArray();
                if (hulls1.Length == 0)
                {
                    return new int[0];      // no hulls were passed in
                }

                // Get the location of all the cells
                Rectangle3DIndexedMapped[] cells1 = field.GetCells();

                #region Filter AABB

                // Remove non aabb matches
                Rect3D[] aabbs = hulls1.Select(o => Math3D.GetAABB_Rect(o[0].AllPoints)).ToArray();

                Rectangle3DIndexedMapped[] cells2 = cells1.Where(o =>
                {
                    Rect3D cellRect = o.ToRect3D();
                    return aabbs.Any(p => p.OverlapsWith(cellRect));
                }).ToArray();

                if (cells2.Length == 0)
                {
                    return new int[0];      // this should never happen
                }

                #endregion

                //TODO: When multiple hulls are passed in, ignore cells that are outside of a particular hull's aabb

                #region Test triangles

                // Look for intersecting edges
                int[] edgeMatches = new int[0];
                if (cells2.Length > 0)
                {
                    // aabbs is for entire hulls.  This needs to be for each triangle in each hull
                    Tuple<ITriangle, Rect3D>[] hullTrianglesAABBs = hulls.SelectMany(o => o.Select(p => new Tuple<ITriangle, Rect3D>(p, Math3D.GetAABB_Rect(p)))).ToArray();

                    // Now compare each remaining candidate cell to each triangle of each hull
                    edgeMatches = GetBlockedCellsSprtEdgeMap(cells2).
                        AsParallel().
                        Where(o => hullTrianglesAABBs.Any(p => IsEdgeMatch(p, o.Item1))).
                        SelectMany(o => o.Item2.Select(p => cells2[p].Mapping.Offset1D)).       // add all the cells that neighbor this corner point
                        Distinct().     // need distinct, since cells were added multiple times
                        ToArray();
                }

                #endregion

                // Exit Function
                return edgeMatches;
            }