From 2fd9cc46ff2428bb2fa891f47002e9d3e7585583 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Sat, 13 Aug 2022 11:33:30 +0100 Subject: init: import project --- utils.js | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100755 utils.js (limited to 'utils.js') diff --git a/utils.js b/utils.js new file mode 100755 index 0000000..f92d48f --- /dev/null +++ b/utils.js @@ -0,0 +1,276 @@ + +"use strict"; + +// Cleans the scene and spawns an instance of a cube (also updates +// the cubies map). +function buildCube(data) +{ + clearCubies(scene); + cubies.clear(); + + // Solved configuration + cubies.set(0, new Cubie(0,0,[{ key: 0, value: data[0][0] },{ key: 2, value: data[0][1] },{ key: 4, value: data[0][2] }])); + cubies.set(1, new Cubie(1,1,[{ key: 0, value: data[1][0] },{ key: 2, value: data[1][1] },{ key: 5, value: data[1][2] }])); + cubies.set(2, new Cubie(2,2,[{ key: 1, value: data[2][0] },{ key: 2, value: data[2][1] },{ key: 5, value: data[2][2] }])); + cubies.set(3, new Cubie(3,3,[{ key: 1, value: data[3][0] },{ key: 2, value: data[3][1] },{ key: 4, value: data[3][2] }])); + cubies.set(4, new Cubie(4,4,[{ key: 0, value: data[4][0] },{ key: 3, value: data[4][1] },{ key: 4, value: data[4][2] }])); + cubies.set(5, new Cubie(5,5,[{ key: 0, value: data[5][0] },{ key: 3, value: data[5][1] },{ key: 5, value: data[5][2] }])); + cubies.set(6, new Cubie(6,6,[{ key: 1, value: data[6][0] },{ key: 3, value: data[6][1] },{ key: 5, value: data[6][2] }])); + cubies.set(7, new Cubie(7,7,[{ key: 1, value: data[7][0] },{ key: 3, value: data[7][1] },{ key: 4, value: data[7][2] }])); + + // Adding cubies to scene + for (var i = 0; i < cubies.size; i++) + { + scene.add(cubies.get(i).mesh); + } + + needsRender = true; +} + +var solvedConfig = [ + ["white", "green", "red"], + ["white", "green", "orange"], + ["yellow", "green", "orange"], + ["yellow", "green", "red"], + ["white", "blue", "red"], + ["white", "blue", "orange"], + ["yellow", "blue", "orange"], + ["yellow", "blue", "red"], + ]; + +function solvedCube() +{ + buildCube(solvedConfig); +} + +function scramble() +{ + var moves = []; + var rotations = ["pitchA", "pitchB", "rollA", "rollB", "yawA", "yawB"]; + + for(var i = 0; i < Math.random()*10+10; i++) + { + moves.push({ move: rotations[Math.floor(Math.random() * rotations.length)], dir: (Math.random() < 0.5) ? 1 : -1 }); + } + + if (! animator) + { + scramb = true; + animator = new Animator(moves); + animator.goOn(); + } +} + + +function clearCubies(node) +{ + cubies.forEach(function(value) + { + node.remove(value.mesh); + }); +} + +// Get the contents of the file "fname". +// Returns an object with two attributes: +// - succeeded: true if the function was able to retrieve the file. +// - contents: the contents retrieved or an empty string. +function getFileContents(fname) { + /* + // Request file content via HTTP's GET request + var xmlhttp = new XMLHttpRequest(); + xmlhttp.responseType = "text/plain"; // Content is not XML! + + xmlhttp.open("GET", "file:\\\\" + fname, false); + + // NOTE: This can take some time if the server is remote + // which means the UI might freeze for some time... + xmlhttp.send(); + + var status = true; + var contents = ""; + + if (xmlhttp.status != 200) { + status = false; + } + else + { + contents = xmlhttp.responseText; + } + + return {succeeded: status, contents: contents}; + */ +} + +function loadShaders() +{ + var tmp,vs,fs; + + tmp = getFileContents("vs.glsl"); + if (!tmp.succeeded) + { + window.alert('Failed to load Blinn-Phong vertex shader: vs.glsl'); + } + vs = tmp.contents; + + tmp = getFileContents("fs.glsl"); + if (!tmp.succeeded) + { + window.alert('Failed to load Blinn-Phong fragment shader: fs.glsl'); + } + fs = tmp.contents; + + return { vertex: vs, fragment: fs }; +} + +// Updates position after a complete animation. +// Don't touch it, if you can't understand it! +function updatePositions() +{ + scene.remove(face); + + var temp = cubies.get(current_animation.cubies[0]); + for(var i = 0; Math.abs(i) < 4; i += current_animation.dir) + { + var keys, colors; + var c_new, c_old = temp; + switch (current_animation.cubies[mod(i+current_animation.dir,4)]) + { + case 0: keys = [0,2,4]; break; + case 1: keys = [0,2,5]; break; + case 2: keys = [1,2,5]; break; + case 3: keys = [1,2,4]; break; + case 4: keys = [0,3,4]; break; + case 5: keys = [0,3,5]; break; + case 6: keys = [1,3,5]; break; + case 7: keys = [1,3,4]; break; + } + switch (current_animation.name) + { + case "pitch": colors = [0,2,1]; break; + case "roll": colors = [1,0,2]; break; + case "yaw": colors = [2,1,0]; break; + } + c_new = new Cubie(c_old.key, + current_animation.cubies[mod(i+current_animation.dir,4)], + [{ key: keys[0], value: c_old.colors[colors[0]].value }, + { key: keys[1], value: c_old.colors[colors[1]].value }, + { key: keys[2], value: c_old.colors[colors[2]].value } + ]); + temp = cubies.get(current_animation.cubies[mod(i+current_animation.dir,4)]); + cubies.set(current_animation.cubies[mod(i+current_animation.dir,4)], c_new); + scene.add(c_new.mesh); + } + + needsRender = true +} + +// Right module operator. +// Beware the Javascript module! (it doesn't work with negative integers) +function mod(n, m) +{ + return ((n % m) + m) % m; +} + +// Open a local file. +function selectFile(loop) +{ + var element = document.createElement('div'); + element.innerHTML = ''; + var fileInput = element.firstChild; + + fileInput.addEventListener('change', function() { + var file = fileInput.files[0]; + if (file.name.match(/\.(txt)$/)) + { + var reader = new FileReader(); + reader.onload = function() { + var data = parseData(reader.result); + buildCube(data.cube); + if (data.solutions[0].length > 0) { + animator = new Animator(data.solutions[0]); + animator.goOn(); + } + }; + reader.readAsText(file); + } else { + alert("File not supported, .txt files only"); + } + }); + + fileInput.click(); +} + +function saveToFile(filename, content) { + var elem = document.createElement('a'); + elem.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content)); + elem.setAttribute('download', filename); + + document.body.appendChild(elem); + elem.click(); + document.body.removeChild(elem); +} + +// Parse a local file +function parseData(text) +{ + var data = [], instance; + var moves = [], predicates; + var i = -1, pred; + var lines = text.split("\n"); + + instance = new Array(8); + + // Look for the first line with an answer + while(lines[++i].search(/Answer:/g) !== 0) { } + // Parse answers + while(i < lines.length && lines[i++].search(/Answer:/g) === 0) + { + predicates = lines[i++].split(" "); + + pred = predicates[predicates.length-1]; + if (pred.search(/solved/i) === 0) { + moves = new Array(parseInt(pred.substring(pred.indexOf("(") + 1,pred.indexOf(")")))); + } + + for(var j = 0; j < predicates.length; j++) + { + pred = predicates[j].split(","); + + if(predicates[j].search(/move/i) === 0) + { + switch (pred[1]) + { + case "pitch": var move = (parseInt(pred[2]) == 0) ? "pitchA" : "pitchB"; break; + case "roll": var move = (parseInt(pred[2]) == 0) ? "rollA" : "rollB"; break; + case "yaw": var move = (parseInt(pred[2]) == 0) ? "yawA" : "yawB"; break; + } + + var ind = parseInt(pred[0].substring(pred[0].indexOf("(")+1)); + if(ind < moves.length) + { + moves[ind] = + { + move: move, + dir: parseInt(pred[3].substr(0,pred[3].length-1)) + }; + } + + } else if(predicates[j].search(/is/i) === 0) { + + if(parseInt(pred[0].substring(pred[0].indexOf("(")+1)) === 0) + { + instance[parseInt(pred[1])] = [ + pred[2], + pred[3], + pred[4].substr(0,pred[4].length-1) + ]; + } + } + + } + + data.push(moves); + } + + return { cube: instance, solutions: data }; +} -- cgit v1.2.3