Unity引擎的Rotation是如何實現的?
可以自己手動算旋轉矩陣
參考了一下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
;
}
上一篇:這種錄音筆怎麼充電?
下一篇:蜂蜜怎麼喝更好?