Example #1
0
        private static int[] GetFieldSphere(Point3D point, double radius, FluidField3D field)
        {
            // Get the box that contains the return circle
            var center = GetFieldPoint_XYZ(point, field);
            var min    = GetFieldPoint_XYZ(new Point3D(point.X - radius, point.Y - radius, point.Z - radius), field);
            var max    = GetFieldPoint_XYZ(new Point3D(point.X + radius, point.Y + radius, point.Z + radius), field);

            // Get points that are inside the circle
            List <int> retVal             = new List <int>();
            double     maxDistance        = radius * field.Size;
            double     maxDistanceSquared = maxDistance * maxDistance;

            for (int x = min.Item1; x <= max.Item1; x++)
            {
                for (int y = min.Item2; y <= max.Item2; y++)
                {
                    for (int z = min.Item3; z <= max.Item3; z++)
                    {
                        double dx = x - center.Item1;
                        double dy = y - center.Item2;
                        double dz = z - center.Item3;
                        double distanceSquared = (dx * dx) + (dy * dy) + (dz * dz);

                        if (distanceSquared <= maxDistanceSquared)
                        {
                            retVal.Add(field.Get1DIndex(x, y, z));
                        }
                    }
                }
            }

            // Exit Function
            return(retVal.ToArray());
        }
Example #2
0
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                // Field
                _field           = new FluidField3D(40);
                _field.Diffusion = 0;
                _field.Damping   = 0;

                // Sliders
                PropertyInfo[] propsOptions = typeof(FluidField3D).GetProperties();
                _propLinks.Add(new SliderShowValues.PropSync(trkDiffusion, propsOptions.Where(o => o.Name == "Diffusion").First(), _field, 0, .03));
                _propLinks.Add(new SliderShowValues.PropSync(trkDamping, propsOptions.Where(o => o.Name == "Damping").First(), _field, 0, .1));
                _propLinks.Add(new SliderShowValues.PropSync(trkTimestep, propsOptions.Where(o => o.Name == "TimeStep").First(), _field, 0, 100));
                _propLinks.Add(new SliderShowValues.PropSync(trkIterations, propsOptions.Where(o => o.Name == "Iterations").First(), _field, 0, 20));

                trkBrushSize.Minimum = 0;
                trkBrushSize.Maximum = .5;
                trkBrushSize.Value   = .15;

                trkVelocityMultiplier.Minimum = .1;
                trkVelocityMultiplier.Maximum = 20;
                trkVelocityMultiplier.Value   = 3;

                trkBrushDepth.Minimum = 0;
                trkBrushDepth.Maximum = 1;
                trkBrushDepth.Value   = .5;

                // Create a new image
                Image img = new Image();
                RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.NearestNeighbor);
                RenderOptions.SetEdgeMode(img, EdgeMode.Aliased);

                // Add this image to the canvas
                grdFluid.Children.Add(img);

                // Create the bitmap, and set
                _bitmap = new WriteableBitmap(_field.Size, _field.Size, UtilityWPF.DPI, UtilityWPF.DPI, PixelFormats.Bgra32, null);

                img.Source  = _bitmap;
                img.Stretch = Stretch.Fill;

                // Timer
                _timer           = new DispatcherTimer();
                _timer.Interval  = TimeSpan.FromMilliseconds(1);
                _timer.Tick     += Timer_Tick;
                _timer.IsEnabled = true;

                // Need to manually set the scrollviewer's height (a binding can't be conditional - see Window_SizeChanged)
                expanderScrollViewer.MaxHeight = expanderRow.ActualHeight;

                _isInitialized = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Example #3
0
        private static Tuple <int, int, int> GetFieldPoint_XYZ(Point3D point, FluidField3D field)
        {
            int x = Convert.ToInt32(Math.Round(point.X * field.Size));

            if (x < 0)
            {
                x = 0;
            }
            else if (x >= field.Size)
            {
                x = field.Size - 1;
            }

            int y = Convert.ToInt32(Math.Round(point.Y * field.Size));

            if (y < 0)
            {
                y = 0;
            }
            else if (y >= field.Size)
            {
                y = field.Size - 1;
            }

            int z = Convert.ToInt32(Math.Round(point.Z * field.Size));

            if (z < 0)
            {
                z = 0;
            }
            else if (z >= field.Size)
            {
                z = field.Size - 1;
            }

            return(Tuple.Create(x, y, z));
        }
Example #4
0
        private static void DrawFieldSprtDoIt(byte[] pixels, double[] ink, bool[] blocked, int size, byte[] colorZFront, byte[] colorZBack, AxisFor pixelX, AxisFor pixelY, AxisFor pixelZ)
        {
            List <Mapping_2D_1D> flattened = new List <Mapping_2D_1D>();

            // Setup the pixel array
            //for (int y2D = pixelY.Start; pixelY.IsPos ? y2D <= pixelY.Stop : y2D >= pixelY.Stop; y2D += pixelY.Increment)
            foreach (int y2D in pixelY.Iterate())
            {
                int offsetY = pixelY.GetValueForOffset(y2D) * size;

                //for (int x2D = pixelX.Start; pixelX.IsPos ? x2D <= pixelX.Stop : x2D >= pixelX.Stop; x2D += pixelX.Increment)
                foreach (int x2D in pixelX.Iterate())
                {
                    int offset = offsetY + pixelX.GetValueForOffset(x2D);

                    flattened.Add(new Mapping_2D_1D(x2D, y2D, offset));
                }
            }

            // Each pixel of the output bitmap can be added up independently, so employ some threading
            flattened.AsParallel().ForAll(o =>
            {
                //TODO: Color is 6.5 times slower than byte array
                List <byte[]> colorColumn = new List <byte[]>();

                for (int z2D = pixelZ.Start; pixelZ.IsPos?z2D <= pixelZ.Stop : z2D >= pixelZ.Stop; z2D += pixelZ.Increment)
                {
                    int x = -1, y = -1, z = -1;
                    pixelX.Set3DIndex(ref x, ref y, ref z, o.X);
                    pixelY.Set3DIndex(ref x, ref y, ref z, o.Y);
                    pixelZ.Set3DIndex(ref x, ref y, ref z, z2D);

                    int index = FluidField3D.Get1DIndex(x, y, z, size);
                    if (blocked[index])
                    {
                        // Blocked cells are all white, so save the overlay method a bit of work, and throw out everything behind this
                        colorColumn.Clear();
                        colorColumn.Add(new byte[] { 255, 255, 255, 255 });
                        continue;
                    }

                    double inkCell = ink[index];

                    if (Math1D.IsNearZero(inkCell))
                    {
                        continue;
                    }

                    byte[] depthColor = UtilityWPF.AlphaBlend(colorZBack, colorZFront, UtilityCore.GetScaledValue_Capped(0, 1, 0, size - 1, z));

                    int alpha = Convert.ToInt32(Math.Round(inkCell * 255));
                    if (alpha < 0)
                    {
                        alpha = 0;
                    }
                    else if (alpha > 255)
                    {
                        alpha = 255;
                    }

                    colorColumn.Add(new byte[] { Convert.ToByte(alpha), depthColor[1], depthColor[2], depthColor[3] });
                }

                byte[] color = colorColumn.Count > 0 ? UtilityWPF.OverlayColors(colorColumn) : new byte[] { 0, 0, 0, 0 };

                pixels[o.Offset1D * 4 + 0] = color[3];       // Blue
                pixels[o.Offset1D * 4 + 1] = color[2];       // Green
                pixels[o.Offset1D * 4 + 2] = color[1];       // Red
                pixels[o.Offset1D * 4 + 3] = color[0];       // Alpha
            });
        }
Example #5
0
        private static void DrawField(WriteableBitmap bitmap, FluidField3D field, ViewDirection viewDirection, byte[] colorZFront, byte[] colorZBack)
        {
            Int32Rect rect = new Int32Rect(0, 0, field.Size, field.Size);
            int       size = rect.Width * rect.Height * 4;

            byte[] pixels = new byte[size];

            double[] ink     = field.Ink;
            bool[]   blocked = field.Blocked;

            switch (viewDirection)
            {
            case ViewDirection.Front:
                #region Front

                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.X, 0, field.Size - 1),
                                  new AxisFor(Axis.Y, 0, field.Size - 1),
                                  new AxisFor(Axis.Z, field.Size - 1, 0)); // pixel z needs to start at the back, because the colors are overlaid

                #endregion
                break;

            case ViewDirection.Right:
                #region Right

                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.Z, 0, field.Size - 1),
                                  new AxisFor(Axis.Y, 0, field.Size - 1),
                                  new AxisFor(Axis.X, 0, field.Size - 1));

                #endregion
                break;

            case ViewDirection.Left:
                #region Left

                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.Z, field.Size - 1, 0),
                                  new AxisFor(Axis.Y, 0, field.Size - 1),
                                  new AxisFor(Axis.X, field.Size - 1, 0));

                #endregion
                break;

            case ViewDirection.Top:
                #region Top

                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.X, 0, field.Size - 1),
                                  new AxisFor(Axis.Z, field.Size - 1, 0),
                                  new AxisFor(Axis.Y, field.Size - 1, 0));

                #endregion
                break;

            case ViewDirection.Bottom:
                #region Bottom

                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.X, 0, field.Size - 1),
                                  new AxisFor(Axis.Z, 0, field.Size - 1),
                                  new AxisFor(Axis.Y, 0, field.Size - 1));

                #endregion
                break;

            case ViewDirection.Back:
                #region Back

                //NOTE: This one is up for interpretation.  I will rotate left to right, because I think that is more intuitive.  If rotating
                //top to bottom, it would be upside down from the way I am presenting
                DrawFieldSprtDoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                                  new AxisFor(Axis.X, field.Size - 1, 0),
                                  new AxisFor(Axis.Y, 0, field.Size - 1),
                                  new AxisFor(Axis.Z, 0, field.Size - 1));

                // The alternate
                //DrawField_DoIt(pixels, ink, blocked, field.Size, colorZFront, colorZBack,
                //    new AxisFor(Axis.X, 0, field.Size - 1),
                //    new AxisFor(Axis.Y, field.Size - 1, 0),
                //    new AxisFor(Axis.Z, 0, field.Size - 1));

                #endregion
                break;

            default:
                throw new ApplicationException("Unknown ViewDirection: " + viewDirection.ToString());
            }

            bitmap.WritePixels(rect, pixels, rect.Width * 4, 0);
        }