实例介绍
【实例简介】
【实例截图】
【实例截图】
【核心代码】
/*
* 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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论