/*
* Copyright 2021 Markus Heimerl, OTH Regensburg
* Licensed under CC BY-NC 4.0
*
* ANY USE OF THIS SOFTWARE MUST COMPLY WITH THE
* CREATIVE COMMONS ATTRIBUTION-NONCOMMERCIAL 4.0 INTERNATIONAL LICENSE
* AGREEMENTS
*/
const m4 = {
degreeToRadians: function(angle){return angle * Math.PI / 180;},
mult: function (mat4_a, mat4_b){
return [mat4_a[0] * mat4_b[0] + mat4_a[1] * mat4_b[4] + mat4_a[2] * mat4_b[8] + mat4_a[3] * mat4_b[12],
mat4_a[0] * mat4_b[1] + mat4_a[1] * mat4_b[5] + mat4_a[2] * mat4_b[9] + mat4_a[3] * mat4_b[13],
mat4_a[0] * mat4_b[2] + mat4_a[1] * mat4_b[6] + mat4_a[2] * mat4_b[10] + mat4_a[3] * mat4_b[14],
mat4_a[0] * mat4_b[3] + mat4_a[1] * mat4_b[7] + mat4_a[2] * mat4_b[11] + mat4_a[3] * mat4_b[15],
mat4_a[4] * mat4_b[0] + mat4_a[5] * mat4_b[4] + mat4_a[6] * mat4_b[8] + mat4_a[7] * mat4_b[12],
mat4_a[4] * mat4_b[1] + mat4_a[5] * mat4_b[5] + mat4_a[6] * mat4_b[9] + mat4_a[7] * mat4_b[13],
mat4_a[4] * mat4_b[2] + mat4_a[5] * mat4_b[6] + mat4_a[6] * mat4_b[10] + mat4_a[7] * mat4_b[14],
mat4_a[4] * mat4_b[3] + mat4_a[5] * mat4_b[7] + mat4_a[6] * mat4_b[11] + mat4_a[7] * mat4_b[15],
mat4_a[8] * mat4_b[0] + mat4_a[9] * mat4_b[4] + mat4_a[10] * mat4_b[8] + mat4_a[11] * mat4_b[12],
mat4_a[8] * mat4_b[1] + mat4_a[9] * mat4_b[5] + mat4_a[10] * mat4_b[9] + mat4_a[11] * mat4_b[13],
mat4_a[8] * mat4_b[2] + mat4_a[9] * mat4_b[6] + mat4_a[10] * mat4_b[10] + mat4_a[11] * mat4_b[14],
mat4_a[8] * mat4_b[3] + mat4_a[9] * mat4_b[7] + mat4_a[10] * mat4_b[11] + mat4_a[11] * mat4_b[15],
mat4_a[12] * mat4_b[0] + mat4_a[13] * mat4_b[4] + mat4_a[14] * mat4_b[8] + mat4_a[15] * mat4_b[12],
mat4_a[12] * mat4_b[1] + mat4_a[13] * mat4_b[5] + mat4_a[14] * mat4_b[9] + mat4_a[15] * mat4_b[13],
mat4_a[12] * mat4_b[2] + mat4_a[13] * mat4_b[6] + mat4_a[14] * mat4_b[10] + mat4_a[15] * mat4_b[14],
mat4_a[12] * mat4_b[3] + mat4_a[13] * mat4_b[7] + mat4_a[14] * mat4_b[11] + mat4_a[15] * mat4_b[15]];
},
createIdentityMatrix: function(){
return [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0];
},
createTranslationMatrix: function(transx, transy, transz){
return [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
transx, transy, transz, 1.0];
},
createXRotationMatrix: function(angleInRadians){
var s = Math.sin(angleInRadians);
var c = Math.cos(angleInRadians);
return [1.0, 0.0, 0.0, 0.0,
0.0, c, s, 0.0,
0.0, -s, c, 0.0,
0.0, 0.0, 0.0, 1.0];
},
createYRotationMatrix: function(angleInRadians){
var s = Math.sin(angleInRadians);
var c = Math.cos(angleInRadians);
return [ c, 0.0, -s, 0.0,
0.0, 1.0, 0.0, 0.0,
s, 0.0, c, 0.0,
0.0, 0.0, 0.0, 1.0];
},
createZRotationMatrix: function(angleInRadians){
var s = Math.sin(angleInRadians);
var c = Math.cos(angleInRadians);
return [ c, s, 0.0, 0.0,
-s, c, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0];
},
createScaleMatrix: function(scalex, scaley, scalez){
return [scalex, 0.0, 0.0, 0.0,
0.0, scaley, 0.0, 0.0,
0.0, 0.0, scalez, 0.0,
0.0, 0.0, 0.0, 1.0];
},
createOrthographicMatrix: function(left, right, bottom, top, near, far){
return [2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, 2 / (near - far), 0,
(left + right) / (left - right), (bottom + top) / (bottom + top), (near + far) / (near - far), 1];
},
createSimpleProjectionMatrix: function(width, height, depth){
return [ (2/width), 0.0, 0.0, 0.0,
0.0, (-2/height), 0.0, 0.0,
0.0, 0.0, (2/depth), 0.0,
-1.0, 1.0, 0.0, 1.0];
},
createPerspectiveMatrix: function(fovInRadians, aspect, near, far){
var f = Math.tan(Math.PI * 0.5 - 0.5 * fovInRadians);
var rangeInv = 1.0 / (near - far);
return [ f/aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, (near + far) * rangeInv, -1,
0, 0, near * far * rangeInv * 2, 0
];
},
// leibnitz forumlar: InvA = 1/det(A) * Aadj
inverse: function(m) {
var m00 = m[0 * 4 + 0];
var m01 = m[0 * 4 + 1];
var m02 = m[0 * 4 + 2];
var m03 = m[0 * 4 + 3];
var m10 = m[1 * 4 + 0];
var m11 = m[1 * 4 + 1];
var m12 = m[1 * 4 + 2];
var m13 = m[1 * 4 + 3];
var m20 = m[2 * 4 + 0];
var m21 = m[2 * 4 + 1];
var m22 = m[2 * 4 + 2];
var m23 = m[2 * 4 + 3];
var m30 = m[3 * 4 + 0];
var m31 = m[3 * 4 + 1];
var m32 = m[3 * 4 + 2];
var m33 = m[3 * 4 + 3];
var tmp_0 = m22 * m33;
var tmp_1 = m32 * m23;
var tmp_2 = m12 * m33;
var tmp_3 = m32 * m13;
var tmp_4 = m12 * m23;
var tmp_5 = m22 * m13;
var tmp_6 = m02 * m33;
var tmp_7 = m32 * m03;
var tmp_8 = m02 * m23;
var tmp_9 = m22 * m03;
var tmp_10 = m02 * m13;
var tmp_11 = m12 * m03;
var tmp_12 = m20 * m31;
var tmp_13 = m30 * m21;
var tmp_14 = m10 * m31;
var tmp_15 = m30 * m11;
var tmp_16 = m10 * m21;
var tmp_17 = m20 * m11;
var tmp_18 = m00 * m31;
var tmp_19 = m30 * m01;
var tmp_20 = m00 * m21;
var tmp_21 = m20 * m01;
var tmp_22 = m00 * m11;
var tmp_23 = m10 * m01;
var t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -
(tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);
var t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -
(tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);
var t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -
(tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);
var t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -
(tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);
var d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);
return [
d * t0,
d * t1,
d * t2,
d * t3,
d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -
(tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),
d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -
(tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),
d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -
(tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),
d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -
(tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),
d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -
(tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),
d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -
(tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),
d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -
(tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),
d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -
(tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),
d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -
(tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),
d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -
(tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),
d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -
(tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),
d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -
(tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02))
];
},
transpose: function(m){
return [ m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15]
];
},
cross: function(a, b) {
return [a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]];
},
subtractVectors: function(a, b) {
return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
},
normalize: function(v) {
var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if (length > 0.000001) {
return [v[0] / length, v[1] / length, v[2] / length];
} else {
return [0, 0, 0];
}
},
lookAt: function(cameraPosition, target, up) {
var zAxis = m4.normalize(m4.subtractVectors(cameraPosition, target));
var xAxis = m4.normalize(m4.cross(up, zAxis));
var yAxis = m4.normalize(m4.cross(zAxis, xAxis));
return [
xAxis[0], xAxis[1], xAxis[2], 0,
yAxis[0], yAxis[1], yAxis[2], 0,
zAxis[0], zAxis[1], zAxis[2], 0,
cameraPosition[0],
cameraPosition[1],
cameraPosition[2],
1,
];
}
};
const parentr3webgl = {
createProgram: function(vertexshader, fragmentshader){
var gl = this.gl;
var program = gl.createProgram();
gl.attachShader(program, vertexshader);
gl.attachShader(program, fragmentshader);
gl.linkProgram(program);
if(gl.getProgramParameter(program, gl.LINK_STATUS)){return program;}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
},
compileShader: function(type, source){
var gl = this.gl;
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){return shader;}
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
},
createShaderProgram: function(vertexshadersource, fragmentshadersource){
var gl = this.gl;
return this.createProgram(this.compileShader(gl.VERTEX_SHADER, vertexshadersource),
this.compileShader(gl.FRAGMENT_SHADER, fragmentshadersource));
},
getAttribLocations: function(program, names){
var attriblocations = {};
for(var i = 0; i < names.length; i++){attriblocations[names[i]]=this.gl.getAttribLocation(program, names[i]);}
return attriblocations; }, getUniformLocations: function(program, names){ var uniformlocations={}; for(var i=0;
i < names.length; i++){uniformlocations[names[i]]=this.gl.getUniformLocation(program, names[i]);} return
uniformlocations; }, init3D: function(){ var gl=this.gl; gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST); }, createModelMatrix: function(tx, ty, tz, rx, ry ,rz, sx, sy, sz){ var
modelmatrix=m4.createIdentityMatrix(); modelmatrix=m4.mult(m4.createTranslationMatrix(tx, ty, tz), modelmatrix);
modelmatrix=m4.mult(m4.createXRotationMatrix(m4.degreeToRadians(rx)), modelmatrix);
modelmatrix=m4.mult(m4.createYRotationMatrix(m4.degreeToRadians(ry)), modelmatrix);
modelmatrix=m4.mult(m4.createZRotationMatrix(m4.degreeToRadians(rz)), modelmatrix);
modelmatrix=m4.mult(m4.createScaleMatrix(sx, sy, sz), modelmatrix); return modelmatrix; }, createBuffer:
function(type, data){ var gl=this.gl; var buffer=gl.createBuffer(); gl.bindBuffer(type, buffer);
gl.bufferData(type, new Float32Array(data), gl.STATIC_DRAW); return buffer; }, connectBufferToAttribute:
function(type, buffer, attriblocation, valuespervertex, enable){ var gl=this.gl; if(enable)
gl.enableVertexAttribArray(attriblocation); gl.bindBuffer(type, buffer); gl.vertexAttribPointer(attriblocation,
valuespervertex, gl.FLOAT, false, 0, 0); }, createTexture: function(dim){ dim=dim ? dim : {x: 1, y: 1}; var
gl=this.gl; var texture=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D,
0, gl.RGBA, dim.x, dim.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); return texture; }, createRandomNoiseTexture:
function(dim){ var gl=this.gl; var tex=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); var data=[];
for(var i=0; i < gl.canvas.width*gl.canvas.height; i++){var col=Math.round(Math.random()*Math.random())*255;
data.push(col, col, col);} gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, dim.x, dim.y, 0, gl.RGB, gl.UNSIGNED_BYTE,
new Uint8Array(data)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); return tex; }, attachTextureSourceAsync:
function(texture, source, flipVertically){ var gl=this.gl; var image=new Image(); image.src=source;
image.addEventListener("load", function(){ if(flipVertically){ var canvas=document.createElement("canvas");
canvas.width=image.width; canvas.height=image.height; canvas.getContext("2d").scale(1, -1);
canvas.getContext("2d").drawImage(image, 0, image.height*-1); var flipImage=new Image();
flipImage.src=canvas.toDataURL("image/png"); flipImage.addEventListener("load", function(){
addTexture(flipImage); }); }else{ addTexture(image); } }); function addTexture(img){
gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
img); gl.generateMipmap(gl.TEXTURE_2D); } } };