Created
October 20, 2016 14:37
-
-
Save julie-is-late/38feed3ef776bd9357527b79f8aab658 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" > | |
<title>Elliptipool with Barriers</title> | |
<script id="vertex-shader" type="x-shader/x-vertex"> | |
attribute vec4 vPosition; | |
uniform mat4 projectionMatrix; | |
varying vec4 color; | |
void | |
main() | |
{ | |
color = vec4(0, abs(vPosition.x) / 100.0, abs(vPosition.y) / 100.0, 1); | |
gl_Position = projectionMatrix * vPosition; | |
} | |
</script> | |
<script id="fragment-shader" type="x-shader/x-fragment"> | |
precision mediump float; | |
varying vec4 color; | |
void | |
main() | |
{ | |
// gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); | |
gl_FragColor = 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="elliptipoolBarriers.js"></script> | |
</head> | |
<body> | |
<canvas id="gl-canvas" width="600" height="600"> | |
Oops ... your browser doesn't support the HTML5 canvas element | |
</canvas> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var gl; | |
var points; | |
var projectionMatrix; | |
var projectionLoc; | |
var numEllipsePoints; | |
var numCirclePoints; | |
var numFociPoints; | |
var circle1, circle2; | |
var currentIntersectTime; | |
const numRays = 1000; // number of rays to draw | |
const A = 100; // x-axis radius | |
const B = 75; // y-axis radius | |
const zeroTolerance = 0.000001; // anything less than this in absolute value is "equal" to zero | |
window.onload = function init() | |
{ | |
var canvas = document.getElementById( "gl-canvas" ); | |
var limit; | |
var xold; | |
var yold; | |
var twopi; | |
var asq; | |
var bsq; | |
var s = [], c = [], new_s = [], new_c = [], n = []; | |
var apart, bpart, cpart, length, dotprod; | |
gl = WebGLUtils.setupWebGL( canvas ); | |
if ( !gl ) { alert( "WebGL isn't available" ); } | |
// Determine window so ellipse will fit completely inside. | |
if (A > B) | |
limit = 1.1 * A; | |
else | |
limit = 1.1 * B; | |
asq = A*A; | |
bsq = B*B; | |
// Draw ellipse, taking advantage of four-fold symmetry. | |
points = []; | |
numEllipsePoints = 0; | |
xold = A; | |
yold = 0.0; | |
twopi = 2.0 * 3.141592654; | |
for (var angle=0.0; angle<0.251; angle+=0.002) | |
{ | |
xnew = A * Math.cos(twopi*angle); | |
ynew = B * Math.sin(twopi*angle); | |
points.push (vec2(xold, yold)); | |
points.push (vec2(xnew, ynew)); | |
points.push (vec2(-xold, yold)); | |
points.push (vec2(-xnew, ynew)); | |
points.push (vec2(xold, -yold)); | |
points.push (vec2(xnew, -ynew)); | |
points.push (vec2(-xold, -yold)); | |
points.push (vec2(-xnew, -ynew)); | |
numEllipsePoints += 8; | |
xold = xnew; | |
yold = ynew; | |
} | |
// Draw the two foci as small circles. | |
numCirclePoints = 0; | |
if (A > B) | |
{ | |
focus = Math.sqrt (asq - bsq); | |
draw_circle (focus, 0.0, 0.02*B); | |
draw_circle (-focus, 0.0, 0.02*B); | |
} | |
else | |
{ | |
focus = Math.sqrt (bsq - asq); | |
draw_circle (0.0, focus, 0.02*A); | |
draw_circle (0.0, -focus, 0.02*A); | |
} | |
numFociPoints = numCirclePoints / 2; | |
// Draw some barriers. | |
numCirclePoints = 0; | |
draw_circle (10, 50, 15); | |
circle1 = new circle (10, 50, 15, numCirclePoints); | |
numCirclePoints = 0; | |
draw_circle (50, -25, 20); | |
circle2 = new circle (50, -25, 20, numCirclePoints); | |
// Draw the rays. Begin inside the foci. | |
if (A > B) | |
{ | |
s[1] = 0.0; | |
s[0] = Math.random() * 0.75*focus; | |
} | |
else | |
{ | |
s[0] = 0.0; | |
s[1] = Math.random() * 0.75*focus; | |
} | |
c[0] = Math.random(); // Determine a random starting direction for the ray. | |
c[1] = Math.random(); | |
for (var i=0; i<numRays; i++) | |
{ | |
// Determine intersection point of current ray with ellipse. | |
apart = bsq*c[0]*c[0] + asq*c[1]*c[1]; | |
bpart = 2.0 * (bsq*s[0]*c[0] + asq*s[1]*c[1]); | |
cpart = bsq*s[0]*s[0] + asq*s[1]*s[1] - asq*bsq; | |
currentIntersectTime = (-bpart + Math.sqrt(bpart*bpart - 4*apart*cpart)) / (2*apart); | |
new_s[0] = s[0] + c[0]*currentIntersectTime; | |
new_s[1] = s[1] + c[1]*currentIntersectTime; | |
n[0] = -bsq * new_s[0]; | |
n[1] = -asq * new_s[1]; | |
// See if there is a closer intersection with any of the barriers. | |
intersect_circle (circle1, s, c, new_s, n); | |
intersect_circle (circle2, s, c, new_s, n); | |
// Save old and new intersection points. | |
points.push (vec2(s)); | |
points.push (vec2(new_s)); | |
// Determine reflected ray's direction. | |
length = Math.sqrt (n[0]*n[0] + n[1]*n[1]); | |
n[0] /= length; | |
n[1] /= length; | |
dotprod = 2 * (c[0]*n[0] + c[1]*n[1]); | |
n[0] *= dotprod; | |
n[1] *= dotprod; | |
c[0] -= n[0]; | |
c[1] -= n[1]; | |
/* Change starting point to intersection point. */ | |
s[0] = new_s[0]; | |
s[1] = new_s[1]; | |
} | |
// Configure WebGL | |
gl.viewport( 0, 0, canvas.width, canvas.height ); | |
gl.clearColor( 1.0, 1.0, 1.0, 1.0 ); | |
// Load shaders and initialize attribute buffers | |
var program = initShaders( gl, "vertex-shader", "fragment-shader" ); | |
gl.useProgram( program ); | |
// Load the data into the GPU | |
var bufferId = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ); | |
gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW ); | |
// Associate our shader variables with our data buffer | |
var vPosition = gl.getAttribLocation( program, "vPosition" ); | |
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( vPosition ); | |
projectionMatrix = ortho(-limit, limit, -limit, limit, -1.0, 1.0); | |
projectionLoc = gl.getUniformLocation( program, "projectionMatrix" ); | |
render(); | |
}; | |
function draw_circle (xc, yc, r) | |
// This function draws a circle of radius r centered at (xc, yc). | |
{ | |
var i, limit, step; | |
limit = 2 * 3.141592654; | |
step = limit / 25; | |
limit += step/2; | |
for (i=0; i<limit; i+=step) | |
{ | |
points.push (vec2(xc+r*Math.cos(i), yc+r*Math.sin(i))); | |
++numCirclePoints; | |
} | |
} | |
function circle (xcenter, ycenter, radius, points) { | |
this.xcenter = xcenter; | |
this.ycenter = ycenter; | |
this.radius = radius; | |
this.points = points; | |
} | |
function intersect_circle (circleItem, s, c, new_s, n) { | |
var h = [], sh = [], shc, discr; | |
h[0] = circleItem.xcenter; | |
h[1] = circleItem.ycenter; | |
sh[0] = s[0] - h[0]; | |
sh[1] = s[1] - h[1]; | |
shc = sh[0]*c[0] + sh[1]*c[1]; | |
discr = (shc*shc - (c[0]*c[0] + c[1]*c[1]) * ((sh[0]*sh[0] + sh[1]*sh[1])-circleItem.radius*circleItem.radius)); | |
if (discr > zeroTolerance) // ray intersects circle | |
{ | |
ti = (-shc-Math.sqrt(discr)) / (c[0]*c[0] + c[1]*c[1]); | |
if ((ti > zeroTolerance) && (ti < currentIntersectTime)) | |
{ | |
currentIntersectTime = ti; | |
new_s[0] = s[0] + c[0]*currentIntersectTime; | |
new_s[1] = s[1] + c[1]*currentIntersectTime; | |
n[0] = new_s[0] - h[0]; | |
n[1] = new_s[1] - h[1]; | |
} | |
} | |
} | |
function render() { | |
var totalPoints = 0; | |
gl.clear (gl.COLOR_BUFFER_BIT); | |
gl.uniformMatrix4fv (projectionLoc, false, flatten(projectionMatrix)); | |
gl.drawArrays (gl.LINES, 0, numEllipsePoints); // outer ellipse | |
totalPoints += numEllipsePoints; | |
//gl.drawArrays (gl.LINE_LOOP, totalPoints, numFociPoints); // first focus | |
totalPoints += numFociPoints; | |
//gl.drawArrays (gl.LINE_LOOP, totalPoints, numFociPoints); // second focus | |
totalPoints += numFociPoints; | |
gl.drawArrays (gl.LINE_LOOP, totalPoints, circle1.points); // circular barriers | |
totalPoints += circle1.points; | |
gl.drawArrays (gl.LINE_LOOP, totalPoints, circle2.points); // circular barriers | |
totalPoints += circle2.points; | |
gl.drawArrays (gl.LINES, totalPoints, 2*numRays); // rays | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment