webgl_game/src/js/common.js

456 lines
11 KiB
JavaScript

export function initializeContext(canvasId) {
const canvas = document.getElementById(canvasId);
const ctx = canvas.getContext("webgl2", { antialias: false });
return ctx;
}
export class Vec2 {
x;
y;
constructor(x, y) {
this.x = x;
this.y = y;
}
static ZERO() {
return new Vec2(0, 0);
}
static ID() {
return new Vec2(1, 1);
}
copy() {
return new Vec2(this.x, this.y);
}
add(other) {
this.x += other.x;
this.y += other.y;
}
addScalar(scalar) {
this.x += scalar;
this.y += scalar;
}
addNew(other) {
return new Vec2(this.x + other.x, this.y + other.y);
}
addScalarNew(scalar) {
return new Vec2(this.x + scalar, this.y + scalar);
}
sub(other) {
this.x -= other.x;
this.y -= other.y;
}
subNew(other) {
let vec = this.copy();
vec.x -= other.x;
vec.y -= other.y;
return vec;
}
multScalar(scalar) {
this.x *= scalar;
this.y *= scalar;
}
multScalarNew(scalar) {
return new Vec2(this.x * scalar, this.y * scalar);
}
div(other) {
if (other.x == 0 ||
other.y == 0) {
throw new Error("Division by zero in Vec4");
}
this.x /= other.x;
this.y /= other.y;
}
divNew(other) {
if (other.x == 0 ||
other.y == 0) {
throw new Error("Division by zero in Vec4");
}
let vec = this.copy();
vec.x /= other.x;
vec.y /= other.y;
return vec;
}
reduce() {
throw new Error("Can't reduce Vec2!");
}
extend(value) {
return new Vec3(this.x, this.y, value);
}
splatToArray() {
return [this.x, this.y];
}
static angle(angle) {
const eps = 1e-6;
let x = Math.cos(angle);
let y = Math.sin(angle);
if ((x > 0 && x < eps)
|| (x < 0 && x > -eps))
x = 0;
if ((y > 0 && y < eps)
|| (y < 0 && y > -eps))
y = 0;
return new Vec2(x, y);
}
}
export class Vec3 {
x;
y;
z;
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
addScalar(scalar) {
this.x += scalar;
this.y += scalar;
this.z += scalar;
}
addScalarNew(scalar) {
let vec = this.copy();
vec.x += scalar;
vec.y += scalar;
vec.z += scalar;
return vec;
}
static ZERO() {
return new Vec3(0, 0, 0);
}
static ID() {
return new Vec3(1, 1, 1);
}
copy() {
return new Vec3(this.x, this.y, this.z);
}
add(other) {
this.x += other.x;
this.y += other.y;
this.z += other.z;
}
addNew(other) {
let vec = this.copy();
vec.x += other.x;
vec.y += other.y;
vec.z += other.z;
return vec;
}
sub(other) {
this.x -= other.x;
this.y -= other.y;
this.z -= other.z;
}
subNew(other) {
let vec = this.copy();
vec.x -= other.x;
vec.y -= other.y;
vec.z -= other.z;
return vec;
}
multScalar(scalar) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
}
multScalarNew(scalar) {
let vec = this.copy();
vec.x *= scalar;
vec.y *= scalar;
vec.z *= scalar;
return vec;
}
div(other) {
if (other.x == 0 ||
other.y == 0 ||
other.z == 0) {
throw new Error("Division by zero in Vec4");
}
this.x /= other.x;
this.y /= other.y;
this.z /= other.z;
}
divNew(other) {
if (other.x == 0 ||
other.y == 0 ||
other.z == 0) {
throw new Error("Division by zero in Vec4");
}
let vec = this.copy();
vec.x /= other.x;
vec.y /= other.y;
vec.z /= other.z;
return vec;
}
reduce() {
return new Vec2(this.x, this.y);
}
extend(value) {
return new Vec4(this.x, this.y, this.z, value);
}
splatToArray() {
return [this.x, this.y, this.z];
}
}
export class Vec4 {
x;
y;
z;
w;
constructor(x, y, z, w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
static ZERO() {
return new Vec4(0, 0, 0, 0);
}
static ID() {
return new Vec4(1, 1, 1, 1);
}
copy() {
return new Vec4(this.x, this.y, this.z, this.w);
}
add(other) {
this.x += other.x;
this.y += other.y;
this.z += other.z;
this.w += other.w;
}
addNew(other) {
let vec = this.copy();
vec.x += other.x;
vec.y += other.y;
vec.z += other.z;
vec.w += other.w;
return vec;
}
addScalar(scalar) {
this.x += scalar;
this.y += scalar;
this.z += scalar;
this.w += scalar;
}
addScalarNew(scalar) {
let vec = this.copy();
vec.x += scalar;
vec.y += scalar;
vec.z += scalar;
vec.w += scalar;
return vec;
}
sub(other) {
this.x -= other.x;
this.y -= other.y;
this.z -= other.z;
this.w -= other.w;
}
subNew(other) {
let vec = this.copy();
vec.x -= other.x;
vec.y -= other.y;
vec.z -= other.z;
vec.w -= other.w;
return vec;
}
multScalar(scalar) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
this.w *= scalar;
}
multScalarNew(scalar) {
let vec = this.copy();
vec.x *= scalar;
vec.y *= scalar;
vec.z *= scalar;
vec.w *= scalar;
return vec;
}
div(other) {
if (other.x == 0 ||
other.y == 0 ||
other.z == 0 ||
other.w == 0) {
throw new Error("Division by zero in Vec4");
}
this.x /= other.x;
this.y /= other.y;
this.z /= other.z;
this.w /= other.w;
}
divNew(other) {
if (other.x == 0 ||
other.y == 0 ||
other.z == 0 ||
other.w == 0) {
throw new Error("Division by zero in Vec4");
}
let vec = this.copy();
vec.x /= other.x;
vec.y /= other.y;
vec.z /= other.z;
vec.w /= other.w;
return vec;
}
reduce() {
return new Vec3(this.x, this.y, this.z);
}
extend(_value) {
throw new Error("Can't extend Vec4");
}
}
export class Mat4 {
data;
constructor(i) {
if (i instanceof Float32Array) {
console.assert(i.length == 16, "Mat4 has to have 16 elements");
this.data = i;
return;
}
else if (typeof (i) === 'number') {
this.data = new Float32Array(16).fill(i);
return;
}
this.data = new Float32Array(16);
}
static IDENTITY() {
return new Mat4(new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
static orthographic(left, right, bottom, top, near, far) {
let data = new Float32Array([
2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, -2 / (far - near), 0,
-(right + left) / (right - left),
-(top + bottom) / (top - bottom),
-(far + near) / (far - near),
1,
]);
return new Mat4(data);
}
static isometric() {
return new Mat4(new Float32Array([
1, -1, 0, 0,
1, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
static isometric_inverse() {
return new Mat4(new Float32Array([
0.5, -0.5, 0, 0,
0.5, 0.5, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
static rotation_x(angle) {
let data = new Float32Array([
1, 0, 0, 0,
0, Math.cos(angle), -Math.sin(angle), 0,
0, Math.sin(angle), Math.cos(angle), 0,
0, 0, 0, 1,
]);
return new Mat4(data);
}
static rotation_y(angle) {
let data = new Float32Array([
Math.cos(angle), 0, Math.sin(angle), 0,
0, 1, 0, 0,
-Math.sin(angle), 0, Math.cos(angle), 0,
0, 0, 0, 1,
]);
return new Mat4(data);
}
static rotation_z(angle) {
let data = new Float32Array([
Math.cos(angle), -Math.sin(angle), 0, 0,
Math.sin(angle), Math.cos(angle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]);
return new Mat4(data);
}
static translate(t) {
return new Mat4(new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
t.x, t.y, t.z, 1,
]));
}
static scale(scales) {
return new Mat4(new Float32Array([
scales.x, 0, 0, 0,
0, scales.y, 0, 0,
0, 0, scales.z, 0,
0, 0, 0, 1,
]));
}
x(n) {
return this.data[n];
}
y(n) {
return this.data[n + 4];
}
z(n) {
return this.data[n + 8];
}
w(n) {
return this.data[n + 12];
}
splat() {
return Array.from(this.data);
}
row(row, data) {
for (let i = 0; i < data.length; ++i)
this.data[i + 4 * row] = data[i];
}
col(col, data) {
for (let i = 0; i < data.length; ++i)
this.data[i * 4 + col] = data[i];
}
transform(v) {
let x = v.x * this.x(0) + v.y * this.y(0) + v.z * this.z(0) + v.w * this.w(0);
let y = v.x * this.x(1) + v.y * this.y(1) + v.z * this.z(1) + v.w * this.w(1);
let z = v.x * this.x(2) + v.y * this.y(2) + v.z * this.z(2) + v.w * this.w(2);
let w = v.x * this.x(3) + v.y * this.y(3) + v.z * this.z(3) + v.w * this.w(3);
v.x = x;
v.y = y;
v.z = z;
v.w = w;
}
transformNew(v) {
let vec = v.copy();
let x = v.x * this.x(0) + v.y * this.y(0) + v.z * this.z(0) + v.w * this.w(0);
let y = v.x * this.x(1) + v.y * this.y(1) + v.z * this.z(1) + v.w * this.w(1);
let z = v.x * this.x(2) + v.y * this.y(2) + v.z * this.z(2) + v.w * this.w(2);
let w = v.x * this.x(3) + v.y * this.y(3) + v.z * this.z(3) + v.w * this.w(3);
vec.x = x;
vec.y = y;
vec.z = z;
vec.w = w;
return vec;
}
multNew(other) {
let m = new Mat4(0);
for (let i = 0; i < 4; ++i) {
for (let j = 0; j < 4; ++j) {
m.data[(i * 4) + j] += this.data[(i * 4) + 0] * other.data[j + 0];
m.data[(i * 4) + j] += this.data[(i * 4) + 1] * other.data[j + 4];
m.data[(i * 4) + j] += this.data[(i * 4) + 2] * other.data[j + 8];
m.data[(i * 4) + j] += this.data[(i * 4) + 3] * other.data[j + 12];
}
}
return m;
}
multScalar(scalar) {
for (let i = 0; i < this.data.length; ++i) {
this.data[i] *= scalar;
}
}
}