Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize: Optimize the lookat function of transform. #701

Merged
merged 8 commits into from
Mar 22, 2022
Merged
49 changes: 34 additions & 15 deletions packages/core/src/Transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { UpdateFlagManager } from "./UpdateFlagManager";
*/
export class Transform extends Component {
private static _tempQuat0: Quaternion = new Quaternion();
private static _tempVec3: Vector3 = new Vector3();
private static _tempVec30: Vector3 = new Vector3();
private static _tempVec31: Vector3 = new Vector3();
private static _tempVec32: Vector3 = new Vector3();
private static _tempMat30: Matrix3x3 = new Matrix3x3();
private static _tempMat31: Matrix3x3 = new Matrix3x3();
private static _tempMat32: Matrix3x3 = new Matrix3x3();
Expand Down Expand Up @@ -434,7 +436,7 @@ export class Transform extends Component {
relativeToLocal?: boolean
): void {
if (typeof translationOrX === "number") {
const translate = Transform._tempVec3;
const translate = Transform._tempVec30;
translate.setValue(translationOrX, <number>relativeToLocalOrY, z);
this._translate(translate, relativeToLocal);
} else {
Expand Down Expand Up @@ -485,24 +487,41 @@ export class Transform extends Component {

/**
* Rotate and ensure that the world front vector points to the target world position.
* @param worldPosition - Target world position
* @param targetPosition - Target world position
* @param worldUp - Up direction in world space, default is Vector3(0, 1, 0)
*/
lookAt(worldPosition: Vector3, worldUp?: Vector3): void {
const position = this.worldPosition;
const EPSILON = MathUtil.zeroTolerance;
if (
Math.abs(position.x - worldPosition.x) < EPSILON &&
Math.abs(position.y - worldPosition.y) < EPSILON &&
Math.abs(position.z - worldPosition.z) < EPSILON
) {
lookAt(targetPosition: Vector3, worldUp?: Vector3): void {
const zAxis = Transform._tempVec30;
Vector3.subtract(this.worldPosition, targetPosition, zAxis);
let axisLen = zAxis.length();
if (axisLen <= MathUtil.zeroTolerance) {
// The current position and the target position are almost the same.
return;
}
const rotMat = Transform._tempMat43;
zAxis.scale(1 / axisLen);
const xAxis = Transform._tempVec31;
if (worldUp) {
Vector3.cross(worldUp, zAxis, xAxis);
} else {
xAxis.setValue(zAxis.z, 0, -zAxis.x);
}
axisLen = xAxis.length();
if (axisLen <= MathUtil.zeroTolerance) {
// @todo:
// 1.worldup is(0,0,0)
// 2.worldUp is parallel to zAxis
return;
}
xAxis.scale(1 / axisLen);
const yAxis = Transform._tempVec32;
Vector3.cross(zAxis, xAxis, yAxis);

worldUp = worldUp ?? Transform._tempVec3.setValue(0, 1, 0);
Matrix.lookAt(position, worldPosition, worldUp, rotMat);
Quaternion.invert(rotMat.getRotation(Transform._tempQuat0), this._worldRotationQuaternion);
const rotMat = Transform._tempMat41;
const { elements: e } = rotMat;
(e[0] = xAxis.x), (e[1] = xAxis.y), (e[2] = xAxis.z);
(e[4] = yAxis.x), (e[5] = yAxis.y), (e[6] = yAxis.z);
(e[8] = zAxis.x), (e[9] = zAxis.y), (e[10] = zAxis.z);
rotMat.getRotation(this._worldRotationQuaternion);
}

/**
Expand Down