Use bezier curves to draw cables.
parent
16d07323ed
commit
c7024336d1
121
main.js
121
main.js
|
@ -15,6 +15,7 @@ var Verlet = function(Width, Height)
|
|||
this.AddConstraint = function(Constraint)
|
||||
{
|
||||
this.Constraints.push(Constraint);
|
||||
return Constraint;
|
||||
}
|
||||
|
||||
this.Update = function(TimeDelta)
|
||||
|
@ -139,28 +140,75 @@ var Constraint = function(Mass1, Mass2)
|
|||
}
|
||||
}
|
||||
|
||||
var Cable = function(Verlet, X1, Y1, X2, Y2, Steps)
|
||||
{
|
||||
Steps = Steps || 10;
|
||||
var StepX = (X2 - X1) / Steps;
|
||||
var StepY = (Y2 - Y1) / Steps;
|
||||
|
||||
this.Masses = [];
|
||||
var LastMass = v.AddMass(new Mass(X1, Y1, 0.5));
|
||||
this.Masses.push(LastMass);
|
||||
LastMass.Active = false;
|
||||
|
||||
for (var i = 1; i <= Steps; i++)
|
||||
{
|
||||
var NewMass = v.AddMass(new Mass(X1 + StepX * i, Y1 + StepY * i, 1));
|
||||
this.Masses.push(NewMass);
|
||||
v.AddConstraint(new Constraint(LastMass, NewMass));
|
||||
LastMass = NewMass;
|
||||
}
|
||||
|
||||
this.BinomialCache = {}
|
||||
this.FastBinomial = function(n, k)
|
||||
{
|
||||
var key = n + ".." + k;
|
||||
if (key in this.BinomialCache)
|
||||
return this.BinomialCache[key];
|
||||
|
||||
function Factorial(num)
|
||||
{
|
||||
var rval=1;
|
||||
for (var i = 2; i <= num; i++)
|
||||
rval = rval * i;
|
||||
return rval;
|
||||
}
|
||||
return (Factorial(n) / (Factorial(k) * Factorial(n - k)));
|
||||
}
|
||||
this.Bezier = function(t)
|
||||
{
|
||||
var Points = this.Masses.length - 1;
|
||||
var ValueX = 0;
|
||||
var ValueY = 0;
|
||||
for (var i = 0; i <= Points; i++)
|
||||
{
|
||||
var Coef = this.FastBinomial(Points, i) * Math.pow(1 -t, Points - i) * Math.pow(t, i);
|
||||
ValueX += Coef * this.Masses[i].X;
|
||||
ValueY += Coef * this.Masses[i].Y;
|
||||
}
|
||||
|
||||
return {X: ValueX, Y: ValueY};
|
||||
}
|
||||
|
||||
this.Render = function(context)
|
||||
{
|
||||
context.strokeStyle = '#FFFFFF';
|
||||
context.beginPath();
|
||||
var First = this.Bezier(0);
|
||||
context.moveTo(First.X, First.Y);
|
||||
for (var T = 1; T < 100; T++)
|
||||
{
|
||||
var t = T / 100;
|
||||
var Next = this.Bezier(t);
|
||||
context.lineTo(Next.X, Next.Y);
|
||||
}
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
var v = new Verlet(800, 600);
|
||||
var m1 = v.AddMass(new Mass( 5, 5, 1));
|
||||
var m2 = v.AddMass(new Mass(20, 5, 1));
|
||||
var m3 = v.AddMass(new Mass(35, 5, 1));
|
||||
var m4 = v.AddMass(new Mass(50, 5, 1));
|
||||
var m5 = v.AddMass(new Mass(65, 5, 1));
|
||||
var m6 = v.AddMass(new Mass(80, 5, 1));
|
||||
m6.Active = false;
|
||||
var cable = new Cable(v, 5, 5, 500, 5);
|
||||
|
||||
var t1 = v.AddMass(new Mass(20, 15, 2));
|
||||
var t2 = v.AddMass(new Mass(0, 45, 2));
|
||||
var t3 = v.AddMass(new Mass(40, 45, 2));
|
||||
v.AddConstraint(new Constraint(m1, m2));
|
||||
v.AddConstraint(new Constraint(m2, m3));
|
||||
v.AddConstraint(new Constraint(m3, m4));
|
||||
v.AddConstraint(new Constraint(m4, m5));
|
||||
v.AddConstraint(new Constraint(m5, m6));
|
||||
|
||||
v.AddConstraint(new Constraint(t1, t2));
|
||||
v.AddConstraint(new Constraint(t1, t3));
|
||||
v.AddConstraint(new Constraint(t3, t2));
|
||||
v.AddConstraint(new Constraint(m1, t1));
|
||||
|
||||
var c = document.getElementById("main");
|
||||
var ctx = c.getContext('2d');
|
||||
|
@ -177,30 +225,21 @@ setInterval(function()
|
|||
|
||||
v.Update(1/50);
|
||||
|
||||
cable.Render(ctx);
|
||||
ctx.fillStyle = '#FFFFFF';
|
||||
for (k in v.Masses)
|
||||
{
|
||||
var m = v.Masses[k];
|
||||
if (typeof(m) == "function")
|
||||
continue;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(m.X, m.Y, 5, 0, Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.strokeStyle = '#FFFFFF';
|
||||
for (k in v.Constraints)
|
||||
{
|
||||
var c = v.Constraints[k];
|
||||
if (typeof(c) == "function")
|
||||
continue;
|
||||
var First = v.Masses[0];
|
||||
var Last = v.Masses[v.Masses.length - 1];
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(First.X, First.Y, 5, 0, Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(c.Mass1.X, c.Mass1.Y);
|
||||
ctx.lineTo(c.Mass2.X, c.Mass2.Y);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.arc(Last.X, Last.Y, 5, 0, Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}, 1000/50);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue