Data Visualization.
Lab Work 3. Interactive 3D Visualization in Processing
Goal of the work
To learn how to design, justify, and implement fully 3D interactive visualizations
in Processing. Students must treat the visualization as a prototype of an analytical
tool built from scratch, develop interactive 3D representations of a real dataset, and
evaluate how effectively the visualization supports analysis and hypothesis testing.
Objectives
1. Describe the subject area and the dataset
Students must examine the dataset and describe:
• the domain and context,
• the data structure and variables,
• why the dataset is suitable for 3D visualization (spatial structure,
multidimensional structure, time as a dimension, hierarchical or positional
relationships).
Expected outcome:
A written description explaining the dataset and expressing why 3D representation
is necessary or beneficial.
2. Prepare the data for 3D visualization in Processing
Students should transform raw data into a format suitable for a 3D visualization
pipeline:
• normalization of numeric variables to 3D coordinates,
• mapping variables to axes or spatial layers,
• encoding categories as colors, shapes, or sizes,
• structuring data into arrays, objects, or tables readable by Processing.
Expected outcome:
Processed CSV/JSON + a structured data loader inside Processing.
3. Formulate at least five analytical hypotheses testable through 3D
interaction
Hypotheses must take advantage of depth, perspective, movement, or spatial
comparison. Examples:
• clusters become visible only in 3D space,
• trends appear as spatial trajectories,
• categories form layers or volumes,
• anomalies stand out when rotating the scene,
• relationships become clearer with interactive distance-based inspection.
Expected outcome:
Five hypotheses + explanation of how the 3D view and interaction make them
testable.
4. Design the 3D visualization and its interactive controls
Students must propose and justify:
• 3D layout (scatter plot, voxel map, layered structure, trajectories, 3D
network, 3D bars, surfaces, etc.),
• camera system (orbit control, free-fly, zoom, rotation),
• interactive features (filtering, highlighting, depth exploration, element
selection),
• visual encodings (color, size, opacity, 3D shape, animation).
Expected outcome:
A conceptual design (sketch or description) + implementation of a separate
Visualization3D class in Processing that encapsulates rendering logic.
5. Implement the interactive 3D visualization in Processing and interpret the
results
Students must build a working Processing sketch with:
• complete 3D rendering using P3D,
• interactive camera controls,
• meaningful interactive elements,
• clean class architecture (main app + visualization class).
Then analyze how effectively the visualization allowed them to confirm or refute
the hypotheses.
Expected outcome:
A functioning 3D interactive Processing application + written interpretation.
Example (Adapted): 3D Interactive Data Visualization in Processing
1. Introduction and conceptual design
Before beginning development, it is necessary to define the goals and analytical
tasks of the work. These choices influence the 3D model, the level of detail, the
chosen spatial metaphor, visibility strategies, and the required degree of
interaction.
In this example, the goal is to design a 3D interactive visualization tool that
reveals multidimensional data patterns through spatial distribution, color, and
rotation-based perspective changes.
We treat the visualization not as a static picture, but as a prototype of an
analytical instrument that enables hypothesis testing by rotating, zooming,
exploring clusters, and inspecting relationships in depth.
We select a visualization type (interactive 3D scatterplot) and determine:
• key visual encodings (position, color, size),
• interaction model (orbit camera, zoom, reset),
• minimalistic but expressive metaphors (spheres as data points),
• multilingual/visual communication (color, shape, movement instead of
extensive text).
Processing is chosen due to its simplicity, Java-based syntax, and native P3D
support for fast 3D rendering and interaction.
The application consists of two core modules:
• setup() – initialization
• draw() – main rendering loop
Data are stored in the data/ folder and loaded at runtime.
2. Dataset description
For demonstration, we use an adapted version of Fisher’s Iris dataset. The original
dataset contains 150 specimens of three iris species, each with four characteristics:
• sepal length
• sepal width
• petal length
• petal width
To convert these values into a 3D visualization, three numeric features are mapped
to x, y, z coordinates, while species labels are mapped to color classes.
This makes the dataset suitable for 3D visualization because:
• clusters may become more distinguishable in space,
• perspective rotation may reveal hidden separations,
• structural relationships can be explored interactively.
3. Preparing data for 3D visualization
To import the dataset, we implement a custom csvToArray() function that
loads the CSV and converts each row into an object of class Bubble. This class is
responsible for storing coordinates and color coding.
Coordinates are normalized using the global variable size (the scale of the 3D
coordinate system), which ensures that Iris measurements, originally in
centimeters, are mapped proportionally to the 3D space.
Example — loading CSV into objects
ArrayList<Bubble> csvReadToArray() {
ArrayList<Bubble> bubbles = new ArrayList<Bubble>();
Table table = loadTable("[Link]", "header");
for (TableRow row : [Link]()) {
float x = (size/10) * [Link]("[Link]");
float y = (size/10) * [Link]("[Link]");
float z = (size/10) * [Link]("[Link]");
String species = [Link]("variety");
color clr = color(255,255,255);
if ([Link]("Setosa")) clr = color(194, 76, 0, 76);
if ([Link]("Versicolor")) clr = color(0, 194, 136, 76);
if ([Link]("Virginica")) clr = color(194, 8, 76);
[Link](new Bubble(x, y, z, clr, 5));
}
return bubbles;
}
4. Implementing the 3D visualization tool
4.1 Class for visual objects
Each data point is represented by a sphere in 3D space. The Bubble class stores:
• spatial coordinates
• color
• radius
• a rendering method
class Bubble {
float x, y, z;
color c;
float r;
Bubble(float x_, float y_, float z_, color c_, float r_) {
x = x_;
y = y_;
z = z_;
c = c_;
r = r_;
}
void display() {
pushMatrix();
noStroke();
lights();
translate(x, y, z);
fill(c);
sphere(r);
popMatrix();
}
}
All spheres are rendered in the draw() method:
for (Bubble b : bubbles) {
[Link]();
}
5. Constructing 3D axes and coordinate planes
To support spatial reasoning, the tool includes labeled axes and a Cartesian grid.
• Axes constructed with line(), colored R–G–B
• Coordinate labels with text()
• Grid generated using iterative steps (size/10)
• A ground plane for reference
The result is a functional 3D coordinate system suitable for analytic tasks.
6. Adding interactive capabilities
A static 3D image is insufficient for analysis; therefore, the visualization includes:
Mouse-driven rotation
Implemented using mouseDragged() and acting on rotation angles:
rotateX(-yAngle);
rotateY(-xAngle);
Zoom control
Mouse wheel scaling modifies a global scale variable:
scale(scaleFactor);
View reset
Left mouse button resets rotation and zoom.
This interaction model transforms the visualization into an exploratory analytical
environment, enabling:
• detection of clusters by rotating perspective
• discovery of linear relationships when viewed along specific axes
• identification of outliers
• spatial comparison of classes
3D Visualization Templates for Processing (P3D)
1. 3D Scatterplot Template (with rotation + point hover)
// ==== MAIN PROGRAM ====
Scatter3D scatter;
float rotX = 0;
float rotY = 0;
boolean dragging = false;
int prevX, prevY;
void setup() {
size(900, 700, P3D);
scatter = new Scatter3D("[Link]");
}
void draw() {
background(245);
translate(width/2, height/2, -300);
rotateX(rotX);
rotateY(rotY);
[Link]();
}
void mousePressed() {
dragging = true;
prevX = mouseX;
prevY = mouseY;
}
void mouseDragged() {
if (dragging) {
rotY += (mouseX - prevX) * 0.01;
rotX -= (mouseY - prevY) * 0.01;
prevX = mouseX;
prevY = mouseY;
}
}
void mouseReleased() {
dragging = false;
}
// ==== CLASS ====
class Scatter3D {
Table table;
ArrayList<PVector> points = new ArrayList<PVector>();
Scatter3D(String file) {
table = loadTable(file, "header,csv");
for (TableRow row : [Link]()) {
[Link](new PVector([Link]("x"), [Link]("y"),
[Link]("z")));
}
}
void display() {
stroke(20);
for (PVector p : points) {
pushMatrix();
translate(p.x, p.y, p.z);
fill(0, 100, 200, 180);
noStroke();
sphere(6);
popMatrix();
}
}
}
2. 3D Bar Chart Template (interactive rotation + bar highlight)
BarChart3D chart;
float angleX, angleY;
boolean drag;
void setup() {
size(900,700,P3D);
chart = new BarChart3D("[Link]");
}
void draw() {
background(250);
translate(width/2, height/2, -400);
rotateX(angleX);
rotateY(angleY);
[Link]();
}
void mouseDragged() {
angleY += (mouseX - pmouseX) * 0.01;
angleX += (mouseY - pmouseY) * 0.01;
}
// ==== CLASS ====
class BarChart3D {
Table table;
float barW = 20;
float barD = 20;
BarChart3D(String file) {
table = loadTable(file, "header,csv");
}
void display() {
int i = 0;
for (TableRow row : [Link]()) {
float h = [Link]("value");
pushMatrix();
translate(i * (barW + 10), -h/2, 0);
if (mouseOver(i, h)) fill(255,100,100);
else fill(100,150,250);
box(barW, h, barD);
popMatrix();
i++;
}
}
boolean mouseOver(int index, float h) {
return false; // можно добавить расчёт пересечения луча
}
}
3. 3D Surface Plot Template (mesh + interactive rotation)
Surface3D surface;
float rx, ry;
void setup() {
size(900,700,P3D);
surface = new Surface3D("[Link]");
}
void draw() {
background(245);
translate(width/2, height/2, -500);
rotateX(rx);
rotateY(ry);
[Link]();
}
void mouseDragged() {
ry += (mouseX - pmouseX) * 0.01;
rx -= (mouseY - pmouseY) * 0.01;
}
class Surface3D {
Table table;
float[][] grid;
int w, h;
Surface3D(String file) {
table = loadTable(file,"header,csv");
w = [Link](0, "width");
h = [Link](0, "height");
grid = new float[w][h];
int idx = 0;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
grid[x][y] = [Link]().get(idx).getFloat("z");
idx++;
}
}
}
void display() {
stroke(200);
noFill();
for (int x=0; x<w-1; x++) {
beginShape(TRIANGLE_STRIP);
for (int y=0; y<h; y++) {
vertex(x*10, y*10, grid[x][y]);
vertex((x+1)*10, y*10, grid[x+1][y]);
}
endShape();
}
}
}
4. 3D Network Graph Template
Graph3D graph;
float ax, ay;
void setup() {
size(900,700,P3D);
graph = new Graph3D("[Link]", "[Link]");
}
void draw() {
background(250);
translate(width/2, height/2, -300);
rotateX(ax);
rotateY(ay);
[Link]();
}
void mouseDragged() {
ay += (mouseX - pmouseX) * 0.01;
ax -= (mouseY - pmouseY) * 0.01;
}
class Node3D {
PVector pos;
int id;
Node3D(int id, float x, float y, float z) {
[Link] = id;
pos = new PVector(x,y,z);
}
}
class Edge3D {
Node3D a, b;
Edge3D(Node3D a, Node3D b) {
this.a = a; this.b = b;
}
}
class Graph3D {
ArrayList<Node3D> nodes = new ArrayList<Node3D>();
ArrayList<Edge3D> edges = new ArrayList<Edge3D>();
Graph3D(String nodeFile, String edgeFile) {
Table nt = loadTable(nodeFile,"header");
for (TableRow r : [Link]()) {
[Link](new Node3D([Link]("id"), [Link]("x"), [Link]("y"),
[Link]("z")));
}
Table et = loadTable(edgeFile,"header");
for (TableRow r : [Link]()) {
[Link](new Edge3D(
[Link]([Link]("source")),
[Link]([Link]("target"))
));
}
}
void display() {
stroke(180);
for (Edge3D e : edges) {
line([Link].x, [Link].y, [Link].z,
[Link].x, [Link].y, [Link].z);
}
for (Node3D n : nodes) {
pushMatrix();
translate([Link].x, [Link].y, [Link].z);
fill(100,0,200);
noStroke();
sphere(8);
popMatrix();
}
}
}
5. 3D Tube Time Series / Ribbon Plot Template
TimeTube tube;
float rx, ry;
void setup() {
size(900,700,P3D);
tube = new TimeTube("[Link]");
}
void draw() {
background(255);
translate(width/2, height/2, -500);
rotateX(rx);
rotateY(ry);
[Link]();
}
void mouseDragged() {
ry += (mouseX - pmouseX) * 0.01;
rx -= (mouseY - pmouseY) * 0.01;
}
class TimeTube {
ArrayList<PVector> pts = new ArrayList<PVector>();
TimeTube(String file) {
Table t = loadTable(file,"header");
for (TableRow r : [Link]()) {
[Link](new PVector([Link]("time"), [Link]("value"),
[Link]("z")));
}
}
void display() {
noFill();
stroke(50,100,200);
strokeWeight(4);
beginShape();
for (PVector p : pts) vertex(p.x, p.y, p.z);
endShape();
}
}
6. (Optional) 3D Parallel Coordinates Template
Parallel3D pc;
float ax, ay;
void setup() {
size(900,700,P3D);
pc = new Parallel3D("[Link]");
}
void draw() {
background(255);
translate(width/2, height/2, -350);
rotateX(ax);
rotateY(ay);
[Link]();
}
void mouseDragged() {
ay += (mouseX - pmouseX) * 0.01;
ax -= (mouseY - pmouseY) * 0.01;
}
class Parallel3D {
ArrayList<float[]> rows = new ArrayList<float[]>();
Parallel3D(String file) {
Table t = loadTable(file,"header");
for (TableRow r : [Link]()) {
float[] vals = {
[Link]("a"),
[Link]("b"),
[Link]("c"),
[Link]("d")
};
[Link](vals);
}
}
void display() {
stroke(0,40);
for (float[] row : rows) {
beginShape();
for (int i=0;i<[Link];i++) {
vertex(i*40, -row[i]*10, i*20);
}
endShape();
}
}
}