Animate
Depth
The HTML file:
<html>
<head>
<script id="vertex-shader" type="x-shader/x-vertex" >
attribute vec4 vStartPosition;
attribute vec4 vEndPosition;
attribute vec4 vColor;
uniform float percent;
varying vec4 f_Color;
void main() {
float fixedPct;
fixedPct = clamp(percent, 0.0, 1.0);
gl_Position = mix(vStartPosition, vEndPosition, fixedPct);
f_Color = vColor;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 f_Color;
void main() {
gl_FragColor = f_Color;
}
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="AniSepTriCanvas.js"></script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
<style>
input {
text-align: right;
}
</style>
</head>
<body>
<h1>A Sierpinski Gasket With Triangles</h1>
<script>
var WIDTH = 500;
var HEIGHT = 500;
var canvas = new Canvas(WIDTH, HEIGHT);
window.addEventListener("load", function(event){
document.getElementById('DepthBox').value = canvas.GetDepth();
});
</script>
<p>
<button type="button" onclick=" canvas.AnimationStep()">Animate 1</button>
<p>
Animate
<label class="switch">
<input type="checkbox" onclick="canvas.ChangeAnimation()">
</label>
<p>
Depth
<input
type="text"
name="Depth"
maxLength = "5"
size = "5"
value = ""
id="DepthBox", onchange="canvas.ChangeDepth(this.value)">
<p>
</body>
The Javascript File
function MakeCanvas(width, height, locID) {
if (width == undefined || width < 0) {
width = 300;
}
if (height == undefined || height < 0) {
height = 300;
}
var canvas = document.createElement('canvas')
canvas.height = height;
canvas.width = width;
if(locID == undefined) {
document.body.appendChild(canvas);
} else {
div = document.getElementById(locID);
if (null == div) {
document.body.appendChild(canvas);
} else {
div.appendChild(canvas);
}
}
document.body.appendChild(canvas);
return canvas;
}
function Canvas(width, height, locID) {
var canvas = MakeCanvas(width, height, locID);
var gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert ("WebGL isn't available");
}
this.gl = gl;
gl.viewport(0,0, width, height);
program = initShaders(gl, "vertex-shader","fragment-shader");
gl.useProgram(program);
// somewhat new code, two vertex buffers.
this.vStartBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.vStartBuffer);
var vPosition = gl.getAttribLocation(program, "vStartPosition");
gl.vertexAttribPointer(vPosition,2,gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(vPosition);
this.vEndBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.vEndBuffer);
vPosition = gl.getAttribLocation(program, "vEndPosition");
gl.vertexAttribPointer(vPosition,2,gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(vPosition);
// a buffer for the colors
this.cBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.cBuffer);
var colorAttribute = gl.getAttribLocation(program, "vColor");
gl.vertexAttribPointer(colorAttribute,3,gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(colorAttribute);
// this is new. Get the location to send pct
this.pctLoc = gl.getUniformLocation(program, "percent");
this.pct = 0;
this.pctStep = 0.01;
gl.uniform1f(this.pctLoc, this.pct);
this.maxDepth = 1;
this.Init();
return this;
}
Canvas.prototype = {
Init: function() {
this.animationState = false;
this.gl.clearColor(1.0, 1.0, 1.0, 1.0);
this.RestartList();
},
RestartList: function() {
this.currentDepth = 0;
var p1 = vec2(-0.8, -0.8);
var p2 = vec2(0, .8);
var p3 = vec2(0.8, -0.8);
this.verts= [p1, p2, p3] ;
var c1 = vec3(Math.random(), Math.random(),Math.random())
var c2 = vec3(Math.random(), Math.random(),Math.random())
var c3 = vec3(Math.random(), Math.random(),Math.random())
this.colors = [c1, c2, c3];
this.MakePoints();
this.MakeOld();
this.UpdateBuffers();
this.Redisplay();
},
UpdateBuffers: function() {
gl = this.gl;
// change the vertex data
gl.bindBuffer(gl.ARRAY_BUFFER, this.vStartBuffer);
gl.bufferData(gl.ARRAY_BUFFER,flatten(this.startV),gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vEndBuffer);
gl.bufferData(gl.ARRAY_BUFFER,flatten(this.verts),gl.DYNAMIC_DRAW);
// change the color data
gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer);
gl.bufferData(gl.ARRAY_BUFFER,flatten(this.colors),gl.DYNAMIC_DRAW);
},
GetDepth: function() {
return this.maxDepth;
},
ChangeDepth: function(newDepth) {
var depth = parseInt(newDepth);
if (depth < 1 ) {
alert("depth must be positive");
return;
}
if (depth > 11) {
alert ("Depth has a max value of 11");
depth = 10;
}
if (depth < this.maxDepth) {
this.maxDepth = depth;
this.RestartList();
} else {
this.maxDepth = depth;
this.MakePoints();
this.MakeOld();
var gl = this.gl;
this.UpdateBuffers();
}
this.Redisplay();
},
Interp: function(a,b,s) {
return a*(1-s) + b*s;
},
HalfPoint: function(p1,p2) {
var x = this.Interp(p1[0],p2[0],.5);
var y = this.Interp(p1[1],p2[1],.5);
return vec2(x,y);
},
AddTri: function(p1, p2, p3, vert, c1, colors) {
vert.push(p1);
colors.push(c1);
vert.push(p2);
var c2 = vec3(Math.random(), Math.random(),Math.random())
colors.push(c2);
vert.push(p3);
var c3 = vec3(Math.random(), Math.random(),Math.random())
colors.push(c3);
},
MakePoints: function(){
var newVertex = [];
var newColors = [];
var a,b,c;
var p1, p2, p3;
if (this.currentDepth < this.maxDepth) {
this.currentDepth++;
for(i =0; i < this.verts.length;i+=3) {
a = this.verts[i];
b = this.verts[i+1]
c = this.verts[i+2];
ap = this.HalfPoint(a,b,.5);
bp = this.HalfPoint(b,c,.5);
cp = this.HalfPoint(c,a,.5);
this.AddTri(a,ap,cp, newVertex, this.colors[i], newColors);
this.AddTri(b,bp,ap, newVertex, this.colors[i+1], newColors);
this.AddTri(c,cp,bp, newVertex, this.colors[i+2], newColors);
}
this.verts = newVertex;
this.colors = newColors;
this.MakePoints();
}
return;
},
MakeOld: function() {
this.startV = [];
var mid;
var tris = this.verts.length/3;
for(var i =0; i < this.verts.length; i+= 9) {
this.startV.push(this.verts[i]);
this.startV.push(this.verts[i+2]);
this.startV.push(this.verts[i+1]);
this.startV.push(this.verts[i+3]);
this.startV.push(this.verts[i+5]);
this.startV.push(this.verts[i+4]);
this.startV.push(this.verts[i+6]);
this.startV.push(this.verts[i+8]);
this.startV.push(this.verts[i+7]);
}
return;
},
Midpoint: function(p1, p2, p3) {
var x = (p1[0]+p2[0]+p3[0])/3;
var y = (p1[1]+p2[1]+p3[1])/3;
return vec2(x,y);
},
ChangeAnimation: function() {
this.animationState = !this.animationState;
if (this.animationState) {
setTimeout(canvas.FakeAnimationStep,20,this);
}
},
IsAnimating: function() {
return this.animationState;
},
FakeAnimationStep: function(me) {
me.AnimationStep();
},
AnimationStep: function() {
this.pct += this.pctStep;
if (this.pct >= 1.0) {
this.pct = 1.0;
this.pctStep *= -1;
}
if (this.pct <= 0.0) {
this.pct = 0.0;
this.pctStep *= -1;
}
if (this.animationState) {
setTimeout(canvas.FakeAnimationStep,20,this);
}
this.gl.uniform1f(this.pctLoc, this.pct);
this.Redisplay();
},
Redisplay: function() {
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length);
return;
}
};