unity quaternion euler change angles c# rotation angle

quaternion - transform rotation c#



Normalizar orientación entre 0 y 360. (8)

Estoy trabajando en una rutina de rotación simple que normaliza una rotación de objetos entre 0 y 360 grados. Mi código C # parece estar funcionando pero no estoy del todo contento con él. ¿Alguien puede mejorar el código a continuación para hacerlo un poco más sólido?

public void Rotate(int degrees) { this.orientation += degrees; if (this.orientation < 0) { while (this.orientation < 0) { this.orientation += 360; } } else if (this.orientation >= 360) { while (this.orientation >= 360) { this.orientation -= 360; } } }


Agregue cualquier múltiplo de 360 ​​grados entre los cuales podrían estar los valores de entrada posibles (para llevarlo por encima de cero), y simplemente tome el restante con%, como este

angle = 382; normalized_angle = (angle+3600) %360; //result = 22

El caso anterior puede tomar ángulos de entrada hasta -3600. Puede agregar cualquier número (múltiplo de 360) locamente alto que haría que el valor de entrada fuera positivo primero.

Por lo general, durante una animación, su valor de fotograma / paso anterior probablemente ya se habrá normalizado en el paso anterior, por lo que estará listo simplemente agregando 360:

normalized_angle = (angle+360) %360;


De alguna manera me burlé de esto rápidamente en AS3, pero debería funcionar (es posible que necesites += en el ángulo)

private Number clampAngle(Number angle) { return (angle % 360) + (angle < 0 ? 360 : 0); }


Este es uno que normaliza a cualquier rango. Útil para normalizar entre [-180,180], [0,180] o [0,360].

(aunque está en C ++)

//Normalizes any number to an arbitrary range //by assuming the range wraps around when going below min or above max double normalise( const double value, const double start, const double end ) { const double width = end - start ; // const double offsetValue = value - start ; // value relative to 0 return ( offsetValue - ( floor( offsetValue / width ) * width ) ) + start ; // + start to reset back to start of original range }

Para ints

//Normalizes any number to an arbitrary range //by assuming the range wraps around when going below min or above max int normalise( const int value, const int start, const int end ) { const int width = end - start ; // const int offsetValue = value - start ; // value relative to 0 return ( offsetValue - ( ( offsetValue / width ) * width ) ) + start ; // + start to reset back to start of original range }

Así que básicamente lo mismo pero sin suelo. La versión que uso personalmente es una genérica que funciona para todos los tipos numéricos y también utiliza un piso redefinido que no hace nada en caso de tipos integrales.


Esto se puede simplificar a lo siguiente.

public void Rotate (int degrees) { this.orientation = (this.orientation + degrees) % 360; if (this.orientation < 0) this.orientation += 360; }

C # sigue las mismas reglas que C y C ++ y i % 360 le dará un valor entre -359 y 359 para cualquier entero, luego la segunda línea es para asegurarse de que esté en el rango de 0 a 359, ambos inclusive.

Si quisieras ser shifty, podrías reducirlo a una línea:

this.orientation = (this.orientation + (degrees % 360) + 360) % 360;

lo que lo mantendría positivo en todas las condiciones, pero es un truco desagradable para guardar una línea de código, así que no lo haría, pero lo explicaré.

De degrees % 360 obtendrá un número entre -359 y 359 . La adición de 360 modificará el rango entre 1 y 719 . Si la orientation ya es positiva, agregar esto garantizará que aún lo sea, y el % 360 final lo devolverá al rango de 0 a 359 .

Como mínimo , puede simplificar su código, ya while se pueden combinar if s y while s. Por ejemplo, el resultado de las condiciones en estas dos líneas:

if (this.orientation < 0) while (this.orientation < 0)

Siempre es lo mismo, por lo tanto no necesitas el entorno if .

Entonces, para ese fin, podrías hacer:

public void Rotate (int degrees) { this.orientation += degrees; while (this.orientation < 0) this.orientation += 360; while (this.orientation > 359) this.orientation -= 360; }

pero todavía me gustaría ir a la versión de módulo, ya que evita los bucles. Esto será importante cuando un usuario ingrese 360,000,000,000 para la rotación (y lo harán , créanme) y luego descubren que tienen que tomar un almuerzo temprano mientras su código se aleja :-)


Función que resulta útil al normalizar ángulos (grados) en el intervalo [0, 360>:

float normalize_angle(float angle) { float k = angle; while(k < 0.0) k += 360.0; while(k >= 360.0) k -= 360.0; return k; }


La fórmula para reorientar los valores circulares, es decir, para mantener el ángulo entre 0 y 359 es:

angle + Math.ceil( -angle / 360 ) * 360

La fórmula generalizada para cambiar la orientación del ángulo puede ser:

angle + Math.ceil( (-angle+shift) / 360 ) * 360

en el que el valor de desplazamiento representa un cambio circular, por ejemplo, quiero valores de -179 a 180, luego se puede representar como: angle + Math.ceil ((-angle-179) / 360) * 360


Prefiero evitar bucles, condicionales, compensaciones arbitrarias (3600) y llamadas Math.____() :

var degrees = -123; degrees = (degrees % 360 + 360) % 360; // degrees: 237


Usar modulo aritmético:

this.orientation += degrees; this.orientation = this.orientation % 360; if (this.orientation < 0) { this.orientation += 360; }