godot 简单实用的旋转和位移平滑插值方案, tween 版本, 方案1 是通用的 unity 支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #相机平滑视角移动 #旧方案 移动超过360 或者负数的角度,会转大圈,也有可能会遇到万向节死锁的问题 func camera_move_old(move_node,move_pos:Vector3,move_rot:Vector3,time): var tween = create_tween().set_parallel() tween.tween_property(move_node, "global_position" ,Vector3(move_pos),time) tween.tween_property(move_node, "global_rotation" ,Vector3(move_rot),time) pass #方案1 采用四元数完成 平滑插值 func camera_move(move_node,move_pos:Vector3,move_rot:Vector3,time): var tween = create_tween().set_parallel() tween.tween_property(move_node, "global_position" ,Vector3(move_pos),time) # init 初始化 旋转的平滑插值 var basis = Basis() # 欧拉角的默认旋转顺序: YXZ var axisX = Vector3( 1 , 0 , 0 ) var rotation_amountX = (move_rot.x) var axisY = Vector3( 0 , 1 , 0 ) var rotation_amountY = (move_rot.y) var axisZ = Vector3( 0 , 0 , 1 ) var rotation_amountZ = (move_rot.z) basis = Basis(axisZ, rotation_amountZ) * basis basis = Basis(axisX, rotation_amountX) * basis basis = Basis(axisY, rotation_amountY) * basis var my_lambda = func (weight): var a = Quaternion(basis) var b = Quaternion(move_node.transform.basis) var c = a.slerp(b,weight / 100.0 ) move_node.transform.basis = Basis(c) pass tween.tween_method(func(weight): my_lambda.call(weight), 0 , 100 ,time) pass #方案2 采用I3D 的提供的API interpolate_with 完成平滑插值 func camera_move_2(move_node,move_pos:Vector3,move_rot:Vector3,time): var tween = create_tween().set_parallel() # init 初始化 旋转的平滑插值 var basis = Basis() # 欧拉角的默认旋转顺序: YXZ var axisX = Vector3( 1 , 0 , 0 ) var rotation_amountX = (move_rot.x) var axisY = Vector3( 0 , 1 , 0 ) var rotation_amountY = (move_rot.y) var axisZ = Vector3( 0 , 0 , 1 ) var rotation_amountZ = (move_rot.z) basis = Basis(axisZ, rotation_amountZ) * basis basis = Basis(axisX, rotation_amountX) * basis basis = Basis(axisY, rotation_amountY) * basis var target_transform = Transform3D(basis,move_pos) #init 旋转和位移 var my_lambda = func (weight): move_node.transform = move_node.transform.interpolate_with(target_transform, weight / 100.0 ) pass tween.tween_method(func(weight): my_lambda.call(weight), 0 , 100 ,time) pass |
godot 引擎源码的实现方案:interpolate_with 方法的实现(考虑了缩放和归一化的问题)
Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { Transform3D interp; Vector3 src_scale = basis.get_scale(); Quaternion src_rot = basis.get_rotation_quaternion(); Vector3 src_loc = origin; Vector3 dst_scale = p_transform.basis.get_scale(); Quaternion dst_rot = p_transform.basis.get_rotation_quaternion(); Vector3 dst_loc = p_transform.origin; interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); interp.origin = src_loc.lerp(dst_loc, p_c); return interp; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2022-12-20 MinIO等设置上传的文件可预览
2015-12-20 C/C++语言参数传递----函数/方法 参数的指针引用传递