如何解决在浏览器中求解显式 Euler 方法的最快方法
我想使用每帧/顶点最少操作的方法在网络浏览器中进行简单的布料模拟,我认为这是显式欧拉。这是一个使用 vanilla JS 的非常基本的初稿,布料是 4D 的,但这不会对算法产生影响:
class Phase {
constructor(r,bf,ns) {
this.r = r;
this.bf = bf;
this.ns = ns;
this.s = math.random([4],2 * math.pi);
this.o = math.multiply(this.r,math.sin(this.s));
}
tck() {
this.s = math.mod(
math.add(this.s,this.bf,math.random([4],this.ns)),2 * math.pi
);
this.o = math.multiply(this.r,math.sin(this.s));
}
}
class Cloth {
constructor(n,d,e) {
this.n = n;
this.d = d;
this.e = e;
this.dt = [];
for (let i = 0; i < this.n; i++) {
this.dt[i] = [];
for (let j = 0; j < this.n; j++) {
this.dt[i][j] = {
p: [i / n,j / n,0],v: [0,0]
};
}
}
}
tck() {
for (let i = 0; i < this.n; i++) {
for (let j = 0; j < this.n; j++) {
if ((i == 0 || i == this.n - 1) && (j == 0 || j == this.n - 1)) {
continue;
}
let nbh = [];
if (0 < i) {
nbh.push(this.dt[i - 1][j]);
}
if (0 < j) {
nbh.push(this.dt[i][j - 1]);
}
if (j < this.n - 1) {
nbh.push(this.dt[i][j + 1]);
}
if (i < this.n - 1) {
nbh.push(this.dt[i + 1][j]);
}
this.dt[i][j].v = math.multiply(this.d,this.dt[i][j].v);
for (let nb of nbh) {
this.dt[i][j].v = math.add(
this.dt[i][j].v,math.multiply(
this.e,math.distance(nb.p,this.dt[i][j].p) - 1 / this.n,math.subtract(nb.p,this.dt[i][j].p)
)
);
}
}
}
for (let i = 0; i < this.n; i++) {
for (let j = 0; j < this.n; j++) {
if ((i == 0 || i == this.n - 1) && (j == 0 || j == this.n - 1)) {
continue;
}
this.dt[i][j].p = math.add(this.dt[i][j].p,this.dt[i][j].v);
}
}
}
drw(ctx,bs,ds) {
ctx.beginPath();
for (let i = 0; i < this.n; i++) {
for (let j = 0; j < this.n; j++) {
if (i < this.n - 1) {
ctx.moveto(
bs + ds * this.dt[i][j].p[0],bs + ds * this.dt[i][j].p[1]
);
ctx.lineto(
bs + ds * this.dt[i + 1][j].p[0],bs + ds * this.dt[i + 1][j].p[1]
);
ctx.stroke();
}
if (j < this.n - 1) {
ctx.beginPath();
ctx.moveto(
bs + ds * this.dt[i][j].p[0],bs + ds * this.dt[i][j].p[1]
);
ctx.lineto(
bs + ds * this.dt[i][j + 1].p[0],bs + ds * this.dt[i][j + 1].p[1]
);
ctx.stroke();
}
}
}
}
}
cloth = new Cloth(20,0.99,5);
phase = [...Array(4)].map(() => new Phase(0.02,0.2,0.001));
cntxt = document.createElement("canvas").getContext("2d");
cntxt.canvas.width = 500;
cntxt.canvas.height = 500;
document.body.append(cntxt.canvas);
(function f() {
cloth.dt[0][0].p = phase[0].o;
cloth.dt[0][cloth.n - 1].p = math.add([0,1,phase[1].o);
cloth.dt[cloth.n - 1][0].p = math.add([1,phase[2].o);
cloth.dt[cloth.n - 1][cloth.n - 1].p = math.add([1,phase[3].o);
cntxt.clearRect(0,500,500);
cloth.drw(cntxt,50,400);
cloth.tck();
for (ph of phase) {
ph.tck();
}
window.requestAnimationFrame(f);
})()
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/9.3.0/math.js"></script>
加快速度的两个明显途径是 WASM 和 WebGL(例如通过 GPU.js)。我从未尝试过 WASM 并且在 WebGL 方面有一些经验,但不是用于通用计算。因此,在我尝试其中之一之前,最终哪个会让我获得最快的结果?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。