2016-10-02 3 views
0

THREE.js 장면에서 객체 회전을 처리하기 위해 코드 조각을 작성했습니다. 그러나 문제는 3D와 관련이 없습니다.JavaScript - 애니메이션 회전 알고리즘

회전 (this.clientRotation)이 this.targetRotation에 정의 된 회전에 도달 할 때까지 내 객체 (this)가 각 함수 호출시 0.25 라디안만큼 회전하도록합니다. 아래의 코드는 렌더링 루프에서 계속 호출되는 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; 
} 

그것은 작동하지만 지나치게 복잡한 것 같다. 이 표준 회전 동작을 달성하는 데 더 최적화 된 방법이 있습니까?

답변

2

다음 코드는 로직을 압축하기 위해 3 진을 사용하는 것과 기능면에서 동일합니다. 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; 
} 

원래 코드는 복잡 이상 보일지도 모르지만, 사실은 당신이 의견을 통해 코드를 문서화하고 코드가 명확하고 읽을 만드는 훌륭한 일을했다고 생각. 내가 변경을 권하는 유일한 nitpick - y는 (비록 당신이 3 자의 팬이 아니라고하더라도) 'if'/ 'else-if'대신에 'if'를 사용하고 또 다른 'if'조건부 . 이것은 'if'조건문이 무엇이든 상관없이 실행되기 때문이며 'if'/ 'else-if'조건문이 성공하면 'else-if'조건문은 검사되지 않고 건너 뜁니다. , 그래서 더 효율적입니다.

+0

나는 또한 종종 터너 리를 사용하지만 개인적으로 어떤 경우에는 코드가없는 코드를 찾는다. else-ifs에 대한 좋은 지적 :) – Rayjax