Округление вектора направления до 8-стороннего компаса

портрет2018facebook.jpg

Современные игровые контроллеры могут указывать в самых разных направлениях. Разработчики игр иногда хотят преобразовать направление джойстика, чтобы получить движение в 8 направлениях . Типичное предлагаемое решение состоит в том, чтобы вычислить угол, округлить его и затем вычислить вектор направления.

 двойной угол = atan2 ( y , x ) ;  
   
  угол = ( int ( округление ( 4 * угол / PI + 8 ) ) % 8 ) * PI / 4 ;  
   
  xout = cos ( угол ) ;  
   
  yout = грех ( угол ) ;  
   

Если вы предполагаете, что вектор направления находится в первом квадранте (и x, и y положительны), то есть прямой способ вычислить решение. Используя 1/sqrt(2) или 0,7071 в качестве решения по умолчанию, сравните x и y с cos(3*pi/8) и cos(pi/8) и переключите их на 1 или 0, только если они больше, чем cos (3*pi/8) или меньше, чем cos(pi/8). Полный код выглядит следующим образом:

 xout = 0,7071067811865475 ;  
   
  вы = 0,7071067811865475 ;  
   
  
   
  если ( x > = 0,923879532511286 ) { // cos(3*pi/8)  
   
    выход = 1 ;  
   
  }  
   
  если ( y > = 0,923879532511286 ) { // cos(3*pi/8)  
   
    ты = 1 ;  
   
  }  
   
  если ( x < 0,3826834323650898 ) { // cos(pi/8)  
   
    выход = 0 ;  
   
  }  
   
  если ( y < 0,3826834323650898 ) { // cos(pi/8)  
   
    ты = 0 ;  
   
  }  
   

Вы можете обобщить решение для случая, когда либо x, либо y (или оба) отрицательны, сначала взяв абсолютное значение, а затем восстановив знак в конце:

 логический xneg = x < 0 ;  
   
  логический yneg = y < 0 ;  
   
  если ( xneg ) {  
   
    х = - х ;  
   
  }  
   
  если ( инэг ) {  
   
    у = - у ;  
   
  }  
   
  двойной исход = 0,7071067811865475 ;  
   
  двойной выход = 0,7071067811865475 ;  
   
  
   
  если ( x > = 0,923879532511286 ) { // cos(3*pi/8)  
   
    исход = 1 ;  
   
  }  
   
  если ( y > = 0,923879532511286 ) { // cos(3*pi/8)  
   
    выход = 1 ;  
   
  }  
   
  если ( x < 0,3826834323650898 ) { // cos(pi/8)  
   
    исход = 0 ;  
   
  }  
   
  если ( y < 0,3826834323650898 ) { // cos(pi/8)  
   
    выход = 0 ;  
   
  }  
   
  если ( xneg ) {  
   
    Исх = - Исх ;  
   
  }  
   
  если ( инэг ) {  
   
    аути = - аути ;  
   
  }  
   

Я написал небольшой бенчмарк, работающий со случайными входными данными . Ваши результаты будут отличаться, но на моем ноутбуке Mac с LLVM 12 я получаю, что прямой подход в 25 раз быстрее.

с касательной 40 нс/вектор
быстрый подход 1,5 нс/вектор

Leave a Comment

Ваш адрес email не будет опубликован.