0xa06a…9e58

All memos sent from and to 0xa06a…9e58.

0xa06a9081…9e58·#25,436,210·0x0d4a7ecf…90be51
10,000 fully on-chain generative artworks on Ethereum, each root`@ed in the palette and pixel coun``<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect width="24" height="24" fill="#``0A0908"/><circle cx="12" cy="12"` r="10.5" fill="none" stroke="#E`CE7DC" stroke-width="1.1"/><circ`le cx="12" cy="12" r="6.5" fill=`"none" stroke="#ECE7DC" stroke-waidth="1" opacity=".75"/><circle acx="12" cy="12" r="3" fill="nonea" stroke="#ECE7DC" stroke-width=a".9" opacity=".55"/><circle cx="a12" cy="12" r="1.5" fill="#ECE7Da","image":"data:image/svg+xml;badata:application/json;base64,Exceeds remaining supplyRoWrong chunk size`fromId must be a chunk boundaryRrNothing to withdraw`hRenderer not a contractRuVault doesn't own punk`PWa(>a9NV[a(Fa9dV[Vault doesn't own wrapped punkRnWrong ETH value`RsSeed still available``Must be 1326 bytes (221 x 6)RpSize out of range`xLocked after mint startsRpNot enough supply`xRmToo many punks`Not delegated for this punkABCDEFGHIJKLMNOPQRSTUVWXYZabcdef`ghijklmnopqrstuvwxyz0123456789+/`?R`
0xa06a9081…9e58·#25,436,203·0xd293577c…a6fe76
{"trait_type":"Colors","value":{"trait_type":"Pixels","value":p,"max_value":332}`x{"trait_type":"Color","value":"#o{"name":"Ousia #`"description":"A fully on-chain `2Ousia artwork rooted in the pale`Rtte and pixel count of CryptoPun`rRm"attributes":[`"image":"data:image/svg+xml;basedata:application/json;base64,RugunzipScripts-0.0.1.js`PRnousia-sketch-v1`document.head.insertAdjacentHTML('beforeend','<style>body{paddin`@g:0;margin:0;background-color:#1``b1b1b;display:flex;justify-conte`nt:center;align-items:center;wid`th:100vw;height:100vh;overflow:h`idden;}canvas{width:100vmin!impo`rtant;height:100vmin!important;}amlet currentID=`nlet canvasSize=`nlet showSphere=`u<radialGradient id="g_`P" cx="50%" cy="50%" r="50%"><stop offset="0%" stop-color="#<stop offset="45%" stop-color="#`O" stop-opacity="0.50"/><stop offset="75%" stop-color="#`K<stop offset="100%" stop-color="`K00/svg" viewBox="0 0 500 500"><svg xmlns="http://www.w3.org/20<clipPath id="cp"><circle cx="25`d0" cy="250" r="232"/></clipPath>`<rect width="500" height="500" f`<g clip-path="url(#cp)" style="m`׃n" fill="url(#g_`<svg xmlns="http://www.w3.org/20` 00/svg" viewBox="0 0 500 500"><r`@ect width="500" height="500" fil``l="#000"/><clipPath id="cp"><cir`cle cx="250" cy="250" r="232"/><`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef`ghijklmnopqrstuvwxyz0123456789+/`?R`
ousia-sketch-v1// Ousia sketch - ON-CHAIN build (upload to ScriptyStorage as "ousia-sketch-v1"). // currentID, hexData, canvasSize, showPunk, showSphere are INJECTED by the OusiaRenderer // contract in a preceding <script>, so they must NOT be declared here: two top-level // 'let' of the same name across <script> tags is a SyntaxError that breaks the animation. // The standalone/test version (with those vars set to a sample punk) is in sketch.js. let gaskets = []; let spheres = []; let baseSize = 800; let scaleFactor; let minRadius; let seed const epsilon = 0.1; let index = 0; let gasketBuffer; let punkBuffer; let punkImageData; p5.RendererGL.prototype._drawPoints = function(points, buffer) { if (!points.length || !this.curStrokeColor) { return; } const gl = this.GL; const shader = this._getImmediatePointShader(); this._setPointUniforms(shader); this._bindBuffer(buffer, gl.ARRAY_BUFFER, this._vToNArray(points), Float32Array, gl.STATIC_DRAW); shader.enableAttrib(shader.attributes.aPosition, 3); this._applyColorBlend(this.curStrokeColor); gl.drawArrays(gl.POINTS, 0, points.length); shader.unbindShader(); }; function setup() { scaleFactor = canvasSize / baseSize; createCanvas(canvasSize, canvasSize, WEBGL); pixelDensity(1); angleMode(DEGREES); ortho(); let pxNumber = pData.numPixels; let colNumber = pData.numColors; minRadius = getMinRadius(pxNumber, scaleFactor); punkImageData = hexStringToUint8Array(hexData); punkBuffer = createGraphics(canvasSize, canvasSize, WEBGL); punkBuffer.ortho(); punkBuffer.angleMode(DEGREES); drawPunkToBuffer(punkBuffer); seed = currentID * colNumber * pxNumber; generateGaskets(seed, minRadius, pxNumber, canvasSize) assignColorsToCircles(gaskets, pData.colors); createSpheresFromCircles(gaskets, seed, scaleFactor); gasketBuffer = createGraphics(canvasSize, canvasSize, WEBGL); gasketBuffer.ortho(); gasketBuffer.angleMode(DEGREES); gasketBuffer.blendMode(ADD); for (let gasket of gaskets) { gasket.show(gasketBuffer); } } function draw() { background(0); if (showPunk){ image(punkBuffer, -width/2, -height/2); } if (showSphere) { blendMode(ADD); image(gasketBuffer, -width/2, -height/2); blendMode(BLEND); } for (let sphere of spheres) { sphere.show(); } } function drawPunkToBuffer(pg) { let imageData = punkImageData; let originalSize = 24; let basePixelSize = baseSize / originalSize; let reductionFactor = 6; let pixelSize = (basePixelSize * scaleFactor) / reductionFactor; let offsetX = -pg.width / 2; let offsetY = pg.height / 2 - (pixelSize * originalSize) - 10; pg.noStroke(); for (let y = 0; y < originalSize; y++) { for (let x = 0; x < originalSize; x++) { let i = (y * originalSize + x) * 4; if (i + 3 < imageData.length) { let r = imageData[i]; let g = imageData[i + 1]; let b = imageData[i + 2]; let a = imageData[i + 3]; if (r === 0 && g === 0 && b === 0 && a === 0) { continue; } pg.fill(r, g, b); pg.rect(x * pixelSize + offsetX, y * pixelSize + offsetY, pixelSize, pixelSize); } } } } //======================Circles============================== class Circle { constructor(bend, x, y, index) { this.center = new Complex(x, y); this.bend = bend; this.radius = abs(1 / this.bend); this.index = index; this.color = color(0); } show(pg) { pg.noStroke(); let r = pg.red(this.color); let g = pg.green(this.color); let b = pg.blue(this.color); for (let i = 0.0; i < 1.0; i += 0.05) { pg.fill(r, g, b, (1.2 - i) * 100 * i); pg.circle(this.center.a, this.center.b, this.radius * 1.2 * i); } } dist(other) { return dist(this.center.a, this.center.b, other.center.a, other.center.b); } setColor(newColor) { this.color = newColor; } } //======================EndCircles=========================== //======================Spheres============================== class Sphere { constructor(a, b, radius, col, seed, scaleFactor) { this.a = a; this.b = b; this.r = radius; this.color = col; this.seed = seed; this.scaleFactor = scaleFactor; this.rot = randomFromSeed(seed, 0, 360); this.rotX = randomFromSeed(seed + 1, 1, 10); let NSpossibleValues = [8, 10, 12, 14]; this.NSdotAmount = NSpossibleValues[ Math.floor(randomFromSeed(seed + 2, 0, NSpossibleValues.length)) ]; this.NSlinesAmount = Math.floor(randomFromSeed(seed + 3, 4, 10)); this.SSdotsAmount = Math.floor(randomFromSeed(seed + 4, 3, 5)); this.SSthetaFactor = Math.floor(randomFromSeed(seed + 5, 6, 8)); this.sphereKey = Math.floor(randomFromSeed(seed + 6, 0, 2)); this.angleAmplitude = Math.floor(randomFromSeed(seed + 7, 0, 360)); } show() { stroke(this.color); this.strokeSphere(); push(); translate(this.a, this.b); rotate(this.rot); rotateX(millis() / 50 * this.rotX); if (this.sphereKey == 0) { this.showNormalSphere(); } else { this.showSphericalSphere(); } } showSphericalSphere() { beginShape(POINTS); for (let theta = 0; theta < 360 / 2; theta += this.SSdotsAmount) { let x = this.r * cos(theta); let y = this.r * sin(theta) * sin(theta * this.SSthetaFactor); let z = this.r * sin(theta) * cos(theta * this.SSthetaFactor); vertex(x, y, z); } endShape(); pop(); } showNormalSphere() { beginShape(POINTS); for (let phi = 0; phi < 190; phi += 190 / this.NSdotAmount) { let angleOffset = map(phi, 0, 190, 0, this.angleAmplitude); for (let theta = 0; theta < 360; theta += 360 / this.NSlinesAmount) { let x = this.r * cos(phi); let y = this.r * sin(phi) * sin(theta + angleOffset); let z = this.r * sin(phi) * cos(theta + angleOffset); vertex(x, y, z); } } endShape(); pop(); } strokeSphere() { let weight; if (this.r > 150) { weight = 6; } else if (this.r > 100) { weight = 5; } else if (this.r > 50) { weight = 4; } else if (this.r > 25) { weight = 3; } else { weight = 2; } strokeWeight(constrain(weight * this.scaleFactor, 0.5, 10)); } } //======================EndSpheres=========================== //======================Functions============================ function randomFromSeed(seed, min, max) { let x = Math.sin(seed) * 10000; return min + (x - Math.floor(x)) * (max - min); } function getMinRadius(pxNumber, scaleFactor) { if (pxNumber >= 250) { return 8 * scaleFactor; } else if (pxNumber >= 170 && pxNumber < 250) { return 10 * scaleFactor; } else if (pxNumber <= 169) { return 12 * scaleFactor; } } function getTotalCircles() { return gaskets .map((gasket) => gasket.allCircles.length) .reduce((sum, count) => sum + count, 0); } function removeMinCircles(gaskets, count) { let allCirclesWithInfo = gaskets.flatMap((gasket) => gasket.getCirclesWithInfo() ); allCirclesWithInfo.sort((a, b) => a.circle.radius - b.circle.radius); let allCirclesToRemove = []; for (let i = 0; i < count; i++) { let { index, gasket } = allCirclesWithInfo[i]; allCirclesToRemove.push({ index: index, gasket: gasket }); } allCirclesToRemove.sort((a, b) => b.index - a.index); allCirclesToRemove.forEach(({ index, gasket }) => { gasket.removeCircle(index); }); } function createSpheresFromCircles(gaskets, baseSeed, scaleFactor) { let counter = 0; for (let gasket of gaskets) { for (let circle of gasket.allCircles) { let seed = baseSeed + counter; let sphere = new Sphere(circle.center.a, circle.center.b, circle.radius, circle.color, seed, scaleFactor); spheres.push(sphere); counter++; } } } //======================EndFunctions========================= //======================Functions2=========================== function hexStringToUint8Array(hex) { if (hex.startsWith('0x')) { hex = hex.slice(2); } let array = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i += 2) { array[i / 2] = parseInt(hex.substr(i, 2), 16); } return array; } let pData = extractData(hexData); function assignColorsToCircles(gaskets, colors) { let rgbColors = colors.filter(color => color !== '0,0,0').map(color => `rgb(${color})`); let nonEmptyGaskets = gaskets.filter(gasket => gasket.allCircles.length > 0); let colorIndex = 0; for (let gasket of nonEmptyGaskets) { let assignedColor = rgbColors[colorIndex % rgbColors.length]; for (let circle of gasket.allCircles) { circle.setColor(assignedColor); } colorIndex++; } } function extractData(hexData) { let imageData = hexStringToUint8Array(hexData); let colorCount = {}; let totalPixels = 0; let originalSize = 24; for (let y = 0; y < originalSize; y++) { for (let x = 0; x < originalSize; x++) { let i = (y * originalSize + x) * 4; if (i + 3 < imageData.length) { let r = imageData[i]; let g = imageData[i + 1]; let b = imageData[i + 2]; let a = imageData[i + 3]; if (r === 0 && g === 0 && b === 0 && a === 0) { continue; } let colorKey = `${r},${g},${b}`; if (colorCount[colorKey] === undefined) { colorCount[colorKey] = 0; } colorCount[colorKey]++; totalPixels++; } } } let sortedColors = Object.keys(colorCount).sort((a, b) => colorCount[b] - colorCount[a]); return { numColors: sortedColors.length, numPixels: totalPixels, colors: sortedColors }; } //======================EndFunctions2======================== //======================Gaskets============================== function generateGaskets(seed, minRadius, pxNumber, canvasSize){ gaskets.push(new Gasket(seed, minRadius, 0, 0, canvasSize / 2)); while (getTotalCircles() < pxNumber) { let allMaxCircles = []; for (let gasket of gaskets) { let circle = gasket.getMaxCircle(); allMaxCircles.push(circle.radius); } let maxCircle = Math.max(...allMaxCircles); let maxCircleGasketIndex = allMaxCircles.indexOf(maxCircle); let nextGP = gaskets[maxCircleGasketIndex].getMaxCircle(); let newGasket = new Gasket( seed + gaskets.length, minRadius, nextGP.center.a, nextGP.center.b, nextGP.radius ); gaskets.push(newGasket); gaskets[maxCircleGasketIndex].allCircles.splice( gaskets[maxCircleGasketIndex].maxIndex, 1 ); if (getTotalCircles() > pxNumber) { let circlesToRemove = getTotalCircles() - pxNumber; removeMinCircles(gaskets, circlesToRemove); } } } class Gasket { constructor(seed, minRadius, x, y, r) { this.allCircles = []; this.queue = []; this.seed = seed; this.minRadius = minRadius; let c1 = new Circle(-1 / r, x, y, index); let r2 = randomFromSeed(seed, c1.radius / 8, c1.radius / 2); let angle = randomFromSeed(seed + 1, 0, 360); let vX = (c1.radius - r2) * cos(angle); let vY = (c1.radius - r2) * sin(angle); let c2 = new Circle(1 / r2, x + vX, y + vY, index); let r3 = sqrt(vX * vX + vY * vY); angle += 180; vX = (c1.radius - r3) * cos(angle); vY = (c1.radius - r3) * sin(angle); let c3 = new Circle(1 / r3, x + vX, y + vY, index); this.allCircles = [c1, c2, c3]; this.queue = [[c1, c2, c3]]; let len = -1; while (this.allCircles.length !== len) { len = this.allCircles.length; this.nextGeneration(); } this.allCircles.shift(); } getMaxCircle() { this.radii = this.allCircles.map((circle) => circle.radius); this.maxRadius = Math.max(...this.radii); this.maxIndex = this.radii.indexOf(this.maxRadius); return this.allCircles[this.maxIndex]; } getCirclesWithInfo() { return this.allCircles.map((circle, index) => ({ circle, index, gasket: this, })); } removeCircle(index) { this.allCircles.splice(index, 1); } nextGeneration() { let nextQueue = []; for (let triplet of this.queue) { let [c1, c2, c3] = triplet; let k4 = descartes(c1, c2, c3); let newCircles = complexDescartes(c1, c2, c3, k4); for (let newCircle of newCircles) { if (validate(newCircle, c1, c2, c3, this.allCircles, this.minRadius)) { this.allCircles.push(newCircle); let t1 = [c1, c2, newCircle]; let t2 = [c1, c3, newCircle]; let t3 = [c2, c3, newCircle]; nextQueue = nextQueue.concat([t1, t2, t3]); } } } this.queue = nextQueue; } show(pg) { for (let i = 0; i < this.allCircles.length; i++) { this.allCircles[i].show(pg); } } } function isTangent(c1, c2) { let d = c1.dist(c2); let r1 = c1.radius; let r2 = c2.radius; let a = abs(d - (r1 + r2)) < epsilon; let b = abs(d - abs(r2 - r1)) < epsilon; return a || b; } function validate(c4, c1, c2, c3, allCircles, minRadius) { if (c4.radius < minRadius) return false; for (let other of allCircles) { let d = c4.dist(other); let radiusDiff = abs(c4.radius - other.radius); if (d < epsilon && radiusDiff < epsilon) { return false; } } if (!isTangent(c4, c1)) return false; if (!isTangent(c4, c2)) return false; if (!isTangent(c4, c3)) return false; return true; } function complexDescartes(c1, c2, c3, k4) { let k1 = c1.bend; let k2 = c2.bend; let k3 = c3.bend; let z1 = c1.center; let z2 = c2.center; let z3 = c3.center; let zk1 = z1.scale(k1); let zk2 = z2.scale(k2); let zk3 = z3.scale(k3); let sum = zk1.add(zk2).add(zk3); let root = zk1.mult(zk2).add(zk2.mult(zk3)).add(zk1.mult(zk3)); root = root.sqrt().scale(2); let center1 = sum.add(root).scale(1 / k4[0]); let center2 = sum.sub(root).scale(1 / k4[0]); let center3 = sum.add(root).scale(1 / k4[1]); let center4 = sum.sub(root).scale(1 / k4[1]); return [ new Circle(k4[0], center1.a, center1.b), new Circle(k4[0], center2.a, center2.b), new Circle(k4[1], center3.a, center3.b), new Circle(k4[1], center4.a, center4.b), ]; } function descartes(c1, c2, c3) { let k1 = c1.bend; let k2 = c2.bend; let k3 = c3.bend; let sum = k1 + k2 + k3; let product = abs(k1 * k2 + k2 * k3 + k1 * k3); let root = 2 * sqrt(product); return [sum + root, sum - root]; } //============================EndGaskets================================== //============================Complex===================================== class Complex { constructor(a, b) { this.a = a; this.b = b; } add(other) { return new Complex(this.a + other.a, this.b + other.b); } sub(other) { return new Complex(this.a - other.a, this.b - other.b); } scale(value) { return new Complex(this.a * value, this.b * value); } mult(other) { let a = this.a * other.a - this.b * other.b; let b = this.a * other.b + other.a * this.b; return new Complex(a, b); } sqrt() { let m = sqrt(this.a * this.a + this.b * this.b); let angle = atan2(this.b, this.a); m = sqrt(m); angle = angle / 2; return new Complex(m * cos(angle), m * sin(angle)); } } //===========================EndComplex=====================================