Skip to content

art

August 26 2023

Hearthstone Battlegrounds has this knack, it's sticky.




T-KT goes great here


Hearthstone Battlegrounds has this knack, it's sticky. Twice, you place seventh. Tough luck, you think. Two rounds straight, both no cigar. Your mind tickles towards, what's the point? A whisper of giving it up. Then, bam, you land first or second. Pride swells. A soft glow envelops you. You're hooked. You want more. You can't stop.

These fuckers at Blizzard really nailed the Gambler's Fallacy lmao.

But unlike the casino where the house always wins, no one wins (outside of useless MMR)


another Rajiv W


bramdroid/invocation.js at main · bramses/bramdroid
Contribute to bramses/bramdroid development by creating an account on GitHub.
added user quota logic for smart commands – all stored in a local json file!



never forget sora chopping actual buildings in half like tofu


the bot auto links books now
vorticism

August 25 2023

and perhaps a discord was born?

Mulling over a comfy spot for my small projects, I had a twinkling—Discord could be it. Each bot could handle its own chore, instead of firing up a whole stack.

The good parts are clear as day:

  • It works with mobile and desktop.
  • Any user could get chummy with their own curated list of bots.
  • No need to craft baffling UIs for mainly, well, text-based tasks—like function calls or database lookups.
  • I've long since resolved that the output of p5 makes more sense as pictures or movies than code for end users—unless someone wants to sow their own seed data for an image, I can manage that with bots as well.
  • A community? I could grow one.
  • Channel-specific invites, they're a thing.
  • A stable (ish) API.
  • An app store to lure an audience—no need to don the hat of a content creator.
  • Wonky CSS, not my problem.
  • Templates for multiple bots, no sweat.

But, clouds have their silver lining:

  • Running a discord server, well, that's on me.
  • I might lock myself in a discord bot world, straying from the freedom of the open web.

GitHub - bramses/bramdroid
Contribute to bramses/bramdroid development by creating an account on GitHub.

i made so many misplays this game

run a blog instead! stream of conciousness creativity!
the next napoleon will come from the world of bits, not atoms 
mark zuckerberg lore just dropped

An appeal to reason is 80% appeal, 20% reason.


Discord Bot Command Ideas


PSA: BAKI IS BACK – HE'S FINALLY FIGHTING YUJIRO


August 23 2023

Out-of-towners often mistake Manhattan as the whole of NYC, I feel.

Out-of-towners often mistake Manhattan as the whole of NYC, I feel. Take the time to explore spots like Bay Ridge, or Cortelyou Road.

You'll find calm there, perhaps even a surprising dose of the suburban. The real perk of living in an area like Bay Ridge vs a suburb outside of Corpus Christi? A train line linking you straight to the heart of Union Square or Grand Central in under an hour.






This Goes INSANELY HARD
that bass line UGHHH, this whole video is SO GOOD Some of my favorite frames (literally every still frame could be a desktop wallpaper):




When you see those tier 7 minions in your game, do me a favor, grab Tess. Just trust me on this.



your day is just starting!

Kingdom Hearts Menu Style Portfolio
~~ dearly beloved ~~

STYLEEEE

I am the one who decides.




The gallery feature on Ubud is acting up. Beats me why.


Trying out Spear in Discord. Maybe it's something that could tickle the fancy of vault members, make them feel special. Definitely can picture it being a neat bonus!


Another day done, neatly cut into boxes of time. This time block journal, it's kind of become a friend. Excited to think where I might be in a few months - maybe a master at wrestling time.


GPT helps me to write, and I like that. It’s like the words I jot down aren't my own, they’re not precious. So, when it comes to chopping them up and pruning them, I don't flinch. And, there's something cool about typing in shorthand, or even in low key, lowercase letters. GPT just takes it, and churns out sentences that sound as real as rain splattering on a windowpane.

August 22 2023

New season of Hearthstone! Goodbye, next forty-eight hours.

New season of Hearthstone! Goodbye, next forty-eight hours. I'll be captive to this relentless obsession. Alongside Baldur's Gate 3, of course.




This patch, it sucks from the get-go. Bannana Slammas for life, I suppose.

broken combo
only broken enough for fourth place i suppose

The billboards up in Soho stir something within me. Something McLuhan might've coined, about the package being more valuable more than the item inside. The ads on NYC's billboards, uncountable as they are, most fade from memory like a worn-out jazz record. But their very existence on the giant sized wall, catching the eye of the odd twenty-somethings, mid-pilgrimage to their temple of Equinox, that broadcasts its own message. Sure, I could plaster an ad on some wall in a silent town but that lacks the jazz, the hum and pulse of the viewer's gaze, which makes all the difference in selling the song. Plenty artists wallow unseen, only a handful get to wallow under the spotlight.


Leaders need this one thing more than anything else: good sense. It's the same when it comes to your body, your thoughts, your work life. Be your own arbiter of good judgement.


Photos...they've been the game for me on Instagram lately, kind of like a guilty pleasure I suppose. Don't know why.

It's ludicrous when you think about how I'm using Instagram, disregarding entirely how they mapped out the service. Truly not giving a flying fuckkk. It's like a Finstagram, but taken to the logical conclusion of really only using Instagram for a glorified photo storage service. Picture it: me following no one, completely ignoring ads on the feed the company worked so hard on to build! A strange way to play, right?

But in its way, it's transformative. Instagram morphs into something else, a simple yet miraculous platform for my photos, a sanctuary. It's effortless to stick in my favorite tunes too, lending a voice to every image. And the filters? Oh, the filters. An array of options with a single, easy tap. Quite something, isn't it?



Oddly enough, I found myself the central character in some LLM tutorial – an instructional piece about using these LLMs for cold outreach on LinkedIn, of all things. Seeing this offered some clarity, unsheathing the mystery of the spam deluge that keeps finding me. Particularly from the VCs, the constant hum in the background. Leave me alone dammit!


Random post logic – all credit goes to the original creator: milkythemes!

<script>
    function loadScript(url, callback) {
    const head = document.head;
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    script.onreadystatechange = callback;
    script.onload = callback;
    head.appendChild(script);
}

function luckyPost() {
    let ghostVersion = typeof version == 'undefined' ? 'v3.0' : version;
    let apiKey =
        typeof key == 'undefined' ?
            console.error('Ghost integration API key is missing. Please refer to documentation at https://milkythemes.com/plugins/lucky-post') : key;

    const pageUrl = `${window.location.protocol}//${window.location.hostname}`;

    const api = new GhostContentAPI({
        url: pageUrl,
        key: apiKey,
        version: ghostVersion
    });

    const postUrl = [];

    const randomBtn = document.getElementsByClassName("btn-random");
    const stringHostUrl = `[href="${pageUrl}/#rdm-post/"]`
    const randomPost = document.querySelector(stringHostUrl);
    
    const randomPostSelector = document.querySelectorAll('[href="https://www.bramadams.dev/rdm-post/"]');

    for (let i = 0; i < randomPostSelector.length; i++) {
        randomPostSelector[i].text = `Loading...`
    }


    api.posts
        .browse({ limit: 250 })
        .then((posts) => {
            posts.forEach((post) => {
                postUrl.push(post.slug)
            });
        })
        .then(() => {
        const randomPostSelector = document.querySelectorAll('[href="https://www.bramadams.dev/rdm-post/"]');
        
        for (let i = 0; i < randomPostSelector.length; i++) {
            randomPostSelector[i].text = `Open Random Post!`
            randomPostSelector[i].href = `${pageUrl}/${randomUrl(postUrl)}`
        }
            
        }).catch(() => {
    		const randomPostSelector = document.querySelectorAll('[href="https://www.bramadams.dev/rdm-post/"]');
        
            for (let i = 0; i < randomPostSelector.length; i++) {
                randomPostSelector[i].text = `OOPS!`
                randomPostSelector[i].href = `https://www.bramadams.dev/`
            }
    	});

    // The randomUrl function is used to grab a random array from the list 
    function randomUrl(postUrl) {
        return postUrl[Math.floor(Math.random() * postUrl.length)];
    }
}

loadScript('https://unpkg.com/@tryghost/content-api@latest/umd/content-api.min.js', luckyPost);
</script>

Tier 7 exists.


SOMEBODY HAS TO DIE

Blue Lock got dark!


big carbon copy!

Hey, the kid's scored a page on Wikipedia!

Atrioc - Wikipedia

Sticky Header for Ubud! (Put this in the code injection header)

<style>
    .c-header{
        position: sticky;
        z-index: 1;
        top: 0;
        background: var(--background-primary);
    }
</style>

August 21 2023

Instabrams are back baby! Thanks to Alfred, Obsidian, Ghost, and GPT that is!

I found out today that, oddly enough, my dislike for food—and smells, as an offshoot—liberates my ears. I can fill them with all kinds of sounds, just like I fill my mind with all sorts of books. And who knows, this might make my understanding richer, deeper. After all, tastes and sounds, they both bring in similar complexities, don't they? What's the science behind this, I wonder?


Planning with time blocks using the Time Block Planner is something else, I tell you. Just staring at how my hours roll out in reality, versus where I believe in my mind that they're going.

It really makes me treasure those fresh hours each morning when I draft the plan. But, damn it, they do race by like comets while I'm knee-deep in living them. Sure makes one thing clear though - there's still quite a road ahead of me to align my time better with the stuff that sits front-row in my priorities.


Today, I cranked out a couple scripts that just might fan the flame back into my inconsistent habit of creating Instabrams. Knocked up one heck of a pipeline for DALL-E, taking chunky texts, wringing them dry into neat, crisp summaries, and morphing them into fetching cover art.

Then there's the second script. What does it do? Well, simple: it chews up shorthand blurb, like the one you're picking through now, and spits it back out in the flavor of a certain author close to my heart, our man Murakami himself. Now, you can sneak a peek at both these scripts down below and take in the art piece a notch above.

Both scripts neatly tuck away the outputs onto my clipboard. Handy for the lazybones that like me, can use ‘em just about anywhere across the machine. Embrace sloth!

i wrote two scripts today that should hopefully harken the return of instabrams. i created a dall-e pipeline that takes text, summarizes it and turns into a cover art.
in addition i wrote a script that rewrites shorthand like you are reading now into the style of one of my favorite authors, haurki muarkami. you can see both of the scripts below, and the art for this peice in the image above.
importantly, both copy results to clipboard for usage anywhere across my machine. let's go laziness!

Really would be nowhere without these amazing tools that devs have built (Ghost, Obsidian, GPT). I merely build the ligaments that connect the very solid bones.


GitHub rang the bell for the 700th star on chat gpt md today. It's been awhile since any updates were added, and I can't help but feel a twinge of regret. But the open source world - well, it can be a free ride for some folks, especially amongst the Obsidian folks. It's like being a chef with everyone sampling your soup, but no one foots the bill.

there was an enormous disconnect between how we think open source works and what is actually happening on the ground today. There is a long, and growing, tail of projects that don’t fit the typical model of collaboration. Such projects include Bootstrap, a popular design framework used by an estimated 20% of all websites, where three developers have authored over 73% of commits. Another example is Godot, a software framework for making games, where two developers respond to more than 120 issues opened on their project per week.† -- Working in Public: The Making and Maintenance of Open Source Software

Create a Ghost Cover Image with DallE

import dotenv from "dotenv";
dotenv.config();

import OpenAI from "openai";
import clipboard from "clipboardy";
import fs from "fs";
import fetch from "node-fetch";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function summarizeClipboard() {
  const text = clipboard.readSync();
  // console.log(`Summarizing: ${text}`);
  const completion = await openai.chat.completions.create({
    messages: [
      {
        role: "system",
        content:
          "Summarize the following into a theme and create an art prompt from the feel of the text aesthetically along the lines of: 'an abstract of [some unique lesser known art style from history] version of {x}' where x is the feel of the text aesthetically. Just return the art prompt, say nothing else." +
          text,
      },
    ],
    model: "gpt-4",
  });

  // console.log(`Summary: ${completion.choices[0].message.content}`);

  return completion.choices[0].message.content;
}

async function saveImgFromUrl(url) {
  const response = await fetch(url);
  const buffer = await response.buffer();
  const filename = `./dalle-images/${Date.now()}.jpg`;
  fs.writeFile(filename, buffer, () => console.log("finished downloading!"));

  return filename;
}

async function appendToLog(logItem) {
  const log = JSON.parse(fs.readFileSync("./log.json"));
  log.push(logItem);
  fs.writeFileSync("./log.json", JSON.stringify(log, null, 2));
}

async function main() {
  let prompt = await summarizeClipboard();
  prompt = prompt.replace("Art Prompt: ", "").trim();
  const image = await openai.images.generate({ prompt: prompt });
  const imageUrl = image.data[0].url;

  const imgFilename = await saveImgFromUrl(imageUrl);

  const log = {
    query: clipboard.readSync(),
    prompt: prompt,
    imageUrl: imageUrl,
    imgFilename: imgFilename,
  };

  await appendToLog(log);

  // save prompt to clipboard
  clipboard.writeSync(prompt);
  console.log("./dalle-images/" + imgFilename.replace("./dalle-images/", ""));
}
main();

Rewrite Chicken Scratch as Murakami

import dotenv from "dotenv";
dotenv.config();

import OpenAI from "openai";
import clipboard from "clipboardy";
import fs from "fs";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function rewriteClipboard() {
  const text = clipboard.readSync();
  // console.log(`Rewriting: ${text}`);
  const completion = await openai.chat.completions.create({
    messages: [
      {
        role: "system",
        content:
          "Rewrite the following in the style of Haruki Murakami, using short, punchy, easy to read, simple words that flow. Almost as if spoken cadence. Text:\n" +
          text,
      },
    ],
    model: "gpt-4",
  });

  // console.log(`Rewrite: ${completion.choices[0].message.content}`);

  return completion.choices[0].message.content;
}

async function appendToLog(logItem) {
  const log = JSON.parse(fs.readFileSync("./log.json"));
  log.push(logItem);
  fs.writeFileSync("./log.json", JSON.stringify(log, null, 2));
}

async function main() {
  let prompt = await rewriteClipboard();
  prompt = prompt.replace("Rewrite: ", "").trim();

  const log = {
    query: clipboard.readSync(),
    prompt: prompt,
  };

  await appendToLog(log);

  // save prompt to clipboard
  clipboard.writeSync(prompt);
  console.log("Prompt saved to clipboard");
}
main();

Images From the Script

These have wriggled under my skin, becoming my favorites of the day. You can make buckets of them without breaking much of a sweat. Keep your eyes on the blog – there's more visual feast on the way!

https://bram-adams.ghost.io/content/images/2023/08/bramses_A_Futurism-style_depiction_of_an_abstract_human_figure__e79092cb-85c9-455b-a712-c383189f701b.png
bramses_A_Futurism-style_depiction_of_an_abstract_human_figure__e79092cb-85c9-455b-a712-c383189f701b.png
https://bram-adams.ghost.io/content/images/2023/08/bramses_Art_Prompt_Create_a_Tonalist_and_Symbolist_fusion_manif_17f75554-e2fc-449e-8380-9f44cd92965c.png
bramses_Art_Prompt_Create_a_Tonalist_and_Symbolist_fusion_manif_17f75554-e2fc-449e-8380-9f44cd92965c.png
https://bram-adams.ghost.io/content/images/2023/08/DALL·E-2023-08-21-15.55.18---Art-Prompt_-Create-a-Tonalist-and-Symbolist-fusion-manifesto-of-an-enchanting-wilderness-filled-with-mystic-animals-and-towering-trees-embodying-the-p.png
DALL·E 2023-08-21 15.55.18 - Art Prompt_ Create a Tonalist and Symbolist fusion manifesto of an enchanting wilderness filled with mystic animals and towering trees embodying the p.png
https://bram-adams.ghost.io/content/images/2023/08/1692647643756.jpg
1692647643756.jpg
https://bram-adams.ghost.io/content/images/2023/08/1692645793636.jpg
1692645793636.jpg
https://bram-adams.ghost.io/content/images/2023/08/DALL·E-2023-08-21-15.21.35---Create-an-abstract-version-of-the-Cubism-style-that-portrays-the-challenges-of-financial-burdens-and-health-care-costs.png
DALL·E 2023-08-21 15.21.35 - Create an abstract version of the Cubism style that portrays the challenges of financial burdens and health care costs.png
https://bram-adams.ghost.io/content/images/2023/08/DALL·E-2023-08-21-15.13.12---Create-an-abstract-watercolor-version-of-the-constant-struggle-between-the-expansion-and-collapse-of-the-mind.-Use-vibrant-colors-and-fluid-brushstrok.png
DALL·E 2023-08-21 15.13.12 - Create an abstract watercolor version of the constant struggle between the expansion and collapse of the mind. Use vibrant colors and fluid brushstrok.png
https://bram-adams.ghost.io/content/images/2023/08/bramses_An_abstract_Quilting_Art_version_of_the_intersection_be_bfa3dc6d-2abb-4e57-8699-b8970fdbf520.png
bramses_An_abstract_Quilting_Art_version_of_the_intersection_be_bfa3dc6d-2abb-4e57-8699-b8970fdbf520.png

Half a decade past, this is where I lived.

I snapped this photo, and soon after found myself in a nearby bar, nursing a drink and ruminating on the past five years. I had some predictions right - walking away from full-time software engineering to chase dreams of startups and artistry. But there were surprises too - who could've predicted a pandemic, or AI taking great leaps ahead?

I pondered over the goals I set for myself in 2018 - many still unmet, many still echoing around my head. Is that a good thing or a bad thing? Not sure. But one thing I've learnt is this: success is a recipe. It calls for dogged effort, an accreting outlet for said effort (think: investment returns), a dash of lady luck, and being at the right place just when it's the right time. Voila, dreams come true and they'll call it fate.

Like Ging said to Gon, "I can't get there quite yet, but I'm relishing the ride."

"Five years ahead?" I reckon I'll be there, right at the threshold of that old, worn out door of mine.

Oddly enough, it seems as if my eyes on the photo on the right been brushed with a dash of guyliner. Can't make heads or tails of that, honestly.

bramadams.dev is a reader-supported published Zettelkasten. Both free and paid subscriptions are available. If you want to support my work, the best way is by taking out a paid subscription.

Dipping My Toes Back Into Generative Art

A little play with pixel sorting!

I missed this shit! Generative art is so fun!

Expect more stuff like this soon! (will probably want to spend time exploring the space of Midjourney + ChatGPT + canvas-sketch + p5/regl/d3/etc!)

https://bram-adams.ghost.io/content/images/2023/07/2023.07.22-23.13.15.png
2023.07.22-23.13.15.png
https://bram-adams.ghost.io/content/images/2023/07/2023.07.22-23.16.13.png
2023.07.22-23.16.13.png
https://bram-adams.ghost.io/content/images/2023/07/2023.07.22-23.26.54.png
2023.07.22-23.26.54.png

Code

Pixel Sorting and 3D mix chat with GPT
The 3d shape in question
Loading an image into canvas sketch

const canvasSketch = require("canvas-sketch");
const convexHull = require("convex-hull");
const cameraProject = require("camera-project");
const createCamera = require("perspective-camera");
const { mat4, vec3 } = require("gl-matrix");
const BezierEasing = require("bezier-easing");
const load = require("load-asset");
const Random = require("canvas-sketch-util/random");

const settings = {
  duration: 8,
  animate: true,
  playbackRate: "throttle",
  fps: 24,
};

function brightness(r, g, b) {
  return Math.sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
}

// Other helper functions go here...
// ... (stroke, drawCells, drawCellsNoOverlap, createMesh) ...

// A utility that creates a 3D "crystal" mesh
// The return value is { positions, cells }
const createMesh = () => {
    // Our crystal mesh is the convex hull of N random points on a sphere
    const pointCount = 10;
    const radius = 1;
    const positions = Array.from(new Array(pointCount)).map(() => {
      return Random.onSphere(radius);
    });
  
    // Now let's center the mesh by finding its "centroid"
    const centroid = positions.reduce((sum, pos) => {
      return vec3.add(sum, sum, pos);
    }, [ 0, 0, 0 ]);
    if (positions.length >= 1) {
      vec3.scale(centroid, centroid, 1 / positions.length);
    }
  
    // Translate all the points in the mesh away from centroid
    positions.forEach(pos => {
      vec3.sub(pos, pos, centroid);
    });
  
    // And now get the triangles (i.e. cells) of the 3D mesh
    const cells = convexHull(positions);
    return { cells, positions };
  };
  
  // A utility to stroke an array of 2D points
  const stroke = (context, points) => {
    context.beginPath();
    points.forEach(p => context.lineTo(p[0], p[1]));
    context.lineWidth = 3;
    context.lineJoin = 'round';
    context.lineCap = 'round';
    context.strokeStyle = '#fff';
    context.stroke();
  };
  
  // A simple and fast way to draw a mesh of 2D positions and cells (triangles)
  // This will lead to overlapping edges where two triangles meet
  const drawCells = (context, positions, cells) => {
    cells.forEach(cell => {
      // A 'cell' holds indices into our positions array, so get 2D points
      const points = cell.map(i => positions[i]);
  
      // make sure to close the path before drawing the triangle
      points.push(points[0]);
  
      // stroke the path
      stroke(context, points);
    });
  };
  
  // One quick n' dirty way to fix the above issue of overlapping
  // lines is to instead draw each line as a unique segment, like so:
  const drawCellsNoOverlap = (context, positions, cells) => {
    const edgeMap = {};
    cells.forEach(cell => {
      // For each cell, get a pair of edges
      // Give the pair a 'key' name and ensure it is unique
      for (let i = 0; i < cell.length; i++) {
        const a = cell[i];
        const b = cell[(i + 1) % cell.length];
        const edge = [ a, b ].sort();
        const edgeKey = edge.join(':');
        if (!(edgeKey in edgeMap)) {
          edgeMap[edgeKey] = true;
        }
      }
    });
  
    // Get all unique keys and find positions from indices
    const keys = Object.keys(edgeMap);
    keys.forEach(pair => {
      const indices = pair.split(':');
      const points = indices.map(i => positions[i]);
      // Stroke the line segment A->B
      stroke(context, points);
    });
  };

const sketch = async ({ update }) => {
  // Await the image loader, it returns the loaded <img>
  const image = await load("assets/bramses_A_dissected_view_of_a_formidable_metal_vault_its_numero_059f975b-d628-4803-af73-52c8f5707c00.png");


  // Update the output settings to match the image
  update({
    dimensions: [image.width, image.height],
  });

  // Setup a 3D perspective camera
  const camera = createCamera({
    fov: 80 * Math.PI / 180,
    near: 0.01,
    far: 1000,
    viewport: [ 0, 0, image.width, image.height ]
  });

  // Create our 3D mesh
  const { positions, cells } = createMesh();

  // Define some easing functions
  const easeA = new BezierEasing(0.14, 0.28, 0.48, 0.45);
  const easeB = new BezierEasing(0.14, 0.28, 0.67, 0.46);

  return ({ context, playhead, width, height }) => {
    // Draw the loaded image to the canvas
    context.drawImage(image, 0, 0, width, height);

    // Extract bitmap pixel data
    const pixels = context.getImageData(0, 0, width, height);
    const data = pixels.data;

    // Create an array of indices
    const indices = [...Array(data.length / 4).keys()];

    // Sort indices based on pixel brightness
    indices.sort((a, b) => {
      const offsetA = a * 3.4;
      const offsetB = b * 3.93;

      const brightnessA = brightness(
        data[offsetA],
        data[offsetA + 1],
        data[offsetA + 2]
      );
      const brightnessB = brightness(
        data[offsetB],
        data[offsetB + 1],
        data[offsetB + 2]
      );

      return brightnessA - brightnessB;
    });

    // Create a new pixel array
    const sortedData = new Uint8ClampedArray(data.length);

    // Populate the new array with the sorted pixels
    for (let i = 0; i < indices.length; i++) {
      const sortedIndex = indices[i] * 4;
      const originalIndex = i * 4;

      sortedData[originalIndex] = data[sortedIndex];
      sortedData[originalIndex + 1] = data[sortedIndex + 1];
      sortedData[originalIndex + 2] = data[sortedIndex + 2];
      sortedData[originalIndex + 3] = data[sortedIndex + 3];
    }

    // Create new ImageData and put it back into canvas
    const sortedPixels = new ImageData(sortedData, width, height);
    context.putImageData(sortedPixels, 0, 0);

    // Now we can draw our 3D mesh

    const viewport = [ 0, 0, width, height ];
    camera.viewport = viewport;

    // Make the camera swing back/forward a little
    const zOffset = Math.sin(playhead * Math.PI * -2) * 0.5;

    // Reset camera position, translate it outward, then look at world center
    camera.identity();
    camera.translate([ 0, 0, 3 + zOffset ]);
    camera.lookAt([ 0, 0, 0 ]);
    camera.update();

    // A 3D scene is made up of:
    // - 4x4 Projection Matrix (defines perspective)
    // - 4x4 View Matrix (inverse of camera transformation matrix)
    // - 4x4 Model Matrix (the mesh transformations like rotation, scale, etc)

    const projection = camera.projection;
    const view = camera.view;
    const model = mat4.identity([]);

    // Rotate the mesh in place
    mat4.rotateY(model, model, easeA(playhead) * Math.PI * 2);
    mat4.rotateX(model, model, easeB(playhead) * Math.PI * 2);

    // Get a combined (projection * view * model) matrix
    const combined = mat4.identity([]);
    mat4.multiply(combined, view, model);
    mat4.multiply(combined, projection, combined);

    // "Project" the 3D positions into 2D [ x, y ] points in pixel space
    const points = positions.map(position => {
      return cameraProject([], position, viewport, combined);
    });

    // Draw the mesh
    drawCellsNoOverlap(context, points, cells);
  };
};

canvasSketch(sketch, settings);

bramadams.dev is a reader-supported published Zettelkasten. Both free and paid subscriptions are available. If you want to support my work, the best way is by taking out a paid subscription.

June 13 2023

glitch art, chat loops, farms, code poetry

Videos

I built a plugin that works like a DIY code interpreter where an end user decides what rules GPT should check against. GPT is smart enough to facilitate it's own retry logic, which is neat as hell!

Photos

the town of yakima has a really active git profile

https://bram-adams.ghost.io/content/images/2023/06/yakima-git-commits-1.png
yakima git commits 1.png
https://bram-adams.ghost.io/content/images/2023/06/yakima-git-commits-2.png
yakima git commits 2.png

Art

https://bram-adams.ghost.io/content/images/2023/06/glitch-jun-13-1.png
glitch jun 13 1.png
https://bram-adams.ghost.io/content/images/2023/06/glitch-jun-13-2.png
glitch jun 13 2.png
https://bram-adams.ghost.io/content/images/2023/06/glitch-jun-13-3.png
glitch jun 13 3.png

Code

One thing I do a lot is append text to specific headings in a MD file, so this Python script helps with just that!!

append_smart_file
append text to a specified md heading

Playing around with the e2e experience of a Readwise quote > app (or pseudocode). I also just got an iPad so I'm playing with the Freeform app :)

Poetry

Experimenting with Code Poetry more as an art form. Here's a few GPT results from my favorite song rn, Ascencionism:

Python:

ChatGPT
A conversational AI system that listens, learns, and challenges

Visual Basic:

Class Desire ' Well, I know what you want from me
    Property Reflection As Boolean ' You want someone to be your reflection
    Property Deception As Boolean ' Your bitter deception
    Function SetFree() ' Setting you free
        ' So you take what you want and leave
        Return True
    End Function
End Class

Class Mystery ' Who made you like this?
    Property BodyLanguage As String ' Who encrypted your dark gospel in body language?
    Property BlissfulAnguish As Boolean ' Synapses snap back in blissful anguish
End Class

Class PastLife ' Tell me you met me in past lives, past life
    Property InsideEating As Boolean ' Past what might be eating me from the inside, darling
    Property RhythmHalfDeity As Boolean ' Half of a rhythm, half deity
    Property GlitchesOrGaps As String ' Glitches in the code or gaps in a strange dream
End Class

Class Fantasy ' Tell me you guessed my future and it mapped onto your fantasy
    Property Mannequin As Boolean ' Turn me into your mannequin
    Property PuppetQueen As Boolean ' and I'll turn you into my puppet queen
End Class

Class DanceInTheDark ' Won't you come and dance in the dark with me?
    ' Show me what you are, I am desperate to know
    Property PerfectEnemy As Boolean ' Nobody better than the perfect enemy
    Property DigitalDemons As Boolean ' Digital demons make the night feel heavenly
End Class

Class Reality ' Make it real
    ' 'Cause anything's better than the way I feel right now
    Property BlacklitParadise As Boolean ' I can offer you a blacklit paradise
    Property DiamondsInTrees As Boolean ' Diamonds in the trees, pentagrams in the night sky
    Property LipstickChemtrailsRedflagsPinkNails As Boolean ' Lipstick, chemtrails, red flags, pink nails
End Class

Class Eye
    Property Door As Boolean ' With one eye on the door
    Property Rail As Boolean ' other eye on a rail
    Property ScarletTrail As Boolean ' Other, other eye following a scarlet trail
    Property HolyGrail As Boolean ' And the last few drops from the Holy Grail, now
End Class

Class DarkFashion
    ' Rose gold chains, ripped lace, cut glass
    ' Blood stains on the collar, please, just don't ask
    Function Feast() ' Be the first to the feast, let's choke on the past
        ' And take to the broken skies at last
        Return True
    End Function
End Class

Class Ascend ' You cannot watch me ascend
    ' And I know what you want from me
    Property Same As Boolean ' You want the same as me
    Property Redemption As Boolean ' My redemption, eternal ascension
    Function SetFree() ' Setting me free
        ' So I'll take what I want then leave
        Return True
    End Function
End Class

Class Disappear ' You make me wish I could disappear, oh
    ' You make me wish I could disappear
    Function Wish() As Boolean
        Return True
    End Function
End Class

bramadams.dev is a reader-supported published Zettelkasten. Both free and paid subscriptions are available. If you want to support my work, the best way is by taking out a paid subscription.

Can a Robot Write a Symphony? Yes Lol

https://t.co/bXEqFi8zqr

(View Tweet)

Imagine creativity just turns out to be a subset of computation. Imagine that the logic leaps of conjecture and discovering good explanations is just an eigenvector calculation in the frontal lobe or some shit.