UNPKG

verlet

Version:
164 lines (127 loc) 4.86 kB
<!DOCTYPE html> <html lang="en"> <head> <title>Verlet Fractal Trees</title> <meta charset="UTF-8" /> <link rel="stylesheet" href="../css/style.css" type="text/css" media="screen, projection" /> <link href='http://fonts.googleapis.com/css?family=Libre+Baskerville:400,700,400italic' rel='stylesheet' type='text/css'> <script type="text/javascript" src="../js/verlet-1.0.0.js"></script> </head> <body> <script type="text/javascript" src="../site/js/common.js"></script> <div id="header"> <h1><a href="../">verlet-js</a> / <em>Fractal Tree</em></h1> <div id="bsa"> <script type="text/javascript" src="http://cdn.adpacks.com/adpacks.js?legacyid=1285933&zoneid=1386&key=3df5e2ea1c6a237386fb9d4cdf5b99f0&serve=C6SD52Y&placement=subprotocolcom&circle=dev" id="_adpacks_js"></script> </div> <p> <h4>Author</h4> <a href="http://subprotocol.com/">Sub Protocol</a> <h4>Summary</h4> Recursively generated fractal tree demonstrating both distance and angular constraints. <h4>Source Code</h4> <a href="https://github.com/subprotocol/verlet-js/blob/master/examples/tree.html">View on GitHub</a> </p> </div> <canvas id="scratch" style="width: 800px; height: 500px;"></canvas> <script type="text/javascript"> function lerp(a, b, p) { return (b-a)*p + a; } VerletJS.prototype.tree = function(origin, depth, branchLength, segmentCoef, theta) { var lineCoef = 0.7; this.origin = origin; this.base = new Particle(origin); this.root = new Particle(origin.add(new Vec2(0,10))); var composite = new this.Composite(); composite.particles.push(this.base); composite.particles.push(this.root); composite.pin(0); composite.pin(1); var branch = function(parent, i, nMax, coef, normal) { var particle = new Particle(parent.pos.add(normal.scale(branchLength*coef))); composite.particles.push(particle); var dc = new DistanceConstraint(parent, particle, lineCoef); dc.p = i/nMax; // a hint for drawing composite.constraints.push(dc); particle.leaf = !(i < nMax); if (i < nMax) { var a = branch(particle, i+1, nMax, coef*coef, normal.rotate(new Vec2(0,0), -theta)); var b = branch(particle, i+1, nMax, coef*coef, normal.rotate(new Vec2(0,0), theta)); var jointStrength = lerp(0.7, 0, i/nMax); composite.constraints.push(new AngleConstraint(parent, particle, a, jointStrength)); composite.constraints.push(new AngleConstraint(parent, particle, b, jointStrength)); } return particle; } var firstBranch = branch(this.base, 0, depth, segmentCoef, new Vec2(0,-1)); composite.constraints.push(new AngleConstraint(this.root, this.base, firstBranch, 1)); // animates the tree at the beginning var noise = 10; var i; for (i=0;i<composite.particles.length;++i) composite.particles[i].pos.mutableAdd(new Vec2(Math.floor(Math.random()*noise, Math.floor(Math.random()*noise)))); this.composites.push(composite); return composite; } window.onload = function() { var canvas = document.getElementById("scratch"); // canvas dimensions var width = parseInt(canvas.style.width); var height = parseInt(canvas.style.height); // 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.gravity = new Vec2(0,0); sim.friction = 0.98; // entities var tree1 = sim.tree(new Vec2(width/4,height-120), 5, 70, 0.95, (Math.PI/2)/3); var tree2 = sim.tree(new Vec2(width - width/4,height-120), 5, 70, 0.95, (Math.PI/2)/3); tree2.drawParticles = function(ctx, composite) { var i; for (i=0;i<composite.particles.length;++i) { var particle = composite.particles[i]; if (particle.leaf) { ctx.beginPath(); ctx.arc(particle.pos.x, particle.pos.y, 25, 0, 2*Math.PI); ctx.fillStyle = "#679d7c"; ctx.fill(); } } } tree2.drawConstraints = function(ctx, composite) { var i; ctx.save(); ctx.strokeStyle = "#543324"; ctx.lineCap = "round"; for (i=0;i<composite.constraints.length;++i) { var constraint = composite.constraints[i]; if (!(constraint instanceof DistanceConstraint && typeof constraint.p != "undefined")) continue; ctx.beginPath(); ctx.moveTo(constraint.a.pos.x, constraint.a.pos.y); ctx.lineTo(constraint.b.pos.x, constraint.b.pos.y); ctx.lineWidth = lerp(10,2,constraint.p); ctx.stroke(); } ctx.restore(); } // animation loop var loop = function() { sim.frame(16); sim.draw(); requestAnimFrame(loop); }; loop(); }; </script> <div id="footer"> Copyright 2013 Sub Protocol and other contributors. <br/><a href="http://subprotocol.com/">http://subprotocol.com/</a> </div> </body>