From c6455b69351122fc08dc4f77c424f202e188d613 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 23 Jan 2024 16:37:01 +0100 Subject: [PATCH 01/13] ft bozo but in 3D --- frontend/static/js/3D/buffers.js | 20 ++++ frontend/static/js/3D/maths/gl-matrix-min.js | 28 +++++ frontend/static/js/3D/shaders.js | 61 +++++++++++ frontend/static/js/index.js | 3 +- frontend/static/js/views/GameView3D.js | 102 +++++++++++++++++++ 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 frontend/static/js/3D/buffers.js create mode 100644 frontend/static/js/3D/maths/gl-matrix-min.js create mode 100644 frontend/static/js/3D/shaders.js create mode 100644 frontend/static/js/views/GameView3D.js diff --git a/frontend/static/js/3D/buffers.js b/frontend/static/js/3D/buffers.js new file mode 100644 index 0000000..324da51 --- /dev/null +++ b/frontend/static/js/3D/buffers.js @@ -0,0 +1,20 @@ +function initBuffers(gl) +{ + const positionBuffer = initPositionBuffer(gl); + + return { position: positionBuffer }; +} + +function initPositionBuffer(gl) +{ + const positionBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + + const positions = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]; + + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); + return positionBuffer; +} + +export { initBuffers }; diff --git a/frontend/static/js/3D/maths/gl-matrix-min.js b/frontend/static/js/3D/maths/gl-matrix-min.js new file mode 100644 index 0000000..b52c082 --- /dev/null +++ b/frontend/static/js/3D/maths/gl-matrix-min.js @@ -0,0 +1,28 @@ +/*! +@fileoverview gl-matrix - High performance matrix and vector operations +@author Brandon Jones +@author Colin MacKenzie IV +@version 2.7.0 + +Copyright (c) 2015-2018, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}("undefined"!=typeof self?self:this,function(){return function(t){var n={};function r(a){if(n[a])return n[a].exports;var e=n[a]={i:a,l:!1,exports:{}};return t[a].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=t,r.c=n,r.d=function(t,n,a){r.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:a})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,n){if(1&n&&(t=r(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var e in t)r.d(a,e,function(n){return t[n]}.bind(null,e));return a},r.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(n,"a",n),n},r.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},r.p="",r(r.s=10)}([function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.setMatrixArrayType=function(t){n.ARRAY_TYPE=t},n.toRadian=function(t){return t*e},n.equals=function(t,n){return Math.abs(t-n)<=a*Math.max(1,Math.abs(t),Math.abs(n))};var a=n.EPSILON=1e-6;n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,n.RANDOM=Math.random;var e=Math.PI/180},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.len=n.sqrDist=n.dist=n.div=n.mul=n.sub=void 0,n.create=e,n.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},n.fromValues=function(t,n,r,e){var u=new a.ARRAY_TYPE(4);return u[0]=t,u[1]=n,u[2]=r,u[3]=e,u},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},n.set=function(t,n,r,a,e){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t},n.subtract=u,n.multiply=o,n.divide=i,n.ceil=function(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t[2]=Math.ceil(n[2]),t[3]=Math.ceil(n[3]),t},n.floor=function(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t[2]=Math.floor(n[2]),t[3]=Math.floor(n[3]),t},n.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t[3]=Math.min(n[3],r[3]),t},n.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t[3]=Math.max(n[3],r[3]),t},n.round=function(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t[2]=Math.round(n[2]),t[3]=Math.round(n[3]),t},n.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t},n.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t},n.distance=s,n.squaredDistance=c,n.length=f,n.squaredLength=M,n.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=-n[3],t},n.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t[3]=1/n[3],t},n.normalize=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u;o>0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=a*o,t[2]=e*o,t[3]=u*o);return t},n.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]},n.lerp=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t[3]=i+a*(r[3]-i),t},n.random=function(t,n){var r,e,u,o,i,s;n=n||1;do{r=2*a.RANDOM()-1,e=2*a.RANDOM()-1,i=r*r+e*e}while(i>=1);do{u=2*a.RANDOM()-1,o=2*a.RANDOM()-1,s=u*u+o*o}while(s>=1);var c=Math.sqrt((1-i)/s);return t[0]=n*r,t[1]=n*e,t[2]=n*u*c,t[3]=n*o*c,t},n.transformMat4=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3];return t[0]=r[0]*a+r[4]*e+r[8]*u+r[12]*o,t[1]=r[1]*a+r[5]*e+r[9]*u+r[13]*o,t[2]=r[2]*a+r[6]*e+r[10]*u+r[14]*o,t[3]=r[3]*a+r[7]*e+r[11]*u+r[15]*o,t},n.transformQuat=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2],c=r[3],f=c*a+i*u-s*e,M=c*e+s*a-o*u,h=c*u+o*e-i*a,l=-o*a-i*e-s*u;return t[0]=f*c+l*-o+M*-s-h*-i,t[1]=M*c+l*-i+h*-o-f*-s,t[2]=h*c+l*-s+f*-i-M*-o,t[3]=n[3],t},n.str=function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=n[0],s=n[1],c=n[2],f=n[3];return Math.abs(r-i)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(e-s)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(s))&&Math.abs(u-c)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(o-f)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(f))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(){var t=new a.ARRAY_TYPE(4);return a.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t}function u(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t}function o(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t[3]=n[3]*r[3],t}function i(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t[3]=n[3]/r[3],t}function s(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return Math.sqrt(r*r+a*a+e*e+u*u)}function c(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return r*r+a*a+e*e+u*u}function f(t){var n=t[0],r=t[1],a=t[2],e=t[3];return Math.sqrt(n*n+r*r+a*a+e*e)}function M(t){var n=t[0],r=t[1],a=t[2],e=t[3];return n*n+r*r+a*a+e*e}n.sub=u,n.mul=o,n.div=i,n.dist=s,n.sqrDist=c,n.len=f,n.sqrLen=M,n.forEach=function(){var t=e();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=4),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i1?0:e<-1?Math.PI:Math.acos(e)},n.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=n[0],i=n[1],s=n[2];return Math.abs(r-o)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(e-i)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(i))&&Math.abs(u-s)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(s))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(){var t=new a.ARRAY_TYPE(3);return a.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function u(t){var n=t[0],r=t[1],a=t[2];return Math.sqrt(n*n+r*r+a*a)}function o(t,n,r){var e=new a.ARRAY_TYPE(3);return e[0]=t,e[1]=n,e[2]=r,e}function i(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t}function s(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t}function c(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t}function f(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return Math.sqrt(r*r+a*a+e*e)}function M(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return r*r+a*a+e*e}function h(t){var n=t[0],r=t[1],a=t[2];return n*n+r*r+a*a}function l(t,n){var r=n[0],a=n[1],e=n[2],u=r*r+a*a+e*e;return u>0&&(u=1/Math.sqrt(u),t[0]=n[0]*u,t[1]=n[1]*u,t[2]=n[2]*u),t}function v(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}n.sub=i,n.mul=s,n.div=c,n.dist=f,n.sqrDist=M,n.len=u,n.sqrLen=h,n.forEach=function(){var t=e();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=3),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;ia.EPSILON?(t[0]=n[0]/e,t[1]=n[1]/e,t[2]=n[2]/e):(t[0]=1,t[1]=0,t[2]=0);return r},n.multiply=f,n.rotateX=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+o*i,t[1]=e*s+u*i,t[2]=u*s-e*i,t[3]=o*s-a*i,t},n.rotateY=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s-u*i,t[1]=e*s+o*i,t[2]=u*s+a*i,t[3]=o*s-e*i,t},n.rotateZ=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+e*i,t[1]=e*s-a*i,t[2]=u*s+o*i,t[3]=o*s-u*i,t},n.calculateW=function(t,n){var r=n[0],a=n[1],e=n[2];return t[0]=r,t[1]=a,t[2]=e,t[3]=Math.sqrt(Math.abs(1-r*r-a*a-e*e)),t},n.slerp=M,n.random=function(t){var n=a.RANDOM(),r=a.RANDOM(),e=a.RANDOM(),u=Math.sqrt(1-n),o=Math.sqrt(n);return t[0]=u*Math.sin(2*Math.PI*r),t[1]=u*Math.cos(2*Math.PI*r),t[2]=o*Math.sin(2*Math.PI*e),t[3]=o*Math.cos(2*Math.PI*e),t},n.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u,i=o?1/o:0;return t[0]=-r*i,t[1]=-a*i,t[2]=-e*i,t[3]=u*i,t},n.conjugate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},n.fromMat3=h,n.fromEuler=function(t,n,r,a){var e=.5*Math.PI/180;n*=e,r*=e,a*=e;var u=Math.sin(n),o=Math.cos(n),i=Math.sin(r),s=Math.cos(r),c=Math.sin(a),f=Math.cos(a);return t[0]=u*s*f-o*i*c,t[1]=o*i*f+u*s*c,t[2]=o*s*c-u*i*f,t[3]=o*s*f+u*i*c,t},n.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"};var a=i(r(0)),e=i(r(5)),u=i(r(2)),o=i(r(1));function i(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}function s(){var t=new a.ARRAY_TYPE(4);return a.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function c(t,n,r){r*=.5;var a=Math.sin(r);return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=Math.cos(r),t}function f(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],s=r[1],c=r[2],f=r[3];return t[0]=a*f+o*i+e*c-u*s,t[1]=e*f+o*s+u*i-a*c,t[2]=u*f+o*c+a*s-e*i,t[3]=o*f-a*i-e*s-u*c,t}function M(t,n,r,e){var u=n[0],o=n[1],i=n[2],s=n[3],c=r[0],f=r[1],M=r[2],h=r[3],l=void 0,v=void 0,d=void 0,b=void 0,m=void 0;return(v=u*c+o*f+i*M+s*h)<0&&(v=-v,c=-c,f=-f,M=-M,h=-h),1-v>a.EPSILON?(l=Math.acos(v),d=Math.sin(l),b=Math.sin((1-e)*l)/d,m=Math.sin(e*l)/d):(b=1-e,m=e),t[0]=b*u+m*c,t[1]=b*o+m*f,t[2]=b*i+m*M,t[3]=b*s+m*h,t}function h(t,n){var r=n[0]+n[4]+n[8],a=void 0;if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var e=0;n[4]>n[0]&&(e=1),n[8]>n[3*e+e]&&(e=2);var u=(e+1)%3,o=(e+2)%3;a=Math.sqrt(n[3*e+e]-n[3*u+u]-n[3*o+o]+1),t[e]=.5*a,a=.5/a,t[3]=(n[3*u+o]-n[3*o+u])*a,t[u]=(n[3*u+e]+n[3*e+u])*a,t[o]=(n[3*o+e]+n[3*e+o])*a}return t}n.clone=o.clone,n.fromValues=o.fromValues,n.copy=o.copy,n.set=o.set,n.add=o.add,n.mul=f,n.scale=o.scale,n.dot=o.dot,n.lerp=o.lerp;var l=n.length=o.length,v=(n.len=l,n.squaredLength=o.squaredLength),d=(n.sqrLen=v,n.normalize=o.normalize);n.exactEquals=o.exactEquals,n.equals=o.equals,n.rotationTo=function(){var t=u.create(),n=u.fromValues(1,0,0),r=u.fromValues(0,1,0);return function(a,e,o){var i=u.dot(e,o);return i<-.999999?(u.cross(t,n,e),u.len(t)<1e-6&&u.cross(t,r,e),u.normalize(t,t),c(a,t,Math.PI),a):i>.999999?(a[0]=0,a[1]=0,a[2]=0,a[3]=1,a):(u.cross(t,e,o),a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=1+i,d(a,a))}}(),n.sqlerp=function(){var t=s(),n=s();return function(r,a,e,u,o,i){return M(t,a,o,i),M(n,e,u,i),M(r,t,n,2*i*(1-i)),r}}(),n.setAxes=function(){var t=e.create();return function(n,r,a,e){return t[0]=a[0],t[3]=a[1],t[6]=a[2],t[1]=e[0],t[4]=e[1],t[7]=e[2],t[2]=-r[0],t[5]=-r[1],t[8]=-r[2],d(n,h(n,t))}}()},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=function(){var t=new a.ARRAY_TYPE(16);a.ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0);return t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},n.clone=function(t){var n=new a.ARRAY_TYPE(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},n.fromValues=function(t,n,r,e,u,o,i,s,c,f,M,h,l,v,d,b){var m=new a.ARRAY_TYPE(16);return m[0]=t,m[1]=n,m[2]=r,m[3]=e,m[4]=u,m[5]=o,m[6]=i,m[7]=s,m[8]=c,m[9]=f,m[10]=M,m[11]=h,m[12]=l,m[13]=v,m[14]=d,m[15]=b,m},n.set=function(t,n,r,a,e,u,o,i,s,c,f,M,h,l,v,d,b){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t[6]=i,t[7]=s,t[8]=c,t[9]=f,t[10]=M,t[11]=h,t[12]=l,t[13]=v,t[14]=d,t[15]=b,t},n.identity=e,n.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[3],u=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=r,t[6]=n[9],t[7]=n[13],t[8]=a,t[9]=u,t[11]=n[14],t[12]=e,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},n.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15],p=r*i-a*o,P=r*s-e*o,A=r*c-u*o,E=a*s-e*i,O=a*c-u*i,R=e*c-u*s,y=f*d-M*v,q=f*b-h*v,x=f*m-l*v,_=M*b-h*d,Y=M*m-l*d,L=h*m-l*b,S=p*L-P*Y+A*_+E*x-O*q+R*y;if(!S)return null;return S=1/S,t[0]=(i*L-s*Y+c*_)*S,t[1]=(e*Y-a*L-u*_)*S,t[2]=(d*R-b*O+m*E)*S,t[3]=(h*O-M*R-l*E)*S,t[4]=(s*x-o*L-c*q)*S,t[5]=(r*L-e*x+u*q)*S,t[6]=(b*A-v*R-m*P)*S,t[7]=(f*R-h*A+l*P)*S,t[8]=(o*Y-i*x+c*y)*S,t[9]=(a*x-r*Y-u*y)*S,t[10]=(v*O-d*A+m*p)*S,t[11]=(M*A-f*O-l*p)*S,t[12]=(i*q-o*_-s*y)*S,t[13]=(r*_-a*q+e*y)*S,t[14]=(d*P-v*E-b*p)*S,t[15]=(f*E-M*P+h*p)*S,t},n.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15];return t[0]=i*(h*m-l*b)-M*(s*m-c*b)+d*(s*l-c*h),t[1]=-(a*(h*m-l*b)-M*(e*m-u*b)+d*(e*l-u*h)),t[2]=a*(s*m-c*b)-i*(e*m-u*b)+d*(e*c-u*s),t[3]=-(a*(s*l-c*h)-i*(e*l-u*h)+M*(e*c-u*s)),t[4]=-(o*(h*m-l*b)-f*(s*m-c*b)+v*(s*l-c*h)),t[5]=r*(h*m-l*b)-f*(e*m-u*b)+v*(e*l-u*h),t[6]=-(r*(s*m-c*b)-o*(e*m-u*b)+v*(e*c-u*s)),t[7]=r*(s*l-c*h)-o*(e*l-u*h)+f*(e*c-u*s),t[8]=o*(M*m-l*d)-f*(i*m-c*d)+v*(i*l-c*M),t[9]=-(r*(M*m-l*d)-f*(a*m-u*d)+v*(a*l-u*M)),t[10]=r*(i*m-c*d)-o*(a*m-u*d)+v*(a*c-u*i),t[11]=-(r*(i*l-c*M)-o*(a*l-u*M)+f*(a*c-u*i)),t[12]=-(o*(M*b-h*d)-f*(i*b-s*d)+v*(i*h-s*M)),t[13]=r*(M*b-h*d)-f*(a*b-e*d)+v*(a*h-e*M),t[14]=-(r*(i*b-s*d)-o*(a*b-e*d)+v*(a*s-e*i)),t[15]=r*(i*h-s*M)-o*(a*h-e*M)+f*(a*s-e*i),t},n.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],s=t[7],c=t[8],f=t[9],M=t[10],h=t[11],l=t[12],v=t[13],d=t[14],b=t[15];return(n*o-r*u)*(M*b-h*d)-(n*i-a*u)*(f*b-h*v)+(n*s-e*u)*(f*d-M*v)+(r*i-a*o)*(c*b-h*l)-(r*s-e*o)*(c*d-M*l)+(a*s-e*i)*(c*v-f*l)},n.multiply=u,n.translate=function(t,n,r){var a=r[0],e=r[1],u=r[2],o=void 0,i=void 0,s=void 0,c=void 0,f=void 0,M=void 0,h=void 0,l=void 0,v=void 0,d=void 0,b=void 0,m=void 0;n===t?(t[12]=n[0]*a+n[4]*e+n[8]*u+n[12],t[13]=n[1]*a+n[5]*e+n[9]*u+n[13],t[14]=n[2]*a+n[6]*e+n[10]*u+n[14],t[15]=n[3]*a+n[7]*e+n[11]*u+n[15]):(o=n[0],i=n[1],s=n[2],c=n[3],f=n[4],M=n[5],h=n[6],l=n[7],v=n[8],d=n[9],b=n[10],m=n[11],t[0]=o,t[1]=i,t[2]=s,t[3]=c,t[4]=f,t[5]=M,t[6]=h,t[7]=l,t[8]=v,t[9]=d,t[10]=b,t[11]=m,t[12]=o*a+f*e+v*u+n[12],t[13]=i*a+M*e+d*u+n[13],t[14]=s*a+h*e+b*u+n[14],t[15]=c*a+l*e+m*u+n[15]);return t},n.scale=function(t,n,r){var a=r[0],e=r[1],u=r[2];return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*e,t[5]=n[5]*e,t[6]=n[6]*e,t[7]=n[7]*e,t[8]=n[8]*u,t[9]=n[9]*u,t[10]=n[10]*u,t[11]=n[11]*u,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},n.rotate=function(t,n,r,e){var u=e[0],o=e[1],i=e[2],s=Math.sqrt(u*u+o*o+i*i),c=void 0,f=void 0,M=void 0,h=void 0,l=void 0,v=void 0,d=void 0,b=void 0,m=void 0,p=void 0,P=void 0,A=void 0,E=void 0,O=void 0,R=void 0,y=void 0,q=void 0,x=void 0,_=void 0,Y=void 0,L=void 0,S=void 0,w=void 0,I=void 0;if(s0?(r[0]=2*(c*s+h*e+f*i-M*u)/l,r[1]=2*(f*s+h*u+M*e-c*i)/l,r[2]=2*(M*s+h*i+c*u-f*e)/l):(r[0]=2*(c*s+h*e+f*i-M*u),r[1]=2*(f*s+h*u+M*e-c*i),r[2]=2*(M*s+h*i+c*u-f*e));return o(t,n,r),t},n.getTranslation=function(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t},n.getScaling=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[4],o=n[5],i=n[6],s=n[8],c=n[9],f=n[10];return t[0]=Math.sqrt(r*r+a*a+e*e),t[1]=Math.sqrt(u*u+o*o+i*i),t[2]=Math.sqrt(s*s+c*c+f*f),t},n.getRotation=function(t,n){var r=n[0]+n[5]+n[10],a=0;r>0?(a=2*Math.sqrt(r+1),t[3]=.25*a,t[0]=(n[6]-n[9])/a,t[1]=(n[8]-n[2])/a,t[2]=(n[1]-n[4])/a):n[0]>n[5]&&n[0]>n[10]?(a=2*Math.sqrt(1+n[0]-n[5]-n[10]),t[3]=(n[6]-n[9])/a,t[0]=.25*a,t[1]=(n[1]+n[4])/a,t[2]=(n[8]+n[2])/a):n[5]>n[10]?(a=2*Math.sqrt(1+n[5]-n[0]-n[10]),t[3]=(n[8]-n[2])/a,t[0]=(n[1]+n[4])/a,t[1]=.25*a,t[2]=(n[6]+n[9])/a):(a=2*Math.sqrt(1+n[10]-n[0]-n[5]),t[3]=(n[1]-n[4])/a,t[0]=(n[8]+n[2])/a,t[1]=(n[6]+n[9])/a,t[2]=.25*a);return t},n.fromRotationTranslationScale=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],s=e+e,c=u+u,f=o+o,M=e*s,h=e*c,l=e*f,v=u*c,d=u*f,b=o*f,m=i*s,p=i*c,P=i*f,A=a[0],E=a[1],O=a[2];return t[0]=(1-(v+b))*A,t[1]=(h+P)*A,t[2]=(l-p)*A,t[3]=0,t[4]=(h-P)*E,t[5]=(1-(M+b))*E,t[6]=(d+m)*E,t[7]=0,t[8]=(l+p)*O,t[9]=(d-m)*O,t[10]=(1-(M+v))*O,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t},n.fromRotationTranslationScaleOrigin=function(t,n,r,a,e){var u=n[0],o=n[1],i=n[2],s=n[3],c=u+u,f=o+o,M=i+i,h=u*c,l=u*f,v=u*M,d=o*f,b=o*M,m=i*M,p=s*c,P=s*f,A=s*M,E=a[0],O=a[1],R=a[2],y=e[0],q=e[1],x=e[2],_=(1-(d+m))*E,Y=(l+A)*E,L=(v-P)*E,S=(l-A)*O,w=(1-(h+m))*O,I=(b+p)*O,N=(v+P)*R,g=(b-p)*R,T=(1-(h+d))*R;return t[0]=_,t[1]=Y,t[2]=L,t[3]=0,t[4]=S,t[5]=w,t[6]=I,t[7]=0,t[8]=N,t[9]=g,t[10]=T,t[11]=0,t[12]=r[0]+y-(_*y+S*q+N*x),t[13]=r[1]+q-(Y*y+w*q+g*x),t[14]=r[2]+x-(L*y+I*q+T*x),t[15]=1,t},n.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[1]=f+m,t[2]=h-b,t[3]=0,t[4]=f-m,t[5]=1-c-v,t[6]=l+d,t[7]=0,t[8]=h+b,t[9]=l-d,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},n.frustum=function(t,n,r,a,e,u,o){var i=1/(r-n),s=1/(e-a),c=1/(u-o);return t[0]=2*u*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*s,t[6]=0,t[7]=0,t[8]=(r+n)*i,t[9]=(e+a)*s,t[10]=(o+u)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*u*2*c,t[15]=0,t},n.perspective=function(t,n,r,a,e){var u=1/Math.tan(n/2),o=void 0;t[0]=u/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=e&&e!==1/0?(o=1/(a-e),t[10]=(e+a)*o,t[14]=2*e*a*o):(t[10]=-1,t[14]=-2*a);return t},n.perspectiveFromFieldOfView=function(t,n,r,a){var e=Math.tan(n.upDegrees*Math.PI/180),u=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),s=2/(o+i),c=2/(e+u);return t[0]=s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*s*.5,t[9]=(e-u)*c*.5,t[10]=a/(r-a),t[11]=-1,t[12]=0,t[13]=0,t[14]=a*r/(r-a),t[15]=0,t},n.ortho=function(t,n,r,a,e,u,o){var i=1/(n-r),s=1/(a-e),c=1/(u-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*s,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+r)*i,t[13]=(e+a)*s,t[14]=(o+u)*c,t[15]=1,t},n.lookAt=function(t,n,r,u){var o=void 0,i=void 0,s=void 0,c=void 0,f=void 0,M=void 0,h=void 0,l=void 0,v=void 0,d=void 0,b=n[0],m=n[1],p=n[2],P=u[0],A=u[1],E=u[2],O=r[0],R=r[1],y=r[2];if(Math.abs(b-O)0&&(l=1/Math.sqrt(l),f*=l,M*=l,h*=l);var v=s*h-c*M,d=c*f-i*h,b=i*M-s*f;(l=v*v+d*d+b*b)>0&&(l=1/Math.sqrt(l),v*=l,d*=l,b*=l);return t[0]=v,t[1]=d,t[2]=b,t[3]=0,t[4]=M*b-h*d,t[5]=h*v-f*b,t[6]=f*d-M*v,t[7]=0,t[8]=f,t[9]=M,t[10]=h,t[11]=0,t[12]=e,t[13]=u,t[14]=o,t[15]=1,t},n.str=function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},n.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2)+Math.pow(t[9],2)+Math.pow(t[10],2)+Math.pow(t[11],2)+Math.pow(t[12],2)+Math.pow(t[13],2)+Math.pow(t[14],2)+Math.pow(t[15],2))},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t[9]=n[9]+r[9],t[10]=n[10]+r[10],t[11]=n[11]+r[11],t[12]=n[12]+r[12],t[13]=n[13]+r[13],t[14]=n[14]+r[14],t[15]=n[15]+r[15],t},n.subtract=i,n.multiplyScalar=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t[9]=n[9]*r,t[10]=n[10]*r,t[11]=n[11]*r,t[12]=n[12]*r,t[13]=n[13]*r,t[14]=n[14]*r,t[15]=n[15]*r,t},n.multiplyScalarAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t[9]=n[9]+r[9]*a,t[10]=n[10]+r[10]*a,t[11]=n[11]+r[11]*a,t[12]=n[12]+r[12]*a,t[13]=n[13]+r[13]*a,t[14]=n[14]+r[14]*a,t[15]=n[15]+r[15]*a,t},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=t[4],s=t[5],c=t[6],f=t[7],M=t[8],h=t[9],l=t[10],v=t[11],d=t[12],b=t[13],m=t[14],p=t[15],P=n[0],A=n[1],E=n[2],O=n[3],R=n[4],y=n[5],q=n[6],x=n[7],_=n[8],Y=n[9],L=n[10],S=n[11],w=n[12],I=n[13],N=n[14],g=n[15];return Math.abs(r-P)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(P))&&Math.abs(e-A)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(A))&&Math.abs(u-E)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(E))&&Math.abs(o-O)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(O))&&Math.abs(i-R)<=a.EPSILON*Math.max(1,Math.abs(i),Math.abs(R))&&Math.abs(s-y)<=a.EPSILON*Math.max(1,Math.abs(s),Math.abs(y))&&Math.abs(c-q)<=a.EPSILON*Math.max(1,Math.abs(c),Math.abs(q))&&Math.abs(f-x)<=a.EPSILON*Math.max(1,Math.abs(f),Math.abs(x))&&Math.abs(M-_)<=a.EPSILON*Math.max(1,Math.abs(M),Math.abs(_))&&Math.abs(h-Y)<=a.EPSILON*Math.max(1,Math.abs(h),Math.abs(Y))&&Math.abs(l-L)<=a.EPSILON*Math.max(1,Math.abs(l),Math.abs(L))&&Math.abs(v-S)<=a.EPSILON*Math.max(1,Math.abs(v),Math.abs(S))&&Math.abs(d-w)<=a.EPSILON*Math.max(1,Math.abs(d),Math.abs(w))&&Math.abs(b-I)<=a.EPSILON*Math.max(1,Math.abs(b),Math.abs(I))&&Math.abs(m-N)<=a.EPSILON*Math.max(1,Math.abs(m),Math.abs(N))&&Math.abs(p-g)<=a.EPSILON*Math.max(1,Math.abs(p),Math.abs(g))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function u(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=n[9],l=n[10],v=n[11],d=n[12],b=n[13],m=n[14],p=n[15],P=r[0],A=r[1],E=r[2],O=r[3];return t[0]=P*a+A*i+E*M+O*d,t[1]=P*e+A*s+E*h+O*b,t[2]=P*u+A*c+E*l+O*m,t[3]=P*o+A*f+E*v+O*p,P=r[4],A=r[5],E=r[6],O=r[7],t[4]=P*a+A*i+E*M+O*d,t[5]=P*e+A*s+E*h+O*b,t[6]=P*u+A*c+E*l+O*m,t[7]=P*o+A*f+E*v+O*p,P=r[8],A=r[9],E=r[10],O=r[11],t[8]=P*a+A*i+E*M+O*d,t[9]=P*e+A*s+E*h+O*b,t[10]=P*u+A*c+E*l+O*m,t[11]=P*o+A*f+E*v+O*p,P=r[12],A=r[13],E=r[14],O=r[15],t[12]=P*a+A*i+E*M+O*d,t[13]=P*e+A*s+E*h+O*b,t[14]=P*u+A*c+E*l+O*m,t[15]=P*o+A*f+E*v+O*p,t}function o(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=a+a,s=e+e,c=u+u,f=a*i,M=a*s,h=a*c,l=e*s,v=e*c,d=u*c,b=o*i,m=o*s,p=o*c;return t[0]=1-(l+d),t[1]=M+p,t[2]=h-m,t[3]=0,t[4]=M-p,t[5]=1-(f+d),t[6]=v+b,t[7]=0,t[8]=h+m,t[9]=v-b,t[10]=1-(f+l),t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t}function i(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t[9]=n[9]-r[9],t[10]=n[10]-r[10],t[11]=n[11]-r[11],t[12]=n[12]-r[12],t[13]=n[13]-r[13],t[14]=n[14]-r[14],t[15]=n[15]-r[15],t}n.mul=u,n.sub=i},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=function(){var t=new a.ARRAY_TYPE(9);a.ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0);return t[0]=1,t[4]=1,t[8]=1,t},n.fromMat4=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},n.clone=function(t){var n=new a.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},n.fromValues=function(t,n,r,e,u,o,i,s,c){var f=new a.ARRAY_TYPE(9);return f[0]=t,f[1]=n,f[2]=r,f[3]=e,f[4]=u,f[5]=o,f[6]=i,f[7]=s,f[8]=c,f},n.set=function(t,n,r,a,e,u,o,i,s,c){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t[6]=i,t[7]=s,t[8]=c,t},n.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},n.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},n.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=f*o-i*c,h=-f*u+i*s,l=c*u-o*s,v=r*M+a*h+e*l;if(!v)return null;return v=1/v,t[0]=M*v,t[1]=(-f*a+e*c)*v,t[2]=(i*a-e*o)*v,t[3]=h*v,t[4]=(f*r-e*s)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-c*r+a*s)*v,t[8]=(o*r-a*u)*v,t},n.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8];return t[0]=o*f-i*c,t[1]=e*c-a*f,t[2]=a*i-e*o,t[3]=i*s-u*f,t[4]=r*f-e*s,t[5]=e*u-r*i,t[6]=u*c-o*s,t[7]=a*s-r*c,t[8]=r*o-a*u,t},n.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],s=t[7],c=t[8];return n*(c*u-o*s)+r*(-c*e+o*i)+a*(s*e-u*i)},n.multiply=e,n.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=s,t[6]=h*a+l*o+c,t[7]=h*e+l*i+f,t[8]=h*u+l*s+M,t},n.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=Math.sin(r),l=Math.cos(r);return t[0]=l*a+h*o,t[1]=l*e+h*i,t[2]=l*u+h*s,t[3]=l*o-h*a,t[4]=l*i-h*e,t[5]=l*s-h*u,t[6]=c,t[7]=f,t[8]=M,t},n.scale=function(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},n.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},n.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},n.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},n.fromMat2d=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},n.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[3]=f-m,t[6]=h+b,t[1]=f+m,t[4]=1-c-v,t[7]=l-d,t[2]=h-b,t[5]=l+d,t[8]=1-c-M,t},n.normalFromMat4=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15],p=r*i-a*o,P=r*s-e*o,A=r*c-u*o,E=a*s-e*i,O=a*c-u*i,R=e*c-u*s,y=f*d-M*v,q=f*b-h*v,x=f*m-l*v,_=M*b-h*d,Y=M*m-l*d,L=h*m-l*b,S=p*L-P*Y+A*_+E*x-O*q+R*y;if(!S)return null;return S=1/S,t[0]=(i*L-s*Y+c*_)*S,t[1]=(s*x-o*L-c*q)*S,t[2]=(o*Y-i*x+c*y)*S,t[3]=(e*Y-a*L-u*_)*S,t[4]=(r*L-e*x+u*q)*S,t[5]=(a*x-r*Y-u*y)*S,t[6]=(d*R-b*O+m*E)*S,t[7]=(b*A-v*R-m*P)*S,t[8]=(v*O-d*A+m*p)*S,t},n.projection=function(t,n,r){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/r,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},n.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},n.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t},n.subtract=u,n.multiplyScalar=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t},n.multiplyScalarAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=t[4],s=t[5],c=t[6],f=t[7],M=t[8],h=n[0],l=n[1],v=n[2],d=n[3],b=n[4],m=n[5],p=n[6],P=n[7],A=n[8];return Math.abs(r-h)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(h))&&Math.abs(e-l)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(u-v)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(v))&&Math.abs(o-d)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(d))&&Math.abs(i-b)<=a.EPSILON*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(s-m)<=a.EPSILON*Math.max(1,Math.abs(s),Math.abs(m))&&Math.abs(c-p)<=a.EPSILON*Math.max(1,Math.abs(c),Math.abs(p))&&Math.abs(f-P)<=a.EPSILON*Math.max(1,Math.abs(f),Math.abs(P))&&Math.abs(M-A)<=a.EPSILON*Math.max(1,Math.abs(M),Math.abs(A))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1],v=r[2],d=r[3],b=r[4],m=r[5],p=r[6],P=r[7],A=r[8];return t[0]=h*a+l*o+v*c,t[1]=h*e+l*i+v*f,t[2]=h*u+l*s+v*M,t[3]=d*a+b*o+m*c,t[4]=d*e+b*i+m*f,t[5]=d*u+b*s+m*M,t[6]=p*a+P*o+A*c,t[7]=p*e+P*i+A*f,t[8]=p*u+P*s+A*M,t}function u(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t}n.mul=e,n.sub=u},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.sqrDist=n.dist=n.div=n.mul=n.sub=n.len=void 0,n.create=e,n.clone=function(t){var n=new a.ARRAY_TYPE(2);return n[0]=t[0],n[1]=t[1],n},n.fromValues=function(t,n){var r=new a.ARRAY_TYPE(2);return r[0]=t,r[1]=n,r},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t},n.set=function(t,n,r){return t[0]=n,t[1]=r,t},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t},n.subtract=u,n.multiply=o,n.divide=i,n.ceil=function(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t},n.floor=function(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t},n.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t},n.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t},n.round=function(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t},n.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t},n.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t},n.distance=s,n.squaredDistance=c,n.length=f,n.squaredLength=M,n.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t},n.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t},n.normalize=function(t,n){var r=n[0],a=n[1],e=r*r+a*a;e>0&&(e=1/Math.sqrt(e),t[0]=n[0]*e,t[1]=n[1]*e);return t},n.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]},n.cross=function(t,n,r){var a=n[0]*r[1]-n[1]*r[0];return t[0]=t[1]=0,t[2]=a,t},n.lerp=function(t,n,r,a){var e=n[0],u=n[1];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t},n.random=function(t,n){n=n||1;var r=2*a.RANDOM()*Math.PI;return t[0]=Math.cos(r)*n,t[1]=Math.sin(r)*n,t},n.transformMat2=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e,t[1]=r[1]*a+r[3]*e,t},n.transformMat2d=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e+r[4],t[1]=r[1]*a+r[3]*e+r[5],t},n.transformMat3=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[3]*e+r[6],t[1]=r[1]*a+r[4]*e+r[7],t},n.transformMat4=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[4]*e+r[12],t[1]=r[1]*a+r[5]*e+r[13],t},n.rotate=function(t,n,r,a){var e=n[0]-r[0],u=n[1]-r[1],o=Math.sin(a),i=Math.cos(a);return t[0]=e*i-u*o+r[0],t[1]=e*o+u*i+r[1],t},n.angle=function(t,n){var r=t[0],a=t[1],e=n[0],u=n[1],o=r*r+a*a;o>0&&(o=1/Math.sqrt(o));var i=e*e+u*u;i>0&&(i=1/Math.sqrt(i));var s=(r*e+a*u)*o*i;return s>1?0:s<-1?Math.PI:Math.acos(s)},n.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]},n.equals=function(t,n){var r=t[0],e=t[1],u=n[0],o=n[1];return Math.abs(r-u)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(u))&&Math.abs(e-o)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(o))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(){var t=new a.ARRAY_TYPE(2);return a.ARRAY_TYPE!=Float32Array&&(t[0]=0,t[1]=0),t}function u(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t}function o(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t}function i(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t}function s(t,n){var r=n[0]-t[0],a=n[1]-t[1];return Math.sqrt(r*r+a*a)}function c(t,n){var r=n[0]-t[0],a=n[1]-t[1];return r*r+a*a}function f(t){var n=t[0],r=t[1];return Math.sqrt(n*n+r*r)}function M(t){var n=t[0],r=t[1];return n*n+r*r}n.len=f,n.sub=u,n.mul=o,n.div=i,n.dist=s,n.sqrDist=c,n.sqrLen=M,n.forEach=function(){var t=e();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=2),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i0){r=Math.sqrt(r);var a=n[0]/r,e=n[1]/r,u=n[2]/r,o=n[3]/r,i=n[4],s=n[5],c=n[6],f=n[7],M=a*i+e*s+u*c+o*f;t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=(i-a*M)/r,t[5]=(s-e*M)/r,t[6]=(c-u*M)/r,t[7]=(f-o*M)/r}return t},n.str=function(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=t[4],s=t[5],c=t[6],f=t[7],M=n[0],h=n[1],l=n[2],v=n[3],d=n[4],b=n[5],m=n[6],p=n[7];return Math.abs(r-M)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(e-h)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(h))&&Math.abs(u-l)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(o-v)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(v))&&Math.abs(i-d)<=a.EPSILON*Math.max(1,Math.abs(i),Math.abs(d))&&Math.abs(s-b)<=a.EPSILON*Math.max(1,Math.abs(s),Math.abs(b))&&Math.abs(c-m)<=a.EPSILON*Math.max(1,Math.abs(c),Math.abs(m))&&Math.abs(f-p)<=a.EPSILON*Math.max(1,Math.abs(f),Math.abs(p))};var a=o(r(0)),e=o(r(3)),u=o(r(4));function o(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}function i(t,n,r){var a=.5*r[0],e=.5*r[1],u=.5*r[2],o=n[0],i=n[1],s=n[2],c=n[3];return t[0]=o,t[1]=i,t[2]=s,t[3]=c,t[4]=a*c+e*s-u*i,t[5]=e*c+u*o-a*s,t[6]=u*c+a*i-e*o,t[7]=-a*o-e*i-u*s,t}function s(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}n.getReal=e.copy;n.setReal=e.copy;function c(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[4],s=r[5],c=r[6],f=r[7],M=n[4],h=n[5],l=n[6],v=n[7],d=r[0],b=r[1],m=r[2],p=r[3];return t[0]=a*p+o*d+e*m-u*b,t[1]=e*p+o*b+u*d-a*m,t[2]=u*p+o*m+a*b-e*d,t[3]=o*p-a*d-e*b-u*m,t[4]=a*f+o*i+e*c-u*s+M*p+v*d+h*m-l*b,t[5]=e*f+o*s+u*i-a*c+h*p+v*b+l*d-M*m,t[6]=u*f+o*c+a*s-e*i+l*p+v*m+M*b-h*d,t[7]=o*f-a*i-e*s-u*c+v*p-M*d-h*b-l*m,t}n.mul=c;var f=n.dot=e.dot;var M=n.length=e.length,h=(n.len=M,n.squaredLength=e.squaredLength);n.sqrLen=h},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=function(){var t=new a.ARRAY_TYPE(6);a.ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0);return t[0]=1,t[3]=1,t},n.clone=function(t){var n=new a.ARRAY_TYPE(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},n.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},n.fromValues=function(t,n,r,e,u,o){var i=new a.ARRAY_TYPE(6);return i[0]=t,i[1]=n,i[2]=r,i[3]=e,i[4]=u,i[5]=o,i},n.set=function(t,n,r,a,e,u,o){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t},n.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=r*u-a*e;if(!s)return null;return s=1/s,t[0]=u*s,t[1]=-a*s,t[2]=-e*s,t[3]=r*s,t[4]=(e*i-u*o)*s,t[5]=(a*o-r*i)*s,t},n.determinant=function(t){return t[0]*t[3]-t[1]*t[2]},n.multiply=e,n.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=Math.sin(r),f=Math.cos(r);return t[0]=a*f+u*c,t[1]=e*f+o*c,t[2]=a*-c+u*f,t[3]=e*-c+o*f,t[4]=i,t[5]=s,t},n.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=r[0],f=r[1];return t[0]=a*c,t[1]=e*c,t[2]=u*f,t[3]=o*f,t[4]=i,t[5]=s,t},n.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=r[0],f=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=a*c+u*f+i,t[5]=e*c+o*f+s,t},n.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t[4]=0,t[5]=0,t},n.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},n.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},n.str=function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},n.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+1)},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t},n.subtract=u,n.multiplyScalar=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t},n.multiplyScalarAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t},n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=t[4],s=t[5],c=n[0],f=n[1],M=n[2],h=n[3],l=n[4],v=n[5];return Math.abs(r-c)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(c))&&Math.abs(e-f)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(f))&&Math.abs(u-M)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(M))&&Math.abs(o-h)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(h))&&Math.abs(i-l)<=a.EPSILON*Math.max(1,Math.abs(i),Math.abs(l))&&Math.abs(s-v)<=a.EPSILON*Math.max(1,Math.abs(s),Math.abs(v))};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=r[0],f=r[1],M=r[2],h=r[3],l=r[4],v=r[5];return t[0]=a*c+u*f,t[1]=e*c+o*f,t[2]=a*M+u*h,t[3]=e*M+o*h,t[4]=a*l+u*v+i,t[5]=e*l+o*v+s,t}function u(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t}n.mul=e,n.sub=u},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=function(){var t=new a.ARRAY_TYPE(4);a.ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0);return t[0]=1,t[3]=1,t},n.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},n.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},n.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},n.fromValues=function(t,n,r,e){var u=new a.ARRAY_TYPE(4);return u[0]=t,u[1]=n,u[2]=r,u[3]=e,u},n.set=function(t,n,r,a,e){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t},n.transpose=function(t,n){if(t===n){var r=n[1];t[1]=n[2],t[2]=r}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},n.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*u-e*a;if(!o)return null;return o=1/o,t[0]=u*o,t[1]=-a*o,t[2]=-e*o,t[3]=r*o,t},n.adjoint=function(t,n){var r=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=r,t},n.determinant=function(t){return t[0]*t[3]-t[2]*t[1]},n.multiply=e,n.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+u*i,t[1]=e*s+o*i,t[2]=a*-i+u*s,t[3]=e*-i+o*s,t},n.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],s=r[1];return t[0]=a*i,t[1]=e*i,t[2]=u*s,t[3]=o*s,t},n.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t},n.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},n.str=function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},n.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2))},n.LDU=function(t,n,r,a){return t[2]=a[2]/a[0],r[0]=a[0],r[1]=a[1],r[3]=a[3]-t[2]*r[1],[t,n,r]},n.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t},n.subtract=u,n.exactEquals=function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},n.equals=function(t,n){var r=t[0],e=t[1],u=t[2],o=t[3],i=n[0],s=n[1],c=n[2],f=n[3];return Math.abs(r-i)<=a.EPSILON*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(e-s)<=a.EPSILON*Math.max(1,Math.abs(e),Math.abs(s))&&Math.abs(u-c)<=a.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(o-f)<=a.EPSILON*Math.max(1,Math.abs(o),Math.abs(f))},n.multiplyScalar=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t},n.multiplyScalarAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t};var a=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(r(0));function e(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],s=r[1],c=r[2],f=r[3];return t[0]=a*i+u*s,t[1]=e*i+o*s,t[2]=a*c+u*f,t[3]=e*c+o*f,t}function u(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t}n.mul=e,n.sub=u},function(t,n,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.vec4=n.vec3=n.vec2=n.quat2=n.quat=n.mat4=n.mat3=n.mat2d=n.mat2=n.glMatrix=void 0;var a=l(r(0)),e=l(r(9)),u=l(r(8)),o=l(r(5)),i=l(r(4)),s=l(r(3)),c=l(r(7)),f=l(r(6)),M=l(r(2)),h=l(r(1));function l(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}n.glMatrix=a,n.mat2=e,n.mat2d=u,n.mat3=o,n.mat4=i,n.quat=s,n.quat2=c,n.vec2=f,n.vec3=M,n.vec4=h}])}); diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js new file mode 100644 index 0000000..e46677d --- /dev/null +++ b/frontend/static/js/3D/shaders.js @@ -0,0 +1,61 @@ +const vertex_shader_source = ` + attribute vec4 aPos; + attribute vec4 aColor; + + uniform mat4 uModView; + uniform mat4 uProj; + + varying lowp vec4 vColor; + + void main() + { + gl_Position = uProj * uModView * aPos; + vColor = aColor; + } +`; + +const fragment_shader_source = ` + varying lowp vec4 vColor; + + void main() + { + gl_FragColor = vColor; + } +`; + +function initShaderProgram(gl) +{ + const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertex_shader_source); + const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragment_shader_source); + + const shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) + { + alert(`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}`); + return null; + } + return shaderProgram; +} + +function loadShader(gl, type, source) +{ + const shader = gl.createShader(type); + + gl.shaderSource(shader, source); + gl.compileShader(shader); + + if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) + { + alert(`An error occurred compiling the shaders: ${gl.getShaderInfoLog(shader)}`); + gl.deleteShader(shader); + return null; + } + + return shader; +} + +export { initShaderProgram }; diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index ba8ef78..443c6ad 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -7,7 +7,8 @@ import HomeView from "./views/HomeView.js"; import RegisterView from "./views/accounts/RegisterView.js"; import LogoutView from "./views/accounts/LogoutView.js"; import GameOfflineView from "./views/GameOfflineView.js"; -import GameView from "./views/GameView.js"; +//import GameView from "./views/GameView.js"; +import GameView from "./views/GameView3D.js"; import PageNotFoundView from './views/PageNotFoundView.js' diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js new file mode 100644 index 0000000..afca0e4 --- /dev/null +++ b/frontend/static/js/views/GameView3D.js @@ -0,0 +1,102 @@ +import { client } from "../index.js"; +import { Game } from "../api/game/Game.js"; +import AbstractView from "./abstracts/AbstractView.js"; +import { initShaderProgram } from "../3D/shaders.js" + +export default class extends AbstractView +{ + constructor(params) + { + super(params, "Game"); + this.game = new Game(client, params.id); + this.keys_pressed = []; + this.my_player = undefined; + this.gl = null; + this.shader_prog = null; + } + + initGL() + { + const canvas = document.getElementById('glcanva'); + this.gl = canvas.getContext("webgl"); + + if(this.gl === null) + { + alert("Unable to initialize WebGL. Your browser or machine may not support it. You may also be a bozo"); + return; + } + + this.shader_prog = initShaderProgram(this.gl); + } + + async join_game() + { + await this.game.join() + + let canvas = document.createElement("canvas"); + + canvas.height = this.game.config.size_x; + canvas.width = this.game.config.size_y; + canvas.id = "glcanva"; + + document.getElementById("app").appendChild(canvas); + + this.initGL(); + + this.render_game(); + } + + draw() + { + const canvas = document.getElementById('glcanva'); + if(canvas === null) + return 1; + + this.gl.clearColor(1.0, 1.0, 1.0, 1.0); + this.gl.clearDepth(1.0); + this.gl.enable(this.gl.DEPTH_TEST); + this.gl.depthFunc(this.gl.LEQUAL); + this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + } + + render_game() + { + let loop_id = setInterval(() => { + if (this.game === undefined) + clearInterval(loop_id); + if (this.my_player) + this.my_player.update_paddle(this.keys_pressed); + this.draw(); + this.game?.time.new_frame(); + // 1 sec fps + }, 1000 / 60); + } + + async update_game_state() + { + document.getElementById("game-state").innerText = this.game.state; + + if (this.game.finished === false) + await this.join_game(); + } + + async postInit() + { + let error_code = await this.game.init(); + + if (error_code) + return error_code; + + await this.update_game_state(); + } + + async getHtml() + { + return /* HTML */ ` + +

+
+ `; + } +} + From c429586dc7a185960bfacdf8236f446b5aac3b01 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 24 Jan 2024 21:56:28 +0100 Subject: [PATCH 02/13] 3D GO BRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR --- frontend/static/js/3D/shaders.js | 2 +- frontend/static/js/views/GameView3D.js | 89 +++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index e46677d..1dee092 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -19,7 +19,7 @@ const fragment_shader_source = ` void main() { - gl_FragColor = vColor; + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } `; diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index afca0e4..1a1a584 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -2,6 +2,8 @@ import { client } from "../index.js"; import { Game } from "../api/game/Game.js"; import AbstractView from "./abstracts/AbstractView.js"; import { initShaderProgram } from "../3D/shaders.js" +import { initBuffers } from "../3D/buffers.js" +import "../3D/maths/gl-matrix-min.js" export default class extends AbstractView { @@ -13,11 +15,13 @@ export default class extends AbstractView this.my_player = undefined; this.gl = null; this.shader_prog = null; + this.buffers = null; + this.rotation = 0.0; } initGL() { - const canvas = document.getElementById('glcanva'); + const canvas = document.getElementById('glcanva'); this.gl = canvas.getContext("webgl"); if(this.gl === null) @@ -27,6 +31,7 @@ export default class extends AbstractView } this.shader_prog = initShaderProgram(this.gl); + this.buffers = initBuffers(this.gl); } async join_game() @@ -52,11 +57,91 @@ export default class extends AbstractView if(canvas === null) return 1; - this.gl.clearColor(1.0, 1.0, 1.0, 1.0); + const programInfo = { + program: this.shader_prog, + attribLocations: { + vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), + }, + uniformLocations: { + projectionMatrix: this.gl.getUniformLocation( + this.shader_prog, + "uProj" + ), + modelViewMatrix: this.gl.getUniformLocation(this.shader_prog, "uModView"), + }, + }; + + this.gl.clearColor(0.0, 0.0, 0.0, 1.0); this.gl.clearDepth(1.0); this.gl.enable(this.gl.DEPTH_TEST); this.gl.depthFunc(this.gl.LEQUAL); this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + + const fieldOfView = (45 * Math.PI) / 180; + const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight; + const zNear = 0.1; + const zFar = 100.0; + const projectionMatrix = mat4.create(); + + mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); + + const modelViewMatrix = mat4.create(); + + this.rotation += 0.1; + + mat4.translate( + modelViewMatrix, + modelViewMatrix, + [-0.0, 0.0, -6.0] + ); + + mat4.rotate( + modelViewMatrix, + modelViewMatrix, + this.rotation, + [1, 1, 1], + ); + + this.setPositionAttribute(programInfo); + + this.gl.useProgram(programInfo.program); + + this.gl.uniformMatrix4fv( + programInfo.uniformLocations.projectionMatrix, + false, + projectionMatrix + ); + this.gl.uniformMatrix4fv( + programInfo.uniformLocations.modelViewMatrix, + false, + modelViewMatrix + ); + + { + const offset = 0; + const vertexCount = 4; + this.gl.drawArrays(this.gl.TRIANGLE_STRIP, offset, vertexCount); + } + } + + setPositionAttribute(programInfo) + { + const numComponents = 2; + const type = this.gl.FLOAT; + const normalize = false; + const stride = 0; + + const offset = 0; + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.position); + this.gl.vertexAttribPointer( + programInfo.attribLocations.vertexPosition, + numComponents, + type, + normalize, + stride, + offset + ); + this.gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition); } render_game() From d0b0d83209a682ff2723ad96a4e01ffbd6aa6823 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 24 Jan 2024 23:49:04 +0100 Subject: [PATCH 03/13] pouic long boiiiiiiii --- frontend/static/js/3D/buffers.js | 65 ++++++++++++-- frontend/static/js/3D/shaders.js | 22 +++-- frontend/static/js/views/GameView3D.js | 119 +++++++++++++++++-------- 3 files changed, 154 insertions(+), 52 deletions(-) diff --git a/frontend/static/js/3D/buffers.js b/frontend/static/js/3D/buffers.js index 324da51..0b632fa 100644 --- a/frontend/static/js/3D/buffers.js +++ b/frontend/static/js/3D/buffers.js @@ -1,20 +1,69 @@ function initBuffers(gl) { - const positionBuffer = initPositionBuffer(gl); - - return { position: positionBuffer }; + const vertexBuffer = initVertexBuffer(gl); + const indexBuffer = initIndexBuffer(gl); + const normalBuffer = initNormalBuffer(gl); + return { vertex: vertexBuffer, index : indexBuffer, normal: normalBuffer }; } -function initPositionBuffer(gl) +function initVertexBuffer(gl) { const positionBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); - - const positions = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]; - + const positions = [ + // Front face + -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, + // Back face + -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, + // Top face + -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, + // Bottom face + -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, + // Right face + 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, + // Left face + -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0 + ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); return positionBuffer; } +function initNormalBuffer(gl) +{ + const normalBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); + const vertexNormals = [ + // Front + 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, + // Back + 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, + // Top + 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, + // Bottom + 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, + // Right + 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + // Left + -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, + ]; + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals), gl.STATIC_DRAW); + return normalBuffer; +} + +function initIndexBuffer(gl) +{ + const indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + const indices = [ + 0, 1, 2, 0, 2, 3, // front + 4, 5, 6, 4, 6, 7, // back + 8, 9, 10, 8, 10, 11, // top + 12, 13, 14, 12, 14, 15, // bottom + 16, 17, 18, 16, 18, 19, // right + 20, 21, 22, 20, 22, 23, // left + ]; + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); + return indexBuffer; +} + export { initBuffers }; diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index 1dee092..fce75ca 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -1,25 +1,35 @@ const vertex_shader_source = ` attribute vec4 aPos; - attribute vec4 aColor; + attribute vec3 aNormal; uniform mat4 uModView; uniform mat4 uProj; + uniform mat4 uNormalMat; - varying lowp vec4 vColor; + varying highp vec3 vLighting; void main() { gl_Position = uProj * uModView * aPos; - vColor = aColor; + + highp vec3 ambientLight = vec3(0.3, 0.3, 0.3); + highp vec3 directionalLightColor = vec3(1, 1, 1); + highp vec3 directionalVector = normalize(vec3(0.85, 0.8, 0.75)); + + highp vec4 transformedNormal = uNormalMat * vec4(aNormal, 1.0); + + highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); + vLighting = ambientLight + (directionalLightColor * directional); } `; const fragment_shader_source = ` - varying lowp vec4 vColor; + varying highp vec3 vLighting; void main() { - gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + highp vec3 color = vec3(1.0, 1.0, 1.0); + gl_FragColor = vec4(color * vLighting, 1.0); } `; @@ -50,7 +60,7 @@ function loadShader(gl, type, source) if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(`An error occurred compiling the shaders: ${gl.getShaderInfoLog(shader)}`); + alert(`An error occurred while compiling the shaders: ${gl.getShaderInfoLog(shader)}`); gl.deleteShader(shader); return null; } diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index 1a1a584..b3ab1c8 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -17,6 +17,7 @@ export default class extends AbstractView this.shader_prog = null; this.buffers = null; this.rotation = 0.0; + this.programInfo = null; } initGL() @@ -32,6 +33,19 @@ export default class extends AbstractView this.shader_prog = initShaderProgram(this.gl); this.buffers = initBuffers(this.gl); + + this.programInfo = { + program: this.shader_prog, + attribLocations: { + vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), + vertexNormal: this.gl.getAttribLocation(this.shader_prog, "aNormal"), + }, + uniformLocations: { + projectionMatrix: this.gl.getUniformLocation(this.shader_prog, "uProj"), + modelViewMatrix: this.gl.getUniformLocation(this.shader_prog, "uModView"), + normalMatrix: this.gl.getUniformLocation(this.shader_prog, "uNormalMat"), + }, + }; } async join_game() @@ -57,20 +71,6 @@ export default class extends AbstractView if(canvas === null) return 1; - const programInfo = { - program: this.shader_prog, - attribLocations: { - vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), - }, - uniformLocations: { - projectionMatrix: this.gl.getUniformLocation( - this.shader_prog, - "uProj" - ), - modelViewMatrix: this.gl.getUniformLocation(this.shader_prog, "uModView"), - }, - }; - this.gl.clearColor(0.0, 0.0, 0.0, 1.0); this.gl.clearDepth(1.0); this.gl.enable(this.gl.DEPTH_TEST); @@ -85,63 +85,106 @@ export default class extends AbstractView mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); - const modelViewMatrix = mat4.create(); + this.setPositionAttribute(); + this.setNormalAttribute(); - this.rotation += 0.1; + this.gl.useProgram(this.programInfo.program); + + this.gl.uniformMatrix4fv( + this.programInfo.uniformLocations.projectionMatrix, + false, + projectionMatrix + ); + + this.rotation += 0.025; + + this.renderCube(0.0, 0.0, -15.0, this.rotation); + this.renderCube(0.0, 1.0, -15.0, this.rotation + 0.1); + this.renderCube(-2.0, 0.0, -15.0, this.rotation + 4.3); + this.renderCube(2.0, 3.0, -15.0, this.rotation - 12.4, 5); + } + + renderCube(x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) + { + const modelViewMatrix = mat4.create(); mat4.translate( modelViewMatrix, modelViewMatrix, - [-0.0, 0.0, -6.0] + [x, y, z] ); mat4.rotate( modelViewMatrix, modelViewMatrix, - this.rotation, - [1, 1, 1], + angle, + [0, 1, 1], ); - this.setPositionAttribute(programInfo); - - this.gl.useProgram(programInfo.program); - - this.gl.uniformMatrix4fv( - programInfo.uniformLocations.projectionMatrix, - false, - projectionMatrix + mat4.scale( + modelViewMatrix, + modelViewMatrix, + [sx, sy, sz] ); + + const normalMatrix = mat4.create(); + mat4.invert(normalMatrix, modelViewMatrix); + mat4.transpose(normalMatrix, normalMatrix); + this.gl.uniformMatrix4fv( - programInfo.uniformLocations.modelViewMatrix, + this.programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix ); + this.gl.uniformMatrix4fv( + this.programInfo.uniformLocations.normalMatrix, + false, + normalMatrix, + ); - { - const offset = 0; - const vertexCount = 4; - this.gl.drawArrays(this.gl.TRIANGLE_STRIP, offset, vertexCount); - } + const vertexCount = 36; + const type = this.gl.UNSIGNED_SHORT; + const offset = 0; + this.gl.drawElements(this.gl.TRIANGLES, vertexCount, type, offset); + } + + setNormalAttribute() + { + const numComponents = 3; + const type = this.gl.FLOAT; + const normalize = false; + const stride = 0; + const offset = 0; + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.normal); + this.gl.vertexAttribPointer( + this.programInfo.attribLocations.vertexNormal, + numComponents, + type, + normalize, + stride, + offset, + ); + this.gl.enableVertexAttribArray(this.programInfo.attribLocations.vertexNormal); } setPositionAttribute(programInfo) { - const numComponents = 2; + const numComponents = 3; const type = this.gl.FLOAT; const normalize = false; const stride = 0; - const offset = 0; - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.position); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.vertex); + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.index); this.gl.vertexAttribPointer( - programInfo.attribLocations.vertexPosition, + this.programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset ); - this.gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition); + this.gl.enableVertexAttribArray(this.programInfo.attribLocations.vertexPosition); } render_game() From adf35bd66a5c2b4f9cddc553c452929caa819430 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 27 Jan 2024 13:42:21 +0100 Subject: [PATCH 04/13] yes --- frontend/static/js/3D/shaders.js | 27 +++++++++++++++++++++++++- frontend/static/js/views/GameView3D.js | 14 ++++++------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index fce75ca..07e1bd7 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -7,19 +7,44 @@ const vertex_shader_source = ` uniform mat4 uNormalMat; varying highp vec3 vLighting; +/* + vec3 lightColor = vec3(1.0, 0.8, 0.8); + vec3 lightDir = normalize(vec3(-0.2, -1.0, -0.3)); + vec3 viewPos = vec3(0.0, 0.0, 0.0); + + vec3 calculateLighting() + { + vec3 norm = normalize(aNormal); + // ambient + vec3 ambient = 0.3 * lightColor; + // diffuse + float diff = max(dot(lightDir, norm), 0.0); + vec3 diffuse = diff * lightColor; + // specular + vec3 viewDir = normalize(viewPos - vec3(aPos.xyz)); + vec3 reflectDir = reflect(-lightDir, norm); + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0); + vec3 specular = vec3(0.3) * spec; // assuming bright white light color + + return (ambient + diffuse + specular); + } +*/ void main() { gl_Position = uProj * uModView * aPos; highp vec3 ambientLight = vec3(0.3, 0.3, 0.3); highp vec3 directionalLightColor = vec3(1, 1, 1); - highp vec3 directionalVector = normalize(vec3(0.85, 0.8, 0.75)); + highp vec3 directionalVector = normalize(vec3(1, 15, -1.75)); highp vec4 transformedNormal = uNormalMat * vec4(aNormal, 1.0); highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); vLighting = ambientLight + (directionalLightColor * directional); + +// vLighting = calculateLighting(); } `; diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index b3ab1c8..70eb559 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -16,7 +16,6 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; - this.rotation = 0.0; this.programInfo = null; } @@ -46,6 +45,9 @@ export default class extends AbstractView normalMatrix: this.gl.getUniformLocation(this.shader_prog, "uNormalMat"), }, }; + + this.gl.enable(this.gl.CULL_FACE); + this.gl.cullFace(this.gl.BACK); } async join_game() @@ -77,7 +79,7 @@ export default class extends AbstractView this.gl.depthFunc(this.gl.LEQUAL); this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); - const fieldOfView = (45 * Math.PI) / 180; + const fieldOfView = (90 * Math.PI) / 180; const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight; const zNear = 0.1; const zFar = 100.0; @@ -96,12 +98,8 @@ export default class extends AbstractView projectionMatrix ); - this.rotation += 0.025; - - this.renderCube(0.0, 0.0, -15.0, this.rotation); - this.renderCube(0.0, 1.0, -15.0, this.rotation + 0.1); - this.renderCube(-2.0, 0.0, -15.0, this.rotation + 4.3); - this.renderCube(2.0, 3.0, -15.0, this.rotation - 12.4, 5); + // rendering player bar + this.renderCube(0.0, -5.0, -8.0, 0.0, 5); } renderCube(x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) From 94f3838df3fe438bd103f4749dd79c2930296998 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 27 Jan 2024 13:48:57 +0100 Subject: [PATCH 05/13] fixing shit --- frontend/static/js/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index 8b9de7c..4183cc5 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -7,8 +7,8 @@ import HomeView from "./views/HomeView.js"; import RegisterView from "./views/accounts/RegisterView.js"; import LogoutView from "./views/accounts/LogoutView.js"; import GameOfflineView from "./views/GameOfflineView.js"; -//import GameView from "./views/GameView.js"; -import GameView from "./views/GameView3D.js"; +import GameView from "./views/GameView.js"; +//import GameView from "./views/GameView3D.js"; import PageNotFoundView from './views/PageNotFoundView.js' From f9e9538159176dddaf0af82b1cf6345c9b94f36e Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 30 Jan 2024 22:22:47 +0100 Subject: [PATCH 06/13] aca --- frontend/static/js/3D/shaders.js | 1 + frontend/static/js/api/game/Segment.js | 14 +++++++++++--- frontend/static/js/index.js | 4 ++-- frontend/static/js/views/GameView3D.js | 26 +++++++++++++------------- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index 07e1bd7..a048381 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -93,4 +93,5 @@ function loadShader(gl, type, source) return shader; } +export let shaderInfos = null; export { initShaderProgram }; diff --git a/frontend/static/js/api/game/Segment.js b/frontend/static/js/api/game/Segment.js index 7d6fedc..eaea06b 100644 --- a/frontend/static/js/api/game/Segment.js +++ b/frontend/static/js/api/game/Segment.js @@ -17,8 +17,16 @@ class Segment */ draw(ctx) { - ctx.moveTo(this.start.x, this.start.y); - ctx.lineTo(this.stop.x, this.stop.y); + if(this.gl instanceof CanvasRenderingContext2D) + { + ctx.moveTo(this.start.x, this.start.y); + ctx.lineTo(this.stop.x, this.stop.y); + } + else if(this.gl instanceof WebGLRenderingContext) + { + } + else + alert('Unknown rendering context type'); } from_json(data) @@ -30,4 +38,4 @@ class Segment } } -export { Segment } \ No newline at end of file +export { Segment } diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index 4183cc5..8b9de7c 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -7,8 +7,8 @@ import HomeView from "./views/HomeView.js"; import RegisterView from "./views/accounts/RegisterView.js"; import LogoutView from "./views/accounts/LogoutView.js"; import GameOfflineView from "./views/GameOfflineView.js"; -import GameView from "./views/GameView.js"; -//import GameView from "./views/GameView3D.js"; +//import GameView from "./views/GameView.js"; +import GameView from "./views/GameView3D.js"; import PageNotFoundView from './views/PageNotFoundView.js' diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index 70eb559..bd89f1c 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -2,6 +2,7 @@ import { client } from "../index.js"; import { Game } from "../api/game/Game.js"; import AbstractView from "./abstracts/AbstractView.js"; import { initShaderProgram } from "../3D/shaders.js" +import shaderInfos from "../3D/shaders.js" import { initBuffers } from "../3D/buffers.js" import "../3D/maths/gl-matrix-min.js" @@ -16,7 +17,6 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; - this.programInfo = null; } initGL() @@ -33,7 +33,7 @@ export default class extends AbstractView this.shader_prog = initShaderProgram(this.gl); this.buffers = initBuffers(this.gl); - this.programInfo = { + shaderInfos = { program: this.shader_prog, attribLocations: { vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), @@ -90,16 +90,16 @@ export default class extends AbstractView this.setPositionAttribute(); this.setNormalAttribute(); - this.gl.useProgram(this.programInfo.program); + this.gl.useProgram(shaderInfos.program); this.gl.uniformMatrix4fv( - this.programInfo.uniformLocations.projectionMatrix, + shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix ); - // rendering player bar - this.renderCube(0.0, -5.0, -8.0, 0.0, 5); + //this.game.draw(this.gl); + //this.renderCube(1, 0, -15); } renderCube(x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) @@ -130,12 +130,12 @@ export default class extends AbstractView mat4.transpose(normalMatrix, normalMatrix); this.gl.uniformMatrix4fv( - this.programInfo.uniformLocations.modelViewMatrix, + shaderInfos.uniformLocations.modelViewMatrix, false, modelViewMatrix ); this.gl.uniformMatrix4fv( - this.programInfo.uniformLocations.normalMatrix, + shaderInfos.uniformLocations.normalMatrix, false, normalMatrix, ); @@ -155,17 +155,17 @@ export default class extends AbstractView const offset = 0; this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.normal); this.gl.vertexAttribPointer( - this.programInfo.attribLocations.vertexNormal, + shaderInfos.attribLocations.vertexNormal, numComponents, type, normalize, stride, offset, ); - this.gl.enableVertexAttribArray(this.programInfo.attribLocations.vertexNormal); + this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexNormal); } - setPositionAttribute(programInfo) + setPositionAttribute() { const numComponents = 3; const type = this.gl.FLOAT; @@ -175,14 +175,14 @@ export default class extends AbstractView this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.vertex); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.index); this.gl.vertexAttribPointer( - this.programInfo.attribLocations.vertexPosition, + shaderInfos.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset ); - this.gl.enableVertexAttribArray(this.programInfo.attribLocations.vertexPosition); + this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexPosition); } render_game() From 54c4ae77f20314856f61e0fac99db8ae6aeb73d4 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 10 Feb 2024 19:38:56 +0100 Subject: [PATCH 07/13] AAAAAAAAAAAAAAAAAAAAAAAAH --- frontend/static/js/3D/cube.js | 44 +++++++++++++++++ frontend/static/js/3D/shaders.js | 34 +++++++++---- frontend/static/js/api/game/Ball.js | 21 ++++++-- frontend/static/js/api/game/Game.js | 5 +- frontend/static/js/api/game/Player.js | 42 ++++++++++------ frontend/static/js/api/game/Segment.js | 8 ++- frontend/static/js/api/game/Wall.js | 6 +-- frontend/static/js/views/GameView3D.js | 67 ++++---------------------- 8 files changed, 134 insertions(+), 93 deletions(-) create mode 100644 frontend/static/js/3D/cube.js diff --git a/frontend/static/js/3D/cube.js b/frontend/static/js/3D/cube.js new file mode 100644 index 0000000..3544d4f --- /dev/null +++ b/frontend/static/js/3D/cube.js @@ -0,0 +1,44 @@ +import { shaderInfos } from "../3D/shaders.js" + +function renderCube(ctx, x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) +{ + const modelMatrix = mat4.create(); + + mat4.translate( + modelMatrix, + modelMatrix, + [x, y, z] + ); + + mat4.rotate( + modelMatrix, + modelMatrix, + angle, + [0, 1, 1], + ); + + mat4.scale( + modelMatrix, + modelMatrix, + [sx, sy, sz] + ); + + const normalMatrix = mat4.create(); + mat4.invert(normalMatrix, modelMatrix); + mat4.transpose(normalMatrix, normalMatrix); + + ctx.uniformMatrix4fv( + shaderInfos.uniformLocations.modelMatrix, + false, + modelMatrix + ); + ctx.uniformMatrix4fv( + shaderInfos.uniformLocations.normalMatrix, + false, + normalMatrix, + ); + + ctx.drawElements(ctx.TRIANGLES, 36, ctx.UNSIGNED_SHORT, 0); +} + +export { renderCube }; diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index a048381..19be146 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -2,7 +2,8 @@ const vertex_shader_source = ` attribute vec4 aPos; attribute vec3 aNormal; - uniform mat4 uModView; + uniform mat4 uMod; + uniform mat4 uView; uniform mat4 uProj; uniform mat4 uNormalMat; @@ -33,7 +34,7 @@ const vertex_shader_source = ` */ void main() { - gl_Position = uProj * uModView * aPos; + gl_Position = uView * uProj * uMod * aPos; highp vec3 ambientLight = vec3(0.3, 0.3, 0.3); highp vec3 directionalLightColor = vec3(1, 1, 1); @@ -63,17 +64,32 @@ function initShaderProgram(gl) const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertex_shader_source); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragment_shader_source); - const shaderProgram = gl.createProgram(); - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); + const shader_prog = gl.createProgram(); + gl.attachShader(shader_prog, vertexShader); + gl.attachShader(shader_prog, fragmentShader); + gl.linkProgram(shader_prog); - if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) + if(!gl.getProgramParameter(shader_prog, gl.LINK_STATUS)) { alert(`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}`); return null; } - return shaderProgram; + + shaderInfos = { + program: shader_prog, + attribLocations: { + vertexPosition: gl.getAttribLocation(shader_prog, "aPos"), + vertexNormal: gl.getAttribLocation(shader_prog, "aNormal"), + }, + uniformLocations: { + projectionMatrix: gl.getUniformLocation(shader_prog, "uProj"), + modelMatrix: gl.getUniformLocation(shader_prog, "uMod"), + viewMatrix: gl.getUniformLocation(shader_prog, "uView"), + normalMatrix: gl.getUniformLocation(shader_prog, "uNormalMat"), + }, + }; + + return shader_prog; } function loadShader(gl, type, source) @@ -93,5 +109,5 @@ function loadShader(gl, type, source) return shader; } -export let shaderInfos = null; +export let shaderInfos; export { initShaderProgram }; diff --git a/frontend/static/js/api/game/Ball.js b/frontend/static/js/api/game/Ball.js index bcd0ca1..b8ea96d 100644 --- a/frontend/static/js/api/game/Ball.js +++ b/frontend/static/js/api/game/Ball.js @@ -1,6 +1,6 @@ import { Game } from "./Game.js"; import { Point } from "./Point.js"; - +import { renderCube } from "../../3D/cube.js" class Ball { @@ -38,12 +38,23 @@ class Ball /** * - * @param {CanvasRenderingContext2D} ctx + * @param {CanvasRenderingContext2D} ctx ou pas ptdr */ draw(ctx) { - ctx.rect(this.position_x, this.position_y, this.game.config.ball_size, this.game.config.ball_size); - } + if(ctx instanceof CanvasRenderingContext2D) + { + ctx.rect(this.position_x, this.position_y, this.game.config.ball_size, this.game.config.ball_size); + } + else if(ctx instanceof WebGLRenderingContext) + { + renderCube(ctx, this.position_x, 0, this.position_y, 0, this.game.config.ball_size, this.game.config.ball_size, this.game.config.ball_size); + } + else + { + alert('Unknown rendering context type (wtf)'); + } + } render() { @@ -79,4 +90,4 @@ class Ball } } -export { Ball } \ No newline at end of file +export { Ball } diff --git a/frontend/static/js/api/game/Game.js b/frontend/static/js/api/game/Game.js index 08253b0..e2417a7 100644 --- a/frontend/static/js/api/game/Game.js +++ b/frontend/static/js/api/game/Game.js @@ -74,7 +74,10 @@ class Game */ draw(ctx) { - ctx.clearRect(0, 0, this.config.size_x, this.config.size_y); + if(ctx instanceof CanvasRenderingContext2D) + { + ctx.clearRect(0, 0, this.config.size_x, this.config.size_y); + } this.draw_sides(ctx); this.ball.draw(ctx); } diff --git a/frontend/static/js/api/game/Player.js b/frontend/static/js/api/game/Player.js index 8736db1..296dd5a 100644 --- a/frontend/static/js/api/game/Player.js +++ b/frontend/static/js/api/game/Player.js @@ -79,23 +79,33 @@ class Player */ draw(ctx) { - if (this.is_connected === false) - { - ctx.moveTo(this.rail.start.x, this.rail.start.y); - ctx.lineTo(this.rail.stop.x, this.rail.stop.y); - return; - } - let paddle_pos = new Point(this.rail.start.x + this.diff_x * this.position, - this.rail.start.y + this.diff_y * this.position); + if(ctx instanceof CanvasRenderingContext2D) + { + if (this.is_connected === false) + { + ctx.moveTo(this.rail.start.x, this.rail.start.y); + ctx.lineTo(this.rail.stop.x, this.rail.stop.y); + return; + } + let paddle_pos = new Point(this.rail.start.x + this.diff_x * this.position, + this.rail.start.y + this.diff_y * this.position); + + let start_x = paddle_pos.x - (this.diff_x * (this.paddle_size / 2 / this.rail_size)), + start_y = paddle_pos.y - (this.diff_y * (this.paddle_size / 2 / this.rail_size)), + stop_x = paddle_pos.x + (this.diff_x * (this.paddle_size / 2 / this.rail_size)), + stop_y = paddle_pos.y + (this.diff_y * (this.paddle_size / 2 / this.rail_size)); - - let start_x = paddle_pos.x - (this.diff_x * (this.paddle_size / 2 / this.rail_size)), - start_y = paddle_pos.y - (this.diff_y * (this.paddle_size / 2 / this.rail_size)), - stop_x = paddle_pos.x + (this.diff_x * (this.paddle_size / 2 / this.rail_size)), - stop_y = paddle_pos.y + (this.diff_y * (this.paddle_size / 2 / this.rail_size)); + ctx.moveTo(start_x, start_y); + ctx.lineTo(stop_x, stop_y); + } + else if(ctx instanceof WebGLRenderingContext) + { - ctx.moveTo(start_x, start_y); - ctx.lineTo(stop_x, stop_y); + } + else + { + alert('Unknown rendering context type (wtf)'); + } } from_json(data) @@ -149,4 +159,4 @@ class Player } } -export { Player } \ No newline at end of file +export { Player } diff --git a/frontend/static/js/api/game/Segment.js b/frontend/static/js/api/game/Segment.js index eaea06b..23bf3b6 100644 --- a/frontend/static/js/api/game/Segment.js +++ b/frontend/static/js/api/game/Segment.js @@ -1,4 +1,5 @@ import { Point } from "./Point.js" +import { renderCube } from "../../3D/cube.js" class Segment { @@ -17,16 +18,19 @@ class Segment */ draw(ctx) { - if(this.gl instanceof CanvasRenderingContext2D) + if(ctx instanceof CanvasRenderingContext2D) { ctx.moveTo(this.start.x, this.start.y); ctx.lineTo(this.stop.x, this.stop.y); } - else if(this.gl instanceof WebGLRenderingContext) + else if(ctx instanceof WebGLRenderingContext) { + renderCube(ctx, this.start.x, -3, this.start.y, 0, 0.5, 0.5, 0.5); } else + { alert('Unknown rendering context type'); + } } from_json(data) diff --git a/frontend/static/js/api/game/Wall.js b/frontend/static/js/api/game/Wall.js index be69f42..000d13b 100644 --- a/frontend/static/js/api/game/Wall.js +++ b/frontend/static/js/api/game/Wall.js @@ -14,8 +14,8 @@ class Wall } draw(ctx) - { - this.rail.draw(ctx); + { + this.rail.draw(ctx); } from_json(data) @@ -26,4 +26,4 @@ class Wall } } -export { Wall } \ No newline at end of file +export { Wall } diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index bd89f1c..7d69671 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -1,10 +1,10 @@ import { client } from "../index.js"; import { Game } from "../api/game/Game.js"; import AbstractView from "./abstracts/AbstractView.js"; -import { initShaderProgram } from "../3D/shaders.js" -import shaderInfos from "../3D/shaders.js" +import { initShaderProgram, shaderInfos } from "../3D/shaders.js" import { initBuffers } from "../3D/buffers.js" import "../3D/maths/gl-matrix-min.js" +import { renderCube } from "../3D/cube.js" export default class extends AbstractView { @@ -17,6 +17,8 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; + this.cam_pos = [0, 10, 0]; + this.cam_target = [0, 0, 0]; } initGL() @@ -33,19 +35,6 @@ export default class extends AbstractView this.shader_prog = initShaderProgram(this.gl); this.buffers = initBuffers(this.gl); - shaderInfos = { - program: this.shader_prog, - attribLocations: { - vertexPosition: this.gl.getAttribLocation(this.shader_prog, "aPos"), - vertexNormal: this.gl.getAttribLocation(this.shader_prog, "aNormal"), - }, - uniformLocations: { - projectionMatrix: this.gl.getUniformLocation(this.shader_prog, "uProj"), - modelViewMatrix: this.gl.getUniformLocation(this.shader_prog, "uModView"), - normalMatrix: this.gl.getUniformLocation(this.shader_prog, "uNormalMat"), - }, - }; - this.gl.enable(this.gl.CULL_FACE); this.gl.cullFace(this.gl.BACK); } @@ -84,8 +73,10 @@ export default class extends AbstractView const zNear = 0.1; const zFar = 100.0; const projectionMatrix = mat4.create(); + const viewMatrix = mat4.create(); mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); + mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); this.setPositionAttribute(); this.setNormalAttribute(); @@ -98,52 +89,14 @@ export default class extends AbstractView projectionMatrix ); - //this.game.draw(this.gl); - //this.renderCube(1, 0, -15); - } - - renderCube(x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) - { - const modelViewMatrix = mat4.create(); - - mat4.translate( - modelViewMatrix, - modelViewMatrix, - [x, y, z] - ); - - mat4.rotate( - modelViewMatrix, - modelViewMatrix, - angle, - [0, 1, 1], - ); - - mat4.scale( - modelViewMatrix, - modelViewMatrix, - [sx, sy, sz] - ); - - const normalMatrix = mat4.create(); - mat4.invert(normalMatrix, modelViewMatrix); - mat4.transpose(normalMatrix, normalMatrix); - this.gl.uniformMatrix4fv( - shaderInfos.uniformLocations.modelViewMatrix, + shaderInfos.uniformLocations.viewMatrix, false, - modelViewMatrix - ); - this.gl.uniformMatrix4fv( - shaderInfos.uniformLocations.normalMatrix, - false, - normalMatrix, + viewMatrix ); - const vertexCount = 36; - const type = this.gl.UNSIGNED_SHORT; - const offset = 0; - this.gl.drawElements(this.gl.TRIANGLES, vertexCount, type, offset); + this.game.draw(this.gl); + renderCube(this.gl, 0, 0, 0); } setNormalAttribute() From 7f26b839c348e413457f3ad919be1a5db257d08d Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Mon, 12 Feb 2024 18:34:01 +0100 Subject: [PATCH 08/13] caca --- frontend/static/js/3D/cube.js | 2 + frontend/static/js/3D/shaders.js | 66 ++++++++------------------ frontend/static/js/views/GameView3D.js | 15 +++--- 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/frontend/static/js/3D/cube.js b/frontend/static/js/3D/cube.js index 3544d4f..84aa5f3 100644 --- a/frontend/static/js/3D/cube.js +++ b/frontend/static/js/3D/cube.js @@ -4,6 +4,8 @@ function renderCube(ctx, x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) { const modelMatrix = mat4.create(); + console.log("test") + mat4.translate( modelMatrix, modelMatrix, diff --git a/frontend/static/js/3D/shaders.js b/frontend/static/js/3D/shaders.js index 19be146..641364b 100644 --- a/frontend/static/js/3D/shaders.js +++ b/frontend/static/js/3D/shaders.js @@ -8,33 +8,10 @@ const vertex_shader_source = ` uniform mat4 uNormalMat; varying highp vec3 vLighting; -/* - vec3 lightColor = vec3(1.0, 0.8, 0.8); - vec3 lightDir = normalize(vec3(-0.2, -1.0, -0.3)); - vec3 viewPos = vec3(0.0, 0.0, 0.0); - - vec3 calculateLighting() - { - vec3 norm = normalize(aNormal); - // ambient - vec3 ambient = 0.3 * lightColor; - // diffuse - float diff = max(dot(lightDir, norm), 0.0); - vec3 diffuse = diff * lightColor; - // specular - vec3 viewDir = normalize(viewPos - vec3(aPos.xyz)); - vec3 reflectDir = reflect(-lightDir, norm); - vec3 halfwayDir = normalize(lightDir + viewDir); - float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0); - vec3 specular = vec3(0.3) * spec; // assuming bright white light color - - return (ambient + diffuse + specular); - } -*/ void main() { - gl_Position = uView * uProj * uMod * aPos; + gl_Position = uProj * uView * uMod * aPos; highp vec3 ambientLight = vec3(0.3, 0.3, 0.3); highp vec3 directionalLightColor = vec3(1, 1, 1); @@ -44,8 +21,6 @@ const vertex_shader_source = ` highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); vLighting = ambientLight + (directionalLightColor * directional); - -// vLighting = calculateLighting(); } `; @@ -59,37 +34,37 @@ const fragment_shader_source = ` } `; -function initShaderProgram(gl) +export function initShaderProgram(gl) { const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertex_shader_source); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragment_shader_source); - const shader_prog = gl.createProgram(); - gl.attachShader(shader_prog, vertexShader); - gl.attachShader(shader_prog, fragmentShader); - gl.linkProgram(shader_prog); - - if(!gl.getProgramParameter(shader_prog, gl.LINK_STATUS)) - { - alert(`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}`); - return null; - } + const prog = gl.createProgram(); + gl.attachShader(prog, vertexShader); + gl.attachShader(prog, fragmentShader); + gl.linkProgram(prog); shaderInfos = { - program: shader_prog, + program: prog, attribLocations: { - vertexPosition: gl.getAttribLocation(shader_prog, "aPos"), - vertexNormal: gl.getAttribLocation(shader_prog, "aNormal"), + vertexPosition: gl.getAttribLocation(prog, "aPos"), + vertexNormal: gl.getAttribLocation(prog, "aNormal"), }, uniformLocations: { - projectionMatrix: gl.getUniformLocation(shader_prog, "uProj"), - modelMatrix: gl.getUniformLocation(shader_prog, "uMod"), - viewMatrix: gl.getUniformLocation(shader_prog, "uView"), - normalMatrix: gl.getUniformLocation(shader_prog, "uNormalMat"), + projectionMatrix: gl.getUniformLocation(prog, "uProj"), + modelMatrix: gl.getUniformLocation(prog, "uMod"), + viewMatrix: gl.getUniformLocation(prog, "uView"), + normalMatrix: gl.getUniformLocation(prog, "uNormalMat"), }, }; - return shader_prog; + if(!gl.getProgramParameter(prog, gl.LINK_STATUS)) + { + alert(`Unable to initialize the shader program: ${gl.getProgramInfoLog(prog)}`); + return null; + } + + return prog; } function loadShader(gl, type, source) @@ -110,4 +85,3 @@ function loadShader(gl, type, source) } export let shaderInfos; -export { initShaderProgram }; diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index 7d69671..84f6b68 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -17,7 +17,7 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; - this.cam_pos = [0, 10, 0]; + this.cam_pos = [0, 1, 0]; this.cam_target = [0, 0, 0]; } @@ -68,16 +68,14 @@ export default class extends AbstractView this.gl.depthFunc(this.gl.LEQUAL); this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); - const fieldOfView = (90 * Math.PI) / 180; - const aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight; - const zNear = 0.1; - const zFar = 100.0; const projectionMatrix = mat4.create(); const viewMatrix = mat4.create(); - mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); + mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 1000.0); mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); + mat4.invert(viewMatrix, viewMatrix); + this.setPositionAttribute(); this.setNormalAttribute(); @@ -95,8 +93,8 @@ export default class extends AbstractView viewMatrix ); - this.game.draw(this.gl); - renderCube(this.gl, 0, 0, 0); + renderCube(this.gl, -2, -3, -10, 0, 5); + //this.game.draw(this.gl); } setNormalAttribute() @@ -147,7 +145,6 @@ export default class extends AbstractView this.my_player.update_paddle(this.keys_pressed); this.draw(); this.game?.time.new_frame(); - // 1 sec fps }, 1000 / 60); } From faed2a027df69524871b50ee35bff082203392ea Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 14 Feb 2024 18:48:35 +0100 Subject: [PATCH 09/13] working camera support --- frontend/static/js/3D/cube.js | 2 -- frontend/static/js/api/game/Ball.js | 2 +- frontend/static/js/views/GameView3D.js | 24 ++++++------------------ 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/frontend/static/js/3D/cube.js b/frontend/static/js/3D/cube.js index 84aa5f3..3544d4f 100644 --- a/frontend/static/js/3D/cube.js +++ b/frontend/static/js/3D/cube.js @@ -4,8 +4,6 @@ function renderCube(ctx, x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) { const modelMatrix = mat4.create(); - console.log("test") - mat4.translate( modelMatrix, modelMatrix, diff --git a/frontend/static/js/api/game/Ball.js b/frontend/static/js/api/game/Ball.js index b8ea96d..8d6e1bd 100644 --- a/frontend/static/js/api/game/Ball.js +++ b/frontend/static/js/api/game/Ball.js @@ -48,7 +48,7 @@ class Ball } else if(ctx instanceof WebGLRenderingContext) { - renderCube(ctx, this.position_x, 0, this.position_y, 0, this.game.config.ball_size, this.game.config.ball_size, this.game.config.ball_size); + renderCube(ctx, this.position_x / 1000, 0, this.position_y / 1000, 0, this.game.config.ball_size, this.game.config.ball_size, this.game.config.ball_size); } else { diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index 84f6b68..4585d5e 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -17,8 +17,8 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; - this.cam_pos = [0, 1, 0]; - this.cam_target = [0, 0, 0]; + this.cam_pos = [0, 100, 0]; + this.cam_target = [4, 0, 4]; } initGL() @@ -62,7 +62,7 @@ export default class extends AbstractView if(canvas === null) return 1; - this.gl.clearColor(0.0, 0.0, 0.0, 1.0); + this.gl.clearColor(0.1, 0.1, 0.1, 1.0); this.gl.clearDepth(1.0); this.gl.enable(this.gl.DEPTH_TEST); this.gl.depthFunc(this.gl.LEQUAL); @@ -74,27 +74,15 @@ export default class extends AbstractView mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 1000.0); mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); - mat4.invert(viewMatrix, viewMatrix); - this.setPositionAttribute(); this.setNormalAttribute(); this.gl.useProgram(shaderInfos.program); - this.gl.uniformMatrix4fv( - shaderInfos.uniformLocations.projectionMatrix, - false, - projectionMatrix - ); + this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix); + this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.viewMatrix, false, viewMatrix); - this.gl.uniformMatrix4fv( - shaderInfos.uniformLocations.viewMatrix, - false, - viewMatrix - ); - - renderCube(this.gl, -2, -3, -10, 0, 5); - //this.game.draw(this.gl); + this.game.draw(this.gl); } setNormalAttribute() From 6639f562b8a954a83531c043ee4219d1a0428cc4 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 14 Feb 2024 18:52:43 +0100 Subject: [PATCH 10/13] fixing merge --- frontend/static/js/api/game/Ball.js | 96 ++++++++++++----------------- 1 file changed, 40 insertions(+), 56 deletions(-) diff --git a/frontend/static/js/api/game/Ball.js b/frontend/static/js/api/game/Ball.js index 8d6e1bd..6a0603e 100644 --- a/frontend/static/js/api/game/Ball.js +++ b/frontend/static/js/api/game/Ball.js @@ -1,92 +1,76 @@ import { Game } from "./Game.js"; import { Point } from "./Point.js"; -import { renderCube } from "../../3D/cube.js" + class Ball { /** * * @param {Game} game - * @param {Number} position_x - * @param {Number} position_y - * @param {Number} velocity_x - * @param {Number} velocity_y + * @param {Point} position + * @param {Number} angle + * @param {Number} speed + * @param {Number} size */ - constructor(game, position_x, position_y, velocity_x, velocity_y) + constructor(game, size, position, angle, speed) { /** * @type {Game} */ this.game = game; + + /** + * @type {Point} + */ + this.position = position === undefined ? new Point() : position; + /** * @type {Number} */ - this.position_x = position_x; + this.size = size; + /** * @type {Number} */ - this.position_y = position_y; + this.angle = angle; + /** * @type {Number} */ - this.velocity_x = velocity_x; - /** - * @type {Number} - */ - this.velocity_y = velocity_y; + this.speed = speed; } /** * - * @param {CanvasRenderingContext2D} ctx ou pas ptdr + * @param {CanvasRenderingContext2D} ctx */ draw(ctx) { - if(ctx instanceof CanvasRenderingContext2D) - { - ctx.rect(this.position_x, this.position_y, this.game.config.ball_size, this.game.config.ball_size); - } - else if(ctx instanceof WebGLRenderingContext) - { - renderCube(ctx, this.position_x / 1000, 0, this.position_y / 1000, 0, this.game.config.ball_size, this.game.config.ball_size, this.game.config.ball_size); - } - else - { - alert('Unknown rendering context type (wtf)'); - } - } - - render() - { - /** - * @type {Number} - */ - let new_pos_x = this.position_x + this.velocity_x * this.game.time.deltaTime(); - /** - * @type {Number} - */ - let new_pos_y = position_y + this.velocity_y * this.game.time.deltaTime(); - - if (this._collision(this.position_x, this.position_y, new_pos_x, new_pos_y)) - { - this.velocity_x = -this.velocity_x; - this.velocity_y = -this.velocity_y; - new_pos_x = this.position_x + this.velocity_x * this.game.time.deltaTime(); - new_pos_y = this.position_y + this.velocity_y * this.game.time.deltaTime(); - } - this.position_x = new_pos_x - this.position_y = new_pos_y - - this.velocity_x = this.velocity_x + this.game.config.ball_speed_inc; - this.velocity_y = this.velocity_y + this.game.config.ball_speed_inc; + ctx.rect(this.position.x - this.size / 2, this.position.y - this.size / 2, this.size, this.size); } - update (position_x, position_y, velocity_x, velocity_y) + /** + * + * @param {CanvasRenderingContext2D} ctx + */ + render(ctx) { - this.position_x = position_x; - this.position_y = position_y; - this.velocity_x = velocity_x; - this.velocity_y = velocity_y; + let distance = this.speed * (this.game.time.deltaTime() / 1000) + + this.position.x = this.position.x + distance * Math.cos(this.angle); + this.position.y = this.position.y - distance * Math.sin(this.angle); + + this.draw(ctx); + } + + from_json (data) + { + this.position = this.position.from_json(data.position); + this.size = data.size; + this.angle = data.angle; + this.speed = data.speed; + + return this } } From 6d7b52ae06d51d7c1bb970bccc2393dace245b7b Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 14 Feb 2024 18:53:29 +0100 Subject: [PATCH 11/13] fixing merge --- frontend/static/js/api/game/Player.js | 92 ++++++++------------------- 1 file changed, 27 insertions(+), 65 deletions(-) diff --git a/frontend/static/js/api/game/Player.js b/frontend/static/js/api/game/Player.js index 296dd5a..1802d48 100644 --- a/frontend/static/js/api/game/Player.js +++ b/frontend/static/js/api/game/Player.js @@ -43,26 +43,6 @@ class Player * @type {Segment} */ this.rail = rail === undefined ? new Segment() : rail; - - /** - * @type {Number} - */ - this.rail_size = Math.abs(this.rail.stop.x - this.rail.start.x) + Math.abs(this.rail.stop.y - this.rail.start.y); - - /** - * @type {Number} - */ - this.paddle_size = this.rail_size * this.game.config.paddle_ratio; - - /** - * @type {Number} - */ - this.diff_x = this.rail.stop.x - this.rail.start.x; - - /** - * @type {Number} - */ - this.diff_y = this.rail.stop.y - this.rail.start.y; } /** @@ -79,33 +59,35 @@ class Player */ draw(ctx) { - if(ctx instanceof CanvasRenderingContext2D) - { - if (this.is_connected === false) - { - ctx.moveTo(this.rail.start.x, this.rail.start.y); - ctx.lineTo(this.rail.stop.x, this.rail.stop.y); - return; - } - let paddle_pos = new Point(this.rail.start.x + this.diff_x * this.position, - this.rail.start.y + this.diff_y * this.position); - - let start_x = paddle_pos.x - (this.diff_x * (this.paddle_size / 2 / this.rail_size)), - start_y = paddle_pos.y - (this.diff_y * (this.paddle_size / 2 / this.rail_size)), - stop_x = paddle_pos.x + (this.diff_x * (this.paddle_size / 2 / this.rail_size)), - stop_y = paddle_pos.y + (this.diff_y * (this.paddle_size / 2 / this.rail_size)); + if (this.is_connected === false) + { + ctx.moveTo(this.rail.start.x, this.rail.start.y); + ctx.lineTo(this.rail.stop.x, this.rail.stop.y); + return; + } - ctx.moveTo(start_x, start_y); - ctx.lineTo(stop_x, stop_y); - } - else if(ctx instanceof WebGLRenderingContext) - { + let diff_x = this.rail.stop.x - this.rail.start.x, + diff_y = this.rail.stop.y - this.rail.start.y; - } - else - { - alert('Unknown rendering context type (wtf)'); - } + let rail_length = this.rail.len(), + paddle_length = rail_length * this.game.config.paddle_ratio; + + let paddle_center = new Point(this.rail.start.x + diff_x * this.position, + this.rail.start.y + diff_y * this.position); + + let paddle_start_x = paddle_center.x - (diff_x * (paddle_length / 2 / rail_length)), + paddle_start_y = paddle_center.y - (diff_y * (paddle_length / 2 / rail_length)), + paddle_stop_x = paddle_center.x + (diff_x * (paddle_length / 2 / rail_length)), + paddle_stop_y = paddle_center.y + (diff_y * (paddle_length / 2 / rail_length)); + + let paddle_start = new Point(paddle_start_x, paddle_start_y), + paddle_stop = new Point (paddle_stop_x, paddle_stop_y); + + let paddle = new Segment(paddle_start, paddle_stop); + + console.log(paddle) + + paddle.draw(ctx); } from_json(data) @@ -135,26 +117,6 @@ class Player */ this.rail = this.rail.from_json(data.rail); - /** - * @type {Number} - */ - this.rail_size = Math.abs(this.rail.stop.x - this.rail.start.x) + Math.abs(this.rail.stop.y - this.rail.start.y); - - /** - * @type {Number} - */ - this.paddle_size = this.rail_size * this.game.config.paddle_ratio; - - /** - * @type {Number} - */ - this.diff_x = this.rail.stop.x - this.rail.start.x; - - /** - * @type {Number} - */ - this.diff_y = this.rail.stop.y - this.rail.start.y; - return this } } From f7fbfcad15cbc46db3b3142ac0492463cf2ceeae Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 14 Feb 2024 20:22:07 +0100 Subject: [PATCH 12/13] wat --- "\\" | 166 +++++++++++++++++++++++++ frontend/static/js/3D/cube.js | 12 +- frontend/static/js/api/game/Ball.js | 16 ++- frontend/static/js/api/game/Player.js | 8 +- frontend/static/js/views/GameView3D.js | 8 +- 5 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 "\\" diff --git "a/\\" "b/\\" new file mode 100644 index 0000000..d03060c --- /dev/null +++ "b/\\" @@ -0,0 +1,166 @@ +import { client } from "../index.js"; +import { Game } from "../api/game/Game.js"; +import AbstractView from "./abstracts/AbstractView.js"; +import { initShaderProgram, shaderInfos } from "../3D/shaders.js" +import { initBuffers } from "../3D/buffers.js" +import "../3D/maths/gl-matrix-min.js" +import { renderCube } from "../3D/cube.js" + +export default class extends AbstractView +{ + constructor(params) + { + super(params, "Game"); + this.game = new Game(client, params.id); + this.keys_pressed = []; + this.my_player = undefined; + this.gl = null; + this.shader_prog = null; + this.buffers = null; + this.cam_pos = [0, 1000, 0]; + this.cam_target = [0, 0, 0]; + } + + initGL() + { + const canvas = document.getElementById('glcanva'); + this.gl = canvas.getContext("webgl"); + + if(this.gl === null) + { + alert("Unable to initialize WebGL. Your browser or machine may not support it. You may also be a bozo"); + return; + } + + this.shader_prog = initShaderProgram(this.gl); + this.buffers = initBuffers(this.gl); + + this.gl.enable(this.gl.CULL_FACE); + this.gl.cullFace(this.gl.BACK); + } + + async join_game() + { + await this.game.join() + + let canvas = document.createElement("canvas"); + + canvas.height = this.game.config.size_x; + canvas.width = this.game.config.size_y; + canvas.id = "glcanva"; + + document.getElementById("app").appendChild(canvas); + + this.initGL(); + + this.render_game(); + } + + draw() + { + const canvas = document.getElementById('glcanva'); + if(canvas === null) + return 1; + + this.gl.clearColor(0.1, 0.1, 0.1, 1.0); + this.gl.clearDepth(1.0); + this.gl.enable(this.gl.DEPTH_TEST); + this.gl.depthFunc(this.gl.LEQUAL); + this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + + const projectionMatrix = mat4.create(); + const viewMatrix = mat4.create(); + + mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 10000000.0); + mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); + + this.setPositionAttribute(); + this.setNormalAttribute(); + + this.gl.useProgram(shaderInfos.program); + + this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix); + this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.viewMatrix, false, viewMatrix); + + this.game.render(this.gl); + } + + setNormalAttribute() + { + const numComponents = 3; + const type = this.gl.FLOAT; + const normalize = false; + const stride = 0; + const offset = 0; + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.normal); + this.gl.vertexAttribPointer( + shaderInfos.attribLocations.vertexNormal, + numComponents, + type, + normalize, + stride, + offset, + ); + this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexNormal); + } + + setPositionAttribute() + { + const numComponents = 3; + const type = this.gl.FLOAT; + const normalize = false; + const stride = 0; + const offset = 0; + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.vertex); + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.index); + this.gl.vertexAttribPointer( + shaderInfos.attribLocations.vertexPosition, + numComponents, + type, + normalize, + stride, + offset + ); + this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexPosition); + } + + render_game() + { + let loop_id = setInterval(() => { + if (this.game === undefined) + clearInterval(loop_id); + if (this.my_player) + this.my_player.update_paddle(this.keys_pressed); + this.draw(); + this.game?.time.new_frame(); + }, 1000 / 60); + } + + async update_game_state() + { + document.getElementById("game-state").innerText = this.game.state; + + if (this.game.finished === false) + await this.join_game(); + } + + async postInit() + { + let error_code = await this.game.init(); + + if (error_code) + return error_code; + + await this.update_game_state(); + } + + async getHtml() + { + return /* HTML */ ` + +

+
+ `; + } +} + diff --git a/frontend/static/js/3D/cube.js b/frontend/static/js/3D/cube.js index 3544d4f..8fc59fa 100644 --- a/frontend/static/js/3D/cube.js +++ b/frontend/static/js/3D/cube.js @@ -27,16 +27,8 @@ function renderCube(ctx, x, y, z, angle = 0, sx = 1, sy = 1, sz = 1) mat4.invert(normalMatrix, modelMatrix); mat4.transpose(normalMatrix, normalMatrix); - ctx.uniformMatrix4fv( - shaderInfos.uniformLocations.modelMatrix, - false, - modelMatrix - ); - ctx.uniformMatrix4fv( - shaderInfos.uniformLocations.normalMatrix, - false, - normalMatrix, - ); + ctx.uniformMatrix4fv(shaderInfos.uniformLocations.modelMatrix, false, modelMatrix); + ctx.uniformMatrix4fv(shaderInfos.uniformLocations.normalMatrix, false, normalMatrix); ctx.drawElements(ctx.TRIANGLES, 36, ctx.UNSIGNED_SHORT, 0); } diff --git a/frontend/static/js/api/game/Ball.js b/frontend/static/js/api/game/Ball.js index 6a0603e..6c0d4d7 100644 --- a/frontend/static/js/api/game/Ball.js +++ b/frontend/static/js/api/game/Ball.js @@ -1,6 +1,6 @@ import { Game } from "./Game.js"; import { Point } from "./Point.js"; - +import { renderCube } from "../../3D/cube.js" class Ball { @@ -46,7 +46,19 @@ class Ball */ draw(ctx) { - ctx.rect(this.position.x - this.size / 2, this.position.y - this.size / 2, this.size, this.size); + if(ctx instanceof CanvasRenderingContext2D) + { + ctx.rect(this.position.x - this.size / 2, this.position.y - this.size / 2, this.size, this.size); + } + else if(ctx instanceof WebGLRenderingContext) + { + console.log((this.position.x - this.size / 2) / 10, 0, (this.position.y - this.size / 2) / 10) + renderCube(ctx, (this.position.x - this.size / 2) / 10, 0, (this.position.y - this.size / 2) / 10, 0, this.size * 10, this.size * 10, this.size * 10); + } + else + { + alert('Unknown rendering context type'); + } } /** diff --git a/frontend/static/js/api/game/Player.js b/frontend/static/js/api/game/Player.js index 1802d48..b6b96b3 100644 --- a/frontend/static/js/api/game/Player.js +++ b/frontend/static/js/api/game/Player.js @@ -1,6 +1,7 @@ import { Game } from "./Game.js"; import { Point } from "./Point.js"; import { Segment } from "./Segment.js"; +import { renderCube } from "../../3D/cube.js" class Player { @@ -61,8 +62,11 @@ class Player { if (this.is_connected === false) { - ctx.moveTo(this.rail.start.x, this.rail.start.y); - ctx.lineTo(this.rail.stop.x, this.rail.stop.y); + if(ctx instanceof CanvasRenderingContext2D) + { + ctx.moveTo(this.rail.start.x, this.rail.start.y); + ctx.lineTo(this.rail.stop.x, this.rail.stop.y); + } return; } diff --git a/frontend/static/js/views/GameView3D.js b/frontend/static/js/views/GameView3D.js index 4585d5e..cfdbb8e 100644 --- a/frontend/static/js/views/GameView3D.js +++ b/frontend/static/js/views/GameView3D.js @@ -17,8 +17,8 @@ export default class extends AbstractView this.gl = null; this.shader_prog = null; this.buffers = null; - this.cam_pos = [0, 100, 0]; - this.cam_target = [4, 0, 4]; + this.cam_pos = [0, 500, 0]; + this.cam_target = [0, 0, 35]; } initGL() @@ -71,7 +71,7 @@ export default class extends AbstractView const projectionMatrix = mat4.create(); const viewMatrix = mat4.create(); - mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 1000.0); + mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 10000000.0); mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); this.setPositionAttribute(); @@ -82,7 +82,7 @@ export default class extends AbstractView this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix); this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.viewMatrix, false, viewMatrix); - this.game.draw(this.gl); + this.game.render(this.gl); } setNormalAttribute() From de2488589cf0a579b849e706b40901c355ff35f8 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 21 Feb 2024 16:34:50 +0100 Subject: [PATCH 13/13] adding game mode button to matchmaking view --- "\\" | 166 -------------------- frontend/static/js/index.js | 7 +- frontend/static/js/views/MatchMakingView.js | 21 ++- 3 files changed, 23 insertions(+), 171 deletions(-) delete mode 100644 "\\" diff --git "a/\\" "b/\\" deleted file mode 100644 index d03060c..0000000 --- "a/\\" +++ /dev/null @@ -1,166 +0,0 @@ -import { client } from "../index.js"; -import { Game } from "../api/game/Game.js"; -import AbstractView from "./abstracts/AbstractView.js"; -import { initShaderProgram, shaderInfos } from "../3D/shaders.js" -import { initBuffers } from "../3D/buffers.js" -import "../3D/maths/gl-matrix-min.js" -import { renderCube } from "../3D/cube.js" - -export default class extends AbstractView -{ - constructor(params) - { - super(params, "Game"); - this.game = new Game(client, params.id); - this.keys_pressed = []; - this.my_player = undefined; - this.gl = null; - this.shader_prog = null; - this.buffers = null; - this.cam_pos = [0, 1000, 0]; - this.cam_target = [0, 0, 0]; - } - - initGL() - { - const canvas = document.getElementById('glcanva'); - this.gl = canvas.getContext("webgl"); - - if(this.gl === null) - { - alert("Unable to initialize WebGL. Your browser or machine may not support it. You may also be a bozo"); - return; - } - - this.shader_prog = initShaderProgram(this.gl); - this.buffers = initBuffers(this.gl); - - this.gl.enable(this.gl.CULL_FACE); - this.gl.cullFace(this.gl.BACK); - } - - async join_game() - { - await this.game.join() - - let canvas = document.createElement("canvas"); - - canvas.height = this.game.config.size_x; - canvas.width = this.game.config.size_y; - canvas.id = "glcanva"; - - document.getElementById("app").appendChild(canvas); - - this.initGL(); - - this.render_game(); - } - - draw() - { - const canvas = document.getElementById('glcanva'); - if(canvas === null) - return 1; - - this.gl.clearColor(0.1, 0.1, 0.1, 1.0); - this.gl.clearDepth(1.0); - this.gl.enable(this.gl.DEPTH_TEST); - this.gl.depthFunc(this.gl.LEQUAL); - this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); - - const projectionMatrix = mat4.create(); - const viewMatrix = mat4.create(); - - mat4.perspective(projectionMatrix, (90 * Math.PI) / 180, this.gl.canvas.clientWidth / this.gl.canvas.clientHeight, 0.1, 10000000.0); - mat4.lookAt(viewMatrix, this.cam_pos, this.cam_target, [0, 1, 0]); - - this.setPositionAttribute(); - this.setNormalAttribute(); - - this.gl.useProgram(shaderInfos.program); - - this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.projectionMatrix, false, projectionMatrix); - this.gl.uniformMatrix4fv(shaderInfos.uniformLocations.viewMatrix, false, viewMatrix); - - this.game.render(this.gl); - } - - setNormalAttribute() - { - const numComponents = 3; - const type = this.gl.FLOAT; - const normalize = false; - const stride = 0; - const offset = 0; - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.normal); - this.gl.vertexAttribPointer( - shaderInfos.attribLocations.vertexNormal, - numComponents, - type, - normalize, - stride, - offset, - ); - this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexNormal); - } - - setPositionAttribute() - { - const numComponents = 3; - const type = this.gl.FLOAT; - const normalize = false; - const stride = 0; - const offset = 0; - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.vertex); - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.index); - this.gl.vertexAttribPointer( - shaderInfos.attribLocations.vertexPosition, - numComponents, - type, - normalize, - stride, - offset - ); - this.gl.enableVertexAttribArray(shaderInfos.attribLocations.vertexPosition); - } - - render_game() - { - let loop_id = setInterval(() => { - if (this.game === undefined) - clearInterval(loop_id); - if (this.my_player) - this.my_player.update_paddle(this.keys_pressed); - this.draw(); - this.game?.time.new_frame(); - }, 1000 / 60); - } - - async update_game_state() - { - document.getElementById("game-state").innerText = this.game.state; - - if (this.game.finished === false) - await this.join_game(); - } - - async postInit() - { - let error_code = await this.game.init(); - - if (error_code) - return error_code; - - await this.update_game_state(); - } - - async getHtml() - { - return /* HTML */ ` - -

-
- `; - } -} - diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index 58cbaa8..98125af 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -5,8 +5,8 @@ import Search from "./views/Search.js"; import HomeView from "./views/HomeView.js"; import LogoutView from "./views/accounts/LogoutView.js"; import GameOfflineView from "./views/GameOfflineView.js"; -//import GameView from "./views/GameView.js"; -import GameView from "./views/GameView3D.js"; +import GameView2D from "./views/GameView.js"; +import GameView3D from "./views/GameView3D.js"; import PageNotFoundView from './views/PageNotFoundView.js' @@ -88,7 +88,8 @@ const router = async(uri) => { { path: "/settings", view: SettingsView }, { path: "/matchmaking", view: MatchMakingView }, { path: "/games/offline", view: GameOfflineView }, - { path: "/games/:id", view: GameView }, + { path: "/games/0/:id", view: GameView2D }, + { path: "/games/1/:id", view: GameView3D }, ]; // Test each route for potential match diff --git a/frontend/static/js/views/MatchMakingView.js b/frontend/static/js/views/MatchMakingView.js index 0414fa2..f0d3547 100644 --- a/frontend/static/js/views/MatchMakingView.js +++ b/frontend/static/js/views/MatchMakingView.js @@ -5,7 +5,8 @@ import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js" export default class extends AbstractAuthenticatedView { constructor(params) { - super(params, "Matchmaking"); + super(params, "Matchmaking"); + this.game_mode = 0; // 0 -> 2D; 1 -> 3D } async press_button() @@ -25,6 +26,20 @@ export default class extends AbstractAuthenticatedView { } } + async press_button_game_mode() + { + if(this.game_mode === 0) + { + document.getElementById("game-mode").value = "3D"; + this.game_mode = 1; + } + else + { + document.getElementById("game-mode").value = "2D"; + this.game_mode = 0; + } + } + ondisconnect(event) { if (event.code === 1000) @@ -36,7 +51,7 @@ export default class extends AbstractAuthenticatedView { { if (data.detail === "game_found") { - navigateTo(`/games/${data.game_id}`); + navigateTo(`/games/${this.game_mode}/${data.game_id}`); return; } this.display_data(data) @@ -51,6 +66,7 @@ export default class extends AbstractAuthenticatedView { async postInit() { document.getElementById("button").onclick = this.press_button.bind(this) + document.getElementById("game-mode").onclick = this.press_button_game_mode.bind(this) } async getHtml() { @@ -58,6 +74,7 @@ export default class extends AbstractAuthenticatedView {

Select mode

+ `; }