Skip to content

Instantly share code, notes, and snippets.

@Akiyah
Created May 1, 2013 10:53
Show Gist options
  • Save Akiyah/5494689 to your computer and use it in GitHub Desktop.
Save Akiyah/5494689 to your computer and use it in GitHub Desktop.
forked: Verlet-JS サンプル
body {
background: #000;
}
<script type="text/javascript" src="http://jsrun.it/assets/9/E/L/f/9ELfm"></script>
<script type="text/javascript" src="http://jsrun.it/assets/g/Q/q/v/gQqv5"></script>
<script type="text/javascript" src="http://jsrun.it/assets/c/R/r/e/cRreR"></script>
<script type="text/javascript" src="http://jsrun.it/assets/f/4/Y/k/f4Ykj"></script>
<body onload="init()">
<canvas id="canvas" style="width: 465px; height: 465px; background: #000;"></canvas>
var segmentsX = 20;
var segmentsY = 10;
function getIndex(x,y) {
return y*segmentsX*2+(x % (segmentsX*2));
}
/*
function getXY(i) {
var x = i % segmentsX;
var y = (i - x) / segmentsX;
return [x, y];
}
*/
function init() {
var canvas = document.getElementById("canvas");
// canvas dimensions
var width = 465;
var height = 465;
// retina
var dpr = window.devicePixelRatio || 1;
canvas.width = width*dpr;
canvas.height = height*dpr;
canvas.getContext("2d").scale(dpr, dpr);
// simulation
var sim = new VerletJS(width, height, canvas);
sim.friction = 1;
sim.highlightColor = "#fff";
sim.gravity = new Vec2(0.02,0.1);
// entities
var min = Math.min(width,height)*0.5;
var cloth = sim.koinobori(new Vec2(width/2,height/2), min, min, 0.99);
cloth.drawConstraints = function(ctx, composite) {
var stride = min/segmentsX;
var x,y;
/*
var d = segmentsX*segmentsY;
for (y=1;y<segmentsY;++y) {
for (x=1;x<segmentsX;++x) {
ctx.beginPath();
// i00 i01
// i10 i11
var i00 = getIndex(x-1, y-1) + d;
var i01 = getIndex(x-1, y) + d;
var i10 = getIndex(x, y-1) + d;
var i11 = getIndex(x, y) + d;
ctx.moveTo(cloth.particles[i00].pos.x, cloth.particles[i00].pos.y);
ctx.lineTo(cloth.particles[i10].pos.x + 1, cloth.particles[i10].pos.y);
ctx.lineTo(cloth.particles[i11].pos.x + 1, cloth.particles[i11].pos.y + 1);
ctx.lineTo(cloth.particles[i01].pos.x, cloth.particles[i01].pos.y + 1);
var off = cloth.particles[i11].pos.x - cloth.particles[i00].pos.x;
off += cloth.particles[i11].pos.y - cloth.particles[i00].pos.y;
off *= 0.25;
var coef = Math.round((Math.abs(off)/stride)*255);
if (coef > 255)
coef = 255;
var c = Math.round((coef + 255*2) / 4);
ctx.fillStyle = "rgb(" + coef + ",0," + (255-coef)+ ")";
ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
ctx.fill();
}
}
*/
function draw(x, light) {
for (y=1;y<segmentsY;++y) {
ctx.beginPath();
// i00 i01
// i10 i11
var i00 = getIndex(x, y-1);
var i01 = getIndex(x, y);
var i10 = getIndex(x+1, y-1);
var i11 = getIndex(x+1, y);
ctx.moveTo(cloth.particles[i00].pos.x, cloth.particles[i00].pos.y);
ctx.lineTo(cloth.particles[i10].pos.x, cloth.particles[i10].pos.y);
ctx.lineTo(cloth.particles[i11].pos.x, cloth.particles[i11].pos.y);
ctx.lineTo(cloth.particles[i01].pos.x, cloth.particles[i01].pos.y);
var off = cloth.particles[i11].pos.x - cloth.particles[i00].pos.x;
off += cloth.particles[i11].pos.y - cloth.particles[i00].pos.y;
off *= 0.25;
var off = cloth.particles[i11].pos.x - cloth.particles[i00].pos.x;
console.log(off);
var coef = Math.round((Math.abs(off)/stride)*255);
if (coef > 255)
coef = 255;
var c = Math.round((coef + 255) / 4);
if (light) {
c = Math.round((coef + 255*3) / 4)
}
var style = "rgb(" + c + "," + c + "," + c + ")";
ctx.fillStyle = style;
ctx.strokeStyle = style;
ctx.fill();
ctx.stroke();
}
}
// (1)
for (x=0;x<segmentsX/2;++x) {
draw(x, false);
}
// (4)
for (x=segmentsX/2-1;x>=0;--x) {
draw(x + segmentsX*3/2, false);
}
// (2)
for (x=0;x<segmentsX/2;++x) {
draw(x + segmentsX/2, true);
}
// (3)
for (x=segmentsX/2-1;x>=0;--x) {
draw(x + segmentsX,true);
}
var c;
for (c in composite.constraints) {
if (composite.constraints[c] instanceof PinConstraint) {
var point = composite.constraints[c];
ctx.beginPath();
ctx.arc(point.pos.x, point.pos.y, 1.2, 0, 2*Math.PI);
ctx.fillStyle = "rgba(255,255,255,1)";
ctx.fill();
}
}
};
cloth.drawParticles = function(ctx, composite) {
var i;
for (i in composite.particles) {
var point = composite.particles[i];
ctx.beginPath();
ctx.arc(point.pos.x, point.pos.y, 1.3, 0, 2*Math.PI);
ctx.fillStyle = "#2dad8f";
//ctx.fill();
}
};
// animation loop
var legIndex = 0;
var loop = function() {
sim.frame(16);
sim.draw();
requestAnimFrame(loop);
};
loop();
}
VerletJS.prototype.koinobori = function(origin, width, height, stiffness) {
var composite = new this.Composite();
var stride = 15;
var x,y;
for (y=0;y<segmentsY;++y) {
for (x=0;x<segmentsX/2;++x) {
var px = origin.x - x*stride - width/2 + stride/2
var py = origin.y + y*stride - height/2 + stride/2;
composite.particles.push(new Particle(new Vec2(px, py)));
}
for (x=0;x<segmentsX/2;++x) {
var px = origin.x + (x - segmentsX/2)*stride - width/2 + stride/2
var py = origin.y + y*stride - height/2 + stride/2;
composite.particles.push(new Particle(new Vec2(px, py)));
}
for (x=0;x<segmentsX/2;++x) {
var px = origin.x + x*stride - width/2 + stride/2
var py = origin.y + y*stride - height/2 + stride/2;
composite.particles.push(new Particle(new Vec2(px, py)));
}
for (x=0;x<segmentsX/2;++x) {
var px = origin.x + (-x + segmentsX/2)*stride - width/2 + stride/2
var py = origin.y + y*stride - height/2 + stride/2;
composite.particles.push(new Particle(new Vec2(px, py)));
}
}
for (y=0;y<segmentsY;++y) {
for (x=0;x<segmentsX*2;++x) {
var i = getIndex(x, y);
var j = getIndex(x+1, y);
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[j], stiffness));
if (y > 0) {
var k = getIndex(x, y-1);
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[k], stiffness));
}
}
}
// ぬいあわせ
var n = 6;
var y = segmentsY-1;
for (x=-n;x<n;++x) {
var i = getIndex(x + segmentsX*2, y-1);
var j = getIndex(-x + segmentsX, y);
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[j], stiffness));
}
composite.pin(getIndex(segmentsX/2-1, 0));
composite.pin(getIndex(segmentsX/2, 0));
composite.pin(getIndex(3*segmentsX/2-1, 0));
composite.pin(getIndex(3*segmentsX/2, 0));
/*
for (x=0;x<segmentsX;++x) {
if (x < 1 || segmentsX - 2 < x)
composite.pin(x);
}
*/
this.composites.push(composite);
return composite;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment