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;
}
复制代码

 

posted @   porter_代码工作者  阅读(656)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源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++语言参数传递----函数/方法 参数的指针引用传递
点击右上角即可分享
微信分享提示