I'm so confused,
I am trying to use mouse and keyboard controls (With WebGL2), and I'm trying to rotate and move the camera with these four functions:
m4.rotateX(m, angleInRadians, dst);
m4.rotateY(m, angleInRadians, dst);
m4.rotateX(m, angleInRadians, dst);
m4.translate(m, v, dst);
(Provided by twgl) And it works fine with X, and Y (When seperate), but when added it provides weird output (As of a gyroscope) Heres what I use to rotate the camera and create the scene:
(() => {
class Camera {
static setPosRot(x, y, z, cx, cy, cz, camera) {
/*
x,y,z = Players X,Y,Z Position
cx,cy,cz = Players X,Y,Z Rotation
*/
m4.identity(camera);
m4.translate(camera, [
x,
y,
z
], camera);
m4.rotateX(camera, ((cx - 90) * Math.PI) / 180, camera);
m4.rotateY(camera, (cy * Math.PI) / 180, camera);
m4.rotateZ(camera, (cz * Math.PI) / 180, camera);
return camera;
}
}
class Block {
#texture;
#x;
#y;
#z;
set texture(texture) {
this.#texture = texture;
}
get getTexture() {
return texture;
}
set x(x = 0) {
x = parseInt(x);
if (isNaN(x)) {
console.warn(`Invalid X pos, exiting`);
return;
}
this.#x = x;
return;
}
set y(y = 0) {
y = parseInt(y);
if (isNaN(y)) {
console.warn(`Invalid Y pos, exiting`);
return;
}
this.#y = y;
return;
}
set z(z = 0) {
z = parseInt(z);
if (isNaN(z)) {
console.warn(`Invalid Z pos, exiting`);
return;
}
this.#z = z;
return;
}
get getX() {
return this.#x;
}
get getY() {
return this.#y;
}
get getZ() {
return this.#z;
}
set pos(pos = [
0,
0,
0
]) {
var x = parseInt(pos[0]);
var y = parseInt(pos[1]);
var z = parseInt(pos[2]);
if (isNaN(x)) {
console.warn(`Invalid X pos, setting to default.`);
x = 0;
}
if (isNaN(y)) {
console.warn(`Invalid Y pos, setting to default.`);
y = 0;
}
if (isNaN(z)) {
console.warn(`Invalid Z pos, setting to default.`);
z = 0;
}
this.#x = x;
this.#y = y;
this.#z = z;
return;
}
get getPos() {
return [
this.#x,
this.#y,
this.#z
]
}
render() {
m4.identity(Render.world);
m4.translate(Render.world, [
this.#x * 3,
this.#y * 3,
this.#z * 3
], Render.world);
m4.multiply(Render.viewProjection, Render.world, Render.worldViewProjection);
m4.inverse(Render.world, Render.worldInverse);
m4.transpose(Render.worldInverse, Render.worldInverseTranspose);
twgl.setBuffersAndAttributes(Render.gl, Render.pinfo, Render.binfo);
twgl.setUniforms(Render.pinfo, {
u_worldViewProjection: Render.worldViewProjection,
u_worldInverseTranspose: Render.worldInverseTranspose,
u_color: [
(this.#x + 2) / 3,
(this.#y + 2) / 3,
(this.#z + 2) / 3,
1
],
u_lightDir: Render.lightDir,
});
twgl.drawBufferInfo(Render.gl, Render.binfo);
}
constructor(x = 0, y = 0, z = 0) {
var x = parseInt(x);
var y = parseInt(y);
var z = parseInt(z);
if (isNaN(x)) {
console.warn(`Invalid X pos, setting to default.`);
x = 0;
}
if (isNaN(y)) {
console.warn(`Invalid Y pos, setting to default.`);
y = 0;
}
if (isNaN(z)) {
console.warn(`Invalid Z pos, setting to default.`);
z = 0;
}
this.#x = x;
this.#y = y;
this.#z = z;
return;
}
}
class Render {
static vertexShader = [
`precision highp float;`,
`uniform mat4 u_worldViewProjection;`,
`uniform mat4 u_worldInverseTranspose;`,
`attribute vec4 position;`,
`attribute vec3 normal;`,
`varying vec3 v_normal;`,
`void main() {`,
`gl_Position = u_worldViewProjection * position;`,
`v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz;`,
`}`
].join(`\n`);
static fragmentShader = [
`precision highp float;`,
`varying vec3 v_normal;`,
`uniform vec3 u_lightDir;`,
`uniform vec4 u_color;`,
`void main() {`,
`vec3 norm = normalize(v_normal);`,
`float light = dot(u_lightDir, norm) * .5 + .5;`,
`gl_FragColor = vec4(u_color.rgb * light, u_color.a);`,
`}`
].join(`\n`);
static canvas;
static gl;
static gl2d;
static program;
static width = 1920;
static height = 1080;
static pinfo;
static binfo;
static #cx = 90;
static #cy = 0;
static #cz = 0;
static #x = 0.0;
static #y = 0.0;
static #z = 0.0;
static webgloptions = {
powerPreference: `default`,
antialias: true,
depth: true
};
static load() {
this.width = document.documentElement.clientWidth;
this.height = document.documentElement.clientHeight;
this.canvas = document.createElement(`canvas`);
this.canvas.id = `root`;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.width = this.width;
this.canvas.style.height = this.height;
document.body.appendChild(this.canvas);
this.canvas = document.getElementById(`root`);
this.canvas.addEventListener(`contextmenu`, event => event.preventDefault());
this.gl = this.canvas.getContext(`webgl2`, this.webgloptions);
this.gl2d = this.canvas.getContext(`2d`, this.webgloptions); // Rendering UI
if (this.gl == null || this.gl == undefined || !this.gl) {
console.warn(`WebGL2 not supported, attempting to use WebGL, expect bugs.`);
this.gl = this.canvas.getContext(`webgl`, this.webgloptions) || this.canvas.getContext(`experimental-webgl`, this.webgloptions);
if (this.gl == null || this.gl == undefined || !this.gl) {
console.error(`Neither WebGL nor WebGL2 is supported, exiting`);
return true;
}
}
this.pinfo = twgl.createProgramInfo(this.gl, [
this.vertexShader,
this.fragmentShader
]);
this.binfo = twgl.primitives.createCubeBufferInfo(this.gl, 1);
this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
return false;
}
static projection = m4.identity();
static camera = m4.identity();
static view = m4.identity();
static viewProjection = m4.identity();
static world = m4.identity();
static worldViewProjection = m4.identity();
static worldInverse = m4.identity();
static worldInverseTranspose = m4.identity();
static lightDir = v3.normalize([1, 2, 3]);
static render() {
requestAnimationFrame(this.render.bind(this));
var now = Date.now() * 0.001;
this.#deltaTime = now - this.#then;
this.#then = now;
this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.gl.clearDepth(1.0);
this.gl.viewport(0, 0, this.width, this.height);
this.gl.enable(this.gl.DEPTH_TEST);
this.gl.enable(this.gl.CULL_FACE);
this.gl.depthFunc(this.gl.LEQUAL);
this.gl.useProgram(this.pinfo.program);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
const fov = (this.#fov * Math.PI) / 180;
const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;
m4.perspective(fov, aspect, 0.0, 100.0, this.projection);
/*
m4.axisRotate(this.camera, m4.getAxis(this.camera, 0), (this.#cx - 90) * Math.PI / 180, this.camera);
m4.axisRotate(this.camera, m4.getAxis(this.camera, 1), this.#cy * Math.PI / 180, this.camera);
m4.axisRotate(this.camera, m4.getAxis(this.camera, 2), this.#cz * Math.PI / 180, this.camera);
*/
/*
m4.rotateX(this.camera, ((this.#cx - 90) * Math.PI) / 180, this.camera);
m4.rotateY(this.camera, (this.#cy * Math.PI) / 180, this.camera);
m4.rotateZ(this.camera, (this.#cz * Math.PI) / 180, this.camera);
*/
this.camera = Camera.setPosRot(this.#x, this.#y, this.#z, this.#cx, this.#cy, this.#cz, this.camera);
m4.inverse(this.camera, this.view);
m4.multiply(this.projection, this.view, this.viewProjection);
for (let z = -1; z <= 1; ++z) {
for (let y = -1; y <= 1; ++y) {
for (let x = -1; x <= 1; ++x) {
if (x === 0 && y === 0 && z === 0) {
continue;
}
const block = new Block();
block.pos = [
x,
y,
z
];
Render.addObj(block);
}
}
}
}
}
})();
(Taken from this website (Runnable))
Twgl does not rotate stuff like mat4 example: Twgl:
function rotateX(m, angleInRadians, dst) {
dst = dst || new MatType(16);
const m10 = m[4];
const m11 = m[5];
const m12 = m[6];
const m13 = m[7];
const m20 = m[8];
const m21 = m[9];
const m22 = m[10];
const m23 = m[11];
const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);
dst[4] = c * m10 + s * m20;
dst[5] = c * m11 + s * m21;
dst[6] = c * m12 + s * m22;
dst[7] = c * m13 + s * m23;
dst[8] = c * m20 - s * m10;
dst[9] = c * m21 - s * m11;
dst[10] = c * m22 - s * m12;
dst[11] = c * m23 - s * m13;
if (m !== dst) {
dst[0] = m[0];
dst[1] = m[1];
dst[2] = m[2];
dst[3] = m[3];
dst[12] = m[12];
dst[13] = m[13];
dst[14] = m[14];
dst[15] = m[15];
}
return dst;
}
function rotateY(m, angleInRadians, dst) {
dst = dst || new MatType(16);
const m00 = m[0 * 4 + 0];
const m01 = m[0 * 4 + 1];
const m02 = m[0 * 4 + 2];
const m03 = m[0 * 4 + 3];
const m20 = m[2 * 4 + 0];
const m21 = m[2 * 4 + 1];
const m22 = m[2 * 4 + 2];
const m23 = m[2 * 4 + 3];
const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);
dst[0] = c * m00 - s * m20;
dst[1] = c * m01 - s * m21;
dst[2] = c * m02 - s * m22;
dst[3] = c * m03 - s * m23;
dst[8] = c * m20 + s * m00;
dst[9] = c * m21 + s * m01;
dst[10] = c * m22 + s * m02;
dst[11] = c * m23 + s * m03;
if (m !== dst) {
dst[4] = m[4];
dst[5] = m[5];
dst[6] = m[6];
dst[7] = m[7];
dst[12] = m[12];
dst[13] = m[13];
dst[14] = m[14];
dst[15] = m[15];
}
return dst;
}
function rotateZ(m, angleInRadians, dst) {
dst = dst || new MatType(16);
const m00 = m[0 * 4 + 0];
const m01 = m[0 * 4 + 1];
const m02 = m[0 * 4 + 2];
const m03 = m[0 * 4 + 3];
const m10 = m[1 * 4 + 0];
const m11 = m[1 * 4 + 1];
const m12 = m[1 * 4 + 2];
const m13 = m[1 * 4 + 3];
const c = Math.cos(angleInRadians);
const s = Math.sin(angleInRadians);
dst[0] = c * m00 + s * m10;
dst[1] = c * m01 + s * m11;
dst[2] = c * m02 + s * m12;
dst[3] = c * m03 + s * m13;
dst[4] = c * m10 - s * m00;
dst[5] = c * m11 - s * m01;
dst[6] = c * m12 - s * m02;
dst[7] = c * m13 - s * m03;
if (m !== dst) {
dst[8] = m[8];
dst[9] = m[9];
dst[10] = m[10];
dst[11] = m[11];
dst[12] = m[12];
dst[13] = m[13];
dst[14] = m[14];
dst[15] = m[15];
}
return dst;
}
Mat4 (What im looking for):
function rotateX(out, a, rad) {
let s = Math.sin(rad);
let c = Math.cos(rad);
let a10 = a[4];
let a11 = a[5];
let a12 = a[6];
let a13 = a[7];
let a20 = a[8];
let a21 = a[9];
let a22 = a[10];
let a23 = a[11];
if (a !== out) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
out[4] = a10 * c + a20 * s;
out[5] = a11 * c + a21 * s;
out[6] = a12 * c + a22 * s;
out[7] = a13 * c + a23 * s;
out[8] = a20 * c - a10 * s;
out[9] = a21 * c - a11 * s;
out[10] = a22 * c - a12 * s;
out[11] = a23 * c - a13 * s;
return out;
}
function rotateY(out, a, rad) {
let s = Math.sin(rad);
let c = Math.cos(rad);
let a00 = a[0];
let a01 = a[1];
let a02 = a[2];
let a03 = a[3];
let a20 = a[8];
let a21 = a[9];
let a22 = a[10];
let a23 = a[11];
if (a !== out) {
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
out[0] = a00 * c - a20 * s;
out[1] = a01 * c - a21 * s;
out[2] = a02 * c - a22 * s;
out[3] = a03 * c - a23 * s;
out[8] = a00 * s + a20 * c;
out[9] = a01 * s + a21 * c;
out[10] = a02 * s + a22 * c;
out[11] = a03 * s + a23 * c;
return out;
}
function rotateZ(out, a, rad) {
let s = Math.sin(rad);
let c = Math.cos(rad);
let a00 = a[0];
let a01 = a[1];
let a02 = a[2];
let a03 = a[3];
let a10 = a[4];
let a11 = a[5];
let a12 = a[6];
let a13 = a[7];
if (a !== out) {
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
out[0] = a00 * c + a10 * s;
out[1] = a01 * c + a11 * s;
out[2] = a02 * c + a12 * s;
out[3] = a03 * c + a13 * s;
out[4] = a10 * c - a00 * s;
out[5] = a11 * c - a01 * s;
out[6] = a12 * c - a02 * s;
out[7] = a13 * c - a03 * s;
return out;
}