Skip to content

Commit

Permalink
Match complex/quaternion rotation methods with matrices
Browse files Browse the repository at this point in the history
  • Loading branch information
yzrmn committed Apr 17, 2024
1 parent 9979bf1 commit 89a5bb0
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 126 deletions.
39 changes: 17 additions & 22 deletions packages/redgeometry-app/src/parts/gpu-cube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,22 @@ function cameraMoveSystem(world: World): void {
return;
}

let camRot = transform.rotation;
let camPos = transform.translation;
const camRot = transform.rotation;

if (mouse.isPressing(MouseButtons.Mouse3)) {
let dx = 0;
let dy = 0;

for (const ev of world.readEvents<InputMouseMotionEvent>("input-mouse-motion")) {
dx -= ev.movementX;
dy -= ev.movementY;
}

const sens = 1 / 250;

camRot.rotateXPre(sens * dy);
camRot.rotateY(sens * dx);
}

let vel = 0.005;
let x = 0;
Expand All @@ -322,28 +336,9 @@ function cameraMoveSystem(world: World): void {
v = v.unitOrZero().mul(delta * vel);
v = camRot.mulVec(v);

camPos = camPos.add(v);
transform.translation = transform.translation.add(v);
}

if (mouse.isPressing(MouseButtons.Mouse3)) {
let dx = 0;
let dy = 0;

for (const ev of world.readEvents<InputMouseMotionEvent>("input-mouse-motion")) {
dx -= ev.movementX;
dy -= ev.movementY;
}

const sens = 1 / 250;
const yaw = sens * dx;
const pitch = sens * dy;

camRot = camRot.rotateXPre(pitch).rotateY(yaw);
}

transform.rotation = camRot;
transform.translation = camPos;

world.updateComponent<TransformComponent>(mainCamera, "transform");

const fovRad = fov * (Math.PI / 180);
Expand Down
8 changes: 6 additions & 2 deletions packages/redgeometry/src/primitives/complex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,14 @@ export class Complex {
return new Vector2(this.a * v.x - this.b * v.y, this.a * v.y + this.b * v.x);
}

public rotate(angle: number): Complex {
public rotate(angle: number): void {
const sin = Math.sin(angle);
const cos = Math.cos(angle);
return new Complex(cos * this.a - sin * this.b, cos * this.b + sin * this.a);
const a = this.a;
const b = this.b;

this.a = cos * a - sin * b;
this.b = cos * b + sin * a;
}

public sub(z: Complex): Complex {
Expand Down
96 changes: 54 additions & 42 deletions packages/redgeometry/src/primitives/quaternion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,100 +267,112 @@ export class Quaternion {
);
}

public rotateX(angleX: number): Quaternion {
public rotateX(angleX: number): void {
const sin = Math.sin(0.5 * angleX);
const cos = Math.cos(0.5 * angleX);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | cos | | a |
// | sin | * | b |
// | 0 | | c |
// | 0 | | d |
return new Quaternion(
cos * this.a - sin * this.b,
cos * this.b + sin * this.a,
cos * this.c - sin * this.d,
cos * this.d + sin * this.c,
);
this.a = cos * a - sin * b;
this.b = cos * b + sin * a;
this.c = cos * c - sin * d;
this.d = cos * d + sin * c;
}

public rotateXPre(angleX: number): Quaternion {
public rotateXPre(angleX: number): void {
const sin = Math.sin(0.5 * angleX);
const cos = Math.cos(0.5 * angleX);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | a | | cos |
// | b | * | sin |
// | c | | 0 |
// | d | | 0 |
return new Quaternion(
this.a * cos - this.b * sin,
this.b * cos + this.a * sin,
this.c * cos + this.d * sin,
this.d * cos - this.c * sin,
);
this.a = a * cos - b * sin;
this.b = b * cos + a * sin;
this.c = c * cos + d * sin;
this.d = d * cos - c * sin;
}

public rotateY(angleY: number): Quaternion {
public rotateY(angleY: number): void {
const sin = Math.sin(0.5 * angleY);
const cos = Math.cos(0.5 * angleY);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | cos | | a |
// | 0 | * | b |
// | sin | | c |
// | 0 | | d |
return new Quaternion(
cos * this.a - sin * this.c,
cos * this.b + sin * this.d,
cos * this.c + sin * this.a,
cos * this.d - sin * this.b,
);
this.a = cos * a - sin * c;
this.b = cos * b + sin * d;
this.c = cos * c + sin * a;
this.d = cos * d - sin * b;
}

public rotateYPre(angleY: number): Quaternion {
public rotateYPre(angleY: number): void {
const sin = Math.sin(0.5 * angleY);
const cos = Math.cos(0.5 * angleY);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | a | | cos |
// | b | * | 0 |
// | c | | sin |
// | d | | 0 |
return new Quaternion(
this.a * cos - this.c * sin,
this.b * cos - this.d * sin,
this.c * cos + this.a * sin,
this.d * cos + this.b * sin,
);
this.a = a * cos - c * sin;
this.b = b * cos - d * sin;
this.c = c * cos + a * sin;
this.d = d * cos + b * sin;
}

public rotateZ(angleZ: number): Quaternion {
public rotateZ(angleZ: number): void {
const sin = Math.sin(0.5 * angleZ);
const cos = Math.cos(0.5 * angleZ);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | cos | | a |
// | 0 | * | b |
// | 0 | | c |
// | sin | | d |
return new Quaternion(
cos * this.a - sin * this.d,
cos * this.b - sin * this.c,
cos * this.c + sin * this.b,
cos * this.d + sin * this.a,
);
this.a = cos * a - sin * d;
this.b = cos * b - sin * c;
this.c = cos * c + sin * b;
this.d = cos * d + sin * a;
}

public rotateZPre(angleZ: number): Quaternion {
public rotateZPre(angleZ: number): void {
const sin = Math.sin(0.5 * angleZ);
const cos = Math.cos(0.5 * angleZ);
const a = this.a;
const b = this.b;
const c = this.c;
const d = this.d;

// | a | | cos |
// | b | * | 0 |
// | c | | 0 |
// | d | | sin |
return new Quaternion(
this.a * cos - this.d * sin,
this.b * cos + this.c * sin,
this.c * cos - this.b * sin,
this.d * cos + this.a * sin,
);
this.a = a * cos - d * sin;
this.b = b * cos + c * sin;
this.c = c * cos - b * sin;
this.d = d * cos + a * sin;
}

public sub(q: Quaternion): Quaternion {
Expand Down
4 changes: 2 additions & 2 deletions packages/redgeometry/tests/primitives/complex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ test("Complex - rotate", () => {
const a = 1;
const z = Complex.fromRotationAngle(a);

const z1 = z.rotate(-a);
z.rotate(-a);

expectToBeCloseComplex(z1, Complex.createIdentity());
expectToBeCloseComplex(z, Complex.createIdentity());
});

test("Quaternion - mulPt/mulVec", () => {
Expand Down
Loading

0 comments on commit 89a5bb0

Please sign in to comment.