UNPKG

cannondice

Version:

3D-rendered dice for modern browsers with Cannon.js physics. Based on Teal's excellent 3D dice javascript component

260 lines 9.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var three_1 = require("three"); var cannon_1 = require("cannon"); var randomOrgApiKey = 'f6e74d7b-070e-4f85-865d-d859fc0d078b'; var _randomStorage = []; var _useTrueRandom = true; function useTrueRandom(value) { _useTrueRandom = value; } exports.useTrueRandom = useTrueRandom; function initRng(callback) { if (!_randomStorage.length && _useTrueRandom) { var body = { jsonrpc: '2.0', method: 'generateDecimalFractions', params: { apiKey: randomOrgApiKey, n: 512, decimalPlaces: 2, id: 1 } }; this.http .post('https://api.random.org/json-rpc/1/invoke', body, { headers: { 'Content-Type': 'application/json-rpc' } }) .subscribe(function (response) { if (response.ok) { response .json() .then(function (x) { return (_randomStorage = x.random.data); }) .catch(function () { return useTrueRandom(false); }); } else { useTrueRandom(false); } }); if (callback) callback(); } } exports.initRng = initRng; function removeCssClass(el, className) { var c = el.getAttribute('class'); if (c) { var index = c.search('\\b' + className + '\\b'); if (index !== -1) { var c2 = c.substr(0, index) + c.substr(index + className.length).replace(/\s+/g, ' '); if (c !== c2) { el.setAttribute('class', c2); } } } } exports.removeCssClass = removeCssClass; function addCssClass(el, className) { var c = el.getAttribute('class'); var value; if (!c || !c.trim()) { value = className; } else { var index = c.search('\\b' + className + '\\b'); if (index === -1) { value = c.trim() + ' ' + className; } } if (value) { el.setAttribute('class', value); } } exports.addCssClass = addCssClass; function bind(sel, eventName, func, bubble) { if (eventName.constructor === Array) { eventName.forEach(function (x) { sel.addEventListener(x, func, bubble ? bubble : false); }); } else { sel.addEventListener(eventName, func, bubble ? bubble : false); } } exports.bind = bind; function unbind(sel, eventName, func, bubble) { if (eventName.constructor === Array) { eventName.forEach(function (x) { sel.removeEventListener(x, func, bubble ? bubble : false); }); } else { sel.removeEventListener(eventName, func, bubble ? bubble : false); } } exports.unbind = unbind; function rng() { if (_randomStorage.length === 1) { initRng(); } return _randomStorage.length ? _randomStorage.pop() : Math.random(); } exports.rng = rng; function copy(obj) { if (!obj) return obj; return copyto(obj, new obj.constructor()); } function copyto(obj, res) { if (obj == null || typeof obj !== 'object') return obj; if (obj instanceof Array) { for (var i = obj.length - 1; i >= 0; --i) res[i] = copy(obj[i]); } else { for (var i in obj) { if (obj.hasOwnProperty(i)) res[i] = copy(obj[i]); } } return res; } exports.copyto = copyto; function createShape(vertices, faces, radius) { var cv = vertices.map(function (v) { return new cannon_1.Vec3(v.x * radius, v.y * radius, v.z * radius); }); var cf = faces.map(function (x, i) { return faces[i].slice(0, faces[i].length); }); // BUG: @types/cannon incorrectly declares 2nd param as number[] return new cannon_1.ConvexPolyhedron(cv, cf); } function createGeometry(vertices, faces, radius, tab, af) { var geom = new three_1.Geometry(); for (var i = 0; i < vertices.length; ++i) { var vertex = vertices[i].multiplyScalar(radius); /*vertex.index = */ geom.vertices.push(vertex) /* - 1 */; } for (var i = 0; i < faces.length; ++i) { var ii = faces[i]; var fl = ii.length - 1; var aa = Math.PI * 2 / fl; for (var j = 0; j < fl - 2; ++j) { geom.faces.push(new three_1.Face3(ii[0], ii[j + 1], ii[j + 2], [ geom.vertices[ii[0]], geom.vertices[ii[j + 1]], geom.vertices[ii[j + 2]] ], new three_1.Color(0), ii[fl] + 1)); geom.faceVertexUvs[0].push([ new three_1.Vector2((Math.cos(af) + 1 + tab) / 2 / (1 + tab), (Math.sin(af) + 1 + tab) / 2 / (1 + tab)), new three_1.Vector2((Math.cos(aa * (j + 1) + af) + 1 + tab) / 2 / (1 + tab), (Math.sin(aa * (j + 1) + af) + 1 + tab) / 2 / (1 + tab)), new three_1.Vector2((Math.cos(aa * (j + 2) + af) + 1 + tab) / 2 / (1 + tab), (Math.sin(aa * (j + 2) + af) + 1 + tab) / 2 / (1 + tab)) ]); } } geom.computeFaceNormals(); geom.boundingSphere = new three_1.Sphere(new three_1.Vector3(), radius); return geom; } function chamferGeometry(vectors, faces, chamfer) { var chamferVectors = []; var chamferFaces = []; var cornerFaces = vectors.map(function (x) { return []; }); for (var i = 0; i < faces.length; ++i) { var ii = faces[i]; var fl = ii.length - 1; var centerPoint = new three_1.Vector3(); var face = new Array(fl); for (var j = 0; j < fl; ++j) { var vv = vectors[ii[j]].clone(); centerPoint.add(vv); cornerFaces[ii[j]].push((face[j] = chamferVectors.push(vv) - 1)); } centerPoint.divideScalar(fl); for (var j = 0; j < fl; ++j) { var vv = chamferVectors[face[j]]; vv .subVectors(vv, centerPoint) .multiplyScalar(chamfer) .addVectors(vv, centerPoint); } face.push(ii[fl]); chamferFaces.push(face); } for (var i = 0; i < faces.length - 1; ++i) { for (var j = i + 1; j < faces.length; ++j) { var pairs = [], lastm = -1; for (var m = 0; m < faces[i].length - 1; ++m) { var n = faces[j].indexOf(faces[i][m]); if (n >= 0 && n < faces[j].length - 1) { if (lastm >= 0 && m != lastm + 1) pairs.unshift([i, m], [j, n]); else pairs.push([i, m], [j, n]); lastm = m; } } if (pairs.length != 4) continue; chamferFaces.push([ chamferFaces[pairs[0][0]][pairs[0][1]], chamferFaces[pairs[1][0]][pairs[1][1]], chamferFaces[pairs[3][0]][pairs[3][1]], chamferFaces[pairs[2][0]][pairs[2][1]], -1 ]); } } for (var i = 0; i < cornerFaces.length; ++i) { var cf = cornerFaces[i]; var face = [cf[0]]; var count = cf.length - 1; while (count) { for (var m = faces.length; m < chamferFaces.length; ++m) { var index = chamferFaces[m].indexOf(face[face.length - 1]); if (index >= 0 && index < 4) { if (--index == -1) { index = 3; } var nextVertex = chamferFaces[m][index]; if (cf.indexOf(nextVertex) >= 0) { face.push(nextVertex); break; } } } --count; } face.push(-1); chamferFaces.push(face); } return { vectors: chamferVectors, faces: chamferFaces }; } function createDiceGeometry(vertices, faces, radius, tab, af, chamfer) { var vectors = new Array(vertices.length); for (var i = 0; i < vertices.length; ++i) { vectors[i] = new three_1.Vector3().fromArray(vertices[i]).normalize(); } var cg = chamferGeometry(vectors, faces, chamfer); var geom = createGeometry(cg.vectors, cg.faces, radius, tab, af); //const geom = createGeometry(vectors, faces, radius, tab, af); // Without chamfer geom.cannonShape = createShape(vectors, faces, radius); return geom; } exports.createDiceGeometry = createDiceGeometry; function calculateTextureSize(approx) { return Math.pow(2, Math.floor(Math.log(approx) / Math.log(2))); } exports.calculateTextureSize = calculateTextureSize; function randomizeVector(vector) { var randomAngle = rng() * Math.PI / 5 - Math.PI / 5 / 2; var vec = new three_1.Vector2(vector.x * Math.cos(randomAngle) - vector.y * Math.sin(randomAngle), vector.x * Math.sin(randomAngle) + vector.y * Math.cos(randomAngle)); if (vec.x == 0) vec.x = 0.01; if (vec.y == 0) vec.y = 0.01; return vec; } exports.randomizeVector = randomizeVector; //# sourceMappingURL=dicelib.js.map