let points = [[0.3971449136734009, 0.2810116410255432, -0.3767290413379669], [0.23243144154548645, 0.3703259527683258, -0.3767290413379669], [0.30626851320266724, 0.23012861609458923, 0.08654531836509705], [0.15029972791671753, -0.29410237073898315, -0.3767290413379669], [0.3065343499183655, -0.2082172930240631, -0.3767290413379669], [0.3111562132835388, -0.06059299036860466, 0.13771235942840576], [0.16147799789905548, -0.09371967613697052, 0.23468825221061707], [0.36976975202560425, 0.12388059496879578, 0.08632178604602814], [0.31842663884162903, -0.019846681505441666, 0.3223131597042084], [0.20939035713672638, 0.15419937670230865, 0.2242213636636734], [0.17552560567855835, 0.012471526861190796, 0.27797016501426697], [0.16723567247390747, 0.1499461680650711, -0.3767290413379669], [0.4233801066875458, 0.1499461680650711, -0.3767290413379669], [0.3200271725654602, -0.22131121158599854, 0.026444125920534134], [0.15823997557163239, -0.25929194688796997, 0.0673588365316391], [0.44944703578948975, 0.1499461680650711, -0.06793694198131561], [0.2280614674091339, 0.36611324548721313, -0.2975170314311981], [0.38751867413520813, 0.2724340260028839, -0.293896347284317], [0.2147921323776245, 0.3551100790500641, -0.2049424648284912], [0.3594103455543518, 0.2775343060493469, -0.19233158230781555], [0.0, 0.42153987288475037, -0.2989161014556885], [0.0, 0.4475290775299072, -0.3767290413379669], [0.0, 0.10908085107803345, 0.23466001451015472], [0.0, -0.29616573452949524, 0.08896146714687347], [0.0, 0.1499461680650711, -0.3767290413379669], [0.0, -0.1545914262533188, 0.23468825221061707], [0.0, 0.012471422553062439, 0.28773677349090576], [0.0, -0.29410237073898315, -0.3767290413379669], [0.0, 0.3850858211517334, -0.2098153829574585], [0.15266574919223785, 0.33635783195495605, 0.08654531091451645], [0.0, 0.34858277440071106, 0.08654531836509705], [0.3163855969905853, -0.30245065689086914, -0.2832803726196289], [0.15313652157783508, -0.3652721643447876, -0.2640822231769562], [0.43641358613967896, 0.1499461680650711, -0.2795500159263611], [0.0, -0.3652721643447876, -0.2640821933746338], [0.3884555399417877, 0.012471545487642288, -0.3767290413379669], [0.34046298265457153, 0.012471519410610199, 0.11201705783605576], [0.1587677001953125, 0.01247154176235199, -0.3767290413379669], [0.384737104177475, 0.012471544556319714, -0.026815753430128098], [0.0, 0.012471549212932587, -0.3767290413379669], [0.39989548921585083, 0.012471545487642288, -0.30725497007369995], [-0.3971449136734009, 0.2810116410255432, -0.3767290413379669], [-0.23243144154548645, 0.3703259527683258, -0.3767290413379669], [-0.30626851320266724, 0.23012861609458923, 0.08654531836509705], [-0.15029972791671753, -0.29410237073898315, -0.3767290413379669], [-0.3065343499183655, -0.2082172930240631, -0.3767290413379669], [-0.3111562132835388, -0.06059299036860466, 0.13771235942840576], [-0.16147799789905548, -0.09371967613697052, 0.23468825221061707], [-0.36976975202560425, 0.12388059496879578, 0.08632178604602814], [-0.31842663884162903, -0.019846681505441666, 0.3223131597042084], [-0.20939035713672638, 0.15419937670230865, 0.2242213636636734], [-0.17552560567855835, 0.012471526861190796, 0.27797016501426697], [-0.16723567247390747, 0.1499461680650711, -0.3767290413379669], [-0.4233801066875458, 0.1499461680650711, -0.3767290413379669], [-0.3200271725654602, -0.22131121158599854, 0.026444125920534134], [-0.15823997557163239, -0.25929194688796997, 0.0673588365316391], [-0.44944703578948975, 0.1499461680650711, -0.06793694198131561], [-0.2280614674091339, 0.36611324548721313, -0.2975170314311981], [-0.38751867413520813, 0.2724340260028839, -0.293896347284317], [-0.2147921323776245, 0.3551100790500641, -0.2049424648284912], [-0.3594103455543518, 0.2775343060493469, -0.19233158230781555], [-0.15266574919223785, 0.33635783195495605, 0.08654531091451645], [-0.3163855969905853, -0.30245065689086914, -0.2832803726196289], [-0.15313652157783508, -0.3652721643447876, -0.2640822231769562], [-0.43641358613967896, 0.1499461680650711, -0.2795500159263611], [-0.3884555399417877, 0.012471545487642288, -0.3767290413379669], [-0.34046298265457153, 0.012471519410610199, 0.11201705783605576], [-0.1587677001953125, 0.01247154176235199, -0.3767290413379669], [-0.384737104177475, 0.012471544556319714, -0.026815753430128098], [-0.39989548921585083, 0.012471545487642288, -0.30725497007369995]]; const connections = [[0, 1], [0, 12], [0, 17], [1, 11], [1, 16], [1, 21], [2, 7], [2, 9], [2, 19], [2, 29], [3, 4], [3, 27], [3, 32], [3, 37], [4, 31], [4, 35], [5, 6], [5, 8], [5, 13], [5, 36], [6, 8], [6, 10], [6, 14], [6, 25], [7, 8], [7, 9], [7, 15], [7, 36], [8, 9], [8, 10], [8, 36], [9, 10], [9, 22], [9, 29], [10, 26], [11, 12], [11, 24], [11, 37], [12, 33], [12, 35], [13, 14], [13, 31], [13, 38], [14, 23], [14, 32], [15, 19], [15, 33], [15, 38], [16, 17], [16, 18], [16, 20], [17, 19], [17, 33], [18, 19], [18, 28], [18, 29], [20, 21], [20, 28], [20, 57], [21, 24], [21, 42], [22, 26], [22, 30], [22, 50], [23, 25], [23, 34], [23, 55], [24, 39], [24, 52], [25, 26], [25, 47], [26, 51], [27, 34], [27, 39], [27, 44], [28, 30], [28, 59], [29, 30], [30, 61], [31, 32], [31, 40], [32, 34], [33, 40], [34, 63], [35, 37], [35, 40], [36, 38], [37, 39], [38, 40], [39, 67], [41, 42], [41, 53], [41, 58], [42, 52], [42, 57], [43, 48], [43, 50], [43, 60], [43, 61], [44, 45], [44, 63], [44, 67], [45, 62], [45, 65], [46, 47], [46, 49], [46, 54], [46, 66], [47, 49], [47, 51], [47, 55], [48, 49], [48, 50], [48, 56], [48, 66], [49, 50], [49, 51], [49, 66], [50, 51], [50, 61], [52, 53], [52, 67], [53, 64], [53, 65], [54, 55], [54, 62], [54, 68], [55, 63], [56, 60], [56, 64], [56, 68], [57, 58], [57, 59], [58, 60], [58, 64], [59, 60], [59, 61], [62, 63], [62, 69], [64, 69], [65, 67], [65, 69], [66, 68], [68, 69]]; const blobcatColor = { light: "#df8e1d", dark: "#f9e2af" } const focalLength = 1; const radians = (2 * Math.PI / 360) * 3; const rotationalMatrix = [ [Math.cos(radians), -Math.sin(radians), 0], [Math.sin(radians), Math.cos(radians), 0], [0, 0, 1] ] let blobcatElement = null; function dot(a, b) { const rows = a.length; const colsA = a[0].length; const colsB = b[0].length; const result = Array.from({ length: rows }, () => Array(colsB).fill(0)); for (let i = 0; i < rows; i++) { for (let j = 0; j < colsB; j++) { for (let k = 0; k < colsA; k++) { result[i][j] += a[i][k] * b[k][j]; } } } return result; } function getLine( x1, y1, x2, y2, multiply, offsetX, offsetY, zIndex ) { let hr = document.createElement("hr"); x1 = x1 * multiply; y1 = y1 * multiply; x2 = x2 * multiply; y2 = y2 * multiply; hr.style.position = "absolute"; hr.style.left = `${x1 + offsetX}px`; hr.style.top = `${y1 + offsetY}px`; hr.style.height = `1px`; hr.style.width = `${Math.sqrt(((x2-x1) * (x2-x1)) + ((y2-y1) * (y2-y1)))}px`; hr.style.rotate = `${Math.atan2(y2 - y1, x2 - x1)}rad`; hr.style.transformOrigin = `0 0.5px`; hr.style.backgroundColor = light ? blobcatColor.light : blobcatColor.dark; hr.style.border = "0"; hr.style.zIndex = zIndex return hr; } function blobcatFrame() { if (!blobcatElement || !WINDOWS.blob) { return; } let screenCoordinates = points.map((a) => ([ (focalLength * a[0]) / (a[1] + focalLength), -(focalLength * a[2]) / (a[1] + focalLength) ])); let hrElements = connections.map((a) => ( getLine(...screenCoordinates[a[0]], ...screenCoordinates[a[1]], 300, WINDOWS.blob.width / 2 + 11, WINDOWS.blob.height / 2 + 11, WINDOWS.blob.zIndex) )); blobcatElement.innerHTML = ""; blobcatElement.append(...hrElements); points = dot(points, rotationalMatrix); } function createBlob() { createWindow({ id: "blob", title: "~/spinny-cat", content: "
", onDestroy: destroyBlob, height: 450 }); blobcatElement = document.getElementById("blobcat"); } function destroyBlob() { blobcatElement = null; } setInterval(blobcatFrame, 1000 / 30);