Skip to content

Commit

Permalink
fix(Matrix4): Fix matrix calculation error of lookAt (Orillusion#231)
Browse files Browse the repository at this point in the history
Fix matrix calculation error when executing the lookAt function from a special angle(90/270).
Delete the wrong Euler angles calculation method
Delete the wrong Euler angles calculation method
Delete the wrong Euler angles calculation method.
  • Loading branch information
hellmor authored Jun 28, 2023
1 parent 13608a8 commit a1617f6
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 58 deletions.
31 changes: 5 additions & 26 deletions src/components/Transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,39 +397,18 @@ export class Transform extends ComponentBase {
* @param up up direction
*/
public lookAt(pos: Vector3, target: Vector3, up: Vector3 = Vector3.UP) {
this._targetPos = target.clone();
this._localPos.copyFrom(pos);
this.notifyLocalChange();
this._targetPos ||= new Vector3();
this._targetPos.copyFrom(target);

this.localPosition = pos;

Matrix4.helpMatrix.lookAt(pos, target, up);
Matrix4.helpMatrix.invert();
var prs: Vector3[] = Matrix4.helpMatrix.decompose(Orientation3D.QUATERNION);
Quaternion.CALCULATION_QUATERNION.x = prs[1].x;
Quaternion.CALCULATION_QUATERNION.y = prs[1].y;
Quaternion.CALCULATION_QUATERNION.z = prs[1].z;
Quaternion.CALCULATION_QUATERNION.w = prs[1].w;
Quaternion.CALCULATION_QUATERNION.toEulerAngles(this._localRot);

if (this.eventPositionChange) {
this.eventDispatcher.dispatchEvent(this.eventPositionChange);
}

if (this.onPositionChange) {
this.onPositionChange();
}

if (this.onRotationChange) {
this.onRotationChange();
}

if (this.eventRotationChange) {
this.eventDispatcher.dispatchEvent(this.eventRotationChange);
}
this.localRotQuat = Quaternion.CALCULATION_QUATERNION.copyFrom(prs[1]);
}




public decomposeFromMatrix(matrix: Matrix4, orientationStyle: string = 'eulerAngles'): this {
let prs = matrix.decompose(orientationStyle);

Expand Down
18 changes: 8 additions & 10 deletions src/math/Matrix4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ export class Matrix4 {
*/
public lookAt(eye: Vector3, at: Vector3, up: Vector3 = Vector3.Y_AXIS): void {
let data = this.rawData;
at.subtract(eye, Vector3.HELP_0);
let zAxis: Vector3 = Vector3.HELP_0;
let zAxis: Vector3 = at.subtract(eye, Vector3.HELP_0);
if (zAxis.length < 0.0001) {
zAxis.z = 1;
}
Expand All @@ -362,14 +361,12 @@ export class Matrix4 {
} else {
zAxis.z += 0.0001;
}
zAxis.normalize();
}

zAxis.normalize();
up.cross(zAxis, xAxis);

xAxis = up.cross(zAxis, xAxis).normalize();

xAxis.normalize(); //
let yAxis = zAxis.crossProduct(xAxis, Vector3.HELP_2);
let yAxis = zAxis.crossProduct(xAxis, Vector3.HELP_2).normalize();

data[0] = xAxis.x;
data[1] = yAxis.x;
Expand Down Expand Up @@ -1433,6 +1430,7 @@ export class Matrix4 {
return this;
}

private static decomposeRawData = new Float32Array(16).fill(0)
/**
* Decompose the current matrix
* @param orientationStyle The default decomposition type is Orientation3D.EULER_ANGLES
Expand All @@ -1445,8 +1443,8 @@ export class Matrix4 {
public decompose(orientationStyle: string = 'eulerAngles', target?: Vector3[]): Vector3[] {
let q: Quaternion = Quaternion.CALCULATION_QUATERNION;
let vec: Vector3[] = target ? target : Matrix4._prs;
this.copyRawDataTo(Matrix4.helpMatrix.rawData);
let mr = Matrix4.helpMatrix.rawData;
this.copyRawDataTo(Matrix4.decomposeRawData);
let mr = Matrix4.decomposeRawData;

let pos: Vector3 = vec[0];
pos.x = mr[12];
Expand Down Expand Up @@ -1548,7 +1546,7 @@ export class Matrix4 {
q.y = (mr[6] + mr[9]) / (4 * q.z);
q.w = (mr[1] - mr[4]) / (4 * q.z);
}
q.toEulerAngles(rot);
q.getEulerAngles(rot);

break;
}
Expand Down
25 changes: 3 additions & 22 deletions src/math/Quaternion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,26 +332,6 @@ export class Quaternion {
return this;
}

/**
* Fills a target Vector3D object with the Euler angles that form the rotation represented by this quaternion.
* @param target An optional Vector3D object to contain the Euler angles. If not provided, a new object is created.
* @returns The Vector3D containing the Euler angles.
*/
public toEulerAngles(target: Vector3 = null): Vector3 {
target ||= new Vector3();
target.x = Math.atan2(2.0 * (this.w * this.x + this.y * this.z), 1.0 - 2.0 * (this.x * this.x + this.y * this.y));

var temp: number = 2.0 * (this.w * this.y - this.z * this.x);
temp = this.clampf(temp, -1.0, 1.0);
target.y = Math.asin(temp);
target.z = Math.atan2(2.0 * (this.w * this.z + this.x * this.y), 1.0 - 2.0 * (this.y * this.y + this.z * this.z));

target.x /= DEGREES_TO_RADIANS;
target.y /= DEGREES_TO_RADIANS;
target.z /= DEGREES_TO_RADIANS;
return target;
}

/**
* Sets the current quaternion from the rotation matrix
* @param m
Expand Down Expand Up @@ -418,7 +398,7 @@ export class Quaternion {
var qw;
var a2;

eulers = eulers === undefined ? new Vector3() : eulers;
eulers ||= new Vector3();

qx = this.x;
qy = this.y;
Expand Down Expand Up @@ -538,12 +518,13 @@ export class Quaternion {
* Copies the data from a quaternion into this instance.
* @param q The quaternion to copy from.
*/
public copyFrom(q: Quaternion | Vector3) {
public copyFrom(q: Quaternion | Vector3): this {
var v = this;
v.x = q.x;
v.y = q.y;
v.z = q.z;
v.w = q.w;
return this;
}

/**
Expand Down

0 comments on commit a1617f6

Please sign in to comment.