#javascript #3d #projection
Вопрос:
сегодня я пытался создать механизм рендеринга 3D-каркаса с использованием JavaScript; обратите внимание, что моя цель-в конечном итоге создать шутер rails, поэтому преобразования камеры пока не очень важны для меня. Однако, похоже, я не могу заставить перспективную проекцию хорошо работать:
This is my code for rendering, note my dependence on glMatrix:
export default (() =>
{
const { mat4, vec3 } = glMatrix;
function line(pixels, a_x = 0, a_y = 0, b_x = 0, b_y = 0, color = 0xFF0000)
{
// Bresenham's algorithm
};
function translate(point, pos)
{
vec3.add(point, point, pos);
}
function rotate(point, pos, rot)
{
vec3.rotateX(point, point, pos, rot[0]);
vec3.rotateY(point, point, pos, rot[1]);
vec3.rotateZ(point, point, pos, rot[2]);
};
function transform(point, pos, rot)
{
translate(point, pos);
rotate(point, pos, rot);
};
return {
Camera: class
{
constructor(pos, fudge)
{
/* Unused
this.pos = pos;
this.rot = [0, 0, 0]; */
this.fudge = fudge;
}
fudged(p)
{
return this.fudge / (p[2] this.fudge);
}
},
Model: class
{
constructor(verts, edges, faces)
{
this.faces = faces;
this.edges = edges;
this.verts = verts;
this.pos = [0, 0, 0];
this.rot = [0, 0, 0];
this.scale = [1, 1, 1];
}
render(camera, pixels)
{
for (const face of this.faces)
{
for (const index of face.edges)
{
const edge = this.edges[index];
const a = [...this.verts[edge.verts[0]]];
const b = [...this.verts[edge.verts[1]]];
transform(a, this.pos, this.rot);
transform(b, this.pos, this.rot);
const a_p = camera.fudged(a);
const b_p = camera.fudged(b);
line(pixels, a[0] * a_p, a[1] * a_p, b[0] * b_p, b[1] * b_p, edge.color);
}
}
}
},
};
})();
And this is the code that sets the scene up:
import Wireframe from './wireframe.js';
export default function main()
{
const canvas = document.querySelector `canvas`;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const ctx = canvas.getContext('2d');
const camera = new Wireframe.Camera([canvas.width / 2, canvas.height / 2, 200], canvas.width);
const model = new Wireframe.Model(
[ // Verts
[-50, -50, 50], [50, -50, 50],
[50, 50, 50], [-50, 50, 50],
[50, 50, -50], [-50, 50, -50],
[-50, -50, -50], [50, -50, -50]],
[ // Edges
{ color: 0xFFC800, verts: [0, 1] },
{ color: 0x20C8FF, verts: [1, 2] },
{ color: 0x00C800, verts: [2, 3] },
{ color: 0xC82020, verts: [3, 0] },
{ color: 0xFFC800, verts: [3, 5] },
{ color: 0x20C8FF, verts: [5, 6] },
{ color: 0x00C800, verts: [6, 0] },
{ color: 0xC82020, verts: [0, 3] },
{ color: 0xFFC800, verts: [4, 5] },
{ color: 0x20C8FF, verts: [5, 6] },
{ color: 0x00C800, verts: [6, 7] },
{ color: 0xC82020, verts: [7, 4] }],
[ // Faces
{ edges: [0, 1, 2, 3] },
{ edges: [4, 5, 6, 7] },
{ edges: [8, 9, 10, 11] }]);
model.pos = [canvas.width / 2, canvas.height / 2, 0];
const draw = (() =>
{
return mil =>
{
window.requestAnimationFrame(draw);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
model.render(camera, pixels);
model.rot[1] = 0.01;
ctx.putImageData(pixels, 0, 0);
};
})();
window.requestAnimationFrame(draw);
};
Any help here is appreciated, thank you.