Huichol Pattern Generator |
Custom Software for the creation of animated patterns based on MesoAmerican Huichol Art |
Images / Code Snippets |
The Huichol Pattern Generator is software for the generation of colorfull patterns that animate over a grid. It is based on the kind of structure present in the art of the Huichol, a Mexican MesoAmerican culture. Their art usually depicts animals and symbols from their mythology, constructed with very colorfull geometric patterns, highly saturated palettes, and composed with beads arranged over an hexagonal grid that completely covers the statue or artwork. The software is originally coded to generate patterns that will be later composed for a projection of a fullDome experience at the Buenos Aires Planetarium, as part of the Understanding Visual Music International Conference 2016. Along with Mario Guzmán (Mario's webSite), we are putting together a piece of animated motion graphics that takes the audience inside a Mexican Temazcal, to embark on a visually intense journey towards the constellation of The Pleiades.
The software is in beta v0.9, with some minor bugs but ready for production use. With the Huichol Pattern Generator, you can:
Coded in Processing |
// Images |
// The Sun |
// The Chamán |
// The Software's Editor Options and Color Palette Sidebar |
// Code Snippets |
Some Processing code snippets used in this software, that might come in handy for other stuff: // View to Canvas Transform: PVector viewToCanvasTransform(PVector viewCoords, PVector canvasTranslation, float canvasScale) { PVector invertedTranslation = PVector.mult(canvasTranslation, -1); PVector newCoords = PVector.add(viewCoords, invertedTranslation); return newCoords.mult(1.0f / canvasScale); } PVector canvasToViewTransform(PVector canvasCoords, PVector canvasTranslation, float canvasScale) { PVector scaledCoord = PVector.mult(canvasCoords, canvasScale); return PVector.add(scaledCoord, canvasTranslation); } // Neighbour detection over hexagonal grid:
int[] getNeighboursIndex(int index, int gridWidth, int pointsCount) { int[] neighbours; // CHECK: 1)CORNER POINTS -> 2)BORDERS -> 3)INSIDE OF GRID if (index == 0) { // FIRST POINT neighbours = new int[2]; neighbours[0] = index + 1; neighbours[1] = index + gridWidth; return neighbours; } else if (index == (gridWidth - 1)) { // TOP RIGHT POINT neighbours = new int[3]; neighbours[0] = index + gridWidth; neighbours[1] = index + gridWidth - 1; neighbours[2] = index - 1; return neighbours; } else if (index == pointsCount - 1) { // BOTTOM RIGHT (LAST) POINT if (isEvenRow(index - (gridWidth - 1), gridWidth)) { neighbours = new int[3]; neighbours[0] = index - 1; neighbours[1] = index - gridWidth - 1; neighbours[2] = index - gridWidth; return neighbours; } else { neighbours = new int[2]; neighbours[0] = index - 1; neighbours[1] = index - gridWidth; return neighbours; } } else if (index == (pointsCount - gridWidth)) { // BOTTOM LEFT POINT if (isEvenRow(index, gridWidth)) { neighbours = new int[2]; neighbours[0] = index - gridWidth; neighbours[1] = index + 1; return neighbours; } else { neighbours = new int[3]; neighbours[0] = index - gridWidth; neighbours[1] = index - gridWidth + 1; neighbours[2] = index + 1; return neighbours; } } else if (index < gridWidth) { // TOP BORDER neighbours = new int[4]; neighbours[0] = index + 1; neighbours[1] = index + gridWidth; neighbours[2] = index + gridWidth - 1; neighbours[3] = index - 1; return neighbours; } else if ((index - (gridWidth - 1)) % gridWidth == 0) { // RIGHT BORDER if (isEvenRow(index - (gridWidth - 1), gridWidth)) { neighbours = new int[5]; neighbours[0] = index + gridWidth; neighbours[1] = index + gridWidth - 1; neighbours[2] = index - 1; neighbours[3] = index - gridWidth - 1; neighbours[4] = index - gridWidth; return neighbours; } else { neighbours = new int[3]; neighbours[0] = index + gridWidth; neighbours[1] = index - 1; neighbours[2] = index - gridWidth; return neighbours; } } else if (index > (pointsCount - gridWidth)) { // BOTTOM BORDER if (isEvenRow(index, gridWidth)) { neighbours = new int[4]; neighbours[0] = index - 1; neighbours[1] = index - gridWidth - 1; neighbours[2] = index - gridWidth; neighbours[3] = index + 1; return neighbours; } else { neighbours = new int[4]; neighbours[0] = index - 1; neighbours[1] = index - gridWidth; neighbours[2] = index - gridWidth + 1; neighbours[3] = index + 1; return neighbours; } } else if (index % gridWidth == 0) { // LEFT BORDER if (isEvenRow(index, gridWidth)) { neighbours = new int[3]; neighbours[0] = index - gridWidth; neighbours[1] = index + 1; neighbours[2] = index + gridWidth; return neighbours; } else { neighbours = new int[5]; neighbours[0] = index - gridWidth; neighbours[1] = index - gridWidth + 1; neighbours[2] = index + 1; neighbours[3] = index + gridWidth + 1; neighbours[4] = index + gridWidth; return neighbours; } } else { // THE POINT IS INSIDE THE GRID if (isEvenRow(index - (index % gridWidth), gridWidth)) { neighbours = new int[6]; neighbours[0] = index + 1; neighbours[1] = index + gridWidth; neighbours[2] = index + gridWidth - 1; neighbours[3] = index - 1; neighbours[4] = index - gridWidth - 1; neighbours[5] = index - gridWidth; return neighbours; } else { neighbours = new int[6]; neighbours[0] = index + 1; neighbours[1] = index + gridWidth + 1; neighbours[2] = index + gridWidth; neighbours[3] = index - 1; neighbours[4] = index - gridWidth; neighbours[5] = index - gridWidth + 1; return neighbours; } } } boolean isEvenRow(int i, int gridWidth) { // CALCULATES IF ROW IS EVEN/ODD BASED ON INDEX OF FIRST POINT IN ROW return (i / gridWidth) % 2 == 0 ? true : false; }
|