Skip to content

Commit

Permalink
port rotate from gl-matrix for vec2, vec3. fixes #23
Browse files Browse the repository at this point in the history
  • Loading branch information
mreinstein authored and greggman committed Mar 22, 2024
1 parent 4e0a639 commit b89fa2b
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 1 deletion.
23 changes: 23 additions & 0 deletions src/vec2-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,26 @@ export function transformMat3(v: Vec2, m: Mat3, dst?: Vec2): Vec2 {
return dst;
}

/**
* Rotate a 2D vector
*
* @param a The vec2 point to rotate
* @param b The origin of the rotation
* @param rad The angle of rotation in radians
* @returns the rotated vector
*/
export function rotate(a: Vec2, b: Vec2, rad: number, dst?: Vec2) {
dst = dst || new VecType(2);

// Translate point to the origin
const p0 = a[0] - b[0];
const p1 = a[1] - b[1];
const sinC = Math.sin(rad);
const cosC = Math.cos(rad);

//perform rotation and translate to correct position
dst[0] = p0 * cosC - p1 * sinC + b[0];
dst[1] = p0 * sinC + p1 * cosC + b[1];

return dst;
}
98 changes: 97 additions & 1 deletion src/vec3-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -786,4 +786,100 @@ export function getScaling(m: Mat4, dst: Vec3) {
dst[1] = Math.sqrt(yx * yx + yy * yy + yz * yz);
dst[2] = Math.sqrt(zx * zx + zy * zy + zz * zz);
return dst;
}
}

/**
* Rotate a 3D vector around the x-axis
*
* @param {ReadonlyVec3} a The vec3 point to rotate
* @param {ReadonlyVec3} b The origin of the rotation
* @param {Number} rad The angle of rotation in radians
* @param dst - The vector to set. If not passed a new one is created.
* @returns the rotated vector
*/
export function rotateX(a: Vec3, b: Vec3, rad: number, dst?: Vec3) {
dst = dst || new VecType(3);
const p = [];
const r = [];

//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];

//perform rotation
r[0] = p[0];
r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad);

//translate to correct position
dst[0] = r[0] + b[0];
dst[1] = r[1] + b[1];
dst[2] = r[2] + b[2];

return dst;
}

/**
* Rotate a 3D vector around the y-axis
*
* @param {ReadonlyVec3} a The vec3 point to rotate
* @param {ReadonlyVec3} b The origin of the rotation
* @param {Number} rad The angle of rotation in radians
* @param dst - The vector to set. If not passed a new one is created.
* @returns the rotated vector
*/
export function rotateY(a: Vec3, b: Vec3, rad: number, dst?: Vec3) {
dst = dst || new VecType(3);
const p = [];
const r = [];

// translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];

// perform rotation
r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
r[1] = p[1];
r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad);

// translate to correct position
dst[0] = r[0] + b[0];
dst[1] = r[1] + b[1];
dst[2] = r[2] + b[2];

return dst;
}

/**
* Rotate a 3D vector around the z-axis
*
* @param {ReadonlyVec3} a The vec3 point to rotate
* @param {ReadonlyVec3} b The origin of the rotation
* @param {Number} rad The angle of rotation in radians
* @param dst - The vector to set. If not passed a new one is created.
* @returns {vec3} out
*/
export function rotateZ(a: Vec3, b: Vec3, rad: number, dst?: Vec3) {
dst = dst || new VecType(3);
const p = [];
const r = [];

// translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];

// perform rotation
r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
r[2] = p[2];

// translate to correct position
dst[0] = r[0] + b[0];
dst[1] = r[1] + b[1];
dst[2] = r[2] + b[2];

return dst;
}
25 changes: 25 additions & 0 deletions test/tests/vec2-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,5 +471,30 @@ describe('vec2', () => {
check(Float32Array);
check(Float64Array);

describe('rotate', function() {
describe('rotation around world origin [0, 0, 0]', function() {
let vecA, vecB, result;
beforeEach(function () {
vecA = [0, 1];
vecB = [0, 0];
result = vec2.rotate(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [0, -1]);
});
});
describe('rotation around an arbitrary origin', function () {
let vecA, vecB, result;
beforeEach(function () {
vecA = [6, -5];
vecB = [0, -5];
result = vec2.rotate(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [-6, -5]);
});
});
});

});

71 changes: 71 additions & 0 deletions test/tests/vec3-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -480,5 +480,76 @@ describe('vec3', () => {
check(Float32Array);
check(Float64Array);

let vecA, vecB, result;

describe('rotateX', function () {
describe('rotation around world origin [0, 0, 0]', function () {
beforeEach(function () {
vecA = [0, 1, 0];
vecB = [0, 0, 0];
result = vec3.rotateX(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [0, -1, 0]);
});
});

describe('rotation around an arbitrary origin', function () {
beforeEach(function () {
vecA = [2, 7, 0];
vecB = [2, 5, 0];
result = vec3.rotateX(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [2, 3, 0]);
});
});
});

describe('rotateY', function () {
describe('rotation around world origin [0, 0, 0]', function () {
beforeEach(function() {
vecA = [1, 0, 0];
vecB = [0, 0, 0];
result = vec3.rotateY(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [-1, 0, 0]);
});
});
describe('rotation around an arbitrary origin', function () {
beforeEach(function () {
vecA = [-2, 3, 10];
vecB = [-4, 3, 10];
result = vec3.rotateY(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [-6, 3, 10]);
});
});
});

describe('rotateZ', function () {
describe('rotation around world origin [0, 0, 0]', function () {
beforeEach(function () {
vecA = [0, 1, 0];
vecB = [0, 0, 0];
result = vec3.rotateZ(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [0, -1, 0]);
});
});
describe('rotation around an arbitrary origin', function () {
beforeEach(function () {
vecA = [0, 6, -5];
vecB = [0, 0, -5];
result = vec3.rotateZ(vecA, vecB, Math.PI);
});
it("should return the rotated vector", function () {
assertEqualApproximately(result, [0, -6, -5]);
});
});
});
});

0 comments on commit b89fa2b

Please sign in to comment.