Drawing a framed rectangle?

Hi, I would like to draw a framed rectangular shape as the image i attached above.
So far, the only way I know how to draw this shape is by simply using 4 ofRectangle.
I wonder if there’s any simpler(more efficient) way to draw this shape.
Thanks in advance.

Hi, you can adjust the width of the line with ofSetLineWidth() defore drawing the rectangle. Remember to use ofNoFill() to draw the rectangle empty inside

1 Like

Hi, I tried that already but It was impossible to make it look like the one in the image above since you’ll see some empty areas in the 4 corner sections as that corners don’t get applied by ofSetLineWidth.

True… then another way would be to draw a big black rectangle, and then a white rectangle in the middle. Do you want to preserve the background inside the frame?

Yes, I want to preserve the background inside the frame. So it should be transparent in the middle area.

Hi! You can create your own meshes in OF. Follow this chapter from OF’s Book to learn a bit more.

If you have any questions, just let us know. Have fun!

1 Like

Thanks, I just had a look into it and I tried to create a simple shape but it didn’t work.

Here’s the code I used.

void ofApp::draw() {

ofTranslate(100, 100);

mesh.setMode(OF_PRIMITIVE_LINES);

ofVec3f vec1(0, 0, 0);
ofVec3f vec2(100, 0, 0);
ofVec3f vec3(100, 100, 0);
ofVec3f vec4(0, 100, 0);
ofVec3f vec5(0, 0, 0);

ofVec3f vec6(20, 20, 0);
ofVec3f vec7(80, 20, 0);
ofVec3f vec8(80, 80, 0);
ofVec3f vec9(20, 80, 0);
ofVec3f vec10(20, 20, 0);

mesh.addVertex(vec1);
mesh.addVertex(vec2);
mesh.addVertex(vec3);
mesh.addVertex(vec4);
mesh.addVertex(vec5);

mesh.addVertex(vec6);
mesh.addVertex(vec7);
mesh.addVertex(vec8);
mesh.addVertex(vec9);
mesh.addVertex(vec10);

mesh.draw();

}

okay, if I add one more vertex to finish the shape, which is “ofVec3f vec11(0,0,0);” then it kind of works. it looks like this.

But when I delete “mesh.setMode(OF_PRIMITIVE_LINES);” in order to make it a filled shape, it becomes just a large filled rectangle

How can I fill only the frame area not the whole rectangle?

The first thing to consider is that ofmesh stores the data you add to it. Which means that, for example, you only need to add your vertices once. Otherwise, unless you clear it, you will just keep adding the same data over and over again.

Second, it’s all about triangles! Mind this. Really do. :slight_smile:

So when you add data (vertex position, color, texture coordinate, normal) you usually don’t had repeated data. For now you are just adding the unique data to each vertex. For example, if you have a triangle, you add 3 vertices. You don’t add a forth to “close” the shape. That’s the GPU job.

Also, when you are adding the data, each vector of data is connected. If on the second position you want a green vertex, so the second element you add to the color vector must be green.

After you have this list of data, now you have to start to create triangles. You do so by adding indices to the index list. For each triangle /face you add three indices. So, if you add 5, 13, and 15. You’ll create a face with the values in the 5, 13 and 15th values of vertex, color, etc.

There are other things to take into account, like winding order and correct index for texture coordinates. But since you are working on 2d with face culling off and flat color, we can worry about that later.

So, back to your mesh. Finally I know! :smiley:

You have a 8 vertices shape with a flat color. So, you’ll need to add 8 vertices and 8 colors. After that you’ll need to think how you are going to divide that into triangles. And then, you add the indices.

Let’s say you name your vertices from 0 to 7. Starting on the top left, going clockwise outter rectangle and then inner rectangle. Like you did, but without the re-addding.

Example:

mesh.addVertex(ofVec3f(0, 0, 0));
mesh.addVertex(ofVec3f(300, 0, 0));
mesh.addVertex(ofVec3f(300, 200, 0));
mesh.addVertex(ofVec3f(0, 200, 0));

mesh.addVertex(ofVec3f(20, 20, 0));
mesh.addVertex(ofVec3f(280, 20, 0));
mesh.addVertex(ofVec3f(280, 180, 0));
mesh.addVertex(ofVec3f(20, 180, 0));

mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);
mesh.addColor(ofColor::red);



mesh.addIndex(0);
mesh.addIndex(1);
mesh.addIndex(4);

mesh.addIndex(4);
mesh.addIndex(1);
mesh.addIndex(5);

mesh.addIndex(1);
mesh.addIndex(2);
mesh.addIndex(5);

mesh.addIndex(5);
mesh.addIndex(2);
mesh.addIndex(6);

mesh.addIndex(2);
mesh.addIndex(3);
mesh.addIndex(6);

mesh.addIndex(6);
mesh.addIndex(3);
mesh.addIndex(7);

mesh.addIndex(3);
mesh.addIndex(0);
mesh.addIndex(7);

mesh.addIndex(7);
mesh.addIndex(0);
mesh.addIndex(4);

Just do this on setup and call different primitive modes to see the differences.

1 Like

you can also just use ofPath, draw with fill to black a big rectangle and then a small one inside, the small one will “cut out” of the first one and create a mesh you can see through:

path.setFillColor(ofColor::black);
path.rectangle(0, 0, 100, 100);
path.rectangle(20, 20, 60, 60);
3 Likes

Thanks a lot for your amazing explanation.
Now I understand how to properly draw 2d stuffs with ofMesh :smile:

It looks like it’s the simplest solution.
Thanks Arturo. I will try it out.

You’re welcome, glad to help! :smile:

And yes, Arturo’s solution is the simplest. And openFrameworks does an amazing job simplifying and creating shortcuts for a lot of stuff. But I believe that as soon as people start to make the right questions, they should start to dig deeper and have more control. :smiley:

Either way, have fun and come back to the forum with you have any questions.

2 Likes