# Where to Start? Generating Meshes from an Image

**URL:** <https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501>\
**Category:** Coding Questions\
**Created:** [May 22, 2019, 5:08pm UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501 "2019-05-22T17:08:12Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rand\_colors](https://avatars.discourse-cdn.com/v4/letter/r/3ab097/32.png) [@rand\_colors](https://discourse.processing.org/u/rand_colors)\
**Post date:** [May 22, 2019, 5:08pm UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501/1 "2019-05-22T17:08:12Z")

</div>

Hi everyone,  
I took a look at the OF tutorials, and I’m trying to understand how to do this [https://openframeworks.cc/ofBook/chapters/generativemesh.html](https://openframeworks.cc/ofBook/chapters/generativemesh.html)  
in Processing.  
It’s not essential for this first step to make a 3D mesh, I just like the way that the image look like,  
with this kind of “image processing”  
here what I mean: [https://openframeworks.cc/ofBook/images/generativemesh/images/StarLinesFirstMeshSmall.png](https://openframeworks.cc/ofBook/images/generativemesh/images/StarLinesFirstMeshSmall.png)

I suppose that I need to use the HE\_Mesh library, or maybe, openGL/GLSL directly or maybe I just need to work with vertex/beginShape(LINES) etc…?

Where can I find the right mesh choice in HE\_Mesh?  
Where can I choose the primitive tipe ?

If you could guide me would be awesome.

I looked at the he\_mesh examples, but there are too many irons in the fire.

thanks  
R\_Colors

---

<div class="post-metadata">

**Author:** ![humayung](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/humayung/32/6089_2.png) [@humayung](https://discourse.processing.org/u/humayung)\
**Post date:** [May 22, 2019, 5:48pm UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501/2 "2019-05-22T17:48:52Z")

</div>

Hi, that’s very interesting project!  
Thank you for sharing!

This code work with lines, not the mesh  
after following the tutorial, i got this

 ![Screenshot%20from%202019-05-23%2000-45-34](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/87fe3b0f2d76a587838b798c16fb47ebc592dc57.png)

tried to convert it into processing.  
except for the color

```auto
PImage image;
ArrayList<PVector> vertices = new ArrayList<PVector>();
void setup() {
  size(800, 800);
  background(0);
  noFill();
  stroke(255, 100, 0);
  
  image = loadImage("stars.png");
  //beginShape();
  float intensityThreshold = 255.0;
  int w = image.width;
  int h = image.height;
  for (int x=0; x<w; ++x) {
    for (int y=0; y<h; ++y) {
      color c = image.get(x, y);
      float intensity = brightness(c);
      if (intensity >= intensityThreshold) {
        vertices.add(new PVector(x, y));
      }
    }
  }
  //endShape();
  float num = 0;
  float connectionDistance = 15;
  int numVerts = vertices.size();
  stroke(255 ,100, 0, 50);
  println(numVerts * numVerts);
  for (int a=0; a<numVerts; ++a) {
    PVector verta = vertices.get(a);
    for (int b=a+1; b<numVerts; ++b) {
      PVector vertb = vertices.get(b);
      float distance = dist(verta.x, verta.y, vertb.x, vertb.y);//abs(verta.sub(vertb).mag());
      if (distance <= connectionDistance) {
        // In OF_PRIMITIVE_LINES, every pair of vertices or indices will be
        // connected to form a line
        line(verta.x, verta.y, vertb.x, vertb.y);
      }
    }
    num += numVerts - 1;
    //println((num / sq(numVerts) * 100) + "%");
  }
}

```

for the color, you need to research on how to draw gradient colored line

---

<div class="post-metadata">

**Author:** ![rand\_colors](https://avatars.discourse-cdn.com/v4/letter/r/3ab097/32.png) [@rand\_colors](https://discourse.processing.org/u/rand_colors)\
**Post date:** [May 22, 2019, 9:30pm UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501/3 "2019-05-22T21:30:17Z")

</div>

Really thank you!  
looks super nice!

I added a simple function to make the background interpolated in radial way.and I’m working on  
the code finded here to make gradient colored lines.  
// grad lines [https://forum.processing.org/two/discussion/5620/how-to-draw-a-gradient-colored-line](https://forum.processing.org/two/discussion/5620/how-to-draw-a-gradient-colored-line)

```auto
// computationally killer like...

void backgroundGradient(){
 
for(int y = 0; y < height; y++){
  for( int x = 0; x < width; x++){
    float distFromCent = dist(x,y, width/2, height/2);
  stroke(450-distFromCent,0,100);
 

  point(x,y);
  }
}  
}

```

I’m tring to adapt this code… extracting the colors from the pixel.arrays

```auto
float x1, y1, x2, y2;
color a, b;
 
void setup() {
  size(600, 600);
  noStroke();
  a = color(255, 0, 0);
  b = color(0, 255, 0);
  reset();
}
 
void draw() {
  background(0);
  gradientLine(x1, x2, y1, y2, a, b);
}
 
void mousePressed() {
  reset();
}
 
void gradientLine(float x1, float y1, float x2, float y2, color a, color b) {
  float deltaX = x2-x1;
  float deltaY = y2-y1;
  float tStep = 1.0/dist(x1, y1, x2, y2);
  for (float t = 0.0; t < 1.0; t += tStep) {
    fill(lerpColor(a, b, t));
    ellipse(x1+t*deltaX, y1+t*deltaY, 3, 3);
  }
}
 
void reset() {
  x1 = random(width);
  y1 = random(height);
  x2 = random(width);
  y2 = random(height);
}

```

 ![a](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f826a2197bb596f13d3b29f0425fb856a9219180.png)

```auto
// grad lines https://forum.processing.org/two/discussion/5620/how-to-draw-a-gradient-colored-line
PImage image;
ArrayList<PVector> vertices = new ArrayList<PVector>();
void setup() {
  size(800, 800);
//background(0);
   backgroundGradient();

 // noFill();
  //stroke(255, 100, 0);
  int loc = 0;
  
  image = loadImage("stars.png");
  //beginShape();
  float intensityThreshold = 255.0;
  int w = image.width;
  int h = image.height;
  color c = color(0);
  color c1 = color(0);
 color c2 = color(0);
  for (int x=0; x<w; ++x) {
    for (int y=0; y<h; ++y) {
       c = image.get(x, y);
      float intensity = brightness(c);
      if (intensity >= intensityThreshold) {
        vertices.add(new PVector(x, y));
        
      }
    }
  }

  //endShape();
  
  //Color from image 
  // you can use c = image.get(x, y); as well
  // for (int x=0; x<w; ++x) {
  // for (int y=0; y<h-1; ++y) {
  
  // loc = x + y*image.width;
  // // Color according to the image
  // c1 = image.pixels[loc];
  // c2 = image.pixels[loc+1];
      
  // }
  //}
  //
  
  
  float num = 0;
  float connectionDistance = 15;
  int numVerts = vertices.size();
 // stroke(c);
 // stroke(255 ,100, 0, 50);
  println(numVerts * numVerts);
  for (int a=0; a<numVerts; ++a) {
    PVector verta = vertices.get(a);
    for (int b=a+1; b<numVerts; ++b) {
      PVector vertb = vertices.get(b);
      float distance = dist(verta.x, verta.y, vertb.x, vertb.y);//abs(verta.sub(vertb).mag());
      if (distance <= connectionDistance) {
        // In OF_PRIMITIVE_LINES, every pair of vertices or indices will be
        // connected to form a line
        // fixed colors to debug it
         
        gradientLine(verta.x, verta.y, vertb.x, vertb.y,color(255, 0, 0,50),color(0, 255, 0,50));
      }
     
    }
    num += numVerts - 1;
    //println((num / sq(numVerts) * 100) + "%");
  }
  

}

void draw(){if(key == 's')saveFrame("a"+".png");}

void gradientLine(float x1, float y1, float x2, float y2, color a, color b) {
  float deltaX = x2-x1;
  float deltaY = y2-y1;
  float tStep = 1.0/dist(x1, y1, x2, y2);
  for (float t = 0.0; t < 1.0; t += tStep) {
    fill(lerpColor(a, b, t));
    ellipse(x1+t*deltaX, y1+t*deltaY, 0.1, 0.1);
  }
}

void backgroundGradient(){
 
for(int y = 0; y < height; y++){
  for( int x = 0; x < width; x++){
    float distFromCent = dist(x,y, width/2, height/2);
  stroke(450-distFromCent,0,100);
 

  point(x,y);
  }
}  

}

```

with fixed gradientLine setted to get the color from the vertices.

 ![a](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/05c4bc2f018abe50950d2666c880eed0e3378678.jpeg)

```auto
PImage image;
ArrayList<PVector> vertices = new ArrayList<PVector>();
void setup() {
  size(800, 800);
 // background(126);
   backgroundGradient();
 
  int loc = 0;
 
  image = loadImage("stars.png");
  //beginShape();
  float intensityThreshold = 255.0;
  int w = image.width;
  int h = image.height;
  color c = color(0);
  for (int x=0; x<w; ++x) {
    for (int y=0; y<h; ++y) {
       c = image.get(x, y);
      float intensity = brightness(c);
      if (intensity >= intensityThreshold) {
        vertices.add(new PVector(x, y));
        
      }
    }
  }

  //endShape();
 
  float num = 0;
  float connectionDistance = 15;
  int numVerts = vertices.size();

  println(numVerts * numVerts);
  for (int a=0; a<numVerts; ++a) {
    PVector verta = vertices.get(a);
    for (int b=a+1; b<numVerts; ++b) {
      PVector vertb = vertices.get(b);
      float distance = dist(verta.x, verta.y, vertb.x, vertb.y);//abs(verta.sub(vertb).mag());
      if (distance <= connectionDistance) {
      // gradient line    
        gradientLine(verta.x, verta.y, vertb.x, vertb.y,image.get((int)verta.x, (int)verta.y),image.get((int)vertb.x, (int)vertb.y));
      }
     
    }
    num += numVerts - 1;
    //println((num / sq(numVerts) * 100) + "%");
  }
  

}

void draw(){}

void gradientLine(float x1, float y1, float x2, float y2, color a, color b) {
  float deltaX = x2-x1;
  float deltaY = y2-y1;
  float tStep = 1.0/dist(x1, y1, x2, y2);
   noStroke();
  for (float t = 0.0; t < 1.0; t += tStep) {
    fill(lerpColor(a, b, t));
    ellipse(x1+t*deltaX, y1+t*deltaY, 1, 1);
  }
}

void backgroundGradient(){
for(int y = 0; y < height; y++){
  for( int x = 0; x < width; x++){
    float distFromCent = dist(x,y, width/2, height/2);
  stroke(300-distFromCent,300-distFromCent,300-distFromCent,200);
  point(x,y);
  }
}  
}

void keyPressed(){
 if(key == 's')saveFrame("a"+".png");
}

```

---

<div class="post-metadata">

**Author:** ![humayung](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/humayung/32/6089_2.png) [@humayung](https://discourse.processing.org/u/humayung)\
**Post date:** [May 23, 2019, 8:23am UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501/4 "2019-05-23T08:23:19Z")

</div>

It would run faster if you use _Quadtree_ for distance threshold checking. And then remove vertices that are not connected atleast to one other vertex.

---

<div class="post-metadata">

**Author:** ![rand\_colors](https://avatars.discourse-cdn.com/v4/letter/r/3ab097/32.png) [@rand\_colors](https://discourse.processing.org/u/rand_colors)\
**Post date:** [May 23, 2019, 7:18pm UTC](https://discourse.processing.org/t/where-to-start-generating-meshes-from-an-image/11501/5 "2019-05-23T19:18:59Z")

</div>

> [@humayung](#):
>
> _Quadtree_

I’m looking at those links to try to understand what is this “mystic” quadtree :  
[Quadtree - Wikipedia](https://en.wikipedia.org/wiki/Quadtree) // point QuadTree

[![](https://img.youtube.com/vi/OJxEcs0w_kE/maxresdefault.jpg "Coding Challenge #98.1: Quadtree - Part 1") ](https://www.youtube.com/watch?v=OJxEcs0w_kE)

[![](https://img.youtube.com/vi/QQx_NmCIuCY/maxresdefault.jpg "Coding Challenge #98.2: Quadtree - Part 2") ](https://www.youtube.com/watch?v=QQx_NmCIuCY&t=14s)

[![](https://img.youtube.com/vi/z0YFFg_nBjw/maxresdefault.jpg "Coding Challenge #98.3: Quadtree Collisions - Part 3") ](https://www.youtube.com/watch?v=z0YFFg_nBjw&t=22s)

> **[Quadtree | Mesh generation using quadtrees](https://en.wikipedia.org/wiki/Quadtree#Mesh_generation_using_quadtrees)**
>
> This section summarizes a chapter from a book by Har-Peled and de Berg et al.
> Mesh generation is essentially the triangulation of a point set for which further processing may be performed. As such, it is desirable for the resulting triangulation to have certain properties (like non-uniformity, triangles that are not "too skinny", large triangles in sparse areas and small triangles in dense ones, etc.) to make further processing quicker and less error-prone. Quadtrees built on the point set can b...

// Recursion  
Recursion is simply achieved by writing a function that calls itself one or more times.

> **[Codebox: Explore Recursion with Processing](https://makezine.com/article/technology/arduino/codebox-explore-recursion-with-processing/)**
>
> This Codebox shows how to create a variety of geometric designs using recursion.

> **[Recursion / Examples](https://processing.org/examples/recursion.html)**
>
> A demonstration of recursion, which means functions call themselves. Notice how the drawCircle() function calls itself at the end of its block. It continues to do this until the variable "level" is eq…

> **[Recursive Tree / Examples](https://processing.org/examples/tree.html)**
>
> Renders a simple tree-like structure via recursion. The branching angle is calculated as a function of the horizontal mouse location. Move the mouse left and right to change the angle.

// quad tree in processing  
[https://thecodingtrain.com/CodingChallenges/098.1-quadtree.html](https://thecodingtrain.com/CodingChallenges/098.1-quadtree.html)

thanks
