我正在制作基于画布的动画,并且我试图在2D画布中获得3D效果。
到目前为止,情况进展顺利!我已经得到了我的"轨道三角形线"工作得很好:
var c = document.createElement('canvas');
c.width = c.height = 100;
document.body.appendChild(c);
var ctx = c.getContext("2d");
function Triangles() {
this.rotation = {
x: Math.random()*Math.PI*2,
y: Math.random()*Math.PI*2,
z: Math.random()*Math.PI*2
};
/* Uncomment this for testing perspective...
this.rotation = {
x: Math.PI/2,
y: 0,
z: 0
};
*/
}
Triangles.prototype.draw = function(t) {
this.rotation.z += t/1000;
var i, points;
for( i=0; i<15; i++) {
points = [
this.computeRotation(Math.cos(0.25*i),-Math.sin(0.25*i),0),
this.computeRotation(Math.cos(0.25*(i+1)),-Math.sin(0.25*(i+1)),-0.1),
this.computeRotation(Math.cos(0.25*(i+1)),-Math.sin(0.25*(i+1)),0.1)
];
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(50+40*points[0][0],50+40*points[0][1]);
ctx.lineTo(50+40*points[1][0],50+40*points[1][1]);
ctx.lineTo(50+40*points[2][0],50+40*points[2][1]);
ctx.closePath();
ctx.fill();
}
};
Triangles.prototype.computeRotation = function(x,y,z) {
var rz, ry, rx;
rz = [
Math.cos(this.rotation.z) * x - Math.sin(this.rotation.z) * y,
Math.sin(this.rotation.z) * x + Math.cos(this.rotation.z) * y,
z
];
ry = [
Math.cos(this.rotation.y) * rz[0] + Math.sin(this.rotation.y) * rz[2],
rz[1],
-Math.sin(this.rotation.y) * rz[0] + Math.cos(this.rotation.y) * rz[2]
];
rx = [
ry[0],
Math.cos(this.rotation.x) * ry[1] - Math.sin(this.rotation.x) * ry[2],
Math.sin(this.rotation.x) * ry[1] + Math.cos(this.rotation.x) * ry[2]
];
return rx;
};
var tri = new Triangles();
requestAnimationFrame(function(start) {
function step(t) {
var delta = t-start;
ctx.clearRect(0,0,100,100)
tri.draw(delta);
start = t;
requestAnimationFrame(step);
}
step(start);
});
&#13;
正如你所看到的,它使用旋转矩阵来计算旋转后点的位置,并且我使用它来使用输出x和y坐标绘制三角形。
我想通过使用z坐标并为此动画添加透视来更进一步,这将使三角形在前景时略大,而在背景中则更小。但是,我不知道该怎么做。
我想这更像是一个数学问题,而不是编程问题,对不起!
答案 0 :(得分:1)
定义焦距以控制透视量。值越大,透视量越少。然后
var fl = 200; // focal length;
var px = 100; // point in 3D space
var py = 200;
var pz = 500;
然后得到屏幕X,Y
var sx = (px * fl) / pz;
var sy = (py * fl) / pz;
结果点相对于视图的中心,因此您需要将其居中到画布上。
sx += canvas.width/2;
sy += canvas.height/2;
这是重点。
假设被观察的点位于视图的前方,并且远离焦点的焦距。
答案 1 :(得分:0)
我已经设法找到一个基本的解决方案,但我确定有更好的解决方案,所以如果你有更完整的答案,请随意添加它!但是现在......
由于坐标系已经基于原点而直接在Z
轴上观察(x,y)
平面,因此实际上只需将(x,y)
坐标乘以值与z
成比例。例如,x * (z+2)/2
在这种情况下可以正常使用
但是,必然会有一个更恰当,更通用的解决方案!