【问题标题】:JavaScript - Animated rotation algorithmJavaScript - 动画旋转算法
【发布时间】:2017-02-10 17:24:18
【问题描述】:

我刚刚编写了一段代码来处理 THREE.js 场景中的对象旋转。但问题不是 3D 特定的。

我希望我的对象 (this) 在每个函数调用时转动 0.25 弧度,直到它的旋转 (this.clientRotation) 达到 this.targetRotation 中定义的旋转。下面的代码是在渲染循环中不断调用的 update() 函数的内容。

我必须检查当前和目标旋转之间的绝对差是否高于每次调用的旋转量 (0.25),以避免在几乎达到目标旋转时来回转动。

我必须检查旋转(以弧度为单位)差异是否超过 180 度,在这种情况下,最短的转弯将是相反的方向。

我必须检查更新后的旋转是否保持在 -PI 和 +PI(0 到 360 度)之间。

//Move only if we find a delta big enough between the target rotation and current rotation
//Rotation goes from -PI to +PI
this.rotationSpeed = 0.25;

var absDiff = Math.abs(this.clientRotation - this.targetRotation);
if(absDiff > this.rotationSpeed){

  if(absDiff < Math.PI){

    //Less than 180 degrees, turn towards the target
    if(this.targetRotation > this.clientRotation) this.clientRotation += this.rotationSpeed;
    if(this.targetRotation < this.clientRotation) this.clientRotation -= this.rotationSpeed;
  } else {

    //More than 180 degrees this way, so it is shorter to turn the other way
    if(this.targetRotation > this.clientRotation) this.clientRotation -= this.rotationSpeed;
    if(this.targetRotation < this.clientRotation) this.clientRotation += this.rotationSpeed;
  }

  //If rotation radians becomes more than a complete 360 turn, start again from 0
//If it goes below 0, start again down from 360
  if(this.clientRotation > Math.PI) this.clientRotation -= Math.PI*2;
  if(this.clientRotation < -Math.PI) this.clientRotation += Math.PI*2;
}

它有效,但似乎过于复杂。是否有更优化的方式来实现这种标准旋转行为?

【问题讨论】:

    标签: javascript three.js rotation trigonometry radians


    【解决方案1】:

    下面的代码在功能上是相同的,只是使用三元组来压缩逻辑。 IMO 它更容易阅读,但它完全是首选。

    this.rotationSpeed = 0.25;
    var absDiff = Math.abs(this.clientRotation - this.targetRotation);
    if(absDiff > this.rotationSpeed) {
      var lessThan180 = absDiff < Math.PI;
      if(this.targetRotation > this.clientRotation) {
        this.clientRotation = (lessThan180) ? this.clientRotation + this.rotationSpeed : this.clientRotation - this.rotationSpeed;
      } else if (this.targetRotation < this.clientRotation) {
        this.clientRotation = (lessThan180) ? this.clientRotation - this.RotationSpeed : this.clientRotation + this.rotationSpeed; 
      }
      this.clientRotation = (this.clientRotation > Math.PI) ? this.clientRotation - Math.PI*2 : this.clientRotation + Math.PI*2; 
    }
    

    您的原始代码可能看起来过于复杂,但实际上我认为您在通过 cmets 记录代码并使代码清晰易读方面做得很好。无论如何,我建议改变的唯一挑剔的事情(即使你不是三元组的粉丝)是使用 'if'/'else-if''s 而不是 'if' 然后另一个 'if' 条件.这是因为无论如何都会运行两个“if”条件,而在“if”/“else-if”中,如果“if”语句条件成功,则不会检查并跳过“else-if”条件,所以效率更高。

    【讨论】:

    • 我也经常使用三元组,但我个人发现在某些情况下没有它们的代码会更清晰。 else-ifs 的好点:)
    猜你喜欢
    • 2013-05-29
    • 2021-06-26
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多