【发布时间】:2018-08-13 15:08:19
【问题描述】:
我编写了一个简单的函数,它使用 DDA 算法来实现 2D 光线追踪(命名为 findCollision),但是在某些情况下它的行为似乎很奇怪;
function findCollision(position, direction, world, maxDistance = 10) {
const steps = Math.max(
Math.abs(direction.x),
Math.abs(direction.y),
);
const increment = {
x: direction.x / steps,
y: direction.y / steps,
};
let x = position.x;
let y = position.y;
for (let i = 0; i < maxDistance; i++) {
const roundedX = Math.round(x);
const roundedY = Math.round(y);
if (world[roundedX] && world[roundedX][roundedY]) {
return { x, y };
}
x += increment.x;
y += increment.y;
}
return null;
}
const CELL_SIZE = 32;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const center = { x: 4, y: 4 };
const map = [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
];
Object.assign(canvas, {
width: 500,
height: 500,
});
function draw() {
for (let i = 0; i < Math.PI * 2; i += Math.PI / 32) {
const dX = Math.cos(i);
const dY = Math.sin(i);
const collision = findCollision(center, { x: dX, y: dY }, map, 64);
if (!collision) {
continue;
}
context.strokeStyle = 'rgba(0, 0, 0, 0.5)';
context.beginPath();
context.moveTo(center.x * CELL_SIZE, center.y * CELL_SIZE);
context.lineTo(collision.x * CELL_SIZE, collision.y * CELL_SIZE);
context.stroke();
context.fillStyle = 'rgba(0, 0, 0, 0.1)';
context.fillRect(collision.x * CELL_SIZE, collision.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
}
}
requestAnimationFrame(draw);
document.body.appendChild(canvas);
从输出中可以看出,任何指向画布顶部或左侧的光线都超出了碰撞区域 1 个方块(即 1 个增量)。我的算法有什么问题?
【问题讨论】:
标签: javascript raytracing