问题描述
我使用 x
和 y
的随机坐标并设置 z=0
在场景中生成了一个相机,并调整相机的方向,使其看起来在 (0,0) 点上.我的目标是使用地面上随机生成的速度向量向前移动相机(因此 z
保持 0
)。我想确保相机的新位置在向前移动后处于有效范围内,以相对于当前焦点/方向的度数定义。更具体地说,我确定“有效范围”的方法是确保新位置在旧相机焦点的 45 度以内(向左 -45 度,向右 +45 度)。有人可以写一段关于我如何实现这一目标的伪代码吗?
这是我的尝试,但这似乎不是帮助我实现我想要的正确方法:
camera_dir = (0,0) - current_cam_pos
while True:
vel_vec=[uniform(-max_vel,max_vel),uniform(-max_vel,max_vel)] # generate a random veLocity vector
new_pos = camera_dir + vel_vec # compute a new position (and camera direction vector) for the camera
if (compute_angle(new_pos,camera_dir) < 45 or compute_angle(new_pos,camera_dir) > 315):
break
解决方法
您可以使用:
// 45° in rad
double validAngle = Math.PI / 4;
ThreadLocalRandom random = ThreadLocalRandom.current();
Vector2D camPosition = new Vector2D(0,-1);
Vector2D camTarget= new Vector2D(0,0);
Vector2D camDirection = camTarget.subtract(camPosition).normalize();
double cosPhi = camDirection.x;
double phi = Math.acos(cosPhi);
double alpha = random.nextDouble(-validAngle,validAngle);
double angle = phi + alpha;
Vector2D velocity = new Vector2D(Math.cos(angle),Math.sin(angle)).multiply(speed);
Vector2D newPosition = position.add(velocity.multiply(deltaTime));
这种方法是用 Java 编写的,但对于其他语言应该是非常可移植的。
但是,我认为这不是一个完美的解决方案,因为这种方法使用了大量三角函数,这在您必须在每一帧中更新相机的游戏中可能代价高昂。
该方法使用凸轮方向和 x 轴之间的角度以及允许的最大角度来计算最终矢量。首先,我计算凸轮方向和 x 轴之间夹角的余弦并将其命名为 phi
。 phi 的余弦为:camDirection.dotProduct(new Vector2D(1,0));
,即凸轮方向的 x 分量。因此,假设您的凸轮方向是 (0,1),即 y 轴。那么 phi
是 90°。现在您只需生成一个介于 -45° 和 45° 之间的随机数(将其转换为弧度)并将此角度 alpha
添加到 phi
。结果 angle
将在相对于 x 轴的 [135°;45°] 范围内。现在你有了一个相对于 x 轴的角度,并用 (cos(angle),sin(angle))
计算你的二维向量。您可以测试生成的方向向量是否在允许的最大角度内:
Vector2D newDirection = new Vector2D(Math.cos(angle),Math.sin(angle));
double cosBeta = newDirection.dotProduct(camDirection);
double beta = Math.acos(cosBeta);
beta
将始终在所需范围内,并表示相机方向和生成的速度方向之间的角度。下图应说明此方法:
感谢您指出 camDirection.dotProduct(new Vector2D(1,0));
表示相机方向的 x 分量。我改变了那个。 :)