Ray Marching
More efficient ray-casting!
by ElijahCirioli
HTML
<canvas id="canvas" width="600" height="600"></canvas>
CSS
#canvas {
border: 3px solid black;
}
JavaScript
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var objects = [];
var angle = 0;
var x = 50;
var y = 300;
function Circle(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
Circle.prototype.distance = function(x, y) {
return Math.sqrt(((y - this.y) * (y - this.y)) + ((x - this.x) * (x - this.x))) - this.r;
}
function Square(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
Square.prototype.distance = function(x, y) {
var dx = 0;
var dy = 0;
if (x < this.x - this.r) { //left
dx = this.x - this.r - x;
} else if (x > this.x + this.r) { //right
dx = this.x + this.r - x;
}
if (y < this.y - this.r) { //top
dy = this.y - this.r - y;
} else if (y > this.y + this.r) { //bottom
dy = this.y + this.r - y;
}
return magnitude(dx, dy);
}
function setup() {
objects.push(new Circle(300, 500, 80));
objects.push(new Circle(120, 400, 30));
objects.push(new Circle(320, 160, 100));
objects.push(new Circle(360, 310, 10));
objects.push(new Circle(470, 400, 60));
objects.push(new Square(100, 60, 50));
objects.push(new Square(550, 280, 30));
requestAnimationFrame(draw);
}
function draw() {
//draw background
context.fillStyle = "white";
context.fillRect(0, 0, canvas.width, canvas.height);
//draw objects
context.fillStyle = "red";
for (var i = 0; i < objects.length; i++) {
var o = objects[i];
if (o instanceof Circle) {
context.beginPath();
context.arc(o.x, o.y, o.r, 0, 2 * Math.PI);
context.fill();
} else {
context.fillRect(o.x - o.r, o.y - o.r, o.r * 2, o.r * 2);
}
}
//cast ray
var dist = castRay(x, y);
//draw ray
context.fillStyle = "black";
context.font = "16px arial";
if (dist < 99999) {
context.fillText(dist.toFixed(3), 520, 585);
} else {
context.fillText("infinity", 520, 585);
}
context.strokeStyle = "black";
context.lineWidth = 2;
context.beginPath();
context.moveTo(x, y);
context.lineTo(x + (700 * Math.cos(angle)), y + (700 *...