xxxxxxxxxx
170
// Global variables for the maps and map settings.
let colorMap, velocityMap;
let mapDisplaySize, mapResolution, gridSize;
function setup() {
//frameRate(30);
// Initialize the canvas and map settings.
createCanvas(400, 400);
mapDisplaySize = Math.min(width, height);
mapResolution = 4*12;
gridSize = mapDisplaySize / mapResolution;
// Generate a new maps and render the scene.
initialize();
}
function mousePressed() {
// On mouse press, initialize the maps and re-render.
initialize();
}
function draw() {
background(255);
// Render the maps
renderColorMap();
renderVelocityMap();
// update the color map
updateColorMap();
//updateVelocityMapAdvect()
}
// render the color map
function renderColorMap() {
noStroke();
for (let y = 0; y < mapResolution; y++) {
for (let x = 0; x < mapResolution; x++) {
fill(arrayToColor(colorMap[y][x]));
rect(gridSize * x,gridSize * y, gridSize, gridSize);
}
}
}
// Render the velocity map as arrows.
function renderVelocityMap() {
noFill();
stroke(0);
for (let y = 0; y < mapResolution; y++) {
for (let x = 0; x < mapResolution; x++) {
const cx = gridSize * x + gridSize * 0.5;
const cy = gridSize * y + gridSize * 0.5;
const g = velocityMap[y][x];
drawArrow(cx - g[0] * gridSize * 0.25, cy - g[1] * gridSize * 0.25, cx + g[0] * gridSize * 0.25, cy + g[1] * gridSize * 0.25);
}
}
}
// Update the velocityMap based on the velocityMap itself
function updateVelocityMapAdvect() {
const newVelocityMap = [];
for (let y = 0; y < mapResolution; y++) {
newVelocityMap.push([]);
for (let x = 0; x < mapResolution; x++) {
const sx = x - velocityMap[y][x][0];
const sy = y - velocityMap[y][x][1];
newVelocityMap[y].push(sampleMap(velocityMap, sx, sy));
}
}
velocityMap = newVelocityMap;
}
// Update the colorMap based on the velocityMap
function updateColorMap() {
const newColorMap = [];
for (let y = 0; y < mapResolution; y++) {
newColorMap.push([]);
for (let x = 0; x < mapResolution; x++) {
const sx = x - velocityMap[y][x][0];
const sy = y - velocityMap[y][x][1];
newColorMap[y].push(sampleMap(colorMap, sx, sy));
}
}
colorMap = newColorMap;
}
function arrayToColor(arr) {
return color(arr[0] * 255, arr[1] * 255, arr[2] * 255);
}
function lerpArrays(arrayA, arrayB, t) {
const newArray = [];
for (let i = 0; i < arrayA.length; i ++) {
newArray.push(arrayA[i] * (1 - t) + arrayB[i] * t);
}
return newArray;
}
// Sample the color interpolating 4 cells around the specified point
function sampleMap(map, sx, sy) {
const ix0 = smallerIndex(sx);
const ix1 = largerIndex(sx);
const iy0 = smallerIndex(sy);
const iy1 = largerIndex(sy);
const tx = sx - Math.floor(sx);
const ty = sy - Math.floor(sy);
const mixA = lerpArrays(map[iy0][ix0], map[iy0][ix1], tx);
const mixB = lerpArrays(map[iy1][ix0], map[iy1][ix1], tx);
const mix = lerpArrays(mixA, mixB, ty);
return mix;
}
function wrap(n) {
return (n + mapResolution) % mapResolution;
}
function smallerIndex(n) {
return Math.floor(n + mapResolution) % mapResolution;
}
function largerIndex(n) {
return Math.ceil(n + mapResolution) % mapResolution;
}
function initialize() {
// Use Array fill and map methods for cleaner map initialization
colorMap = Array(mapResolution).fill().map((_, y) =>
Array(mapResolution).fill().map((_, x) => [
x < mapResolution / 2 ? 0 : 1,
y < mapResolution / 2 ? 0 : 1,
1
])
);
// velocityMap = Array(mapResolution).fill().map((_, y) =>
// Array(mapResolution).fill().map((_, x) => [
// y < mapResolution / 2 ? 0.5 : -0.5,
// x < mapResolution / 2 ? -0.5 : 0.5
// ])
const center = mapResolution / 2;
// );
velocityMap = Array(mapResolution).fill().map((_, y) =>
Array(mapResolution).fill().map((_, x) => {
const deltaX = x - center;
const deltaY = y - center;
const angle = Math.atan2(deltaY, deltaX) - Math.PI / 2; // Subtract Math.PI / 2 for a clockwise circle
const magnitude = 0.5; // Adjust the velocity magnitude as needed
const vx = magnitude * Math.cos(angle);
const vy = magnitude * Math.sin(angle);
return [vx, vy];
})
);
}
// Draw an arrow from (x0, y0) to (x1, y1) with proper arrowheads.
function drawArrow(x0, y0, x1, y1) {
const headSize = 3;
line(x0, y0, x1, y1);
let v = createVector(x1 - x0, y1 - y0).normalize();
line(x1, y1, x1 - v.y * headSize - v.x * headSize, y1 + v.x * headSize - v.y * headSize);
line(x1, y1, x1 + v.y * headSize - v.x * headSize, y1 - v.x * headSize - v.y * headSize);
}