UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

657 lines (560 loc) 18.4 kB
var Matrix4 = require('../../src/math/Matrix4'); describe('Phaser.Math.Matrix4', function () { it('should create a matrix with identity values by default', function () { var m = new Matrix4(); var v = m.val; expect(v[0]).toBe(1); expect(v[5]).toBe(1); expect(v[10]).toBe(1); expect(v[15]).toBe(1); expect(v[1]).toBe(0); expect(v[2]).toBe(0); expect(v[3]).toBe(0); expect(v[4]).toBe(0); expect(v[6]).toBe(0); expect(v[7]).toBe(0); expect(v[8]).toBe(0); expect(v[9]).toBe(0); expect(v[11]).toBe(0); expect(v[12]).toBe(0); expect(v[13]).toBe(0); expect(v[14]).toBe(0); }); it('should copy values from another matrix when passed to constructor', function () { var a = new Matrix4(); a.val[0] = 2; a.val[5] = 3; a.val[10] = 4; a.val[15] = 5; var b = new Matrix4(a); expect(b.val[0]).toBe(2); expect(b.val[5]).toBe(3); expect(b.val[10]).toBe(4); expect(b.val[15]).toBe(5); }); it('should have a Float32Array as the val property', function () { var m = new Matrix4(); expect(m.val).toBeInstanceOf(Float32Array); expect(m.val.length).toBe(16); }); describe('clone', function () { it('should return a new Matrix4 with the same values', function () { var m = new Matrix4(); m.val[0] = 7; m.val[5] = 8; var c = m.clone(); expect(c).not.toBe(m); expect(c.val[0]).toBe(7); expect(c.val[5]).toBe(8); }); }); describe('setValues', function () { it('should set all 16 values correctly', function () { var m = new Matrix4(); m.setValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); var v = m.val; for (var i = 0; i < 16; i++) { expect(v[i]).toBe(i + 1); } }); it('should return this', function () { var m = new Matrix4(); var result = m.setValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); expect(result).toBe(m); }); }); describe('copy', function () { it('should copy values from source matrix', function () { var src = new Matrix4(); src.setValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); var dst = new Matrix4(); dst.copy(src); for (var i = 0; i < 16; i++) { expect(dst.val[i]).toBe(src.val[i]); } }); }); describe('fromArray', function () { it('should set values from an array', function () { var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; var m = new Matrix4(); m.fromArray(arr); for (var i = 0; i < 16; i++) { expect(m.val[i]).toBe(arr[i]); } }); }); describe('zero', function () { it('should set all values to zero', function () { var m = new Matrix4(); m.zero(); for (var i = 0; i < 16; i++) { expect(m.val[i]).toBe(0); } }); }); describe('identity', function () { it('should reset matrix to identity', function () { var m = new Matrix4(); m.zero(); m.identity(); var v = m.val; expect(v[0]).toBe(1); expect(v[5]).toBe(1); expect(v[10]).toBe(1); expect(v[15]).toBe(1); expect(v[1]).toBe(0); expect(v[4]).toBe(0); expect(v[14]).toBe(0); }); }); describe('xyz', function () { it('should set translation values with identity rotation', function () { var m = new Matrix4(); m.xyz(3, 5, 7); var v = m.val; expect(v[12]).toBe(3); expect(v[13]).toBe(5); expect(v[14]).toBe(7); expect(v[0]).toBe(1); expect(v[5]).toBe(1); expect(v[10]).toBe(1); expect(v[15]).toBe(1); }); }); describe('scaling', function () { it('should set scaling values', function () { var m = new Matrix4(); m.scaling(2, 3, 4); var v = m.val; expect(v[0]).toBe(2); expect(v[5]).toBe(3); expect(v[10]).toBe(4); expect(v[15]).toBe(1); expect(v[1]).toBe(0); expect(v[4]).toBe(0); }); }); describe('transpose', function () { it('should transpose the matrix', function () { var m = new Matrix4(); m.setValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); m.transpose(); var v = m.val; expect(v[0]).toBe(1); expect(v[1]).toBe(5); expect(v[2]).toBe(9); expect(v[3]).toBe(13); expect(v[4]).toBe(2); expect(v[5]).toBe(6); expect(v[6]).toBe(10); expect(v[7]).toBe(14); }); it('should leave identity matrix unchanged', function () { var m = new Matrix4(); m.transpose(); var v = m.val; expect(v[0]).toBe(1); expect(v[5]).toBe(1); expect(v[10]).toBe(1); expect(v[15]).toBe(1); expect(v[1]).toBe(0); }); }); describe('determinant', function () { it('should return 1 for the identity matrix', function () { var m = new Matrix4(); expect(m.determinant()).toBeCloseTo(1, 5); }); it('should return 0 for the zero matrix', function () { var m = new Matrix4(); m.zero(); expect(m.determinant()).toBe(0); }); it('should return correct determinant for a known matrix', function () { var m = new Matrix4(); m.scaling(2, 3, 4); expect(m.determinant()).toBeCloseTo(24, 5); }); }); describe('invert', function () { it('should invert the identity matrix to identity', function () { var m = new Matrix4(); m.invert(); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(1, 5); expect(v[15]).toBeCloseTo(1, 5); }); it('should produce a matrix that when multiplied gives identity', function () { var m = new Matrix4(); m.setValues(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1); var inv = m.clone(); inv.invert(); m.multiply(inv); var v = m.val; expect(v[0]).toBeCloseTo(1, 4); expect(v[5]).toBeCloseTo(1, 4); expect(v[10]).toBeCloseTo(1, 4); expect(v[15]).toBeCloseTo(1, 4); expect(v[1]).toBeCloseTo(0, 4); expect(v[4]).toBeCloseTo(0, 4); }); it('should return this without change for a singular matrix', function () { var m = new Matrix4(); m.zero(); var original = Array.from(m.val); m.invert(); for (var i = 0; i < 16; i++) { expect(m.val[i]).toBe(original[i]); } }); }); describe('getInverse', function () { it('should copy and invert the given matrix', function () { var src = new Matrix4(); src.scaling(2, 2, 2); var dst = new Matrix4(); dst.getInverse(src); expect(dst.val[0]).toBeCloseTo(0.5, 5); expect(dst.val[5]).toBeCloseTo(0.5, 5); expect(dst.val[10]).toBeCloseTo(0.5, 5); }); }); describe('multiply', function () { it('should multiply by identity and return same values', function () { var m = new Matrix4(); m.setValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); var original = Array.from(m.val); var identity = new Matrix4(); m.multiply(identity); for (var i = 0; i < 16; i++) { expect(m.val[i]).toBeCloseTo(original[i], 4); } }); it('should return this', function () { var m = new Matrix4(); var other = new Matrix4(); expect(m.multiply(other)).toBe(m); }); }); describe('translateXYZ', function () { it('should translate on an identity matrix', function () { var m = new Matrix4(); m.translateXYZ(5, 10, 15); var v = m.val; expect(v[12]).toBeCloseTo(5, 5); expect(v[13]).toBeCloseTo(10, 5); expect(v[14]).toBeCloseTo(15, 5); }); it('should accumulate translations', function () { var m = new Matrix4(); m.translateXYZ(1, 2, 3); m.translateXYZ(4, 5, 6); var v = m.val; expect(v[12]).toBeCloseTo(5, 5); expect(v[13]).toBeCloseTo(7, 5); expect(v[14]).toBeCloseTo(9, 5); }); }); describe('scaleXYZ', function () { it('should scale the matrix components', function () { var m = new Matrix4(); m.scaleXYZ(2, 3, 4); var v = m.val; expect(v[0]).toBeCloseTo(2, 5); expect(v[5]).toBeCloseTo(3, 5); expect(v[10]).toBeCloseTo(4, 5); }); }); describe('rotateX', function () { it('should rotate 90 degrees around X axis', function () { var m = new Matrix4(); m.rotateX(Math.PI / 2); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(0, 5); expect(v[6]).toBeCloseTo(1, 5); expect(v[9]).toBeCloseTo(-1, 5); expect(v[10]).toBeCloseTo(0, 5); }); it('should return this', function () { var m = new Matrix4(); expect(m.rotateX(0.5)).toBe(m); }); }); describe('rotateY', function () { it('should rotate 90 degrees around Y axis', function () { var m = new Matrix4(); m.rotateY(Math.PI / 2); var v = m.val; expect(v[0]).toBeCloseTo(0, 5); expect(v[2]).toBeCloseTo(-1, 5); expect(v[8]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(0, 5); }); }); describe('rotateZ', function () { it('should rotate 90 degrees around Z axis', function () { var m = new Matrix4(); m.rotateZ(Math.PI / 2); var v = m.val; expect(v[0]).toBeCloseTo(0, 5); expect(v[1]).toBeCloseTo(1, 5); expect(v[4]).toBeCloseTo(-1, 5); expect(v[5]).toBeCloseTo(0, 5); }); }); describe('fromQuat', function () { it('should produce identity matrix from identity quaternion', function () { var q = { x: 0, y: 0, z: 0, w: 1 }; var m = new Matrix4(); m.fromQuat(q); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(1, 5); expect(v[15]).toBeCloseTo(1, 5); expect(v[1]).toBeCloseTo(0, 5); expect(v[4]).toBeCloseTo(0, 5); }); }); describe('perspective', function () { it('should generate a perspective matrix', function () { var m = new Matrix4(); m.perspective(Math.PI / 4, 16 / 9, 0.1, 100); var v = m.val; expect(v[3]).toBe(0); expect(v[7]).toBe(0); expect(v[11]).toBe(-1); expect(v[15]).toBe(0); expect(v[0]).toBeGreaterThan(0); expect(v[5]).toBeGreaterThan(0); }); }); describe('ortho', function () { it('should generate an orthographic projection matrix', function () { var m = new Matrix4(); m.ortho(-1, 1, -1, 1, 0.1, 100); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[15]).toBeCloseTo(1, 5); expect(v[3]).toBe(0); expect(v[7]).toBe(0); }); }); describe('lookAt', function () { it('should return identity when eye equals center', function () { var eye = { x: 0, y: 0, z: 0 }; var center = { x: 0, y: 0, z: 0 }; var up = { x: 0, y: 1, z: 0 }; var m = new Matrix4(); m.lookAt(eye, center, up); var v = m.val; expect(v[0]).toBe(1); expect(v[5]).toBe(1); expect(v[10]).toBe(1); expect(v[15]).toBe(1); }); it('should generate a valid view matrix for standard camera setup', function () { var eye = { x: 0, y: 0, z: 5 }; var center = { x: 0, y: 0, z: 0 }; var up = { x: 0, y: 1, z: 0 }; var m = new Matrix4(); m.lookAt(eye, center, up); var v = m.val; expect(v[15]).toBeCloseTo(1, 5); expect(v[14]).toBeCloseTo(-5, 5); }); }); describe('getMaxScaleOnAxis', function () { it('should return 1 for the identity matrix', function () { var m = new Matrix4(); expect(m.getMaxScaleOnAxis()).toBeCloseTo(1, 5); }); it('should return the largest scale value', function () { var m = new Matrix4(); m.scaling(2, 5, 3); expect(m.getMaxScaleOnAxis()).toBeCloseTo(5, 5); }); it('should handle uniform scaling', function () { var m = new Matrix4(); m.scaling(4, 4, 4); expect(m.getMaxScaleOnAxis()).toBeCloseTo(4, 5); }); }); describe('fromRotationTranslation', function () { it('should set translation from vector', function () { var q = { x: 0, y: 0, z: 0, w: 1 }; var v = { x: 3, y: 4, z: 5 }; var m = new Matrix4(); m.fromRotationTranslation(q, v); var vals = m.val; expect(vals[12]).toBeCloseTo(3, 5); expect(vals[13]).toBeCloseTo(4, 5); expect(vals[14]).toBeCloseTo(5, 5); expect(vals[15]).toBe(1); }); it('should set rotation from identity quaternion', function () { var q = { x: 0, y: 0, z: 0, w: 1 }; var v = { x: 0, y: 0, z: 0 }; var m = new Matrix4(); m.fromRotationTranslation(q, v); var vals = m.val; expect(vals[0]).toBeCloseTo(1, 5); expect(vals[5]).toBeCloseTo(1, 5); expect(vals[10]).toBeCloseTo(1, 5); }); }); describe('multiplyMatrices', function () { it('should multiply two identity matrices to produce identity', function () { var a = new Matrix4(); var b = new Matrix4(); var out = new Matrix4(); out.zero(); out.multiplyMatrices(a, b); var v = out.val; expect(v[0]).toBeCloseTo(1, 4); expect(v[5]).toBeCloseTo(1, 4); expect(v[10]).toBeCloseTo(1, 4); expect(v[15]).toBeCloseTo(1, 4); }); }); describe('adjoint', function () { it('should return the identity for the identity matrix (scaled by det=1)', function () { var m = new Matrix4(); m.adjoint(); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(1, 5); expect(v[15]).toBeCloseTo(1, 5); }); }); describe('makeRotationAxis', function () { it('should produce identity for zero angle', function () { var axis = { x: 0, y: 1, z: 0 }; var m = new Matrix4(); m.makeRotationAxis(axis, 0); var v = m.val; expect(v[0]).toBeCloseTo(1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(1, 5); expect(v[15]).toBeCloseTo(1, 5); }); it('should rotate 180 degrees around Y axis', function () { var axis = { x: 0, y: 1, z: 0 }; var m = new Matrix4(); m.makeRotationAxis(axis, Math.PI); var v = m.val; expect(v[0]).toBeCloseTo(-1, 5); expect(v[5]).toBeCloseTo(1, 5); expect(v[10]).toBeCloseTo(-1, 5); }); }); describe('fromRotationXYTranslation', function () { it('should use position directly when translateFirst is true', function () { var rotation = { x: 0, y: 0, z: 0 }; var position = { x: 5, y: 6, z: 7 }; var m = new Matrix4(); m.fromRotationXYTranslation(rotation, position, true); var v = m.val; expect(v[12]).toBeCloseTo(5, 5); expect(v[13]).toBeCloseTo(6, 5); expect(v[14]).toBeCloseTo(7, 5); }); it('should transform position when translateFirst is false', function () { var rotation = { x: 0, y: 0, z: 0 }; var position = { x: 5, y: 6, z: 7 }; var m = new Matrix4(); m.fromRotationXYTranslation(rotation, position, false); var v = m.val; expect(v[12]).toBeCloseTo(5, 5); expect(v[13]).toBeCloseTo(6, 5); expect(v[14]).toBeCloseTo(7, 5); }); }); });