Community Gardens has been nominated for a Webby! Please vote for me!

Technical Summary

Curious about how Community Gardens was built?

Community Gardens is a data-driven generative art installation that runs inside a browser.

Built using javascript and threejs, it generates plants. Each plant represents a student that we have food and housing insecurity information about.

Data Processing

Dr Mary Haskett conducted a survey last year that collects information from students. Some students are well-resourced and others face insecurities. The survey clarified exactly how much insecurity students face, and we learned that 9.6% of students experienced homeless over the past year.

My job starts with the data. The survey results are exported from a spreadsheet to a json file. The file is zipped to preserve bandwidth. It was an 8 meg json file, but I got it down to 145k by removing irrelevant values and zipping the file.

Once the file is loaded and unzipped, the Insecurity Calculator processes the data. It calculates:

  • Resources Incoming
  • Energy Outgoing
  • Community Fitness
  • Personal Scarcity
  • Emotional Health

These values drive a bunch of plant characteristics, but we're not done with the data yet. We need to aggregate the data in meaningful ways.

Gardens can be created based around a certain statistic, and derived at any time. Available stastics are:

  • BelowPovertyLine
  • CommunityGarden
  • DidNotEatForADay
  • EarnALot
  • EarnALotAndAreHungry
  • EnergyOutgoing
  • ExperienceHunger
  • FirstGeneration
  • FoodInsecurity
  • HighGPA
  • HighHealth
  • HighResources
  • HousingInsecurity
  • Inhabitable
  • LowHealth
  • OutOfState
  • PellGrant
  • SkipMeals
  • SleptOutside
  • Wellness
  • WorkALotAndAreHungry

Gardens

Once the aggregate data is available, gardens are created. A garden consists of a data model, a grouping of plants and a layout for the plants. Gardens can also be configured with colors and backgrounds.

The available chapters are:

  • DidNotEatForADayChapter
  • EnergyOutgoingChapter
  • FirstGenerationChapter
  • HighGPAChapter
  • HousingInsecurityChapter
  • OutOfStateChapter
  • PellGrantChapter
  • RandomGardenChapter
  • ResourcedChapter
  • SummerGardenChapter
  • WellnessChapter
  • WinterGardenChapter

Spawns

Each garden creates multiple Spawn instances. a Spawn is responsible for deriving plant properties based on the data, instantiating and managing (animateIn and removal of) the plant instances.

Available Spawn classes are:

  • Solomon's Seal Spawn
  • Asimina Triloba Spawn
  • Stellaria Pubera Spawn

Modifiers

The connection of data-to-plant-properties happens in the Transformers. Each transformer accepts data input (calculated from the InsecurityCalculator) and outputs plant properties, as defined in attribute modifiers.

For instance, the age modifier accepts a student's age and then transforms the props.petalCount accordingly.

The available modifiers are:

  • AgeModifier
  • BelowPovertyLineModifier
  • CommunityFitnessModifier
  • DegreeModifier
  • EmotionalHealthModifier
  • EnergyOutgoingModifier
  • FirstGenModifier
  • GPAModifier
  • HealthModifier
  • HousingInsecurityModifier
  • InsecurityModifier
  • OutOfStateModifier
  • PellGrantModifier
  • PersonalScarcityModifier
  • ResourcesIncomingModifier
  • ShareModifier

Plants

The plants are essentially data holders for the transformed properties when they are instantiated, but once the createChildren method is called, the geometry, materials, and mesh are created and added to the scene. This method of deferred instantiation prevents dropped frames while creating multiple plants.

The geometries are created algorithmically in three parts:

  1. Stem
  2. Leaves or petals
  3. Berries or pollen

The algorithm creates geometries and applies different materials based on the properties assigned to the plant.

Plant Properties

Each plant property is settable and will trigger a redraw of the plant. The available properties are:

setAnimated(animated)
setDuration(duration)
setDelay(delay)
setRandomSeed(randomSeed) setWindForce(windForce)
setWindDirection(windDirection)
setHeight(height)
setOffset(offset)
setDisplacement(displacement)
setThickness(thickness)
setPointCount(pointCount)
setPetalStartPoint(petalStartPoint)
setPetalEndPoint(petalEndPoint)
setRotationStart(rotationStart)
setRotationEnd(rotationEnd)
setSizeStart(sizeStart)
setSizeEnd(sizeEnd)
setColor(color)
setHSLBase(hslBase)
setHSLRange(hslRange)
setBerryCount(berryCount)
setBerrySize(berrySize)
setBerryRotation(berryRotation)
setBerryColor(berryColor)
setBerryDistanceFromStem(berryDistanceFromStem)
setBerrySpiral(berrySpiral)
setOpenness(openness)
setPetalCount(petalCount)
setLeafCount(leafCount)
setLeafStartPoint(leafStartPoint)
setLeafEndPoint(leafEndPoint)
setRearPetalCount(rearPetalCount)
setPetalWidth(petalWidth)
setPetalLength(petalLength)
setPetalDistanceFromCenter(petalDistanceFromCenter)
setRotationAxis(rotationAxis)
setRotationAngle(rotationAngle)
setTranslateToY(translateToY)
setPetalRotation(petalRotation)

BasePlant

BasePlant is responsible for common plant tasks, like drawing the stem, handling setter methods for all the properties, cleaning the instance for garbage collection, the animateIn and animateOut methods.

BaseRenderable

BaseRenderable is resonsible for managing state in a react-like manner. Even if multiple properties change, the render method is only called once.

A plant has a focal point which tells the camera where exactly to look at it while focusing.

Layouts

Plants can be arranged in a variety of layouts.

Layouts can be sized with a bounds object, which is a Vector3 of width, height, and depth.

The available layouts are:

  • CircularLayout
  • GridLayout
  • RandomLayout

Scene

Once the meshes have been created with the appropriate data and added to a scene, threejs handles rendering.

Controls

Threejs supports moving and rotating any 3d object, including the camera. Assigning camera position props as part of a TweenMax tween, we can create fluid camera movement.

The specific process is to choose a random plant and obtain its focal point. Tween the camera and the cameraTarget to that location. Once the camera completes its tween, another plant is chosen and the process is repeated.

Environments

The application behaves differently depending on the device it's running. There are two main breakpoints:

  • Large Display: Used for Immersion Theatre, the Commons Wall, the Visualization Wall, and the Art Wall at Hunt Library. These devices have a timeMultiplier parameter set to 0.3, which slows the entire scene down to 30%. Certain displays also turn sidebars and 3D titles on to display additional content, and the camera is set to autopilot.
  • Desktop and handheld: Used everywhere else. The number of plants created is reduced. The camera is set to user-controlled, and the sidebar is turned off.

Properties can be manually overriden via query string. The available query strings are:

  • timeMultiplier: 1 is normal, <1 slows the installation down. Useful for large displays where movement is accelerated because the perceived distance is so much higher than on desktop or devices.
  • quantityMultipler: The more powerful the GPU, more plants will be created. This ranges from 1 to 5. 10 will likely blow your computer up.
  • seed: used to recreate a specific garden. Note that seeds are output to the console on instantiation: if you see something you need to recreate, simply note the output and append to the query string, ie ?seed=123
  • DPR: Device pixel ratio can be lowered to increase framerate at the cost of decreasing resolution. Try ?dpr=0.1 for mad pixelation.
  • debug: set ?debug=1 to enable debug mode. This includes framerate stats, color palletes, and a gui for manipulating the camera.

Bridging react with three.js

Although threejs is all javascript, it's not immediately obvious how to render it inside a react compnent's render method, especially if you need to share data from redux. I followed this direction, which worked quite well.

Technologies that made Community Gardens possible

The project is all javascript and WebGL, meaning it runs on 20' walls in the Hunt Library's Immersion Theatre, on a desktop, or a mobile device (although with fewer plants on smaller devices to make sure phones don't blow up).

  • threejs is for 3D rendering
  • three.bas, a buffer animation system, enables hundreds of individual geometries to be animated in an efficient manner
  • Meshline to draw lines in 3D space. Using brushstrokes as textures results in very pleasing aesthetic.
  • Random Seed to recreate random sequences across installations
  • react for the UI
  • dat.gui for rapid testing of variables
  • detect-gpu to throttle features per device
  • glamorous for styling the UI
  • gsap for tweening
  • lodash for data-parsing utilities
  • react helmet for SEO support within a SPA
  • react redux for bindings
  • JSZip for uncompressing zip files in the browser.
  • Google Fonts for Alegreya and Alegreya Sans.
  • typography for ... typography.

Community Gardens
Mailing List

This project was funded by the
Andrew W. Mellon Foundation.

Copyright © 2019 lucastswick. All rights reserved.