实例介绍
【实例简介】
【实例截图】
【实例截图】
【核心代码】
/* * 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; } } } } }
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论