Final Project

This final project was inspired by what’s currently transpiring to aquariums within the country during this pandemic. I’m a huge fan of aquariums and am constantly nervous about how much these vital institutions are struggling to stay afloat while visitors can’t go walk through their physical buildings and admire all of the different marine life. I wanted this project to bring a little awareness to this extremely niche but nevertheless devastated part of the current fabric of the world being heavily impacted by the pandemic.

For this project, the viewer just needs to click on the canvas to cycle through
different facts about COVID-19’s impact on aquariums and marine life. They can also make the aquarist move across the screen and view the passing marine life with their mouse. The visuals and designs of the animals were based off the Monterey Bay Aquarium‘s illustrated advertisements. Each animal moves across the screen at different speeds as the illustrated background moves with them.

If I had more time on this project, I definitely would have added a level of
interactivity with the marine life, whether through animations triggered by clicks or sounds to accompany the piece. I’m pretty proud of how it turned out though.

sketch
var teal;
var barColor;

var tankbg;
var kelp;
var sunlight;

var sidewayScroll = 0;
var bgLength = 2100;
var bgHeight = 600;

let turtleCycle = [];
let animatedFrame = 0;
let turtleX = 0;
let time = 0;

let rayY = 0;
let rayX = 0;
var ray;

let seahorseY = 0;
let seahorseX = 0;
var seahorse;

var sharkY = 0;
var sharkX = 0;
var shark;

var orangefishX = 0;
var orangefishY = 0;
var orangefish;

var dx = [];
var c = [];
var x = [];
var y = [];

var employeeLeft;
var employeeRight;

var facts = ["Because the pandemic has reduced tourism, there has been a huge baby sea turtle boom in Florida's beaches.", "Stingrays and other fish have been showing signs of loneliness since the pandemic started due to the lack of visitor interactions.", "An endangered species of seahorse has returned to Dorset in the UK due to the coronavirus lockdown.", "Aquariums around the country are struggling to stay afloat due to COVID-19 closures and lack of financial help from the federal government.", "Many aquariums are now showing exhibits virtually to keep visitors engaged at home."];
var index = 0;

function preload() {
    //exhibit images
    tankbg = loadImage("tankbg.png");
    kelp = loadImage("kelp.png");
    sunlight = loadImage("light.png");

    //turtle images
    turtleCycle[0] = loadImage("turtle-02.png");
    turtleCycle[1] = loadImage("turtle-03.png");
    turtleCycle[2] = loadImage("turtle-04.png");
    turtleCycle[3] = loadImage("turtle-05.png");
    turtleCycle[4] = loadImage("turtle-06.png");
    turtleCycle[5] = loadImage("turtle-05.png");
    turtleCycle[6] = loadImage("turtle-04.png");
    turtleCycle[7] = loadImage("turtle-03.png");

    //stingray image
    ray = loadImage("ray.png");

    //seahorse image
    seahorse = loadImage("seahorse.png");

    //shark
    shark = loadImage("shark.png");

    //orange fish
    orangefish = loadImage("orangefish.png");

    //employee
    employeeLeft = loadImage("employee_left.png");
    employeeRight = loadImage("employee_right.png");

}

function setup() {
    createCanvas(600, 450);

    //tank setup
    teal = color(89, 185, 189);
    barColor = color(20, 48, 67);

    //fish setup
    for (i = 0; i < 100; i++) {
        dx[i] = random(-2, 2);
        c[i] = color(random(100), random(175), random(100), 50);
        x[i] = random(25, width - 25);
        y[i] = random(25, height - 25);
    }

}

function draw() {
    noStroke();
    background(teal);

    //sunlight
    image(sunlight, width/4, 0, 400, bgHeight);

    for (i = 0; i < 100; i++) {
        fish(x[i], y[i], dx[i], c[i]);
        x[i] += dx[i];

        if (x[i] > width - 20){
            dx[i] = -dx[i];
        }
        else if (x[i] < 0){
            dx[i] = -dx[i];
        } 
    }

    //shark
    image(shark, sharkX, sharkY, 189.42, 47.7);

    sharkX = sharkX + 1;
    if (sharkX >= width) {
        sharkX = -300;
        sharkY = random(200, 400);
    }

    //scrolling background
    image(tankbg, sidewayScroll, -150, bgLength, bgHeight);
    image(tankbg, sidewayScroll + bgLength, -150, bgLength, bgHeight);

    //sea turtle
    image(turtleCycle[animatedFrame], turtleX, 100, 200, 97);

    if (time > 13) {
        turtleX += 13;
        animatedFrame += 1;
        if (animatedFrame >= turtleCycle.length) {
            animatedFrame = 0;
        }
        time = 0;
    }
    time++;
    if (turtleX > width) {
        turtleX = -500;
    }

    //orange fish
    image(orangefish, orangefishX, orangefishY, 243, 86.3);

    orangefishX = orangefishX + 2;
    if (orangefishX >= width) {
        orangefishX = -600;
        orangefishY = random(0, 400);
    }

    //seahorse
    image(seahorse, seahorseX, seahorseY, 25, 45);
    image(seahorse, seahorseX + 50, seahorseY + 50, 35, 55);

    seahorseX = seahorseX + 0.5;
    if (seahorseX >= width) {
        seahorseX = -100;
        seahorseY = random(0, 400);
    }

    //scrolling kelp
    image(kelp, sidewayScroll, -150, bgLength, bgHeight);
    image(kelp, sidewayScroll + bgLength, -150, bgLength, bgHeight);

    sidewayScroll -= 1;
    if (sidewayScroll <= -bgLength) {
        sidewayScroll = 0;
    }

    //stingray
    image(ray, rayX, rayY, 150, 192);

    rayY = rayY + 1;
    if (rayY >= height) {
        rayY = -300;
        rayX = random(-400, 100);
    }
    else {
        rayX = rayX + 1;
    }
    
    //glass tank bars
    fill(barColor);
    rect(200, 0, 15, height);
    rect(400, 0, 15, height);

    //aquarium employee
    let canvasEdge = constrain(mouseX, width/4, 400);
    if (mouseX < width/2) {
        image(employeeLeft, canvasEdge, 300, 82, 172.6);
    } else {
        image(employeeRight, canvasEdge, 300, 82, 172.6);
    }
 
    //pandemic facts
    let factsEdge = constrain(mouseX, 50, 400);
    fill(255, 200);
    rect(factsEdge, 200, 175, 85, 10);
    fill(0);
    textSize(10);
    textFont("Volte");
    text(facts[index], factsEdge + 15, 212, 150, 200);

}

//background fish
function fish(x, y, dx, c) {
    fill(c);
    ellipse(x, y, 20, 10);

    if(dx < 0) {
        triangle(x+10, y, x+15, y-5, x+15, y+5);
    }
    else {
        triangle(x-10, y, x-15, y-5, x-15, y+5);
    }
}

//click to cycle through pandemic facts
function mousePressed() {
    index = floor(random(facts.length));
    if (index == facts.length) {
        index = 0;
    }
}
Exhibit background, made in Illustrator
Sea turtle, made in Illustrator
Stingray, made in Illustrator
Spotted Bamboo Shark, made in Illustrator
Seahorse, made in Illustrator
Aquarist, made in Illustrator

Looking Outwards 09 – On Looking Onwards

Because Season 2 of Disney’s The Mandalorian just premiered last Friday, I wanted to discuss t.chen’s 5th Looking Outwards post on Industrial Light and Magic’s phenomenal real-time 3D rendering for The Mandalorian. As t.chen mentioned in their post, ILM is a motion picture VFX company founded by George Lucas in 1975 and can trace its roots back to the original Star Wars trilogy.

Although ILM has always been a huge pioneer within the VFX industry, the company broke new ground through The Mandalorian‘s background and atmosphere through “The Volume,” a huge, circular stage of LED screens that display whatever planet or setting the scene requires. Everything within the background is rendered in real-time through Unreal Engine, so if the director wants the sun to set or entire cities to be built or put away, The Volume can provide these specifications.

I wanted to add onto t.chen’s original post that this technique is ironically not new – many films since the mid-1900’s have utilized the rear screen projection technique to achieve this effect. However, The Volume opens up new possibilities of having backgrounds respond in real-time, rather than prerecord background footage or have actors act in a green screen set and construct the world in postproduction. It’s incredibly exciting to consider how this will change filmmaking in the future.

Project 9: Portrait

owl
var myPhoto;

function preload(){
    var owlPhoto = "https://i.imgur.com/ldqKQ6T.jpg";
    myPhoto = loadImage(owlPhoto);
}

function setup() {
    createCanvas(400, 375);
    imageMode(CENTER);
    noStroke();
    background(0);
    myPhoto.resize(400, 400);
    myPhoto.loadPixels();
    frameRate(20);
}

function draw() {

    //drawing color and location from the photo
    var x = floor(random(myPhoto.width));
    var y = floor(random(myPhoto.height));
    fill(myPhoto.get(x, y));

    if (mouseIsPressed) {
        textSize(10);
        text("HOOT", x, y); //write "HOOT" on the canvas
    } else {
        owl(x, y); //draw an owl's face
    }
}

//referenced from our Functions lecture
//drawing owl eyes and a beak
function owl(x, y){

    push();
    translate(x, y);
    noStroke();
    scale(0.35);
    ellipse(-17.5, -65, 20, 20);
    ellipse(17.5, -65, 20, 20);
    quad(0, -58, 4, -51, 0, -44, -4, -51);
    pop();
}

The portrait is drawn through tiny owl faces that each consist of two eyes and a beak. If you press your mouse down, you can draw the word “HOOT” all over the canvas as well.

For this project, I chose a photo of myself with an owl from an owl cafe in Tokyo. I thought it was cute that the owl was also looking at its own picture on my phone.

Original Photo

Starting out
After a minute
After 2 minutes

Looking Outwards 08: The Creative Practice of an Individual

Out of all the speakers throughout the Eyeo Series, I was most drawn to Jane Friedhoff and her whimsical works. Jane is an interdisciplinary creative technologist, artist, and independent game developer. Her goal is to “blur the lines between as many media and genres as she can,” which really spoke to my experiences within the School of Art here at CMU. Friedhoff was previously at The New York Times’ Research & Development Lab and The Office for Creative Research, a hybrid research group that studied the intersection of culture, education, and technology to make tools and experiences that humanized data. As of 2018, she’s currenting working with the Google Creative Lab.

I was really drawn to Friedhoff’s work because of how they enable users to see beauty and have fun within every day small spaces, like her AR experiment Hidden World. Her talk about creating games about power fantasies and her deconstruction of that term in relation to game design, worldbuilding, and stepping away from current societal power dynamics was really engaging and added a level of depth and sophistication to her works that I want to emulate when discussing my own works in the future.

Friedhoff’s Website

Project 7: Curves

I was really drawn to the rounded curves of the Cardioid and wanted to see how much I could alter this shape based on my mouse’s position. Based on your mouse’s position on the canvas, the Cardioid will change in shape and color.

curves
var nPoints = 100;
var CARDIOID = 0;
var curveMode = CARDIOID;

function setup() {
    createCanvas(480, 480);
    noStroke();
    frameRate(20);
    pinkColor = color(255, 179, 184);
    paleGreen = color(236, 255, 214);
    paleBlue = color(224, 222, 255);
    yellowColor = color(254, 255, 222);
}

function draw() {
    //change color of background depending on MouseY
    let changeBG = map(mouseY, 0, height, 0, 1);
    var changeColor = lerpColor(paleGreen, paleBlue, changeBG);
    background(changeColor);

    //drawing the cardioid
    push();
    rotate(-(PI/2.0));
    translate(-width/4.0, height/2);
    switch (curveMode) {
        case CARDIOID:
            drawCardioidCurve();
            break;
    }
    pop();
}

function drawCardioidCurve() {
    //Cardioid: https://mathworld.wolfram.com/Cardioid.html
    //x = a cos t(1 - cos t)
    //y = a sing t(1 - cos t)

    var x;
    var y;
    var a = 150.0;
    var stifleMouse = constrain(mouseX/2.5, 0, width);

    //changing cardioid color
    let changeShape = map(mouseY, 0, height, 0, 1);
    var shapeColor = lerpColor(pinkColor, yellowColor, changeShape);
    fill(shapeColor);

    //cardioid shape
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var t = map(i, stifleMouse, nPoints, 0, TWO_PI);
        x = a * cos(t) * (1 - cos(t));
        y = a * sin(t) * (1 - cos(t));
        vertex(x, y);
    }
    endShape(CLOSE);
}

Looking Outwards 07: Information Visualization

A visualization of human development levels in 2013.

For this week’s Looking Outwards, I was drawn to Dutch creative developer Jurjen Verhagen’s online data visualization Human Development Tree, an interactive platform that lets users visualize a level of human development based on set conditions of life expectancy, expected years of education, mean years of education, a country’s GDP, the country’s ideals on gender equality, and a color of your choice. Based on your input, the platform will reveal
your “ideal tree” with leaves. Leaves that fall off the tree represent current countries that don’t meet your conditions in 1985. More leaves grow back on tree as the data visualization progresses to the year 2013.

You can change the color of the tree’s leaves.

I thought this project was a super fascinating way to combine data and gamification in a fun but educational way. This visualization taught me a lot about human development and how much the world has changed since 1985, as well as leave me curious on how the tree’s leaves would have changed since 2013. I’m really curious on what kinds of algorithms Verhagen combined with
his beautiful 3D models, and if he ever plans on updating this project to reflect data from 2020.

Interact with the data visualization here.

Project 6: Abstract Clock

(The illustration file wasn’t loading properly so I had to embed it twice!)

Since Nintendo recently announced that Hyrule Warriors: Age of Calamity is coming out soon, I decided to create a clock inspired by The Legend of Zelda’s Breath of the Wild. The sky changes color depending on the hour, the clouds move across the sky every minute, and pink sparkles appear every second.

breath of the wild
var dusk;
var dawn;
var sparkleX = [];
var sparkleY = [];
var randomW = [];
var randomH = [];
let yPerl = 0.0;

function preload() {
    mySon = loadImage("link_illustration.png");
}

function setup() {
    createCanvas(480, 300);
    //angleMode(DEGREES);

    greenDusk = color(162, 219, 202); //dusk sky color
    yellowDawn = color(252, 246, 211); //dawn sky color
    mountainColor = color(56, 116, 150); //color of the mountains
    cloudColor = color(225, 223, 184); //colod of the clouds
    ledgeColor = color(19, 68, 97); //color of Link's ledge
    ledgeShadow = color(4, 42, 50, 75); //color of ledge shadow
    hyrulePink = color(255, 145, 203); //color of the sparkles

    lerpValue = 0;
    dusk = "nightfall";
    dawn = "daybreak";
    sunlight = "sunrise";
    moonlight = "twilight";

    //sparkles
    for (i = 0; i < 60; i++) {
        sparkleX[i] = random(width);
        sparkleY[i] = random(175, 300);
        randomW[i] = random(3, 6);
        randomH[i] = random(3, 6);
    }
}

function draw() {
    background(0);
    noStroke();
    sky(); //sky incremently changes color based on hour

    push(); //clouds move across sky based on minute
    var m = minute();
    driftingCloud = map(m, 0, 60, 0, width);
    translate(driftingCloud, 0);
    clouds();
    pop();

    mountains(); //randomly generated mountains
    castle(); //castle in the distance

    //sparkles in the horizon
    fill(hyrulePink);

    for (i = 0; i < second(); i++) {
        rect(sparkleX[i], sparkleY[i], randomW[i], randomH[i]);
    }
    
    //ledge that Link stands on
    ledge();

    //illustration of Link
    scale(0.2);
    image(mySon, 1100, 350);

}

//sky incremently changes color each hour
function sky() {
    var h = hour();

    if (dawn === "daybreak") {
        lerpValue = map(h, 23, 0, 0, 1);
    }
    else {
        lerpValue = map(h, 0, 23, 0, 1);
    }

    if (h < 12) {
        lerpValue = map(h, 0, 11.5, 0, 1);
    } else {
        lerpValue = map(h, 11.5, 23, 1, 0);
    }
    
    var skyChange = lerpColor(greenDusk, yellowDawn, lerpValue);
    fill(skyChange);
    rect(0, 0, width, height);
}

//mountain horizon
function mountains() {
    fill(mountainColor);
    beginShape();
    let xPerl = 0;

    for (let x = 0; x <= width; x += 10){
        let y = map(noise(xPerl), 0, 1, 150, 200);
        vertex(x, y);
        xPerl += 0.2;
    }

    yPerl += 0.2;
    vertex(width, height);
    vertex(0, height);
    endShape(CLOSE);
}

//clouds based on minute
function clouds() {
    fill(cloudColor);
    var m = minute();

    for (var c = 0; c <= m; c++) {

        //top left middle cloud
        push();
        scale(0.75);
        translate(0, -50);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //middle cloud
        push();
        translate(150, -20);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top left small cloud
        push();
        scale(0.5);
        translate(-70, -80);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //bottom left large cloud
        push();
        scale(1.25);
        translate(-90, -20);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top right cloud
        push();
        scale(0.75);
        translate(320, -80);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top middle cloud
        push();
        scale(0.5);
        translate(50, -110);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //far left middle cloud
        push();
        translate(-250, -50);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();
    }
}

//ledge where Link is standing
function ledge() {
    push();
    fill(ledgeColor);
    translate(width/1.8, height + 10);
    beginShape();
    vertex(-30, -50);
    vertex(0, -90);
    vertex(90, -85);
    vertex(130, -40);
    vertex(160, 50);
    vertex(-60, 50);
    endShape(CLOSE);
    pop();

    push();
    fill(ledgeShadow);
    translate(width/1.8, height + 10);
    beginShape();
    vertex(-10, -75);
    vertex(0, -90);
    vertex(90, -85);
    vertex(130, -40);
    vertex(160, 50);
    endShape(CLOSE);
    pop();
}

//castle in the horizon
function castle() {
    fill(mountainColor);
    rect(125, 110, 30, 100); //castle tower
    rect(102, 150, 75, 100); //castle building
    rect(90, 165, 100, 50); //castle ledge
    rect(122.5, 125, 35, 10); //lower level of castle
    triangle(120, 110, 140, 50, 160, 110); //main spire
    triangle(100, 150, 107.5, 110, 115, 150); //left spire
    triangle(165, 150, 172.5, 110, 180, 150); //right spire
    triangle(85, 200, 92.5, 130, 100, 200); //bottom left spire
    triangle(180, 200, 187.5, 130, 195, 200); //bottom right spire

    //windows
    fill(greenDusk);
    rect(135, 110, 5, 10);
    rect(130, 110, 2, 10);
    rect(135, 140, 10, 10);

    //jagged rocks from mountain
    push();
    fill(mountainColor);
    rectMode(CENTER);
    translate(450, 225);
    rotate(PI/1.2);
    rect(0, 0, 50, 250);
    rotate(PI/4.0);
    rect(415, -150, 40, 250);
    rect(200, -50, 35, 250);
    pop();
}
Sketch of the clock’s features.
Quick sketch of Link I drew for this project.

Looking Outwards 06: Randomness

Robbie Barrat’s Neural Network Balenciaga series is a fascinating
amalgamation of AI, fashion, and the fine line between creativity
and mimicry. Barrat utilized new neural network processing methods
to analyze the similarities in thousands of images from Balenciaga
runway shows and lookbooks and pushed this data to another one of
his neural networks, prompting the system to interpret what makes
Balenciaga Balenciaga. The results are random but creative
mishmashes of what the AI learned from thousands of images and
is trained to think Balenciaga looks like.

I was especially drawn to this work because of how it throws the whole
concept of randomness into question – the AI may generate random iterations
of Balenciaga outfits, but the iterations look so similar to each other
that it makes the viewer ponder about the original source material itself.
I additionally was interested in this glimpse into how generative algorithms
really work – the AI doesn’t know what Balenciaga or fashion really is, yet
tries to replicate these foreign concepts to its best approximation and
succeeds quite well.

Project 5: Wallpaper

When creating this wallpaper, I kept thinking of the kitschy nautical patterns you’d find plastered on the walls of seaside restaurants. I drew a lot of inspiration from cute illustrations on Pinterest that emulate this niche aesthetic.

nautical
function setup() {
    createCanvas(550, 550);
    background(220);
    bgColor = color(180, 218, 221);
    floatyColor = color(215, 53, 76);
    wheelColor = color(115, 175, 193);
}

function draw() {
    background(bgColor);

    //seashells
    for(var c = -5; c < width; c += 93) {
        for(var d = -5; d < height; d += 200) {
            push();
            translate(c, d);
            seashell();
            pop();
        }
    }

    //seashells again
    for(var e = -10; e < width; e += 95) {
        for(var f = 95; f < height; f += 190) {
            push();
            translate(e, f);
            seashell();
            pop();
        }
    }

    //wheel
    for(var x = 45; x < width; x += 190) {
        for(var y = 40; y < height; y += 200) {
            push();
            translate(x, y);
            woodenWheel();
            pop();
        }
    }

    //flotation devices
    for(var a = 5; a < width; a += 180) {
        for(var b = 0; b < height; b += 180) {
            push();
            translate(a, b);
            floaty();
            pop();
        }
    }
}

//the blue & white steering wheels
function woodenWheel() {
    fill(bgColor);
    noStroke();
    ellipse(38, 37, 45, 45);

    handles = 8; //number of handles on the steering wheels
    handleAngle = 360/handles; //angle between each handle
    radius = 75/2; //length of each handle
    strokeWeight(4);
    stroke(wheelColor);
    
    for (angle = 270; angle < 600; angle = angle + handleAngle) {
        x = cos(radians(angle)) * radius;
        y = sin(radians(angle)) * radius;
        line(radius, radius, x + radius, y + radius);
    }

    noFill();
    strokeWeight(5);
    stroke(255);
    ellipse(38, 37, 50, 50); //outer wheel
    ellipse(38, 37, 10, 10); //inner spoke
}

function floaty() {
    noFill();
    strokeWeight(20);
    stroke(255);
    ellipse(0, 0, 75, 75);

    noStroke();
    fill(floatyColor);
    arc(9, 9, 75, 75, 0, PI/2); //bottom right red
    arc(-9, 9, 75, 75, HALF_PI, PI); //bottom left red
    arc(-9, -9, 75, 75, PI, HALF_PI + PI); //top left red
    arc(9, -9, 75, 75, HALF_PI + PI, 0); //top right red

    fill(bgColor);
    ellipse(0, 0, 55, 55);
}

function seashell() {
    push();
    noStroke();
    fill(255);
    arc(0, 0, 50, 50, PI + QUARTER_PI, QUARTER_PI - HALF_PI);
    arc(0, -5, 25, 20, QUARTER_PI, PI - QUARTER_PI);
    pop();

    grooves = 4; //number of lines on seashell
    grooveAngles = 60/grooves; //angle of lines on seashell
    radius = 50/2; //length of each line
    strokeWeight(1);
    stroke(bgColor);

    translate(-25, -25);
    for (angle = 225; angle < 325; angle = angle + grooveAngles) {
        x = cos(radians(angle)) * radius;
        y = sin(radians(angle)) * radius;
        line(radius, radius, x + radius, y + radius);
    }
}

Looking Outwards 05: 3D Computer Graphics

One artist whose work I recently came across and really admire is Rebecca Tell,
or “Bexelyn,” the lead artist at Sago Mini. I fell in love with her artwork
“Mr. Strawberry & Friends Go Camping,” in which she utilized the 3d software
Cinema 4D to construct and render a scene of cute little food characters out
camping in a forest.

I was drawn to this piece’s soft color palette, curvy stylization, and cute
character designs, all of which are signature features of Tell’s unique 3D
modeling style. I especially admire this work because of the amount of
intricacies embedded within the canvas – although the camping scene
stylistically looks really simple, Tell had to individually model each character
and prop in the work, as well as color, light, and shade these assets and the
background as well. As someone who’s used 3D software like Maya and Blender before and had difficulties even extruding 3D models correctly, I’m really appreciative of the amount of work Tell put into this piece and hope to apply that same mindset of hard work in all of my future projects.

Mr. Strawberry & Friends Go Camping

Rebecca Tell’s Instagram