Files
grin-web-wallet/scripts/logo.js
2024-12-20 18:08:44 -08:00

1932 lines
58 KiB
JavaScript
Executable File

// Use strict
"use strict";
// Classes
// Logo class
class Logo {
// Public
// Constructor
constructor(application, message, wakeLock) {
// Set application
this.application = application;
// Set message
this.message = message;
// Get main display
this.mainDisplay = $("main");
// Get logo display
this.logoDisplay = this.mainDisplay.children().children("div.logo");
// Get canvas
this.canvas = this.logoDisplay.children().get(0);
// Set closing
this.closing = false;
// Set frame duration
this.frameDuration = 0;
// Set frame duration variation
this.frameDurationVariation = 0;
// Set shader program
this.shaderProgram = Logo.NO_SHADER_PROGRAM;
// Set buffers
this.buffers = [];
// Set textures
this.textures = [];
// Set can show
this.canShow = false;
// Set loaded
this.loaded = false;
// Set compatible
this.compatible = true;
// Set first time show
this.firstTimeShow = true;
// Set context lost
this.contextLost = false;
// Set position
this.position = Logo.INITIAL_POSITION;
// Set orientation
this.orientation = Logo.INITIAL_ORIENTATION;
// Set velocity X
this.velocityX = 0;
// Set velocity Y
this.velocityY = 0;
// Set restore context frame
this.restoreContextFrame = Logo.NO_RESTORE_CONTEXT_FRAME;
// Set close timeout
this.closeTimeout = Logo.NO_CLOSE_TIMEOUT;
// Set start recording rotation
this.startRecordingRotation = false;
// Set recorded rotation
this.recordedRotation = 0;
// Set Tetris
this.tetris = new Tetris(this.application, this.message, wakeLock);
// Set self
var self = this;
// Get WebGL context
this.gl = this.canvas.getContext("webgl", {
// Alpha
"alpha": true,
// Antialiad
"antialias": true,
// Depth
"depth": true,
// Power preference
"powerPreference": "default",
// Stencil
"stencil": false
});
// Check if WebGL isn't supported
if(this.gl === Logo.NO_WEBGL)
// Get experimental WebGL context
this.gl = this.canvas.getContext("experimental-webgl", {
// Alpha
"alpha": true,
// Antialias
"antialias": true,
// Depth
"depth": true,
// Power preference
"powerPreference": "default",
// Stencil
"stencil": false
});
// Check if WebGL is supported
if(this.gl !== Logo.NO_WEBGL) {
// Window unload event
$(window).on("unload", function() {
// Close and don't hide the logo
self.close(false);
});
// Update canvas size
this.updateCanvasSize();
// Get WEBGL lose context extension
var webglLoseContext = self.gl.getExtension("WEBGL_lose_context");
// Canvas WebGL context lost event
$(this.canvas).on("webglcontextlost", function(event) {
// Set context lost
self.contextLost = true;
// Check if not closing
if(self.closing === false) {
// Check if getting WEBGL lose context extension was successful
if(webglLoseContext !== Logo.NO_WEBGL_EXTENSION) {
// Prevent default
event.preventDefault();
// Set restore context frame
self.restoreContextFrame = requestAnimationFrame(function() {
// Set restore context frame to no restore context frame
self.restoreContextFrame = Logo.NO_RESTORE_CONTEXT_FRAME;
// Set close timeout
self.closeTimeout = setTimeout(function() {
// Set close timeout to no close timeout
self.closeTimeout = Logo.NO_CLOSE_TIMEOUT;
// Close
self.close();
}, Logo.CLOSE_IF_NOT_RESTORED_MILLISECONDS);
// Check if context is lost
if(self.gl.isContextLost() === true) {
// Restore context
webglLoseContext.restoreContext();
}
});
}
// Otherwise
else {
// Close
self.close();
}
}
// Canvas WebGL context restored event
}).on("webglcontextrestored", function() {
// Check if restore context frame exists
if(self.restoreContextFrame !== Logo.NO_RESTORE_CONTEXT_FRAME) {
// Cancel restore context frame
cancelAnimationFrame(self.restoreContextFrame);
// Set restore context frame to no restore context frame
self.restoreContextFrame = Logo.NO_RESTORE_CONTEXT_FRAME;
}
// Check if close timeout exists
if(self.closeTimeout !== Logo.NO_CLOSE_TIMEOUT) {
// Clear close timeout
clearTimeout(self.closeTimeout);
// Set close timeout to no close timeout
self.closeTimeout = Logo.NO_CLOSE_TIMEOUT;
}
// Check if not closing
if(self.closing === false) {
// Cleanup
self.cleanUp();
// Initialize
self.initialize(self.canvas["width"], self.canvas["height"]).then(function() {
// Clear context lost
self.contextLost = false;
// Update size
self.updateSize();
// Draw
self.draw();
// Catch errors
}).catch(function(error) {
// Clear context lost
self.contextLost = false;
// Close
self.close();
});
}
});
// Initialize
this.initialize(this.canvas["width"], this.canvas["height"]).then(function() {
// Run
self.run();
// Window resize event
$(window).on("resize", function() {
// Update size
self.updateSize();
// Draw
self.draw();
});
// Update size
self.updateSize();
// Draw
self.draw();
// Set last pointer state
self.lastPointerState = Logo.NO_POINTER_STATE;
// Document pointer move and mouse move logo event
$(document).on("pointermove mousemove.logo", function(event) {
// Check if event is a pointer move
if(event["type"] === "pointermove")
// Turn off document mouse move logo event
$(document).off("mousemove.logo");
// Check if not closing
if(self.closing === false) {
// Check if event's coordinates are within the screen
if(event["pageX"] < self.mainDisplay.width() && event["pageY"] < self.mainDisplay.height()) {
// Get current timestamp
var currentTimestamp = Date.now();
// Check if logo is showing, message isn't showing, and Tetris isn't showing
if(self.logoDisplay.hasClass("notLoaded") === false && self.logoDisplay.hasClass("hide") === false && self.mainDisplay.hasClass("logo") === true && self.logoDisplay.is(":visible") === true && self.message.isShown() === false && self.tetris.isShown() === false) {
// Check if primary pointer button is pressed
if((event["buttons"] & Common.PRIMARY_POINTER_BUTTON_BITMASK) !== 0) {
// Set start recording rotation
self.startRecordingRotation = true;
// Check if last pointer state exists
if(self.lastPointerState !== Logo.NO_POINTER_STATE) {
// Get timestamp change of pointer movement
var timestampChange = (currentTimestamp - self.lastPointerState["Timestamp"]) / Common.MILLISECONDS_IN_A_SECOND;
// Check if timestamp change isn't zero
if(timestampChange !== 0) {
// Get percent of where pointer was is in the canvas
var oldPercentX = (self.lastPointerState["Position X"] - $(self.canvas).offset()["left"]) / $(self.canvas).width();
var oldPercentY = (self.lastPointerState["Position Y"] - $(self.canvas).offset()["top"]) / $(self.canvas).height();
// Get percent of where pointer currently is in the canvas
var newPercentX = (event["pageX"] - $(self.canvas).offset()["left"]) / $(self.canvas).width();
var newPercentY = (event["pageY"] - $(self.canvas).offset()["top"]) / $(self.canvas).height();
// Get minimum and maximum percents in the X axis
if(oldPercentX <= newPercentX) {
var minimumPercentX = oldPercentX;
var maximumPercentX = newPercentX;
}
else {
var minimumPercentX = newPercentX;
var maximumPercentX = oldPercentX;
}
// Get minimum and maximum percents in the Y axis
if(oldPercentY <= newPercentY) {
var minimumPercentY = oldPercentY;
var maximumPercentY = newPercentY;
}
else {
var minimumPercentY = newPercentY;
var maximumPercentY = oldPercentY;
}
// Check if pointer moved over the logo
if(Logo.boundingBoxesCollide(minimumPercentX, minimumPercentY, maximumPercentX, maximumPercentY, Logo.LOGO_PERCENT_SIZE["Minimum X"], Logo.LOGO_PERCENT_SIZE["Minimum Y"], Logo.LOGO_PERCENT_SIZE["Maximum X"], Logo.LOGO_PERCENT_SIZE["Maximum Y"]) === true) {
// Get pointer distances
var distanceX = (event["pageX"] - self.lastPointerState["Position X"]) / $(document).width() * Logo.DISTANCE_RATIO_TO_SCREEN_WIDTH;
var distanceY = (event["pageY"] - self.lastPointerState["Position Y"]) / $(document).height() * Logo.DISTANCE_RATIO_TO_SCREEN_HEIGHT;
// Set pointer velocities
self.velocityX = distanceX / timestampChange * Logo.POINTER_VELOCITY_SCALE_FACTOR;
self.velocityY = distanceY / timestampChange * Logo.POINTER_VELOCITY_SCALE_FACTOR;
}
}
}
}
}
// Update last pointer state
self.lastPointerState = {
// Timestamp
"Timestamp": currentTimestamp,
// Position X
"Position X": event["pageX"],
// Position Y
"Position Y": event["pageY"]
};
}
}
});
// Set loaded
self.loaded = true;
// Set that logo display is loaded
self.logoDisplay.removeClass("notLoaded");
// Catch errors
}).catch(function(error) {
// Close
self.close();
});
}
// Otherwise
else {
// Close
self.close();
}
}
// Show
show() {
// Set self
var self = this;
// Set timeout
setTimeout(function() {
// Set can show
self.canShow = true;
}, Logo.INITIAL_SHOW_DELAY_MILLISECONDS);
// Show logo display
this.logoDisplay.removeClass("hide");
// Logo display transition end or timeout event
this.logoDisplay.transitionEndOrTimeout(function() {
// Set logo display to transition at the correct speed
self.logoDisplay.addClass("normalTransitionSpeed");
}, "opacity");
}
// Hide
hide() {
// Hide logo display
this.logoDisplay.addClass("hide");
}
// Allow showing
allowShowing() {
// Check if compatible
if(this.compatible === true)
// Allow main display to show logo
this.mainDisplay.addClass("logo");
}
// Private
// Update size
updateSize() {
// Update canvas size
this.updateCanvasSize();
// Update last dimensions
this.lastWidth = window["innerWidth"];
this.lastHeight = window["innerHeight"];
// Resize
this.resize(this.canvas["width"], this.canvas["height"]);
}
// Prevent showing
preventShowing() {
// Clear compatible
this.compatible = false;
// Don't allow main display to show logo
this.mainDisplay.removeClass("logo");
}
// Update canvas size
updateCanvasSize() {
// Update canvas size
this.canvas["width"] = this.canvas["clientWidth"];
this.canvas["height"] = this.canvas["clientHeight"];
}
// Initialize
initialize(width, height) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Set matrix array type
glMatrix["glMatrix"].setMatrixArrayType(Array);
// Check if getting EXT texture filter anisotropic extension was successful
var extTextureFilterAnisotropic = self.gl.getExtension("EXT_texture_filter_anisotropic");
if(extTextureFilterAnisotropic !== Logo.NO_WEBGL_EXTENSION) {
// Add anisotropic constants
self.gl["constructor"]["prototype"]["MAX_TEXTURE_MAX_ANISOTROPY_EXT"] = extTextureFilterAnisotropic["MAX_TEXTURE_MAX_ANISOTROPY_EXT"];
self.gl["constructor"]["prototype"]["TEXTURE_MAX_ANISOTROPY_EXT"] = extTextureFilterAnisotropic["TEXTURE_MAX_ANISOTROPY_EXT"];
}
// Set anisotropy
self.anisotropy = Logo.DEFAULT_ANISOTROPY;
// Get max anisotropy
if(typeof self.gl["MAX_TEXTURE_MAX_ANISOTROPY_EXT"] !== "undefined")
self.anisotropy = self.gl.getParameter(self.gl["MAX_TEXTURE_MAX_ANISOTROPY_EXT"]);
// Limit anisotropy
self.anisotropy = Math.min(self.anisotropy, Logo.MAX_ANISOTROPY);
// Set viewport size
self.gl.viewport(0, 0, width, height);
// Enable back face culling
self.gl.enable(self.gl["CULL_FACE"]);
self.gl.cullFace(self.gl["BACK"]);
self.gl.frontFace(self.gl["CCW"]);
// Enable depth testing
self.gl.enable(self.gl["DEPTH_TEST"]);
// Use closer fragments from depth test
self.gl.depthFunc(self.gl["LESS"]);
// Enabe writing to depth buffer
self.gl.depthMask(true);
// Enable alpha blending
self.gl.enable(self.gl["BLEND"]);
self.gl.blendFunc(self.gl["SRC_ALPHA"], self.gl["ONE_MINUS_SRC_ALPHA"]);
// Set clear color
self.gl.clearColor(0, 0, 0, 0);
// Load vertex shader source, fragment shader source, and model
Promise.all([$.ajax({
// URL
"url": "." + getResource(Logo.VERTEX_SHADER_FILE_LOCATION),
// Data type
"dataType": "text"
}), $.ajax({
// URL
"url": "." + getResource(Logo.FRAGMENT_SHADER_FILE_LOCATION),
// Data type
"dataType": "text"
}), $.getJSON("." + getResource(Logo.MODEL_FILE_LOCATION))]).then(function(resources) {
// Check if closing
if(self.closing === true) {
// Reject
reject();
// Return
return;
}
// Get vertex shader source
var vertexShaderSource = resources[0];
// Create vertex shader
var vertexShader = self.gl.createShader(self.gl["VERTEX_SHADER"]);
// Prepend constants to vertex shader source
vertexShaderSource = Logo.SHADER_CONSTANTS + "\n" + vertexShaderSource;
// Compile vertex shader
self.gl.shaderSource(vertexShader, vertexShaderSource);
self.gl.compileShader(vertexShader);
// Check if compiling vertex shader failed
if(self.gl.getShaderParameter(vertexShader, self.gl["COMPILE_STATUS"]) === false) {
// Delete vertex shader
self.gl.deleteShader(vertexShader);
// Reject error
reject("Compiling vertex shader failed.");
// Return
return;
}
// Get fragment shader source
var fragmentShaderSource = resources[1];
// Create fragment shader
var fragmentShader = self.gl.createShader(self.gl["FRAGMENT_SHADER"]);
// Prepend constants to fragment shader source
fragmentShaderSource = Logo.SHADER_CONSTANTS + "\n" + fragmentShaderSource;
// Compile fragment shader
self.gl.shaderSource(fragmentShader, fragmentShaderSource);
self.gl.compileShader(fragmentShader);
// Check if compiling fragment shader failed
if(self.gl.getShaderParameter(fragmentShader, self.gl["COMPILE_STATUS"]) === false) {
// Delete vertex shader
self.gl.deleteShader(vertexShader);
// Delete fragment shader
self.gl.deleteShader(fragmentShader);
// Reject error
reject("Compiling fragment shader failed.");
// Return
return;
}
// Create shader program
self.shaderProgram = self.gl.createProgram();
// Attach vertex shader to shader program
self.gl.attachShader(self.shaderProgram, vertexShader);
// Attach fragment shader to shader program
self.gl.attachShader(self.shaderProgram, fragmentShader);
// Link shader program
self.gl.linkProgram(self.shaderProgram);
// Check if linking shader program failed
if(self.gl.getProgramParameter(self.shaderProgram, self.gl["LINK_STATUS"]) === false) {
// Delete vertex shader
self.gl.deleteShader(vertexShader);
// Delete fragment shader
self.gl.deleteShader(fragmentShader);
// Reject error
reject("Linking shader program failed.");
// Return
return;
}
// Delete vertex shader
self.gl.deleteShader(vertexShader);
// Delete fragment shader
self.gl.deleteShader(fragmentShader);
// Use shader program
self.gl.useProgram(self.shaderProgram);
// Get model
var model = resources[2];
// Create index buffer
var indexBuffer = self.gl.createBuffer();
// Append index buffer to list of buffers
self.buffers.push(indexBuffer);
// Bind index buffer
self.gl.bindBuffer(self.gl["ELEMENT_ARRAY_BUFFER"], indexBuffer);
// Move data into index buffer
self.gl.bufferData(self.gl["ELEMENT_ARRAY_BUFFER"], new Uint16Array(model["Textured Models"][0]["Indices"]), self.gl["STATIC_DRAW"]);
// Create positions buffer
var positionsBuffer = self.gl.createBuffer();
// Append positions buffer to list of buffers
self.buffers.push(positionsBuffer);
// Bind positions buffer
self.gl.bindBuffer(self.gl["ARRAY_BUFFER"], positionsBuffer);
// Move data into positions buffer
self.gl.bufferData(self.gl["ARRAY_BUFFER"], new Float32Array(model["Textured Models"][0]["Positions"]), self.gl["STATIC_DRAW"]);
// Get position attribute location in the shader program
var positionAttribute = self.gl.getAttribLocation(self.shaderProgram, "position");
// Set position attribute to the positions buffer
self.gl.vertexAttribPointer(positionAttribute, 3, self.gl["FLOAT"], false, 0, 0);
// Enable position attribute
self.gl.enableVertexAttribArray(positionAttribute);
// Create text coordinates buffer
var textureCoordinatesBuffer = self.gl.createBuffer();
// Append texture coordinates buffer to list of buffers
self.buffers.push(textureCoordinatesBuffer);
// Bind texture coordinates buffer
self.gl.bindBuffer(self.gl["ARRAY_BUFFER"], textureCoordinatesBuffer);
// Move data into texture coordinates buffer
self.gl.bufferData(self.gl["ARRAY_BUFFER"], new Float32Array(model["Textured Models"][0]["Texture Coordinates"]), self.gl["STATIC_DRAW"]);
// Get texture coordinate attribute location in the shader program
var textureCoordinateAttribute = self.gl.getAttribLocation(self.shaderProgram, "textureCoordinate");
// Set texture coordinate attribute to the texture coordinates buffer
self.gl.vertexAttribPointer(textureCoordinateAttribute, 2, self.gl["FLOAT"], false, 0, 0);
// Enable texture coordinate attribute
self.gl.enableVertexAttribArray(textureCoordinateAttribute);
// Create normals buffer
var normalsBuffer = self.gl.createBuffer();
// Append normals buffer to list of buffers
self.buffers.push(normalsBuffer);
// Bind normals buffer
self.gl.bindBuffer(self.gl["ARRAY_BUFFER"], normalsBuffer);
// Move data into normals buffer
self.gl.bufferData(self.gl["ARRAY_BUFFER"], new Float32Array(model["Textured Models"][0]["Normals"]), self.gl["STATIC_DRAW"]);
// Get normal attribute location in the shader program
var normalAttribute = self.gl.getAttribLocation(self.shaderProgram, "normal");
// Set normal attribute to the texture coordinates buffer
self.gl.vertexAttribPointer(normalAttribute, 3, self.gl["FLOAT"], false, 0, 0);
// Enable normal attribute
self.gl.enableVertexAttribArray(normalAttribute);
// Create tangents buffer
var tangentsBuffer = self.gl.createBuffer();
// Append tangents buffer to list of buffers
self.buffers.push(tangentsBuffer);
// Bind tangents buffer
self.gl.bindBuffer(self.gl["ARRAY_BUFFER"], tangentsBuffer);
// Move data into tangents buffer
self.gl.bufferData(self.gl["ARRAY_BUFFER"], new Float32Array(model["Textured Models"][0]["Tangents"]), self.gl["STATIC_DRAW"]);
// Get tangent attribute location in the shader program
var tangentAttribute = self.gl.getAttribLocation(self.shaderProgram, "tangent");
// Set tangent attribute to the texture coordinates buffer
self.gl.vertexAttribPointer(tangentAttribute, 3, self.gl["FLOAT"], false, 0, 0);
// Enable tangent attribute
self.gl.enableVertexAttribArray(tangentAttribute);
// Create bitangents buffer
var bitangentsBuffer = self.gl.createBuffer();
// Append bitangents buffer to list of buffers
self.buffers.push(bitangentsBuffer);
// Bind bitangents buffer
self.gl.bindBuffer(self.gl["ARRAY_BUFFER"], bitangentsBuffer);
// Move data into bitangents buffer
self.gl.bufferData(self.gl["ARRAY_BUFFER"], new Float32Array(model["Textured Models"][0]["Bitangents"]), self.gl["STATIC_DRAW"]);
// Get bitangent attribute location in the shader program
var bitangentAttribute = self.gl.getAttribLocation(self.shaderProgram, "bitangent");
// Set bitangent attribute to the texture coordinates buffer
self.gl.vertexAttribPointer(bitangentAttribute, 3, self.gl["FLOAT"], false, 0, 0);
// Enable bitangent attribute
self.gl.enableVertexAttribArray(bitangentAttribute);
// Load model's diffuse texture
self.loadTexture((model["Textured Models"][0]["Diffuse Texture Index"] === Logo.NO_TEXTURE_INDEX) ? "" : model["Textures"][model["Textured Models"][0]["Diffuse Texture Index"]]).then(function(diffuseTexture) {
// Check if closing
if(self.closing === true) {
// Reject
reject();
// Return
return;
}
// Get material diffuse map location in the shader
var materialDiffuseMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.diffuseMap");
// Load material diffuse map in the shader
self.gl.uniform1i(materialDiffuseMapLocation, 0);
// Bind diffuse map in the shader
self.gl.activeTexture(self.gl["TEXTURE0"]);
self.gl.bindTexture(self.gl["TEXTURE_2D"], diffuseTexture);
// Load model's specular texture
self.loadTexture((model["Textured Models"][0]["Specular Texture Index"] === Logo.NO_TEXTURE_INDEX) ? "" : model["Textures"][model["Textured Models"][0]["Specular Texture Index"]]).then(function(specularTexture) {
// Check if closing
if(self.closing === true) {
// Reject
reject();
// Return
return;
}
// Get material has specular map location in the shader
var materialHasSpecularMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.hasSpecularMap");
// Load material has specular map in the shader
self.gl.uniform1i(materialHasSpecularMapLocation, specularTexture !== Logo.INVALID_TEXTURE);
// Check if specular texture exists
if(specularTexture !== Logo.INVALID_TEXTURE) {
// Get material specular map location in the shader
var materialSpecularMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.specularMap");
// Load material specular map in the shader
self.gl.uniform1i(materialSpecularMapLocation, 1);
// Bind specular map in the shader
self.gl.activeTexture(self.gl["TEXTURE1"]);
self.gl.bindTexture(self.gl["TEXTURE_2D"], specularTexture);
}
// Load model's emission texture
self.loadTexture((model["Textured Models"][0]["Emission Texture Index"] === Logo.NO_TEXTURE_INDEX) ? "" : model["Textures"][model["Textured Models"][0]["Emission Texture Index"]]).then(function(emissionTexture) {
// Check if closing
if(self.closing === true) {
// Reject
reject();
// Return
return;
}
// Get material has emission map location in the shader
var materialHasEmissionMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.hasEmissionMap");
// Load material has emission map in the shader
self.gl.uniform1i(materialHasEmissionMapLocation, emissionTexture !== Logo.INVALID_TEXTURE);
// Check if emission texture exists
if(emissionTexture !== Logo.INVALID_TEXTURE) {
// Get material emission map location in the shader
var materialEmissionMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.emissionMap");
// Load material emission map in the shader
self.gl.uniform1i(materialEmissionMapLocation, 2);
// Bind emission map in the shader
self.gl.activeTexture(self.gl["TEXTURE2"]);
self.gl.bindTexture(self.gl["TEXTURE_2D"], emissionTexture);
}
// Load model's normal texture
self.loadTexture((model["Textured Models"][0]["Normal Texture Index"] === Logo.NO_TEXTURE_INDEX) ? "" : model["Textures"][model["Textured Models"][0]["Normal Texture Index"]]).then(function(normalTexture) {
// Check if closing
if(self.closing === true) {
// Reject
reject();
// Return
return;
}
// Get material has normal map location in the shader
var materialHasNormalMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.hasNormalMap");
// Load material has normal map in the shader
self.gl.uniform1i(materialHasNormalMapLocation, normalTexture !== Logo.INVALID_TEXTURE);
// Check if normal texture exists
if(normalTexture !== Logo.INVALID_TEXTURE) {
// Get material normal map location in the shader
var materialNormalMapLocation = self.gl.getUniformLocation(self.shaderProgram, "material.normalMap");
// Load material normal map in the shader
self.gl.uniform1i(materialNormalMapLocation, 3);
// Bind normal map in the shader
self.gl.activeTexture(self.gl["TEXTURE3"]);
self.gl.bindTexture(self.gl["TEXTURE_2D"], normalTexture);
}
// Get material shininess location in the shader
var materialShininessLocation = self.gl.getUniformLocation(self.shaderProgram, "material.shininess");
// Load material shininess in the shader
self.gl.uniform1f(materialShininessLocation, model["Textured Models"][0]["Shininess"]);
// Create view matrix
var viewMatrix = glMatrix["mat4"].create();
// Get view matrix location in the shader program
var viewMatrixLocation = self.gl.getUniformLocation(self.shaderProgram, "viewMatrix");
// Load view matrix in the shader program
self.gl.uniformMatrix4fv(viewMatrixLocation, false, viewMatrix);
// Update projection matrix
self.updateProjectionMatrix(width, height);
// Go through all lights
var lightTypeLocations = [];
var lightPositionLocations = [];
var lightConstantAttenuationFactorLocations = [];
var lightLinearAttenuationFactorLocations = [];
var lightQuadraticAttenuationFactorLocations = [];
var lightDirectionLocations = [];
var lightInnerCutOffAngleLocations = [];
var lightOuterCutOffAngleLocations = [];
var lightAmbientColorLocations = [];
var lightDiffuseColorLocations = [];
var lightSpecularColorLocations = [];
for(var i = 0; i < Logo.MAX_NUMBER_OF_LIGHTS; ++i) {
// Get light type location in the shader
lightTypeLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].type"));
// Get light position location in the shader
lightPositionLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].position"));
// Get gight constant attenuation factor location in the shader
lightConstantAttenuationFactorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].constantAttenuationFactor"));
// Get light linear attenuation factor location in the shader
lightLinearAttenuationFactorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].linearAttenuationFactor"));
// Get light quadratic attenuation factor location in the shader
lightQuadraticAttenuationFactorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].quadraticAttenuationFactor"));
// Get light direction location in the shader
lightDirectionLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].direction"));
// Get light inner cut off angle location in the shader
lightInnerCutOffAngleLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].innerCutOffAngle"));
// Get light outer cut off angle location in the shader
lightOuterCutOffAngleLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].outerCutOffAngle"));
// Get light ambient color location in the shader
lightAmbientColorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].ambientColor"));
// Get light diffuse color location in the shader
lightDiffuseColorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].diffuseColor"));
// Get light specular color location in the shader
lightSpecularColorLocations.push(self.gl.getUniformLocation(self.shaderProgram, "lights[" + i.toFixed() + "].specularColor"));
}
// Create lights
var lights = [
Logo.createDirectionalLight(glMatrix["vec3"].normalize(glMatrix["vec3"].create(), glMatrix["vec3"].fromValues(0, 0, -1)), glMatrix["vec3"].fromValues(0.5, 0.5, 0.5), glMatrix["vec3"].fromValues(0.3, 0.3, 0.3), glMatrix["vec3"].fromValues(1, 1, 1))
];
// Go through all lights
for(var i = 0; i < lights["length"]; ++i) {
// Get light
var light = lights[i];
// Load light type
self.gl.uniform1i(lightTypeLocations[i], light["Type"]);
// Check if light is a point light
if(light["Type"] === Logo.POINT_LIGHT_TYPE) {
// Load light position
self.gl.uniform3fv(lightPositionLocations[i], light["Position"]);
// Load light constant attenuation factor
self.gl.uniform1f(lightConstantAttenuationFactorLocations[i], light["Constant Attenuation Factor"]);
// Load light linear attenuation factor
self.gl.uniform1f(lightLinearAttenuationFactorLocations[i], light["Linear Attenuation Factor"]);
// Load light quadratic attenuation factor
self.gl.uniform1f(lightQuadraticAttenuationFactorLocations[i], light["Quadratic Attenuation Factor"]);
}
// Otherwise
else {
// Check if light is a directional light
if(light["Type"] === Logo.DIRECTIONAL_LIGHT_TYPE)
// Load light direction
self.gl.uniform3fv(lightDirectionLocations[i], light["Direction"]);
// Otherwise
else {
// Check if light is a spot light
if(light["Type"] === Logo.SPOT_LIGHT_TYPE) {
// Load light position
self.gl.uniform3fv(lightPositionLocations[i], light["Position"]);
// Load light constant attenuation factor
self.gl.uniform1f(lightConstantAttenuationFactorLocations[i], light["Constant Attenuation Factor"]);
// Load light linear attenuation factor
self.gl.uniform1f(lightLinearAttenuationFactorLocations[i], light["Linear Attenuation Factor"]);
// Load light quadratic attenuation factor
self.gl.uniform1f(lightQuadraticAttenuationFactorLocations[i], light["Quadratic Attenuation Factor"]);
// Load light direction
self.gl.uniform3fv(lightDirectionLocations[i], light["Direction"]);
// Load light inner cut off angle
self.gl.uniform1f(lightInnerCutOffAngleLocations[i], light["Inner Cut Off Angle"]);
// Load light outer cut off angle
self.gl.uniform1f(lightOuterCutOffAngleLocations[i], light["Outer Cut Off Angle"]);
}
}
}
// Load light ambient color
self.gl.uniform3fv(lightAmbientColorLocations[i], light["Ambient Color"]);
// Load light diffuse color
self.gl.uniform3fv(lightDiffuseColorLocations[i], light["Diffuse Color"]);
// Load light specular color
self.gl.uniform3fv(lightSpecularColorLocations[i], light["Specular Color"]);
}
// Check if some lights aren't used
if(i !== Logo.MAX_NUMBER_OF_LIGHTS)
// Load next light's type as invalid
self.gl.uniform1i(lightTypeLocations[i], Logo.INVALID_LIGHT_TYPE);
// Set number of indices
self.numberOfIndices = model["Textured Models"][0]["Indices"]["length"];
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject("Loading normal texture failed.");
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("Loading emission texture failed.");
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("Loading specular texture failed.");
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("Loading diffuse texture failed.");
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("Loading resources failed.");
});
});
}
// Close
close(hideLogo = true) {
// Check if not already closing
if(this.closing === false) {
// Set closing
this.closing = true;
// Check if hiding logo
if(hideLogo === true) {
// Prevent showing
this.preventShowing();
}
// Clean up
this.cleanUp();
}
}
// Clean up
cleanUp() {
// Check if WebGL is supported
if(this.gl !== Logo.NO_WEBGL) {
// Check if shader program exists
if(this.shaderProgram !== Logo.NO_SHADER_PROGRAM) {
// Stop using shader
this.gl.useProgram(Logo.NO_SHADER_PROGRAM);
// Check if context wasn't lost
if(this.contextLost === false) {
// Delete shader program
this.gl.deleteProgram(this.shaderProgram);
}
// Set shader program to no shader program
this.shaderProgram = Logo.NO_SHADER_PROGRAM;
}
// Check if context wasn't lost
if(this.contextLost === false) {
// Go through all buffers
for(var i = 0; i < this.buffers["length"]; ++i) {
// Delete buffer
this.gl.deleteBuffer(this.buffers[i]);
}
}
// Empty buffers
this.buffers = [];
// Check if context wasn't lost
if(this.contextLost === false) {
// Go through all textures
for(var i = 0; i < this.textures["length"]; ++i) {
// Delete texture
this.gl.deleteTexture(this.textures[i]);
}
}
// Empty textures
this.textures = [];
}
}
// Run
run(currentTime = 0) {
// Check if last frame time hasn't been set
if(typeof this.lastFrameTime === "undefined")
// Set last frame time
this.lastFrameTime = currentTime;
// Set frame duration
this.frameDuration = currentTime - this.lastFrameTime;
// Set frame duration variation
this.frameDurationVariation = this.frameDuration * Logo.TIMING_FRAMES_PER_SECOND;
// Set last frame time
this.lastFrameTime = currentTime;
// Can if can show and loaded
if(this.canShow === true && this.loaded === true) {
// Check if first time show
if(this.firstTimeShow === true) {
// Clear first time show
this.firstTimeShow = false;
// Set initial X velocity
this.velocityX = Logo.INITIAL_X_VELOCITY;
}
// Check if X or Y velocity exists
if(this.velocityX !== 0 || this.velocityY !== 0) {
// Limit frame duration variation
this.frameDurationVariation = Math.min(Math.max(this.frameDurationVariation, Logo.MINIMUM_FRAME_DURATION_VARIATION), Logo.MAXIMUM_FRAME_DURATION_VARIATION);
// Rotate orientation on global X axis proportional to Y velocity
var rotationX = glMatrix["quat"].fromEuler(glMatrix["quat"].create(), this.velocityY * Logo.VELOCITY_APPLIED_SCALE_FACTOR * this.frameDurationVariation, 0, 0);
glMatrix["quat"].normalize(this.orientation, glMatrix["quat"].multiply(this.orientation, rotationX, this.orientation));
// Update Y velocity
this.velocityY *= 1 - Math.min(Math.max(Logo.VELOCITY_DEGRADE_SCALE_FACTOR * this.frameDurationVariation, 0), 1);
// Check if Y velocity is too small
if(Math.abs(this.velocityY) < Logo.MINIMUM_VELOCITY_THRESHOLD)
// Clear Y velocity
this.velocityY = 0;
// Rotate orientation on global Y axis proportional to X velocity
var rotationY = glMatrix["quat"].fromEuler(glMatrix["quat"].create(), 0, this.velocityX * Logo.VELOCITY_APPLIED_SCALE_FACTOR * this.frameDurationVariation, 0);
glMatrix["quat"].normalize(this.orientation, glMatrix["quat"].multiply(this.orientation, rotationY, this.orientation));
// Update X velocity
this.velocityX *= 1 - Math.min(Math.max(Logo.VELOCITY_DEGRADE_SCALE_FACTOR * this.frameDurationVariation, 0), 1);
// Check if X velocity is too small
if(Math.abs(this.velocityX) < Logo.MINIMUM_VELOCITY_THRESHOLD)
// Clear X velocity
this.velocityX = 0;
// Check if recording rotation
if(this.startRecordingRotation === true) {
// Update recorded rotation
this.recordedRotation += this.velocityX * Logo.VELOCITY_APPLIED_SCALE_FACTOR * this.frameDurationVariation;
// Check if recorded rotation exceeds Tetris threshold
if(Math.abs(this.recordedRotation) >= Logo.TETRIS_ROTATION_THRESHOLD) {
// Set start recording rotation to false
this.startRecordingRotation = false;
// Reset recorded rotation
this.recordedRotation = 0;
// Check if logo is showing, create or unlock display is shown, message display isn't shown, application isn't showing loading, application isn't disabled, and messages are allowed
if(this.logoDisplay.hasClass("notLoaded") === false && this.logoDisplay.hasClass("hide") === false && this.mainDisplay.hasClass("logo") === true && this.logoDisplay.is(":visible") === true && (this.application.isCreateDisplayShown() === true || this.application.isUnlockDisplayShown() === true) && this.message.isShown() === false && this.application.isShowingLoading() === false && this.application.isDisabled() === false && this.message.getAllowed() === true) {
// Show tetris
this.tetris.show();
}
}
}
// Draw
this.draw();
}
// Otherwise check if frame duration variation is too large
else if(this.frameDurationVariation >= Logo.FORCE_REDRAW_FRAME_DURATION_VARIATION_THRESHOLD) {
// Draw
this.draw();
// Set self
var self = this;
// Go through number of times to draw
for(var i = 0; i < Logo.FORCE_REDRAW_NUMBER_OF_TIMES - 1; ++i) {
// Set timeout
setTimeout(function() {
// Draw
self.draw();
}, i * Logo.FORCE_REDRAW_INTERVAL_SECONDS * Common.MILLISECONDS_IN_A_SECOND);
}
}
}
// Check if not closing
if(this.closing === false) {
// Set self
var self = this;
// Request animation frame
requestAnimationFrame(function(currentTime) {
// Run
self.run(currentTime / Common.MILLISECONDS_IN_A_SECOND);
});
}
}
// Draw
draw() {
// Check if context wasn't lost and not closing
if(this.contextLost === false && this.closing === false) {
// Check if window dimensions changed without triggering a resize event
if(window["innerWidth"] !== this.lastWidth || window["innerHeight"] !== this.lastHeight) {
// Update size
this.updateSize();
}
// Clear color and depth buffers
this.gl.clear(this.gl["COLOR_BUFFER_BIT"] | this.gl["DEPTH_BUFFER_BIT"]);
// Create model matrix
var modelMatrix = Logo.createModelMatrix(this.position, this.orientation, glMatrix["vec3"].fromValues(1, 1, 1));
// Get model matrix location in the shader program
var modelMatrixLocation = this.gl.getUniformLocation(this.shaderProgram, "modelMatrix");
// Load model matrix in the shader program
this.gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
// Draw model
this.gl.drawElements(this.gl["TRIANGLES"], this.numberOfIndices, this.gl["UNSIGNED_SHORT"], 0);
}
}
// Resize
resize(width, height) {
// Check if context wasn't lost and not closing
if(this.contextLost === false && this.closing === false) {
// Set viewport size
this.gl.viewport(0, 0, width, height);
// Update projection matrix
this.updateProjectionMatrix(width, height);
}
}
// Update projection matrix
updateProjectionMatrix(width, height) {
// Check if context wasn't lost and not closing
if(this.contextLost === false && this.closing === false) {
// Create projection matrix
var projectionMatrix = glMatrix["mat4"].perspective(glMatrix["mat4"].create(), glMatrix["glMatrix"].toRadian((height <= Logo.SMALL_HEIGHT_THRESHOLD) ? Logo.SMALL_HEIGHT_FIELD_OF_VIEW : Logo.FIELD_OF_VIEW), width / height, Logo.NEAR_PLANE, Logo.FAR_PLANE);
// Get projection matrix location in the shader program
var projectionMatrixLocation = this.gl.getUniformLocation(this.shaderProgram, "projectionMatrix");
// Load projection matrix in the shader program
this.gl.uniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix);
}
}
// Create model matrix
static createModelMatrix(translation, orientation, scale) {
// Return scaled, rotated, and translated matrix
return glMatrix["mat4"].fromRotationTranslationScale(glMatrix["mat4"].create(), orientation, translation, scale);
}
// Load texture
loadTexture(file) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if file is invalid
if(file["length"] === 0)
// Resolve invalid texture
resolve(Logo.INVALID_TEXTURE);
// Otherwise
else {
// Create image
var image = new Image();
// Image load event
$(image).on("load", function() {
// Check if image has dimensions that aren't powers of two
if((image["width"] & (image["width"] - 1)) !== 0 || (image["height"] & (image["height"] - 1)) !== 0) {
// Get new dimensions to make its dimensions powers of two
var canvasWidth = Math.pow(2, Math.ceil(Math.log(image["width"]) / Math.log(2)));
var canvasHeight = Math.pow(2, Math.ceil(Math.log(image["height"]) / Math.log(2)));
// Create canvas and get its context
var context = $("<canvas></canvas>").attr({
// Width
"width": canvasWidth.toFixed(),
// Height
"height": canvasHeight.toFixed()
}).get(0).getContext("2d");
// Smooth image when resizing
context["imageSmoothingEnabled"] = true;
context["mozImageSmoothingEnabled"] = true;
context["webkitImageSmoothingEnabled"] = true;
context["msImageSmoothingEnabled"] = true;
context["imageSmoothingQuality"] = "high";
// Draw image on canvas
context.drawImage(image, 0, 0, canvasWidth, canvasHeight);
// Get the image's data from the canvas
var imageData = context.getImageData(0, 0, canvasWidth, canvasHeight)["data"];
// Create texture
var texture = self.gl.createTexture();
// Append texture to list of textures
self.textures.push(texture);
// Bind texture
var maxTextureUnit = self.gl.getParameter(self.gl["MAX_COMBINED_TEXTURE_IMAGE_UNITS"]);
self.gl.activeTexture(self.gl["TEXTURE0"] + maxTextureUnit - 1);
self.gl.bindTexture(self.gl["TEXTURE_2D"], texture);
// Set texture wrapping
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_WRAP_S"], self.gl["CLAMP_TO_EDGE"]);
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_WRAP_T"], self.gl["CLAMP_TO_EDGE"]);
// Set texture filtering
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MIN_FILTER"], self.gl["LINEAR_MIPMAP_LINEAR"]);
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MAG_FILTER"], self.gl["LINEAR"]);
// Set max anisotropy
if(typeof self.gl["TEXTURE_MAX_ANISOTROPY_EXT"] !== "undefined")
self.gl.texParameterf(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MAX_ANISOTROPY_EXT"], self.anisotropy);
// Create texture
self.gl.texImage2D(self.gl["TEXTURE_2D"], 0, self.gl["RGBA"], canvasWidth, canvasHeight, 0, self.gl["RGBA"], self.gl["UNSIGNED_BYTE"], new Uint8Array(imageData));
}
// Otherwise
else {
// Create texture
var texture = self.gl.createTexture();
// Append texture to list of textures
self.textures.push(texture);
// Bind texture
var maxTextureUnit = self.gl.getParameter(self.gl["MAX_COMBINED_TEXTURE_IMAGE_UNITS"]);
self.gl.activeTexture(self.gl["TEXTURE0"] + maxTextureUnit - 1);
self.gl.bindTexture(self.gl["TEXTURE_2D"], texture);
// Set texture wrapping
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_WRAP_S"], self.gl["CLAMP_TO_EDGE"]);
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_WRAP_T"], self.gl["CLAMP_TO_EDGE"]);
// Set texture filtering
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MIN_FILTER"], self.gl["LINEAR_MIPMAP_LINEAR"]);
self.gl.texParameteri(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MAG_FILTER"], self.gl["LINEAR"]);
// Set max anisotropy
if(typeof self.gl["TEXTURE_MAX_ANISOTROPY_EXT"] !== "undefined")
self.gl.texParameterf(self.gl["TEXTURE_2D"], self.gl["TEXTURE_MAX_ANISOTROPY_EXT"], self.anisotropy);
// Create texture
self.gl.texImage2D(self.gl["TEXTURE_2D"], 0, self.gl["RGBA"], self.gl["RGBA"], self.gl["UNSIGNED_BYTE"], image);
}
// Create mipmaps
self.gl.generateMipmap(self.gl["TEXTURE_2D"]);
// Resolve texture
resolve(texture);
// Image error event
}).on("error", function(error) {
// Reject error
reject(error);
});
// Set image source
image["src"] = file;
}
});
}
// Create directional light
static createDirectionalLight(direction, ambientColor, diffuseColor, specularColor) {
// Return directional light
return {
// Type
"Type": Logo.DIRECTIONAL_LIGHT_TYPE,
// Direction
"Direction": direction,
// Ambient color
"Ambient Color": ambientColor,
// Diffuse color
"Diffuse Color": diffuseColor,
// Specular color
"Specular Color": specularColor
};
}
// Create point light
static createPointLight(position, constantAttenuationFactor, linearAttenuationFactor, quadraticAttenuationFactor, ambientColor, diffuseColor, specularColor) {
// Return point light
return {
// Type
"Type": Logo.POINT_LIGHT_TYPE,
// Position
"Position": position,
// Constant attenuation factor
"Constant Attenuation Factor": constantAttenuationFactor,
// Linear attenuation factor
"Linear Attenuation Factor": linearAttenuationFactor,
// Quadratic attenuation factor
"Quadratic Attenuation Factor": quadraticAttenuationFactor,
// Ambient color
"Ambient Color": ambientColor,
// Diffuse color
"Diffuse Color": diffuseColor,
// Specular color
"Specular Color": specularColor
};
}
// Create spot light
static createSpotLight(position, direction, constantAttenuationFactor, linearAttenuationFactor, quadraticAttenuationFactor, innerCutOffAngle, outerCutOffAngle, ambientColor, diffuseColor, specularColor) {
// Return spot light
return {
// Type
"Type": Logo.SPOT_LIGHT_TYPE,
// Position
"Position": position,
// Direction
"Direction": direction,
// Constant attenuation factor
"Constant Attenuation Factor": constantAttenuationFactor,
// Linear attenuation factor
"Linear Attenuation Factor": linearAttenuationFactor,
// Quadratic attenuation factor
"Quadratic Attenuation Factor": quadraticAttenuationFactor,
// Inner cut off angle
"Inner Cut Off Angle": Math.cos(glMatrix["glMatrix"].toRadian(innerCutOffAngle)),
// Outer cut off angle
"Outer Cut Off Angle": Math.cos(glMatrix["glMatrix"].toRadian(outerCutOffAngle)),
// Ambient color
"Ambient Color": ambientColor,
// Diffuse color
"Diffuse Color": diffuseColor,
// Specular color
"Specular Color": specularColor
};
}
// Bounding boxes collide
static boundingBoxesCollide(minimumXOne, minimumYOne, maximumXOne, maximumYOne, minimumXTwo, minimumYTwo, maximumXTwo, maximumYTwo) {
// Check if an X axis collision occurred
if((minimumXOne <= minimumXTwo && maximumXOne >= minimumXTwo) || (minimumXOne <= maximumXTwo && maximumXOne >= maximumXTwo) || (minimumXOne >= minimumXTwo && maximumXOne <= maximumXTwo))
// Check if a Y axis collision occurred
if((minimumYOne <= minimumYTwo && maximumYOne >= minimumYTwo) || (minimumYOne <= maximumYTwo && maximumYOne >= maximumYTwo) || (minimumYOne >= minimumYTwo && maximumYOne <= maximumYTwo))
// Return true
return true;
// Return false
return false;
}
// No WebGL
static get NO_WEBGL() {
// Return no WebGL
return null;
}
// No WebGL extension
static get NO_WEBGL_EXTENSION() {
// Return no WebGL extension
return null;
}
// Timing frames per second
static get TIMING_FRAMES_PER_SECOND() {
// Return timing frames per second
return 60;
}
// No shader program
static get NO_SHADER_PROGRAM() {
// Return no shader program
return null;
}
// Field of view
static get FIELD_OF_VIEW() {
// Return field of view
return 70;
}
// Small height field of view
static get SMALL_HEIGHT_FIELD_OF_VIEW() {
// Return small height field of view
return 55;
}
// Small height threshold
static get SMALL_HEIGHT_THRESHOLD() {
// Return small height threshold
return 300;
}
// Near plane
static get NEAR_PLANE() {
// Return near plane
return 10;
}
// Far plane
static get FAR_PLANE() {
// Return far plane
return 50;
}
// Default anisotropy
static get DEFAULT_ANISOTROPY() {
// Return default anisotropy
return 1;
}
// Max anisotropy
static get MAX_ANISOTROPY() {
// Return max anisotropy
return 4;
}
// Max number of lights
static get MAX_NUMBER_OF_LIGHTS() {
// Return max lights
return 1;
}
// Invalid light type
static get INVALID_LIGHT_TYPE() {
// Return invalid light type
return 0;
}
// Directional light type
static get DIRECTIONAL_LIGHT_TYPE() {
// Return directional light type
return Logo.INVALID_LIGHT_TYPE + 1;
}
// Point light type
static get POINT_LIGHT_TYPE() {
// Return point light type
return Logo.DIRECTIONAL_LIGHT_TYPE + 1;
}
// Spot light type
static get SPOT_LIGHT_TYPE() {
// Return spot light type
return Logo.POINT_LIGHT_TYPE + 1;
}
// Shader constants
static get SHADER_CONSTANTS() {
// Return invalid light type
return "const int INVALID_LIGHT_TYPE = " + Logo.INVALID_LIGHT_TYPE + ";\n" +
// Directional light type
"const int DIRECTIONAL_LIGHT_TYPE = " + Logo.DIRECTIONAL_LIGHT_TYPE + ";\n" +
// Point light type
"const int POINT_LIGHT_TYPE = " + Logo.POINT_LIGHT_TYPE + ";\n" +
// Spot light type
"const int SPOT_LIGHT_TYPE = " + Logo.SPOT_LIGHT_TYPE + ";\n" +
// Max number of lights
"const int MAX_NUMBER_OF_LIGHTS = " + Logo.MAX_NUMBER_OF_LIGHTS + ";";
}
// No texture index
static get NO_TEXTURE_INDEX() {
// Return no texture index
return -1;
}
// Invalid texture
static get INVALID_TEXTURE() {
// Return invalid texture
return null;
}
// No pointer state
static get NO_POINTER_STATE() {
// Return no pointer state
return null;
}
// Logo percent size
static get LOGO_PERCENT_SIZE() {
// Return logo percent size
return {
// Minimum X
"Minimum X": 0.212,
// Minimum Y
"Minimum Y": 0.360,
// Maximum X
"Maximum X": 0.794,
// Maximum Y
"Maximum Y": 0.646
};
}
// Velocity applied scale factor
static get VELOCITY_APPLIED_SCALE_FACTOR() {
// Return velocity applied scale factor
return 0.0012;
}
// Velocity degrade scale factor
static get VELOCITY_DEGRADE_SCALE_FACTOR() {
// Return velocity degrade scale factor
return 0.06;
}
// Minimum velocity threshold
static get MINIMUM_VELOCITY_THRESHOLD() {
// Return minimum velocity threshold
return 0.01;
}
// Vertex shader file location
static get VERTEX_SHADER_FILE_LOCATION() {
// Return vertex shader file location
return "./shaders/logo.vert";
}
// Fragment shader file location
static get FRAGMENT_SHADER_FILE_LOCATION() {
// Return fragment shader file location
return "./shaders/logo.frag";
}
// Model file location
static get MODEL_FILE_LOCATION() {
// Return model file location
return "./models/mwc.json";
}
// Minimum frame duration variation
static get MINIMUM_FRAME_DURATION_VARIATION() {
// Return minimum frame duration variation
return -2;
}
// Maximum frame duration variation
static get MAXIMUM_FRAME_DURATION_VARIATION() {
// Return maximum frame duration variation
return 2;
}
// Initial X velocity
static get INITIAL_X_VELOCITY() {
// Return initial X velocity
return 13500;
}
// Initial position
static get INITIAL_POSITION() {
// Return initial position
return glMatrix["vec3"].fromValues(0, 0, -30);
}
// Initial orientation
static get INITIAL_ORIENTATION() {
// Return initial orientation
return glMatrix["quat"].normalize(glMatrix["quat"].create(), glMatrix["quat"].setAxisAngle(glMatrix["quat"].create(), glMatrix["vec3"].fromValues(0, 1, 0), glMatrix["glMatrix"].toRadian(-90)));
}
// Pointer velocity scale factor
static get POINTER_VELOCITY_SCALE_FACTOR() {
// Return pointer velocity scale factor
return 0.6;
}
// Force redraw frame duration variation threshold
static get FORCE_REDRAW_FRAME_DURATION_VARIATION_THRESHOLD() {
// Return force redraw frame duration variation threshold
return 20;
}
// Force redraw number of times
static get FORCE_REDRAW_NUMBER_OF_TIMES() {
// Return force redraw number of times
return 10;
}
// Force redraw interval seconds
static get FORCE_REDRAW_INTERVAL_SECONDS() {
// Return force redraw interval seconds
return 1;
}
// Distance ratio to screen width
static get DISTANCE_RATIO_TO_SCREEN_WIDTH() {
// Return distance ratio to screen width
return 600;
}
// Distance ratio to screen height
static get DISTANCE_RATIO_TO_SCREEN_HEIGHT() {
// Return distance ratio to screen height
return 600;
}
// Initial show delay milliseconds
static get INITIAL_SHOW_DELAY_MILLISECONDS() {
// Return initial show delay milliseconds
return 70;
}
// No restore context frame
static get NO_RESTORE_CONTEXT_FRAME() {
// Return no context frame
return null;
}
// No close timeout
static get NO_CLOSE_TIMEOUT() {
// Return no close timeout
return null;
}
// Close if not restored milliseconds
static get CLOSE_IF_NOT_RESTORED_MILLISECONDS() {
// Return close if not restored milliseconds
return 50;
}
// Tetris rotation threshold
static get TETRIS_ROTATION_THRESHOLD() {
// Return Tetris rotation threshold
return 180 * 3;
}
}
// Main function
// Set global object's logo
globalThis["Logo"] = Logo;