您當前的位置:首頁 > 遊戲

Unity引擎的Rotation是如何實現的?

作者:由 橙色橙汁 發表于 遊戲時間:2022-03-23

Unity引擎的Rotation是如何實現的?半吊子程式猿2022-03-23 10:06:39

可以自己手動算旋轉矩陣

Unity引擎的Rotation是如何實現的?

Unity引擎的Rotation是如何實現的?橙色橙汁2022-03-24 15:36:20

參考了一下blender和Unity4的原始碼,先貼一下原始碼,之後有空再補充回答。

Pick the best euler:

void mat3_normalized_to_compatible_eulO(float eul[3],

const float oldrot[3],

const short order,

const float mat[3][3])

{

float eul1[3], eul2[3];

float d1, d2;

mat3_normalized_to_eulo2(mat, eul1, eul2, order);

compatible_eul(eul1, oldrot);

compatible_eul(eul2, oldrot);

d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]);

d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]);

/* return best, which is just the one with lowest difference */

if (d1 > d2) {

copy_v3_v3(eul, eul2);

}

else {

copy_v3_v3(eul, eul1);

}

}

/* returns two euler calculation methods, so we can pick the best */

static void mat3_normalized_to_eulo2(const float mat[3][3],

float eul1[3],

float eul2[3],

const short order)

{

const RotOrderInfo *R = get_rotation_order_info(order);

short i = R->axis[0], j = R->axis[1], k = R->axis[2];

float cy;

BLI_ASSERT_UNIT_M3(mat);

cy = hypotf(mat[i][i], mat[i][j]);

if (cy > 16。0f * FLT_EPSILON) {

eul1[i] = atan2f(mat[j][k], mat[k][k]);

eul1[j] = atan2f(-mat[i][k], cy);

eul1[k] = atan2f(mat[i][j], mat[i][i]);

eul2[i] = atan2f(-mat[j][k], -mat[k][k]);

eul2[j] = atan2f(-mat[i][k], -cy);

eul2[k] = atan2f(-mat[i][j], -mat[i][i]);

}

else {

eul1[i] = atan2f(-mat[k][j], mat[j][j]);

eul1[j] = atan2f(-mat[i][k], cy);

eul1[k] = 0;

copy_v3_v3(eul2, eul1);

}

void compatible_eul(float eul[3], const float oldrot[3])

{

/* we could use M_PI as pi_thresh: which is correct but 5。1 gives better results。

* Checked with baking actions to fcurves - campbell */

const float pi_thresh = (5。1f);

const float pi_x2 = (2。0f * (float)M_PI);

float deul[3];

unsigned int i;

/* correct differences of about 360 degrees first */

for (i = 0; i < 3; i++) {

deul[i] = eul[i] - oldrot[i];

if (deul[i] > pi_thresh) {

eul[i] -= floorf((deul[i] / pi_x2) + 0。5f) * pi_x2;

deul[i] = eul[i] - oldrot[i];

}

else if (deul[i] < -pi_thresh) {

eul[i] += floorf((-deul[i] / pi_x2) + 0。5f) * pi_x2;

deul[i] = eul[i] - oldrot[i];

}

}

/* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */

if (fabsf(deul[0]) > 3。2f && fabsf(deul[1]) < 1。6f && fabsf(deul[2]) < 1。6f) {

if (deul[0] > 0。0f) {

eul[0] -= pi_x2;

}

else {

eul[0] += pi_x2;

}

}

if (fabsf(deul[1]) > 3。2f && fabsf(deul[2]) < 1。6f && fabsf(deul[0]) < 1。6f) {

if (deul[1] > 0。0f) {

eul[1] -= pi_x2;

}

else {

eul[1] += pi_x2;

}

}

if (fabsf(deul[2]) > 3。2f && fabsf(deul[0]) < 1。6f && fabsf(deul[1]) < 1。6f) {

if (deul[2] > 0。0f) {

eul[2] -= pi_x2;

}

else {

eul[2] += pi_x2;

}

}

}

To display any angle:

private

float

RepeatWorking

float

t

float

length

{

return

t

-

float

)(

Math

Floor

t

/

length

*

length

));

}

private

void

SyncEulerHint

ref

float

[]

eul

Vec3F

vec

{

const

float

twoPi

=

float

)(

2。0

*

Math

PI

);

eul

0

=

RepeatWorking

eul

0

-

vec

X

+

float

Math

PI

twoPi

+

vec

X

-

float

Math

PI

eul

1

=

RepeatWorking

eul

1

-

vec

Y

+

float

Math

PI

twoPi

+

vec

Y

-

float

Math

PI

eul

2

=

RepeatWorking

eul

2

-

vec

Z

+

float

Math

PI

twoPi

+

vec

Z

-

float

Math

PI

}

標簽: Eul  float  deul  mat  eul1