Draw a line using glgraphics

edited March 2014 in GLSL / Shaders

Hi,

I am programming a network visualizing applet. I render each of the nodes of the network using a texture with glgraphics (following the swarming sprites example). I need, however to draw also the links between the nodes. How should I do this? When I use the standard line method link don't appear at the "right" coordinates. I am using processing 1.5.

Thanks for your help!

Tagged:

Answers

  • Well, i can draw a line using:

      lines.beginUpdateVertices();
      for(int i = 0 ; i < numLines ; i++){
        lines.updateVertex(i, random(50), random(50), random(50) );
      }
      lines.endUpdateVertices();
    

    and then lines.render().

    However, i have to render a graph, so not all vertices will be linked. Some may have several links. There will also be non-conected components, which means that i would have sets of isolated nodes. I cant figure out how i should build my model in this case.I guess it doesn't make any sense to have a model with only one line... or does it?

  • I tried with an array of models (one for each link) but fps go very low.

  • edited March 2014

    what do you have in your

    model = new GLModel(this, numPoints, GLModel.POINT_SPRITES, GLModel.DYNAMIC);

    line?

    i think you need LINES rather than POINT_SPRITES. and this will then take pairs of coords and draw a line between each pair (allowing for gaps). if it's LINE (or maybe LINE_STRIP, i can't remember) then it'll draw from one coord to the next, one continuous line.

  • I have lines, like this:

      lines = new GLModel(this, numLines, LINES, GLModel.DYNAMIC);
    

    So, 1. How should I allow the gaps? 2. A continous line sounds problematic, since I need to draw a graph, which is a complex set of nodes and vertices. What is the best solution?

  • Answer ✓

    can't really tell based on the 4 lines of your code we can see...

    it will draw separate lines if you use LINES. your array will have to hold pairs of coordinates, start and end for each line.

    oh, i have an example. it's a STATIC example but hopefully it'll help:

    // a million billion stars...
    // acd 20110723
    
    import codeanticode.glgraphics.*;
    import peasy.*;
    import processing.opengl.*;
    
    int NUM_POINTS = 10;
    int STARS = 9000;
    int SZ = 500;  // size of cube
    
    GLModel lines;
    PeasyCam cam;
    
    void setup() {
      size(720, 720, GLConstants.GLGRAPHICS);
    
      // stars
      // each star has 10 lines, each line has two points.
      lines = new GLModel(this, STARS * NUM_POINTS * 2, LINES, GLModel.STATIC);
      lines.initColors();
      lines.setColors(0);
      lines.beginUpdateVertices();
      int index = 0;
      for (int s = 0 ; s < STARS ; s++) {
        Star star = new Star();
        lines.updateVertex(index++, star.pt[0].x, star.pt[0].y, star.pt[0].z);
        for (int i = 1 ; i < 10 ; i++) {
          lines.updateVertex(index++, star.pt[i].x, star.pt[i].y, star.pt[i].z);
          lines.updateVertex(index++, star.pt[i].x, star.pt[i].y, star.pt[i].z);
        }
        lines.updateVertex(index++, star.pt[0].x, star.pt[0].y, star.pt[0].z);
      }
      lines.endUpdateVertices();
    
      cam = new PeasyCam(this, SZ);
      cam.setMaximumDistance(20000);
      cam.setMinimumDistance(200);
    }
    
    void draw() {
    
      GLGraphics renderer = (GLGraphics)g;
      renderer.beginGL();
      background(255);
      stroke(0);
      renderer.model(lines);
      renderer.endGL();
    }
    
    class Star {
      public PVector[] pt = new PVector[10];
      float radi = 10;
    
      Star() {
        float angle = TWO_PI / 10.0;
        double s;
        for (int i = 0 ; i < 10 ; i++) {
          if ((i % 2) == 0) {
            s = radi;
          } else {
            s = radi * .4;
          }
          PVector tmp = new PVector((float)(s * cos(i * angle)), (float)(s * sin(i * angle)), 0.0);
          pt[i] = tmp;
        }
    
        // orientation of star
        myRotateX(random(TWO_PI));
        myRotateY(random(TWO_PI));
        myRotateZ(random(TWO_PI));
    
        // translate (random position within a sphere radius SZ)
        float x, y, z;
        do {
          x = random(-SZ, SZ);
          y = random(-SZ, SZ);
          z = random(-SZ, SZ);
        } while (x * x + y * y + z * z > SZ * SZ);
    
        for (int i = 0 ; i < 10 ; i++) {
          pt[i].add(x, y, z);
        }    
      }
    
      void myRotateX(float angle) {
        float c = cos(angle);
        float s = sin(angle);
        for (int i = 0 ; i < 10 ; i++) {
          float y = pt[i].y * c - pt[i].z * s;
          float z = pt[i].y * s + pt[i].z * c;
          pt[i].y = y;
          pt[i].z = z;
        }
      }
    
      void myRotateY(float angle) {
        float c = cos(angle);
        float s = sin(angle);
        for (int i = 0 ; i < 10 ; i++) {
          float x = pt[i].x * c - pt[i].z * s;
          float z = pt[i].x * s + pt[i].z * c;
          pt[i].x = x;
          pt[i].z = z;
        }
      }
    
      void myRotateZ(float angle) {
        float c = cos(angle);
        float s = sin(angle);
        for (int i = 0 ; i < 10 ; i++) {
          float x = pt[i].x * c - pt[i].y * s;
          float y = pt[i].x * s + pt[i].y * c;
          pt[i].x = x;
          pt[i].y = y;
        }
      }
    }
    
  • edited March 2014

    Thank you very much koogs. I had assumed that lines were connected one after another (is this the case with LINE_STRIP?) so I was a bit puzzled when it came to drawing a graph. I followed your suggestion and used LINE, which worked perfectly. I have an arraylist of links and an arraylist of people (i'm drawing a social graph). The links hold the indices of the people they have to link to.

      lines = new GLModel(this, links.size()*2, LINES, GLModel.DYNAMIC );
    

    ...

     int vertexIndex = 0;
      lines.beginUpdateVertices();
      for (int i = 0 ; i < links.size() ; i++) {
    
       Link l = (Link) links.get(i);
       PVector v1 =  (people.get(l.indicePart1) ).particula.pos;
       PVector v2 =  (people.get(l.indicePart2) ).particula.pos; 
       lines.updateVertex(vertexIndex, v1.x, v1.y, v1.z);
       vertexIndex++;// Next vertex
       lines.updateVertex(vertexIndex, v2.x, v2.y, v2.z);
       vertexIndex++;
      }
      lines.endUpdateVertices();
    

    Here is the link class

    class Link {
      int indicePart1;
      int indicePart2;
    
      Link(int i1, int i2) {
        indicePart1 = i1;
        indicePart2 = i2;
      }
      void draw(ArrayList losObjetos) {
        VerletObject o1 = ( (Node) losObjetos.get(indicePart1)).particula ;
        VerletObject o2 = ( (Node) losObjetos.get(indicePart2)).particula ;
        stroke(160);
        line(o1.pos.x, o1.pos.y, o1.pos.z, o2.pos.x, o2.pos.y, o2.pos.z);
      }
    }
    

    Now the question is: lets say i want to filter some links, using some kind of criteria. For example, only draw link between a male node and a female node. I should therefore bypass the rendering of a line, or delete it. Is this possible?

  • i think you can draw subsets of the data. yes, according to the javadoc:

    public void render(int first, int last)

    but you'd need to call this for all the (groups of) links you want to draw. might be easier and faster to redo the lines array so it contains only the lines you want and then call render() with no arguments.

Sign In or Register to comment.