# Truchet pattern 3D height map from blurred image

please format code with </> button * homework policy * asking questions

I would like to create a 3D heightmap of a blurred image out of the following truchet pattern grid (via “Processing: Creative Coding and Generative Art in Processing 2”), but I am running into a wall…

``````int tileSize = 24;
int rows = 35;
int cols = 35;
Tile[][] tiles = new Tile[rows][cols];

void setup(){
size(800,800); // (tileSize*rows, tileSize*cols);
smooth();
background(255);

for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
tiles[i][j] = new Tile(j*tileSize, i*tileSize, tileSize);
tiles[i][j].display();
}
}
}

class Tile{
int sz;
int x,y;
int orient;

Tile(int x, int y, int w){
this.x = x;
this.y = y;
sz = w;
orient = int (random(0,3));
}

void display(){
pushMatrix();
translate(x,y);
translate(sz/2, sz/2);
rotate(orient*PI/2);
translate(-sz/2,-sz/2);
fill(0);
triangle(sz,0,sz,sz,0,sz);
popMatrix();
}
}
``````

Hi @asymmetric,

still the same used in earlier post.

Look at it again and try to figure out what’s to do…
As a Hint: read the blurred image into a buffer (maybe convert to grayscale beforehand), and map ie brightness from black to white (-1 to 1) and apply it to the corresponding z-coords (maybe multiplied with a factor, ie. 50.).

Cheers
— mnse

Hi @mnse! I have the following code. How do I fill in the following grid with truchet patterns?

``````//GLOBAL VARIABLES
PImage img;

int borderGap = 10;
int resolution = 100;
//int maxHeight = 0;

Grid grid;

void vertexP(PVector P) {
vertex(P.x, P.y, P.z);
}

void setup() {
size(1000, 1000, P3D);
pixelDensity(2);

grid = new Grid(resolution, borderGap);

smooth(8);
}

void draw() {
background(0);

grid.display();

noLoop();
}

/**
* Give vertices in this order:
*
*  A -- B
*  |    |
*  D -- C
*/
void triangulatedFace(PVector A, PVector B, PVector C, PVector D, boolean flipDiagonal) {
// B -> A -> C -> D
if (flipDiagonal) {
vertexP(B);
vertexP(A);
vertexP(C);
vertexP(D);
} else {
// A -> D -> B -> C
vertexP(A);
vertexP(D);
vertexP(B);
vertexP(C);
}
}

//CLASS
class Grid {
//INSTANCE VARIABLES
PVector[][] points;
boolean[][] diagonals;

//CONSTRUCTOR
Grid(int resolution, int borderGap) {
points = new PVector[resolution][resolution];
diagonals = new boolean[resolution][resolution];

float spaceBetweenPoints = (float) (width - (2 * borderGap)) / (resolution - 1);

img.resize(100,100);
// Construct points
for (int i = 0; i < resolution; i++) {
float x = borderGap + i * spaceBetweenPoints;
for (int j = 0; j < resolution; j++) {
float y = borderGap + j * spaceBetweenPoints;
float pointHeight = 200 *(brightness(img.get(i,j))/ 255-0.8);
points[i][j] = new PVector(x, y, pointHeight);

// Store diagonal info, with 1/2 flip
diagonals[i][j] = random(1) < 0.5;

}
}
}

void displayPoints() {

strokeWeight(1);
stroke(#0BFF00);

for (int i = 0; i < resolution; i++) {
for (int j = 0; j < resolution; j++) {
PVector P = points[i][j];
point(P.x, P.y, P.z);
}
}
}

void displayTriangleStrips() {
stroke(255);
strokeWeight(1);
noFill();

for (int j = 0; j < resolution - 1; j++) {
for (int i = 0; i < resolution - 1; i++) {
beginShape(TRIANGLE_STRIP);

triangulatedFace(
points[i][j],
points[i + 1][j],
points[i + 1][j + 1],
points[i][j + 1],
diagonals[i][j]
);

endShape();
}
}
}

void display() {
displayTriangleStrips();
displayPoints();
}
}
``````

``````int tileSize = 24;
int rows = 35;
int cols = 35;
Tile[][] tiles = new Tile[rows][cols];

void setup(){
size(800,800); // (tileSize*rows, tileSize*cols);
smooth();
background(255);

for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
tiles[i][j] = new Tile(j*tileSize, i*tileSize, tileSize);
tiles[i][j].display();
}
}
}

class Tile{
int sz;
int x,y;
int orient;

Tile(int x, int y, int w){
this.x = x;
this.y = y;
sz = w;
orient = int (random(0,3));
}

void display(){
pushMatrix();
translate(x,y);
translate(sz/2, sz/2);
rotate(orient*PI/2);
translate(-sz/2,-sz/2);
fill(0);
triangle(sz,0,sz,sz,0,sz);
popMatrix();
}
}
``````

Hi @asymmetric,

As you need the colors strictly separated in this case the TRIANGLE_STRIP won’t work due to the kind of coloring behaviour for shared vertices. I’ve changed to draw the triangles separately so they have their own color each. See code below …

Cheers
— mnse

``````import peasy.*;

//GLOBAL VARIABLES
PImage img;

int borderGap = 10;
int resolution = 20;
//int maxHeight = 0;

Grid grid;
PeasyCam cam;

void vertexP(PVector P) {
vertex(P.x, P.y, P.z);
}

void setup() {
size(500, 500, P3D);
cam = new PeasyCam(this,600);
//pixelDensity(1);

grid = new Grid(resolution, borderGap);

smooth(8);
}

void draw() {
background(0);
translate(-width/2, -height/2 , 0);
//rotateY(frameCount/25.);
grid.display();

//noLoop();
}

/**
* Give vertices in this order:
*
*  A -- B
*  |    |
*  D -- C
*/
void triangulatedFace(PVector A, PVector B, PVector C, PVector D, boolean flipDiagonal) {
// B -> A -> C -> D
if (flipDiagonal) {
vertexP(B);
vertexP(A);
vertexP(C);
vertexP(D);
} else {
// A -> D -> B -> C
vertexP(A);
vertexP(D);
vertexP(B);
vertexP(C);
}
}

//CLASS
class Grid {
//INSTANCE VARIABLES
PVector[][] points;
boolean[][] diagonals;
boolean[][] colorswitch;

//CONSTRUCTOR
Grid(int resolution, int borderGap) {
points = new PVector[resolution][resolution];
diagonals = new boolean[resolution][resolution];
colorswitch = new boolean[resolution][resolution];

float spaceBetweenPoints = (float) (width - (2 * borderGap)) / (resolution - 1);

//img.resize(100,100);
// Construct points
for (int i = 0; i < resolution; i++) {
float x = borderGap + i * spaceBetweenPoints;
for (int j = 0; j < resolution; j++) {
float y = borderGap + j * spaceBetweenPoints;
float pointHeight = 200.*noise(i*0.1,j*0.1);//  0;//200 *(brightness(img.get(i,j))/ 255-0.8);
points[i][j] = new PVector(x, y, pointHeight);

// Store diagonal info, with 1/2 flip
diagonals[i][j] = random(1) < 0.5;
colorswitch[i][j] = random(1) < 0.5;
}
}
}

void displayPoints() {

strokeWeight(1);
stroke(#0BFF00);

for (int i = 0; i < resolution; i++) {
for (int j = 0; j < resolution; j++) {
PVector P = points[i][j];
point(P.x, P.y, P.z);
}
}
}

void displayTriangleStrips() {
stroke(255);
strokeWeight(1);
noFill();

for (int j = 0; j < resolution - 1; j++) {
for (int i = 0; i < resolution - 1; i++) {
PVector P1 = points[i][j];
PVector P2 = points[i+1][j];
PVector P3 = points[i+1][j+1];
PVector P4 = points[i][j+1];
noStroke();
beginShape(TRIANGLES);
if (diagonals[i][j]) {
fill(colorswitch[i][j] ? color(255, 0, 0) : color(0, 0, 255));
vertex(P4.x, P4.y, P4.z);
vertex(P1.x, P1.y, P1.z);
vertex(P2.x, P2.y, P2.z);
fill(!colorswitch[i][j] ? color(255, 0, 0) : color(0, 0, 255));
vertex(P4.x, P4.y, P4.z);
vertex(P2.x, P2.y, P2.z);
vertex(P3.x, P3.y, P3.z);
} else {
fill(colorswitch[i][j] ? color(255, 0, 0) : color(0, 0, 255));
vertex(P1.x, P1.y, P1.z);
vertex(P2.x, P2.y, P2.z);
vertex(P3.x, P3.y, P3.z);
fill(!colorswitch[i][j] ? color(255, 0, 0) : color(0, 0, 255));
vertex(P1.x, P1.y, P1.z);
vertex(P4.x, P4.y, P4.z);
vertex(P3.x, P3.y, P3.z);
}

//triangulatedFace(
//  points[i][j],
//  points[i + 1][j],
//  points[i + 1][j + 1],
//  points[i][j + 1],
//  diagonals[i][j]
//);

endShape();
}
}
}

void display() {
displayTriangleStrips();
//displayPoints();
}
}
``````

EDIT: Simply add PeasyCam so you can see it in 3D. Heightmap is random as I don’t have you image.

1 Like

Thank you soooooo much, @mnse!!! You made my day!!! Happy Holidays!

1 Like

Thank you @mnse !! Merry Christmas!!

1 Like