Skip to content

Commit 9d6cb50

Browse files
Added a couple more vectormath operations (#35)
* Add multiply, rotateX, rotateY, and rotateZ and add tests * Implimented multiply, rotateX, rotateY, and rotateZ to the Vector3Builder * Change files * Convert rotation functions to right hand rule & fix linting errors * Fix minor typing issue * Made rotateY counterclockwise again
1 parent 9850896 commit 9d6cb50

File tree

6 files changed

+186
-1
lines changed

6 files changed

+186
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "Implimented multiply, rotateX, rotateY, and rotateZ as new vectormath operations",
4+
"packageName": "@minecraft/math",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

libraries/math/api-report/math.api.md

+8
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ export class Vector3Builder implements Vector3 {
8686
floor(): this;
8787
lerp(vec: Vector3, t: number): this;
8888
magnitude(): number;
89+
multiply(vec: Vector3): this;
8990
normalize(): this;
91+
rotateX(a: number): this;
92+
rotateY(a: number): this;
93+
rotateZ(a: number): this;
9094
scale(val: number): this;
9195
slerp(vec: Vector3, t: number): this;
9296
subtract(v: Vector3): this;
@@ -116,7 +120,11 @@ export class Vector3Utils {
116120
static floor(v: Vector3): Vector3;
117121
static lerp(a: Vector3, b: Vector3, t: number): Vector3;
118122
static magnitude(v: Vector3): number;
123+
static multiply(a: Vector3, b: Vector3): Vector3;
119124
static normalize(v: Vector3): Vector3;
125+
static rotateX(v: Vector3, a: number): Vector3;
126+
static rotateY(v: Vector3, a: number): Vector3;
127+
static rotateZ(v: Vector3, a: number): Vector3;
120128
static scale(v1: Vector3, scale: number): Vector3;
121129
static slerp(a: Vector3, b: Vector3, t: number): Vector3;
122130
static subtract(v1: Vector3, v2: Vector3): Vector3;

libraries/math/src/vector3/coreHelpers.test.ts

+29-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { Vector2, Vector3 } from '@minecraft/server';
55
import { describe, expect, it } from 'vitest';
6-
import { Vector2Utils, Vector3Utils } from './coreHelpers';
6+
import { Vector2Utils, VECTOR3_LEFT, VECTOR3_UP, Vector3Utils } from './coreHelpers';
77

88
describe('Vector3 operations', () => {
99
const v1: Vector3 = { x: 1, y: 2, z: 3 };
@@ -189,4 +189,32 @@ describe('Vector3 operations', () => {
189189
expect(result.y).toBeCloseTo(-0.7071, 3);
190190
expect(result.z).toBeCloseTo(0);
191191
});
192+
193+
it('calculates two vectors multiplied together', () => {
194+
const result: Vector3 = Vector3Utils.multiply(v1, v2);
195+
expect(result).toEqual({ x: 4, y: 10, z: 18 });
196+
});
197+
198+
describe('Vector3 rotation functions', () => {
199+
it(`calculates a vector rotated along the x axis`, () => {
200+
const result = Vector3Utils.rotateX(VECTOR3_UP, Math.PI / 2);
201+
expect(result.x).toBeCloseTo(0);
202+
expect(result.y).toBeCloseTo(0);
203+
expect(result.z).toBeCloseTo(1);
204+
});
205+
206+
it(`calculates a vector rotated along the y axis`, () => {
207+
const result = Vector3Utils.rotateY(VECTOR3_LEFT, Math.PI / 2);
208+
expect(result.x).toBeCloseTo(0);
209+
expect(result.y).toBeCloseTo(0);
210+
expect(result.z).toBeCloseTo(1);
211+
});
212+
213+
it(`calculates a vector rotated along the z axis`, () => {
214+
const result = Vector3Utils.rotateZ(VECTOR3_UP, Math.PI / 2);
215+
expect(result.x).toBeCloseTo(-1);
216+
expect(result.y).toBeCloseTo(0);
217+
expect(result.z).toBeCloseTo(0);
218+
});
219+
});
192220
});

libraries/math/src/vector3/coreHelpers.ts

+62
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,68 @@ export class Vector3Utils {
159159
const tb = Math.sin(t * theta) / sinTheta;
160160
return Vector3Utils.add(Vector3Utils.scale(a, ta), Vector3Utils.scale(b, tb));
161161
}
162+
163+
/**
164+
* multiply
165+
*
166+
* Element-wise multiplication of two vectors together.
167+
* Not to be confused with {@link Vector3Utils.dot} product or {@link Vector3Utils.cross} product
168+
*/
169+
static multiply(a: Vector3, b: Vector3): Vector3 {
170+
return {
171+
x: a.x * b.x,
172+
y: a.y * b.y,
173+
z: a.z * b.z,
174+
};
175+
}
176+
177+
/**
178+
* rotateX
179+
*
180+
* Rotates the vector around the x axis counterclockwise (left hand rule)
181+
* @param a - Angle in radians
182+
*/
183+
static rotateX(v: Vector3, a: number): Vector3 {
184+
let cos = Math.cos(a);
185+
let sin = Math.sin(a);
186+
return {
187+
x: v.x,
188+
y: v.y * cos - v.z * sin,
189+
z: v.z * cos + v.y * sin,
190+
};
191+
}
192+
193+
/**
194+
* rotateY
195+
*
196+
* Rotates the vector around the y axis counterclockwise (left hand rule)
197+
* @param a - Angle in radians
198+
*/
199+
static rotateY(v: Vector3, a: number): Vector3 {
200+
let cos = Math.cos(a);
201+
let sin = Math.sin(a);
202+
return {
203+
x: v.x * cos + v.z * sin,
204+
y: v.y,
205+
z: v.z * cos - v.x * sin,
206+
};
207+
}
208+
209+
/**
210+
* rotateZ
211+
*
212+
* Rotates the vector around the z axis counterclockwise (left hand rule)
213+
* @param a - Angle in radians
214+
*/
215+
static rotateZ(v: Vector3, a: number): Vector3 {
216+
let cos = Math.cos(a);
217+
let sin = Math.sin(a);
218+
return {
219+
x: v.x * cos - v.y * sin,
220+
y: v.y * cos + v.x * sin,
221+
z: v.z,
222+
};
223+
}
162224
}
163225

164226
/**

libraries/math/src/vector3/vectorWrapper.test.ts

+40
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,46 @@ describe('Vector3Builder', () => {
180180
const resultB = vectorA.slerp(vectorB, ratio);
181181
expect(resultA).toEqual(resultB);
182182
});
183+
184+
it('should be able to multiply with the same result as the coreHelpers function', () => {
185+
const vectorA = new Vector3Builder(5, 6, 3);
186+
const vectorB = new Vector3Builder(4, 2, 6);
187+
188+
const resultA = Vector3Utils.multiply(vectorA, vectorB);
189+
190+
const resultB = vectorA.multiply(vectorB);
191+
expect(resultA).toEqual(resultB);
192+
});
193+
194+
it('should be able to rotate over x with the same result as the coreHelpers function', () => {
195+
const vectorA = new Vector3Builder(5, 6, 3);
196+
const angle = Math.PI / 2;
197+
198+
const resultA = Vector3Utils.rotateX(vectorA, angle);
199+
200+
const resultB = vectorA.rotateX(angle);
201+
expect(resultA).toEqual(resultB);
202+
});
203+
204+
it('should be able to rotate over y with the same result as the coreHelpers function', () => {
205+
const vectorA = new Vector3Builder(5, 6, 3);
206+
const angle = Math.PI / 2;
207+
208+
const resultA = Vector3Utils.rotateY(vectorA, angle);
209+
210+
const resultB = vectorA.rotateY(angle);
211+
expect(resultA).toEqual(resultB);
212+
});
213+
214+
it('should be able to rotate over z with the same result as the coreHelpers function', () => {
215+
const vectorA = new Vector3Builder(5, 6, 3);
216+
const angle = Math.PI / 2;
217+
218+
const resultA = Vector3Utils.rotateZ(vectorA, angle);
219+
220+
const resultB = vectorA.rotateZ(angle);
221+
expect(resultA).toEqual(resultB);
222+
});
183223
});
184224

185225
describe('Vector2Builder', () => {

libraries/math/src/vector3/vectorWrapper.ts

+40
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,46 @@ export class Vector3Builder implements Vector3 {
167167
slerp(vec: Vector3, t: number): this {
168168
return this.assign(Vector3Utils.slerp(this, vec, t));
169169
}
170+
171+
/**
172+
* multiply
173+
*
174+
* Element-wise multiplication of two vectors together.
175+
* Not to be confused with {@link Vector3Builder.dot} product or {@link Vector3Builder.cross} product
176+
*/
177+
multiply(vec: Vector3): this {
178+
return this.assign(Vector3Utils.multiply(this, vec));
179+
}
180+
181+
/**
182+
* rotateX
183+
*
184+
* Rotates the vector around the x axis counterclockwise (left hand rule)
185+
* @param a - Angle in radians
186+
*/
187+
rotateX(a: number): this {
188+
return this.assign(Vector3Utils.rotateX(this, a));
189+
}
190+
191+
/**
192+
* rotateY
193+
*
194+
* Rotates the vector around the y axis counterclockwise (left hand rule)
195+
* @param a - Angle in radians
196+
*/
197+
rotateY(a: number): this {
198+
return this.assign(Vector3Utils.rotateY(this, a));
199+
}
200+
201+
/**
202+
* rotateZ
203+
*
204+
* Rotates the vector around the z axis counterclockwise (left hand rule)
205+
* @param a - Angle in radians
206+
*/
207+
rotateZ(a: number): this {
208+
return this.assign(Vector3Utils.rotateZ(this, a));
209+
}
170210
}
171211

172212
/**

0 commit comments

Comments
 (0)