基本信息
源码名称:C# 流媒体模拟例子源码
源码大小:0.02M
文件格式:.rar
开发语言:C#
更新时间:2015-09-14
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300

本次赞助数额为: 2 元 
   源码介绍


/*
 * This Ver:
 * Copyright chocoboboy ( http://twitter.com/chocoboboy )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 */

/**
 * Flash version:
 * Copyright iunpin ( http://wonderfl.net/user/iunpin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6eu4
 */

/**
 * Original Java version:
 * http://grantkot.com/MPM/Liquid.html
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;

namespace LiquidSimulation
{
    public partial class LiquidTest : Form
    {        
        private List<Particle> particles = new List<Particle>();

        private int gsizeX = 100;
        private int gsizeY = 100;
        private int particlesX = 60;
        private int particlesY = 60;

        private List<List<Node>> grid;
        private List<Node> active = new List<Node>();
        private Material water = new Material(1, 1, 1, 1, 1, 1);
        private bool pressed = false;
        private bool pressedprev = false;

        private int mx = 0;
        private int my = 0;
        private int mxprev = 0;
        private int myprev = 0;

        private Bitmap _canvas;
        private Graphics _g;

        private Random rnd = new Random(5);

        public LiquidTest()
        {
            InitializeComponent();
        }

        private void LiquidTest_Load(object sender, EventArgs e)
        {
            this.Height = gsizeY * 4   20;
            this.Width = gsizeX * 4   10;
            pictureBox1.Image = _canvas = new Bitmap(gsizeX * 4, gsizeY * 4);
            _g = Graphics.FromImage(_canvas);

            int i, j;
            grid = new List<List<Node>>();

            for (i = 0; i < gsizeX; i  )
            {
                grid.Add(new List<Node>());
                for (j = 0; j < gsizeY; j  )
                {
                    grid[i].Add(new Node());
                }
            }

            Particle p;
            for (i = 0; i < particlesX; i  )
            {
                for (j = 0; j < particlesY; j  )
                {
                    p = new Particle(water, i   4, j   4, 0, 0);
                    particles.Add(p);
                }
            }

            var action = new Action(() => { paint(null); });
            action.BeginInvoke(new AsyncCallback(ar => { action.EndInvoke(ar); }), null);
        }

        void mouseMoved(object sender, MouseEventArgs e)
        {
            mx = e.X;
            my = e.Y;
        }

        void mouseReleased(object sender, MouseEventArgs e)
        {
            pressed = false;
        }

        void mousePressed(object sender, MouseEventArgs e)
        {
            pressed = true;
        }

        private void paint(object sender)
        {
            while (!(this.Disposing || this.IsDisposed))
            {
                var watch = Stopwatch.StartNew();
                simulate();

                _g.Clear(Color.White);
                
                var data = _canvas.LockBits(new Rectangle(0, 0, _canvas.Width, _canvas.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                unsafe
                {
                    int* ptr = (int*)data.Scan0.ToPointer();

                    foreach (var p in particles)
                    {
                        var x1 = (int)(4 * p.x);
                        var y1 = (int)(4 * p.y);
                        var x2 = (int)(4 * (p.x - p.u));
                        var y2 = (int)(4 * (p.y - p.v));


                        ptr[y1 * gsizeX * 4   x1 - 1] = Color.Blue.ToArgb();
                        ptr[y2 * gsizeX * 4   x2 - 1] = Color.LightBlue.ToArgb();

                        //_canvas.SetPixel(x1, y1, Color.Blue);
                        //_canvas.SetPixel(x2, y2, Color.FromArgb(0x440000FF));
                    }
                }

                _canvas.UnlockBits(data);                
                
                try
                {
                    this.Invoke(new Action(() =>
                    {
                        pictureBox1.Refresh();
                        var fps = 1000 / watch.ElapsedMilliseconds;
                        this.Text = "Liquid Simulation FPS:"   fps;
                    }));
                }
                catch
                {
                }
            }
        }

        private void simulate()
        {
            bool drag = false;
            double mdx = 0.0, mdy = 0.0;
            if (pressed && pressedprev)
            {
                drag = true;
                mdx = 0.25 * (mx - mxprev);
                mdy = 0.25 * (my - myprev);
            }

            pressedprev = pressed;
            mxprev = mx;
            myprev = my;

            //Node n;
            //Particle p;
            foreach (var n in active)
            {
                n.clear();
            }
            //active.length = 0;
            active.Clear();

            int i, j;
            double x, y, phi;
            double fx = 0.0, fy = 0.0;
            foreach (var p in particles)
            {
                p.cx = (int)(p.x - 0.5);
                p.cy = (int)(p.y - 0.5);

                x = p.cx - p.x;
                p.px[0] = (0.5 * x * x   1.5 * x   1.125);
                p.gx[0] = (x   1.5);
                x  = 1.0;
                p.px[1] = (-x * x   0.75);
                p.gx[1] = (-2.0 * x);
                x  = 1.0;
                p.px[2] = (0.5 * x * x - 1.5 * x   1.125);
                p.gx[2] = (x - 1.5);

                y = p.cy - p.y;
                p.py[0] = (0.5 * y * y   1.5 * y   1.125);
                p.gy[0] = (y   1.5);
                y  = 1.0;
                p.py[1] = (-y * y   0.75);
                p.gy[1] = (-2.0 * y);
                y  = 1.0;
                p.py[2] = (0.5 * y * y - 1.5 * y   1.125);
                p.gy[2] = (y - 1.5);

                for (i = 0; i < 3; i  )
                {
                    for (j = 0; j < 3; j  )
                    {
                        var n = grid[p.cx   i][p.cy   j];
                        if (!n.active)
                        {
                            active.Add(n);
                            n.active = true;
                        }
                        phi = p.px[i] * p.py[j];
                        n.m  = phi * p.mat.m;
                        n.d  = phi;
                        n.gx  = p.gx[i] * p.py[j];
                        n.gy  = p.px[i] * p.gy[j];
                    }
                }
            }

            double density, pressure, weight;
            Node n01, n02;
            Node n11, n12;
            int cx, cy;
            int cxi, cyi;

            double pdx, pdy;
            double C20, C02, C30, C03;
            double csum1, csum2;
            double C21, C31, C12, C13, C11;

            double u, u2, u3;
            double v, v2, v3;

            foreach (var p in particles)
            {
                cx = Convert.ToInt32(p.x);
                cy = Convert.ToInt32(p.y);
                cxi = cx   1;
                cyi = cy   1;

                n01 = grid[cx][cy];
                n02 = grid[cx][cyi];
                n11 = grid[cxi][cy];
                n12 = grid[cxi][cyi];

                pdx = n11.d - n01.d;
                pdy = n02.d - n01.d;
                C20 = 3.0 * pdx - n11.gx - 2.0 * n01.gx;
                C02 = 3.0 * pdy - n02.gy - 2.0 * n01.gy;
                C30 = -2.0 * pdx   n11.gx   n01.gx;
                C03 = -2.0 * pdy   n02.gy   n01.gy;
                csum1 = n01.d   n01.gy   C02   C03;
                csum2 = n01.d   n01.gx   C20   C30;
                C21 = 3.0 * n12.d - 2.0 * n02.gx - n12.gx - 3.0 * csum1 - C20;
                C31 = -2.0 * n12.d   n02.gx   n12.gx   2.0 * csum1 - C30;
                C12 = 3.0 * n12.d - 2.0 * n11.gy - n12.gy - 3.0 * csum2 - C02;
                C13 = -2.0 * n12.d   n11.gy   n12.gy   2.0 * csum2 - C03;
                C11 = n02.gx - C13 - C12 - n01.gx;

                u = p.x - cx;
                u2 = u * u;
                u3 = u * u2;
                v = p.y - cy;
                v2 = v * v;
                v3 = v * v2;
                density = n01.d   n01.gx * u   n01.gy * v   C20 * u2   C02 * v2   C30 * u3   C03 * v3   C21 * u2 * v   C31 * u3 * v   C12 * u * v2   C13 * u * v3   C11 * u * v;

                pressure = density - 1.0;
                if (pressure > 2.0)
                    pressure = 2.0;

                fx = 0.0;
                fy = 0.0;

                if (p.x < 4.0)
                    fx  = p.mat.m * (4.0 - p.x);
                else if (p.x > gsizeX - 5)
                    fx  = p.mat.m * (gsizeX - 5 - p.x);

                if (p.y < 4.0)
                    fy  = p.mat.m * (4.0 - p.y);
                else if (p.y > gsizeY - 5)
                    fy  = p.mat.m * (gsizeY - 5 - p.y);

                if (drag)
                {
                    double vx = Math.Abs(p.x - 0.25 * mx);
                    double vy = Math.Abs(p.y - 0.25 * my);
                    if ((vx < 10.0) && (vy < 10.0))
                    {
                        weight = p.mat.m * (1.0 - vx * 0.10) * (1.0 - vy * 0.10);
                        fx  = weight * (mdx - p.u);
                        fy  = weight * (mdy - p.v);
                    }
                }

                for (i = 0; i < 3; i  )
                {
                    for (j = 0; j < 3; j  )
                    {
                        var n = grid[(p.cx   i)][(p.cy   j)];
                        phi = p.px[i] * p.py[j];
                        n.ax  = -((p.gx[i] * p.py[j]) * pressure)   fx * phi;
                        n.ay  = -((p.px[i] * p.gy[j]) * pressure)   fy * phi;
                    }
                }
            }

            foreach (var n in active)
            {
                if (n.m > 0.0)
                {
                    n.ax /= n.m;
                    n.ay /= n.m;
                    n.ay  = 0.03;
                }
            }

            double mu, mv;
            foreach (var p in particles)
            {
                for (i = 0; i < 3; i  )
                {
                    for (j = 0; j < 3; j  )
                    {
                        var n = grid[(p.cx   i)][(p.cy   j)];
                        phi = p.px[i] * p.py[j];
                        p.u  = phi * n.ax;
                        p.v  = phi * n.ay;
                    }
                }
                mu = p.mat.m * p.u;
                mv = p.mat.m * p.v;
                for (i = 0; i < 3; i  )
                {
                    for (j = 0; j < 3; j  )
                    {
                        var n = grid[(p.cx   i)][(p.cy   j)];
                        phi = p.px[i] * p.py[j];
                        n.u  = phi * mu;
                        n.v  = phi * mv;
                    }
                }
            }

            foreach (var n in active)
            {
                if (n.m > 0.0)
                {
                    n.u /= n.m;
                    n.v /= n.m;
                }
            }

            double gu, gv;
            foreach (var p in particles)
            {
                gu = 0.0;
                gv = 0.0;
                for (i = 0; i < 3; i  )
                {
                    for (j = 0; j < 3; j  )
                    {
                        var n = grid[(p.cx   i)][(p.cy   j)];
                        phi = p.px[i] * p.py[j];
                        gu  = phi * n.u;
                        gv  = phi * n.v;
                    }
                }
                p.x  = gu;
                p.y  = gv;
                p.u  = 1.0 * (gu - p.u);
                p.v  = 1.0 * (gv - p.v);
                if (p.x < 1.0)
                {
                    p.x = (1.0   rnd.NextDouble() * 0.01);
                    p.u = 0.0;
                }
                else if (p.x > gsizeX - 2)
                {
                    p.x = (gsizeX - 2 - rnd.NextDouble() * 0.01);
                    p.u = 0.0;
                }
                if (p.y < 1.0)
                {
                    p.y = (1.0   rnd.NextDouble() * 0.01);
                    p.v = 0.0;
                }
                else if (p.y > gsizeY - 2)
                {
                    p.y = (gsizeY - 2 - rnd.NextDouble() * 0.01);
                    p.v = 0.0;
                }
            }
        }
    }
}