将3D向量在2D平面上旋转
2015-2-10 6:39:27
收藏:0
阅读:170
评论:2
我有两个 Vec3s,摄像机前向和炮塔前向。这两个向量都在不同的平面上,其中相机前向基于自由视角相机,而炮塔前向则由它所坐的坦克,坦克所在的地形等决定。炮塔向上和相机向上很少会匹配。
我的问题如下:我想让炮塔能够使用固定速度(每秒44度)旋转,以便它始终与相机指向的方向相交。如果坦克处于一种奇怪的角度,它无法与相机相交,它应该找到最接近的位置并停留在那里,而不是无限制地抖动。
我无法解决这个问题。我尝试了一些我在网上找到的方法,它们总是产生奇怪的结果。
local forward = player.direction:rotate(player.turret, player.up)
local side = forward:cross(player.up)
local projection = self.camera.direction:dot(forward) * forward + self.camera.direction:dot(side) * side
local angle = math.atan2(forward.y, forward.x) - math.atan2(projection.y, projection.x)
if angle ~= 0 then
local dt = love.timer.getDelta()
if angle <= turret_speed * dt then
player.turret_velocity = turret_speed
elseif angle >= -turret_speed * dt then
player.turret_velocity = -turret_speed
else
player.turret_velocity = 0
player.turret = player.turret + angle
end
end

点赞
用户1190664
经过更多的研究和测试,我得到了以下的解决方案。它运作得非常好!
function Gameplay:moved_axisright(joystick, x, y)
if not self.manager.id then return end
local turret_speed = math.rad(44)
local stick = cpml.vec2(-x, -y)
local player = self.players[self.manager.id]
-- 鼠标和轴控制相机视角
self.camera:rotateXY(stick.x * 18, stick.y * 9)
-- 获取相机方向和炮塔方向之间的角度
local fwd = cpml.vec2(0, 1):rotate(player.orientation.z + player.turret)
local cam = cpml.vec2(1, 0):rotate(math.atan2(self.camera.direction.y, self.camera.direction.x))
local angle = fwd:angle_to(cam)
-- 如果炮塔方向不对,进行调整
if math.abs(angle) > 0 then
local function new_angle(direction)
local dt = love.timer.getDelta()
local velocity = direction * turret_speed * dt
return cpml.vec2(0, 1):rotate(player.orientation.z + player.turret + velocity):angle_to(cam)
end
-- 将炮塔旋转到正确的方向
if new_angle(1) < 0 then
player.turret_velocity = turret_speed
elseif new_angle(-1) > 0 then
player.turret_velocity = -turret_speed
else
-- 如果旋转一个完整帧会超出范围,将炮塔设置为相机位置
-- atan2从左边开始,我们还需要添加半个旋转。减去玩家方向以将其转换为本地空间。
player.turret = math.atan2(self.camera.direction.y, self.camera.direction.x) + (math.pi * 1.5) - player.orientation.z
player.turret_velocity = 0
end
end
local direction = cpml.mat4():rotate(player.turret, { 0, 0, 1 }) * cpml.mat4():rotate(player.orientation.z, { 0, 0, 1 })
player.turret_direction = cpml.vec3(direction * { 0, 1, 0, 1 })
end
2015-02-10 09:20:35
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
我会以不同的方式完成它:
在 GCS(全局坐标系统)中获取相机方向向量
c在 GCS 中获取炮塔方向向量
t计算在两个方向中旋转的炮塔方向向量
t0=rotation(-44.0deg/s)*tt1=rotation(+44.0deg/s)*t现在计算点积
a =dot(c,t)a0=dot(c,t0)a1=dot(c,t1)确定炮塔旋转
【注】
cos(向量之间的角度),因为c,t都是单位向量(如果从标准变换矩阵中获取)