Javascript 围绕圆移动阴影

Javascript 围绕圆移动阴影,javascript,math,transformation,Javascript,Math,Transformation,我有一个圆圈,每10秒绕一圈。我试图投射一个阴影,这个阴影与轨道原点(光源)成一定角度,同时也考虑了摄像机的角度 阴影适用于某些角度,但随着相机越来越靠近边缘或越来越自上而下,它看起来越来越不准确,我不知道如何纠正它-这似乎是一个复杂的数学问题,我正在努力找出如何解决 这是动画: 还有我的阴影绘制代码: ctx.beginPath(); //rotate shadow with the planet ctx.translate(originX + obj[i].x, originY + obj

我有一个圆圈,每10秒绕一圈。我试图投射一个阴影,这个阴影与轨道原点(光源)成一定角度,同时也考虑了摄像机的角度

阴影适用于某些角度,但随着相机越来越靠近边缘或越来越自上而下,它看起来越来越不准确,我不知道如何纠正它-这似乎是一个复杂的数学问题,我正在努力找出如何解决

这是动画:

还有我的阴影绘制代码:

ctx.beginPath();

//rotate shadow with the planet
ctx.translate(originX + obj[i].x, originY + obj[i].y);
ctx.rotate(obj[i].angle); //rotate around origin
ctx.translate(-(originX + obj[i].x), -(originY + obj[i].y));


var offsetX = -(10 * Math.sin(obj[0].angle)); //i feel this is the issue
var offsetY = 0; //this too

ctx.rect(originX + obj[i].x + offsetX, originY + obj[i].y + offsetY - 10, 20, 20);
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see
ctx.fill();
通过JSFIDLE,代码变得更有意义,因为它将代码放入更多的上下文中


因此,我认为这与
offsetX
offsetY
变量的数学有关,当用户改变相机角度时,偏移需要适应并改变阴影移动的方式。但是,这真的很难解决。

你这样做是因为你的
obj[i].角度
是基于椭圆坐标,而不是自顶向下视图的x-y坐标(这实际上是你生成其他所有东西的基础,所以我们不需要对它进行计算)

您将需要两个角度,因此我为另一个角度添加了第二个属性。旋转上下文时需要椭圆角度,以便可以从原点垂直于向量。新角度用于计算。您可以将其视为非2D映射版本

obj[i].trueAngle = angle;
现在我们有了工作的价值,我建议为“黑暗面”绘制一个半圆,然后根据需要使用您选择的曲线添加或剪切该区域以完成阴影,例如

// centre on planet
ctx.translate(originX + obj[i].x, originY + obj[i].y);
ctx.rotate(obj[i].angle - Math.PI / 2);
// semicircle dark side
ctx.arc(0, 0, 12, 0, Math.PI, false);
// path along terminator
var offset_terminator = -20 * Math.sin(obj[0].trueAngle) * (1 - camera.angle);
ctx.bezierCurveTo(-7, offset_terminator, 7, offset_terminator, 12, 0);
//fill
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see
ctx.fill();
在这里,我也使阴影比行星大两倍,我只是玩数字,直到我发现一些看起来不错

请注意,我设置了旋转,因此
0,0
是行星的中心,x轴沿终止线移动


因此,如果我理解正确的话,您希望圆中面向原点的半球被照亮,而其余的半球被照亮。无论摄影机角度如何,这都是正确的。正确吗?@AsadSaeeduddin它应该考虑到你观察行星的角度。所以我相信你已经理解正确了。@Asadsaeeddin说得好,基本上它只需要从观众的角度看是正确的。如果你在
camera angle=0
上看边缘,它应该投射全阴影,没有阴影,等等,自上而下
camera angle=1
它会一直投射半阴影。可能类似<代码>ctx.rect(originX+obj[i].x+offsetX*(1-camera.angle),originY+obj[i].y-10,20,20)。。如果你想做弯曲的边缘,这会变得更加复杂,你甚至可能想考虑WebGL而不是2d@PaulS. 如果在演示中从0的摄影机角度观察阴影(侧面),该方法不起作用,因为阴影跳得不正确。我不需要弯曲的阴影。如果你想要更薄的新月体,考虑把<代码> OffStJielEngor <代码>的标量从<代码> -20 < /代码>改为“代码>14”/代码>,这实际上使它看起来非常神奇,为什么魔法数字12和7?他们不应该分别是10和5吗?我想这是为了解释笔划,但如果只是去掉笔划,扩大圆的半径,不是更有意义吗?@FuzzyLogic我选择了
12
,以确保阴影颜色覆盖所有像素,即使边缘混合,因为它们在
10
像素处可能不完美。OP有一个轮廓可以隐藏这一点<代码>11对双方都不起作用。至于
7
,因为它提供了一个漂亮的形状贝塞尔曲线。啊哈,抗锯齿。干得好。从你的帖子中,听起来你很古怪:)哇,这太棒了@PaulS!我不知道你所说的偏移终结者是什么意思,不过我猜这与阴影的真实效果有关,但它看起来太好了!你的数学真的很好:P