How to draw with triangle strips

Hello guys,

I am trying to transfer different examples from Processing to openFrameworks and I am trying to recreate this example from Daniels Shiffmans Coding Challenge series: https://www.youtube.com/watch?v=IKB1hWWedMk
At minute 5.09 he shows how to draw vertices as triangle strips in Processing and I am stuck doing the same procedure in openFrameworks.Any help would be much appreciated :slight_smile:

1 Like

to be more precise in processing when using beginShape(); endShape(); you can specify to draw as triangle strips while the same commands in openFrameworks draws as polygons

Hi,

I think you can do it in 2 steps:
create ofVboMesh, then draw it:

in setup():

ofVboMesh vbo;
    
vbo.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
for( int i = -maxW; i <= maxW; i += 1){
            for( int j = -maxH; j <= maxH; j += 1){
            //need to do the edges too 
                
              //ofNoise stuff;
               float z = ofNoise(i) * 10;
                
                ofVec3f vert = {(float)i, (float)j, z};
                vbo.addVertex(vert);
                vbo.addColor({155, 155, 155});

               // right vertex
               z = ofNoise(i+1) * 10;
               vert = {float)(i+1), (float)j, z};
                vbo.addVertex(vert);
                vbo.addColor({155, 155, 155});

               // bottom vertex
               z = ofNoise(i+maxH * 2) * 10;
               vert = {float)(i), (float)(j+1), z};
                vbo.addVertex(vert);
                vbo.addColor({155, 155, 155});
           }
}

in draw :

v.draw();

Hope this helps to start.
++

Thank you very much! The result is not the same as processing yet but this is the starting point I was looking for :slight_smile:

Hello, i’m trying to transfer the same example.

I have to admit that I’m completely lost with the explanation above.
Why can’t I just transfer the method from Daniel Shiffman to openFrameworks?

When using this loop in draw()

for (int y = 0; y < rows; y++) {
ofBeginShape();
for (int x = 0; x < cols; x++) {
mesh.addVertex(ofVec3f(xscl, yscl, terrain[x][y]));
mesh.addVertex(ofVec3f(x*scl, (y+1)*scl, terrain[x][y+1]));
}
ofEndShape();

and specifying as Triangle Strips in Setup()

mesh.setMode(OF_PRIMITIVE_TRIANGLES);

I get this result instead of a the grid also shown in the youtube video

Also I’m wondering why the screen doesn’t get updated, altough I call ofBackground(0); in the beginning of draw(), just like in the examples provided with openframeworks.

I looked through the learning pages for graphics, the ofBook and the documentation and I just can’t make sense of this.

Can anyone please provide an explanation?

Thank you

edit: although I’m familiar with the concept of vbo’s, I want to save learning that method for later (i.e: When I understood the fundamentals)

Hey,

When writing addVertex, the vertex gets added, but the one which was at the same (x,y) position doesn’t get removed, so your mesh just adds more and more vertices.

Yes my answer wasn’t very clear sorry, it’s because I didn’t test the code…

I have redone it using ofVbo since it’s a more elegant way of doing it( coding wise).
I think you should setup your ofVbomesh in setup, with colors, vertices and indices, then change the vertices z positions during update.

See the example below:

  • in ofApp.h
        ofEasyCam cam;
        int maxW = 400;
        int maxH = 400;
        ofVboMesh vbo;
    
        int res = 5;
        int amplitude = 160;
        float perlinIndexX = 0.0;
        float perlinIndexY = 0.0;
        float incPerlinX = 0.01;
        float incPerlinY = 0.05;

  • in ofApp::setup
   int indexVertex = 0;
    vbo.setMode(OF_PRIMITIVE_TRIANGLES);
    for( int i = -maxW; i <= maxW; i += res){
        perlinIndexY = 0.0;
        for( int j = -maxH; j <= maxH; j += res){
            
            float z = ofNoise(perlinIndexX, perlinIndexY) * amplitude;
            
            ofColor randomSurface = ofColor((float)(i* 255 /(maxW * 2)),
                                (float)(j* 255 /(maxH * 2)),
                                (float)(255 - (i * 255 + j * 255 ) /(maxH * 2 + maxW * 2)));
            
            
            //init triangle
            ofVec3f vert = {(float)i, (float)j, z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            z = ofNoise(perlinIndexX, perlinIndexY + incPerlinY) * amplitude;
            vert = {(float)(i), (float)(j+res), z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            z = ofNoise(perlinIndexX + incPerlinX, perlinIndexY) * amplitude;
            vert = {(float)(i+res), (float)j, z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            
            //bottom triangle
            z = ofNoise(perlinIndexX, perlinIndexY + incPerlinY) * amplitude;
            vert = {(float)(i), (float)(j+res), z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            z = ofNoise(perlinIndexX + incPerlinX, perlinIndexY + incPerlinY) * amplitude;
            vert = {(float)(i + res), (float)(j+res), z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            z = ofNoise(perlinIndexX + incPerlinX, perlinIndexY) * amplitude;
            vert = {(float)(i+res), (float)j, z};
            vbo.addVertex(vert);
            vbo.addColor(randomSurface);
            vbo.addIndex(indexVertex);
            indexVertex +=1;
            
            perlinIndexY += incPerlinY;
            
        }
        perlinIndexX += incPerlinX;
        
    }

in ofApp::draw() :

cam.begin();
vbo.draw();
cam.end();

should look like this :

In the update function, you can reuse the same function as to initialise the vbo, change addVertex to setVertex, not change the colors or indices, and increment the perlinIndexY and perlinIndexX over time to get the sliding effect.

I hope it helps.
Also this is only one way of doing it, there is probably a more elegant way of doing it i guess…

1 Like

Hi, besides Pierre’s extensive code I’d like to point out a very simple thing.
When using an ofMesh or an ofVboMesh you dont need ofBeginShape(); and ofEndShape() as these are used with ofVertex(...) and not with the meshes.
The ofBeginShape(); ofVertex(...); ... ofEndShape();sequence uses what is called the immediate mode which is a lot less efficient than using an ofMesh or an ofVboMesh.
In simple terms you can use, and allocate an ofMesh inside the draw() it is a lot less efficient than using the ofVboMesh but it can be a lot more clearer.

so

void ofApp::draw(){
    ofMesh mesh;
    mesh.setMode(OF_PRIMITIVE_TRIANGLES);
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < cols; x++) {
            mesh.addVertex(ofVec3f(x *scl, y* scl, terrain[x][y]));
            mesh.addVertex(ofVec3f(x*scl, (y+1)*scl, terrain[x][y+1]));
        }
    }
    ofSetColor(255); //or which ever color you want the mesh to be.
    mesh.drawWireframe();//this will draw it as lines
    //mesh.draw(); will draw it as a solid.
}

hope this helps.
cheers.

1 Like

Hi @roymacdonald,

I’ve tried your code above to achieve what OP did, but it doesn’t seem to work!

Here’s what I get:

I’ve literally copied your code. Any ideas?

Also, is there a reason why you chose to use OF_PRIMITIVE_TRIANGLES, instead of OF_PRIMITIVE_TRIANGLE_STRIP?
It gives me a better result, but there now is a superfluous, diagonal line in each row of tris:

Hi,
you are having an overlap in the triangles vertically and horizontally these are not aligned.

yes, definitely. these behave diferently.

There is a fast and easy way to get this done as there is a function in of mesh that does this.


ofMesh myMesh =  ofMesh::plane(
                             100, //float width,
                             100,//float height, 
                             10,//int columns=2,
                             10,// int rows=2,
                             OF_PRIMITIVE_TRIANGLE_STRIP// or OF_PRIMITIVE_TRIANGLES
                             );

take a look at this ofBook chapter which explains how to use meshes

Yes, it seems that way, however I couldn’t really figure out why.

Thanks! I know about mesh planes, but I’m not looking for shortcuts. :wink:

I’m quite familiar with meshes and how they work, but the mode setting is new to me.
In other applications, meshes are usually defined by a flat, ordered collection of vertices. And it’s the faces that define the vertex connections by index. If you for instance want a tri, you define a face with the three vertex indices from the vertex collection that form the triangular face.

Anyways, here’s how I finally solved it the good, old-fashioned way with a flat collection of vertices and “manually” defined faces.

int scale = 20;
int cols = ofGetWidth() / scale + 1;
int rows = ofGetHeight() / scale + 1;

ofMesh mesh;
mesh.setMode(OF_PRIMITIVE_TRIANGLES);

// Setup mesh vertices
for (int y = 0; y < rows; y++) {
    for (int x = 0; x < cols; x++) {
        mesh.addVertex(ofVec3f(x * scale, y * scale, 0.0));
    }
}

// Setup mesh tri faces
for (int y = 0; y < rows - 1; y++) {
    for (int x = 0; x < cols - 1; x++) {
        int i = y * cols + x; // current vertex index
        // First tri
        mesh.addIndex(i);
        mesh.addIndex(i + cols);
        mesh.addIndex(i + cols + 1);
        // Second tri
        mesh.addIndex(i);
        mesh.addIndex(i + cols + 1);
        mesh.addIndex(i + 1);
    }
}

ofSetColor(255);
mesh.draw();

The result is flawless!

Thanks for the reply, @roymacdonald!

1 Like