Skip to content

Instantly share code, notes, and snippets.

@9re
Last active January 2, 2016 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 9re/8345006 to your computer and use it in GitHub Desktop.
Save 9re/8345006 to your computer and use it in GitHub Desktop.
calculation of refraction
<html>
<head>
<title>refract test</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" />
</head>
<body>
<canvas width="465" height="465" id="world"></canvas>
<div class="input">
n1 : <input type="text" id="n1" value="1.000293" />
n2 : <input type="text" id="n2" value="1.333" />
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
var canvas = document.getElementById('world'),
context = canvas.getContext('2d'),
width = canvas.width,
height = canvas.height,
center, n1, n2
;
var VERTEX0,
VERTEX1,
VERTEX2,
VERTEX3,
RI = {}
;
function Vec2(x, y) {
this.x = x;
this.y = y;
}
Vec2.prototype = {
minus : function (other) {
return new Vec2(this.x - other.x, this.y - other.y);
},
plus : function (other) {
return new Vec2(this.x + other.x, this.y + other.y);
},
scalar : function (k) {
return new Vec2(k * this.x, k * this.y);
},
crossProd : function (other) {
return this.x * other.y - this.y * other.x;
},
dot : function (other) {
return this.x * other.x + this.y * other.y;
},
normalize : function () {
var len = Math.sqrt(this.dot(this));
this.x /= len;
this.y /= len;
}
};
function findIntersection(p0, p1) {
var p;
p = hitTest(p0, p1, VERTEX0, VERTEX1);
if (p) {
return p;
}
p = hitTest(p0, p1, VERTEX1, VERTEX2);
if (p) {
return p;
}
p = hitTest(p0, p1, VERTEX2, VERTEX3);
if (p) {
return p;
}
p = hitTest(p0, p1, VERTEX3, VERTEX0);
if (p) {
return p;
}
return undefined;
}
function hitTest(p0, p1, q0, q1) {
var p = p1.minus(p0);
var v = q1.minus(q0).crossProd(p);
if (v === 0) {
console.log("v === 0");
return undefined;
}
var pq = p0.minus(q0);
var u = pq.crossProd(p);
var t = u / v;
if (t < 0 || t > 1) {
return undefined;
}
var l = pq.crossProd(q1.minus(q0));
var k = l / v;
if (k < 0) {
return undefined;
}
var s = 1 - t;
return q0.scalar(s).plus(q1.scalar(t));
}
function refract(n1, n2, a, N) {
var n = n2 / n1;
var k = a.dot(N);
var c = 1 - n * n * (1 - k * k);
var res = undefined;
if (c >= 0) {
c = Math.sqrt(c);
var t = n * k - c;
res = new Vec2(
n * a.x + t * N.x,
n * a.y + t * N.y
);
}
return res;
}
function renderLine(p0, p1, strokeColor) {
context.beginPath();
context.strokeStyle = strokeColor;
context.moveTo(p0.x, p0.y);
context.lineTo(p1.x, p1.y);
context.stroke();
}
function onmousemove(e) {
var mouse = new Vec2(e.x, e.y);
var p = findIntersection(center, mouse);
context.clearRect(0, 0, width, height);
renderLine(new Vec2(center.x, VERTEX0.y), new Vec2(center.x, VERTEX2.y), '#000');
renderLine(new Vec2(VERTEX0.x, center.y), new Vec2(VERTEX2.x, center.y), '#000');
renderLine(center, p, '#ff7700');
var a = center.minus(mouse);
a.normalize();
var refracted = refract(n1, n2, a, new Vec2(0, 1));
p = findIntersection(center, center.plus(refracted));
renderLine(center, p, '#77ff00');
}
function updateN1 () {
var input = document.getElementById('n1');
n1 = input.value;
}
function updateN2 () {
var input = document.getElementById('n2');
n2 = input.value;
}
function init() {
center = new Vec2(width / 2, height / 2);
context.lineWidth = 2;
canvas.addEventListener('mousemove', onmousemove);
updateN1();
updateN2();
document
.getElementById('n1')
.addEventListener('input', updateN1);
document
.getElementById('n2')
.addEventListener('input', updateN2);
VERTEX0 = new Vec2(0, 0);
VERTEX1 = new Vec2(465, 0);
VERTEX2 = new Vec2(465, 465);
VERTEX3 = new Vec2(0, 465);
onmousemove(VERTEX0);
}
init();
html, body {
margin : 0;
border : 0;
padding : 0;
}
.input {
background : rgba(0, 0, 0, 0.7);
width : 465px;
color : white;
position : absolute;
top : 0px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment