3/25/2013 9:26:07 AM
Awesome Demo of Cloth (fabric) using HTML5
https://appdevelopermagazine.com/news_old/files/Cloth-HTML5-20130325-092604.png
App Developer Magazine

Awesome Demo of Cloth (fabric) using HTML5



Richard Harris Richard Harris in Programming Monday, March 25, 2013
1,671

The flexibly of HTML5 and the power of browser physics meet in this neat little demo on fabric which demonstrats how far along real-time simulations have come.


CSS Code:
* {
margin: 0;
  background:#333;
}

p {
  position:absolute;
  top:16px;
  width:auto;
  left:620px;
  color: #777;
  font-family:sans-serif;
  font-size:20px;
}


JS Code:

// settings

var physics_accuracy = 3,
mouse_influence   = 20, 
mouse_cut     = 6,
gravity         = 900, 
  cloth_height     = 30,
cloth_width       = 50,
start_y       = 20,
spacing       = 7,
tear_distance   = 60;


window.requestAnimFrame =
window.requestAnimationFrame       ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame    ||
window.oRequestAnimationFrame      ||
window.msRequestAnimationFrame     ||
function(callback) {
    window.setTimeout(callback, 1000 / 60);
};

var canvas,
ctx,
points,
physics,
mouse = {
down: false,
button: 1,
x: 0,
y: 0,
px: 0,
py: 0
};

window.onload = function() {

canvas = document.getElementById('c');
ctx    = canvas.getContext('2d');

canvas.width  = 600;//window.innerWidth;
canvas.height = 320;//window.innerHeight;

canvas.onmousedown = function(e) {
mouse.button = e.which;
mouse.px = mouse.x;
mouse.py = mouse.y;
mouse.x = e.clientX || e.layerX;
mouse.y = e.clientY || e.layerY;
mouse.down = true;
e.preventDefault();
};

canvas.onmouseup = function(e) {
mouse.down = false;
e.preventDefault();
};

canvas.onmousemove = function(e) {
mouse.px = mouse.x;
mouse.py = mouse.y;
mouse.x = e.clientX || e.layerX;
mouse.y = e.clientY || e.layerY;
e.preventDefault();
};

canvas.oncontextmenu = function(e) {
e.preventDefault(); 
};

init();
};

var Constraint = function(p1, p2, spacing, tear_distance) {

this.p1 = p1;
this.p2 = p2;
this.length = spacing;
this.tear_distance = tear_distance;
};

Constraint.prototype.solve = function() {

var diff_x = this.p1.x - this.p2.x,
diff_y = this.p1.y - this.p2.y,
dist = Math.sqrt(diff_x * diff_x + diff_y * diff_y),
diff = (this.length - dist) / dist;

if (dist > this.tear_distance) this.p1.remove_constraint(this);

var scalar_1 = ((1 / this.p1.mass) / ((1 / this.p1.mass) + (1 / this.p2.mass))),
scalar_2 = 1 - scalar_1;

this.p1.x += diff_x * scalar_1 * diff;
this.p1.y += diff_y * scalar_1 * diff;

this.p2.x -= diff_x * scalar_2 * diff;
this.p2.y -= diff_y * scalar_2 * diff;
};

Constraint.prototype.draw = function() {
ctx.moveTo(this.p1.x, this.p1.y);
ctx.lineTo(this.p2.x, this.p2.y);
};

var Point = function(x, y) {

this.x = x;
this.y = y;
this.px = x;
this.py = y;
this.ax = 0;
this.ay = 0;
this.mass = 1;
this.constraints = [];
this.pinned = false;
this.pin_x;
this.pin_y;
};

Point.prototype.update = function(delta) {

this.add_force(0, this.mass * gravity);

var vx = this.x - this.px,
  vy = this.y - this.py;

delta *= delta;
nx = this.x + 0.99 * vx + 0.5 * this.ax * delta;
ny = this.y + 0.99 * vy + 0.5 * this.ay * delta;

this.px = this.x;
this.py = this.y;

this.x = nx;
this.y = ny;

this.ay = this.ax = 0
};

Point.prototype.update_mouse = function() {

if (!mouse.down) return;

var diff_x = this.x - mouse.x,
diff_y = this.y - mouse.y,
dist   = Math.sqrt(diff_x * diff_x + diff_y * diff_y);

if (mouse.button == 1) {

if(dist < mouse_influence) {
this.px = this.x - (mouse.x - mouse.px) * 1.8;
this.py = this.y - (mouse.y - mouse.py) * 1.8;
}

} else if (dist < mouse_cut) this.constraints = [];
};

Point.prototype.draw = function() {

if (this.constraints.length <= 0) return;
var i = this.constraints.length;
while(i--) this.constraints[i].draw();
};

Point.prototype.solve_constraints = function() {

var i = this.constraints.length;
while(i--) this.constraints[i].solve();

if (this.y < 1) this.y = 2 * (1) - this.y;
else if (this.y > canvas.height-1) this.y = 2 * (canvas.height - 1) - this.y;
 
if (this.x > canvas.width-1) this.x = 2 * (canvas.width - 1) - this.x;
else if (this.x < 1) this.x = 2 * (1) - this.x;

if (this.pinned) {
this.x = this.pin_x;
this.y = this.pin_y; 
}
};

Point.prototype.attach = function(P, spacing, tear_distance) {

this.constraints.push(
new Constraint(this, P, spacing, tear_distance)
);
};

Point.prototype.remove_constraint = function(lnk) {

var i = this.constraints.length;
while(i--) if(this.constraints[i] == lnk) this.constraints.splice(i, 1);
};

Point.prototype.add_force = function(fX, fY) {

this.ax += fX/this.mass;
this.ay += fY/this.mass;
};

Point.prototype.pin = function(pX, pY) {

this.pinned = true;
this.pin_x = pX;
this.pin_y = pY;
};

var Physics = function() {

this.delta_sec = 16 / 1000;
this.accuracy = physics_accuracy;
};

Physics.prototype.update = function() {

var i = this.accuracy;

while(i--) {
var p = points.length;
while(p--) points[p].solve_constraints();
}

i = points.length;
while(i--) {
points[i].update_mouse();
points[i].update(this.delta_sec);
}
};

function init() {
  
physics = new Physics();
points = [];
build_cloth();
update();
}

function update() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

physics.update();
  
ctx.strokeStyle = 'rgba(222,222,222,0.6)';
ctx.beginPath();
var i = points.length;
while(i--) points[i].draw();
ctx.stroke();

requestAnimFrame(update);
}

function build_cloth() {

var start_x = canvas.width / 2 - cloth_width * spacing / 2;

for(var y = 0; y <= cloth_height; y++) {

for(var x = 0; x <= cloth_width; x++) {

var p = new Point(start_x + x * spacing, y * spacing + start_y);

0 != x &&
p.attach(points[points.length - 1], spacing, tear_distance);

0 != y &&
p.attach(points[(y - 1) * (cloth_width + 1) + x], spacing, tear_distance);

0 == y &&
p.pin(p.x, p.y);

points.push(p)
}
}
}

HTML Code:

  Tear the cloth with your mouse.

  Right click and drag to cut the cloth.

  Reduce physics_accuracy if it's laggy, increase it for a better effect.


Read more: http://codepen.io/stuffit/pen/KrAwx

A new way to manage your development projects

Learn the best ways to organize your app development projects, and keep code straight, clients happy, and breathe a easier through launches.
 

The Latest Nerd Ranch Guide (3rd Edition) to Android Programming

Write and run code every step of the way, using Android Studio to create apps that integrate with other apps, download and display pictures from the web, play sounds, and more. Each chapter and app has been designed and tested to provide the knowledge and experience you need to get started in Android development.

Starting your own app business?

How to create a profitable, sustainable business developing and marketing mobile apps.



Comments

There are no comments yet, be the first to leave your remarks.

Leave a Reply