Created
August 21, 2022 15:55
-
-
Save jasoncoon/cb2c0c9ebb6434dc4d719a78bdc42a80 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Beating heart pattern. The heart shape is formed by a square turned 45 degees to form a \"diamond\" which is | |
// the base of the heart. Two semi-circles connect to the upper two sides of the \"diamond\" for the rounded heart | |
// portion. Depending on your resolution, you may want to play with the anti-aliasing distance to improve the | |
// definition and appearance of the heart's outline. | |
// | |
// Debra Ansell (GeekMomProejcts) 8/18/2022 | |
// Ratio of the height of the heart to the length of one side of the diamond inside it | |
// length of one side of the diamond is also the diameter of the circle | |
var ratio = (0.5 + 3*sqrt(2)/4) | |
// Precompute | |
var sqr2_2 = sqrt(2)/2 | |
export var delta = 0.05 // Max antialiasing distance | |
export var height = 0.8 // Height of heart in world units | |
export var xpos = 0.5 // x position of the bottom tip of the heart | |
export var ypos = (1-height)/2 // y position of the heart's tip for it to be centered vertically | |
export var L = height/ratio // Length of a side of the diagonal square forming the bottom of the heart | |
export var Lv = L*sqr2_2 // Half the vertical height of the \"diamond\" | |
var flip = true | |
export function toggleFlip(value) { flip = value } | |
var style = 0 | |
export function triggerUpward() { style = 0 } | |
export function triggerDownward() { style = 1 } | |
export function triggerInward() { style = 2 } | |
export function triggerOutward() { style = 3 } | |
export function triggerClockwise() { style = 4 } | |
export function triggerCounterClockwise() { style = 5 } | |
export function beforeRender(delta) { | |
t1 = time(.02) | |
height = 0.5 + 0.3*sin(t1*PI) // Vary the heart's size with time to make it \"beat\" | |
L = height/ratio | |
Lv = L*sqr2_2 | |
xc = Lv/2 // (xc,yc) are coordinates of the center of the circular part of the heart | |
yc = 3*Lv/2 | |
ypos = 0.5 + height/2 | |
xpos = 0.5 | |
// Uncommenting the code below will cause the position of the heart to move around with time | |
//t2 = time(.035) | |
//t3 = time(.057) | |
//ypos = 0.45 + height/2 + 0.05*wave(t3) | |
//xpos = 0.3 + 0.2*wave(t2) + 0.2*wave(t3) | |
} | |
// The position of the bottom heart point is (x0,y0) | |
// Heart height and x0, y0 are given in world units | |
export function drawHeart(x, y, x0, y0, height, index) { | |
v = 0 // Intensity of the pixel | |
xn = abs(x - x0) // Take advantage of symmetry - only compute half of heart | |
yn = y0 - y // Remove y offset of heart for computations | |
if (yn < Lv) { // This portion of the heart is in the bottom half of the \"diamond\" | |
if (xn < yn) { // Point is inside the heart if it falls inside the line \"y=x\" | |
v = 1 | |
} else { // Check to see if we are close enough for anti aliasing | |
d = (xn - yn)*sqr2_2 // Perpendicular distance to line x = y (makes a (90,45,45) triangle) | |
if (d < delta) { // Inside anti-aliasing distance of the straight portion of heart | |
v = 1-d/delta // Pixel intensity decreases with distance | |
} | |
} | |
} else { // Inside the curved portion of the heart | |
yd = abs(yn - yc) // Vertical distance from center of the circle | |
if (yn < 2*Lv) { // This portion of the heart is below the inverted point | |
if (xn < Lv/2 + sqrt(L*L/4 - yd*yd)) { | |
v = 1 | |
} | |
} else { // This portion of the heart is above the inverted point | |
xd = abs(xn - xc) // Horizontal distance to center of the circular part of the heart | |
if (xd < sqrt(L*L/4 - yd*yd)) { | |
v = 1 | |
} | |
} | |
if (v == 0) { // Anti alias the curved part of the heart | |
d = hypot(xn - xc, yn - yc) - L/2 // Distance from circle forming curved heart boundary | |
if (d < delta) { | |
v = 1-d/delta // Pixel intensity decreases with distance | |
} | |
} | |
} | |
if (style === 0) // upward | |
hsv(y + t1, 1, v*v) | |
else if (style === 1) // downward | |
hsv(y - t1, 1, v*v) | |
else if (style === 2) // inward | |
hsv(hypot(x - .5, y - .5) + t1, 1, v * v) | |
else if (style === 3) // outward | |
hsv(hypot(x - .5, y - .5) - t1, 1, v * v) | |
else { // rotating | |
x1 = (x - .5) * 2 | |
y1 = (y - .5) * 2 | |
dist = sqrt(x1 * x1 + y1 * y1) | |
angle = (atan2(y1, x1) + PI) / PI / 2 | |
if (style === 4) // clockwise | |
hsv(angle + t1, 1, v*v) // hue depends on angle | |
else // counter-clockwise | |
hsv(angle - t1, 1, v*v) // hue depends on angle | |
} | |
} | |
export function render2D(index, x, y) { | |
if (flip) | |
drawHeart(x, 1-y, xpos, ypos, height, index) | |
else | |
drawHeart(x, y, xpos, ypos, height, index) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment