Assignment 1 – “Self-Portrait” by Pi Ko

First, below is the p5 js Editor embedding.

In case p5js Editor website is down, below is the recording of working demo on YouTube.

1) 🤔 Conceptualization

As below, I wanted my self portrait to reflect my silhouette, not too realistic but not too cartoony, but something in the style of graphic novels or marvel/DC comics. I am an artist and engineer, and hence, I also would like to include some bells and whistles which define both my art and engineering aspects. Normally for my everyday casual wear, I usually wear the black Chinese long dress – Changshan (長衫), with a red and black Tangzhuang (唐裝) coat on the top, with my long hair properly tied with a red ribbon as below. 

Moreover, I also wanted the portrait to show my personal emblem, the stylized rectangular Greek letter Pi.

As below, my usual real life portraits will feature me wearing my Chinese traditional outfit, with floating glowing code in futuristic HUD (Head-up display), and some equations that either I derived, or some equations I use in my work frequently. And of course the Pi emblem. This concept perfectly “marries the traditions from the past with the technology of the future, and hence justifying my existence as the artistic engineer in 2024 at present.”

While doing this portrait, here are the constraints I would like to adhere to.

  • Implement the portrait purely in p5js without any external libraries, external files in a single sketch.js file – such that when you copy and paste and run, it will run without additional configuration.
  • Follow the rubrics of the course assignment (do not import any existing image or do not use mouse to draw, and must not be realistic – A manga style silhouette is ‘not’ realistic)
  • In addition to the portrait, have items around me that defines me.
2) ⚙️ Technical Plan of Attack & Implementation

Since this is a “self-portrait” it should contain all the elements that gives the viewer a super brief introduction about a fraction of my life. Hence, below are the individual components used for the composition of the portrait.

  • Portrait : I am a manga/anime artist and animator. The entire portrait is implemented using bezierVertex() functions to allow me greater control over the shapes, and obtain the sketchy graphic novel/manga style I want to achieve. This has to combine 1) the line art and the 2) color. Colors are added in between the bezier curves to fill the shape.  Therefore, a component of my portrait would look like
beginShape();
vertex(324, 76);
bezierVertex(323, 76, 322, 76, 321, 75);
...
bezierVertex(324, 76, 324, 76, 324, 76);
endShape(CLOSE);
fill("#010101");
  • Animated Gears : I am a roboticist, and very fond of gears and servos. The gears are nothing but circles with partial opacity, and rectangles rendered on the side of the circles programmatically.
  • Animated Cubes : I am an XR/VR/AR developer, a 3D artist and a mathematician. Hence, I want to do some maths to show some interactive floating 3D cubes around me to symbolize this aspect of my life. Just because p5 js is a 2D canvas technology does not mean I should not attempt my beloved 3D art here. And just because webGL is available in p5  does not mean I have to follow what everyone is doing. Who needs webGL when we can just do some readings in linear algebra, define the vertices of the cubes, and do some matrix multiplication through rotation matrices in 3D space, and project them to the 2D p5js canvas? The matrix multiplication, and the rendering the projection is coded in my single sketch.js file, a snapshot of the code is as follows.
// Rotation matrices for X, Y, and Z axes
let rotationZ = [
  [cos(angleCube), -sin(angleCube), 0],
  [sin(angleCube), cos(angleCube), 0],
  [0, 0, 1],
];

let rotationY = [
  [cos(angleCube), 0, sin(angleCube)],
  [0, 1, 0],
  [-sin(angleCube), 0, cos(angleCube)],
];

let rotationX = [
  [1, 0, 0],
  [0, cos(angleCube), -sin(angleCube)],
  [0, sin(angleCube), cos(angleCube)],
];
  • Personal Emblem : I am a citizen Sinologist, and have always been inspired by East Asian culture. Traditional Japanese clans have their own family emblems called Mon (紋). I also have one myself, visually designed similar to that used by Nakagawa clan. I can draw my emblem by defining the  (x,y) coordinates of my emblem through an array, and letting vertex function loop through the shape.
function drawPiEmblem(x, y, scale) {
  const points = [
    { x: 46.3, y: 72.7 },
    ...
    { x: 73.3, y: 72.7 },
  ];

  beginShape();
  fill("#903C37");
  for (let i = 0; i < points.length; i++) {
    vertex(x + points[i].x * scale, y + points[i].y * scale);
  }
  endShape(CLOSE);
}
  • Quine Code : I am a Computer Engineer, and quite fond of cool code tricks. In Computer Science, a quine is a computer program which takes no input and produces a copy of its own source code as its only output.  Since I usually put code in my real life portraits, I thought it would be cool for my self portrait to print out its own p5js code at my back. The approach is simple, I just copy the first a few lines of my code and just let it print like a terminal. This would have been a lot cooler if I can go under the hood of p5js, and overwrite its event loop + file reading permissions to read its own source code and print it out dynamically, rather than me hardcoding it.
  • Custom font without using a custom font : I also wanted to use a better font, but I do not want to import anything into my single sketch.js implementation, hence I just produced some other good looking unicode characters using Stylish Text Generator (https://lingojam.com/StylishTextGenerator), if it works it works.
  • Falling Pi Digits : My name is Pi, the infinite mathematical constant which never repeats. This means a lot to me since that name allows me to pull out infinite ideas from my brain, which never repeats (but pratically work, and aesthetically beautiful) at will. Hence, in my portrait, the mouse pointer will drop the digits of pi, as a particle system, in a repeated fashion (because you can’t hard code infinite Pi digits)… So, the mouse pointer at time intervals will drop the digits three, point, one, four, one , five , nine, two ….
  • Backpropagation Equations : I am a published machine learning researcher, and deep learning is my default weapon of choice. Therefore, I wanted to honor the basic four equations which allows me to do my everyday work (sorry Maxwell, your equations take the second priority in my heart). Hence, I have the equations floating around me in my portrait.
  • Accompanying music : I am a multi instrumentalist and a composer, and I wanted to give a background music to my portrait. However, since I am not using any external libraries, and I still want to implement a basic metal guitar riff, I ended up defining two oscillators to symbolize the top two guitar strings in dropped D tuning, and hard coding a metal riff  – but only using the simple waveforms 🙁 . I could have done the wave superpositions to simulate the acoustics and distortion pedal signal processing of the electric guitar, but let it be for now.
3) 🎨 Artistic Plan of Attack & Implementation

Vignette : The white background is bland, and as a big fan of Assassin’s Creed Animus Loading Screens, I wanted a pale vignette effect. However, since I am not importing anything, I just loop over the entire canvas and painting each of the background pixels the right intensity and alpha values.

Rule of third placement : A good rule of thumb in visual composition is to divide the entire canvas in three and place the subjects on these lines. My portrait is on the left line. Checklist checked.

Whitespace consideration : I could have added more because this portrait paints a very limited aspect of my life. I could have added more computational chemistry, professional Game Development, martial arts choreography, epidemiology simulation models, Web Dev , Dev Ops and linguistics and so on – but stopped, to keep the whitespace visually clear, I let the majority of dark colors sit on the left side, and right side of the portrait contains the main whitespace.

Mouse Interactivity : Also, I find my self portrait after coding to be very static, so I browsed through old archives of this Intro to IM blogs. My friend Naz did something cool and interactive with the mouse pointer to give a parallax effect, so I ended up stealing her idea from Self-Portrait by Naz (https://editor.p5js.org/iremnaz/sketches/oxRGnv701).

4) 💪 Challenges

There was zero challenge. I became one with the machine, and implemented the entire sketch.js in one sitting in one boring afternoon, sipping Jasmine tea.

5) 💡 Potential Improvements

One tricky thing is how quick my self portrait code runs (on computers which are slow). Since I am generating a lot of objects and doing a lot, I could have refactored my code more to run more smoothly. For instance, for the falling Pi digits, I can implement an Object pool pattern and reuse the previous particles as soon as they are out of frame. But these are just off the top of my head.

As a bonus, through obfuscation and clever syntax formatting, I could have made the source code of the program actually look like my portrait ascii art, just like how this donut generation code is in the shape of a donut (https://www.a1k0n.net/2006/09/15/obfuscated-c-donut.html). But let it be this time.

6) 🖥️ Source code

🖥️ Source code is just a single sketch.js file at : https://github.com/Pi-31415/Intro-To-IM/blob/main/Assignment-1/sketch.js

📖 References :

Rendering a rotating 3D cube in 2D (https://rosettacode.org/wiki/Draw_a_rotating_cube#JavaScript)

Backpropagation Equations (http://neuralnetworksanddeeplearning.com/chap2.html#the_four_fundamental_equations_behind_backpropagation)

Quine (https://cs.lmu.edu/~ray/notes/quineprograms/)

Stylish Text Generator (https://lingojam.com/StylishTextGenerator)

FREQUENCY CHARTS FOR NOTES ON THE GUITAR (https://douglasniedt.com/frequency-chart-for-notes-on-the-guitar.html)

Self-Portrait by Naz (https://editor.p5js.org/iremnaz/sketches/oxRGnv701)

Japanese crest Nakagawake kurusu (https://en.wikipedia.org/wiki/File:Japense_crest_Nakagawake_kurusu.svg)

Note: GPT-4 is utilized in the implementation of the code.

 

Leave a Reply