Is there a way properly setup the OpenGL version to 3+ without disabling some Openframeworks features?

@roymacdonald I’ve stumbled about the same thing while reading the code, each ofAppBaseWindow has an individual ofBaseApp created and stored in this map:

	std::map<std::shared_ptr<ofAppBaseWindow>,std::shared_ptr<ofBaseApp> > windowsApps;

And you can actually see there are different objects in function called loopOnce (which is called every frame and contradicts its own name)
and here I’m using cout << i->second.get() << endl;
to show the address of the ofBaseApp from each window (I’m using two windows here) and confirm there are different objects/ adresses like this

0x1458e7618
0x67007500620065
-----
void ofMainLoop::loopOnce(){
	if(bShouldClose) return;
	for(auto i = windowsApps.begin(); !windowsApps.empty() && i != windowsApps.end();){
		if(i->first->getWindowShouldClose()){
			auto window = i->first;
			windowsApps.erase(i++); ///< i now points at the window after the one which was just erased
			window->close();
		}else{
			currentWindow = i->first;
			i->first->makeCurrent();
			i->first->update();
			i->first->draw();
			i++; ///< continue to next window
		}
		cout << i->second.get() << endl;
	}
	cout << "-----" << endl;
	loopEvent.notify(this);
}

1 Like

Hey, thanks for sharing all of your opinions. I’ll just quickly respond to your comment about of3dPrimitive::getMesh(). I LOVE that the fact that this is not const! When I call this function, I want and expect to get a non-const reference because I usually want to modify the ofMesh in some way. If I’m ever concerned about modifying it by accident, I’ll make it const in my own code. So, in my opinion, this function returns the perfect and proper type. I feel its my job to fully understand the code that I write, and not to make too many assumptions about code that I use. And, if I need code that is “properly encapsulated”, I’m free to write it as such. Otherwise, I find that of3dPrimitive::getMesh() has worked really really well every time I’ve called it. And I’m super glad it does what it does. And other people may have different opinions about it, and that’s OK. I love this function, and what it returns.

you could almost just as easily create a copy from “getMesh”, mod it, and then pass it with “setMesh”. I do understand why it can seem to be a hassle sometime to go full oop. Those long chains of const methods are painful for everyone. Its tempting to take shortcuts.But those basics have been carefully thought out over many years. There are multiple reasons why they are there. Even if some users might (quite understandably) appreciate the shortcut offered by non const getters, imo a framework that forces you to brake your own encapsulation in order to use some of its features does not seem like a good idea.

humm im re-reading myself before posting… i do sound like a future teacher , :wink:

Yes absolutely you can make a copy of an ofMesh, modify it, and then copy it back into the 3dPrimitive. And I feel this is a very safe, non-pragmatic way to approach programming. C++ allows for this. Passing by copy is a fundamental idea in the language.

But, some objects are relatively large, and some platforms are relatively limited, or aging, or both. And some functions are called every cycle (60 hz). So, making 2 copies (minimum, and more likely 3) of a large object on a relatively limited platform every cycle could slow things down quite a bit, particularly if its done for all such large objects within an application, say a bunch of them in a container. So, there are lots of practical reasons why it makes a ton of sense to choose to use non-const references to modify large objects, as well as to pass them amongst functions in ofApp, or between ofApp and other classes. C++ allows for it; passing by reference is a fundamental idea in the language.

Alternatively, each object could be owned by a unique_ptr, and moved from object to function to object to etc with std::move. Again, C++ allows for this, and move semantics are a basic idea in the modern language.

In my opinion, all three of these are valid approaches. Because of the flexibility in the language, everyone gets to choose the ones they want to use, or even invent new ones if they’re up to it. I feel the choice is based on some set of considerations: practical need; style; maintenance; safety; consistency; legacy code, etc.

Glad you’re thinking of teaching! I have an extended family full of them. Its not an easy job for sure.

Maybe loopOnce() could be called something like loopAgain(), or loopAnother().

Thanks for posting this function! I started thinking about the relationship between the window and ofBaseApp because of this thread, but wasn’t sure where to begin looking.

1 Like

Hey @Thormind I really appreciate your feedback.
I understand your points.

  • I see what you mean by being a student! What is that you are studying, btw? well, whenever you can help it will be welcome.

  • I cant tell if you are ready or not to use a tool such as OF, as I dont know your background, but it looks like you have a good understanding of coding so I would assume that then you are. I wouldn’t use OF to teach coding to beginers, in such case I would use Processing or P5.js.

  • I absolutely agree with you about the docs. It is kind of a mess. We had a conference in Denver just before Covid struck where consolidating the docs was probably the main concern. But, unfortunately covid messed everything and now we are just getting back on out feet. It would be great to make it better.

  • There are 2 “styles” for using the listeners. old and new; ofAddListener and ofEventListener instance, respectively. The templated nature of these make it a bit cryptic to figure out what the correct way of using is, but it all follows the same pattern. Will not go in depth here but this has given me the idea of updating that old doc I wrote about events, as well as reviewing the examples. Yes, both styles are there for old stuff compatibility. I am not sure, in this particular case how an interface or facade could be used.

With this I meant what it is that I think that the OF project was started, not my personal opinion about oop. As mentioned before, it has become a more important thing over the years but it is not that straight forwards as it requieres a lot of rework.
The events system has several examples, including custom events. I don’t see what is the problem with these.

  • Certainly there are lots of things that need to be worked on like as you say coherence between all the uses of begin/end. I will propose having a setViewport method of the cameras.

I don’t agree with the idea that being able to modify something by a getter is a big no, although, I have no background in computer sciences, I only have years of working with code and a pragmatic point of view. For instance, making primitive.getMesh() const implies that for modifying the mesh (which is something often done, as well as needed) you willl end up having to copy and duplicate a lot of info, which in lots of cases can create a big performance penalty.

I’m doing a bachelor’s degree in computer science.

Imo: create 2 categories of interfaces/abstract classes: one for basic event sources and one for basic event listeners. The “source” interfaces would only need to be extended. The “listener” interfaces would have a set of pure virtual methods the user would define to listen to those events. Some parts of the current event system would be automatically handled by those interface.

Exemple: lets say we have 2 classes: “Rectangle”, and “RectangleListener”. We want “RectangleListener” to react to clicks inside “Rectangle”.

class Rectangle : public MouseClickEvent { nothing else to do, by extending "MouseEventObject" rectangle is automatically registered and will generate an event on click}
class RectangleListener : public MouseClickListener {
...
  // This method is automatically called when an attached object generates a mouse click event.
  virtual void onMouseClick(ofMouseEventArgs& args) override; 
...
}

And lets say we have a class named “MainApp”:

class MainApp {
...
  void initListeners();
  Rectangle startButton;
  RectangleListener startButtonListener
...
}
void MainApp::initListeners() {
  startButton.addListener(startButtonListener);
}

I dont know if you’ve ever worked with Java Swing, but this would be a perfect example of what i’m suggesting. Users dont have to search for the “perfect setups” in order to create or listen to events. Those setups are provided by the interfaces and abstract classes. All the users need to know is which one to implement/extend for the event type they need.

You already have a method called “getMeshPtr” that should cover all the problems you listed. The problem is that by not having a “const” alternative with “getMesh”, users following regular encapsulation rules are left with no choice if they need to call the getter within a const method. So basically they need to rewrite their code and brake their own encapsulation. I dont know if you’ve ever wrote a tightly encapsulated program in C++, but one non const getter you are forced to use can mean many hours of code rewrite.

Glad i could help :slight_smile:

Hi @Thormind
I see what you mean about events/listeners. Well, that´s not how OF works. The events system is a callback function based system, rather than a class inheritance based system. Essentially what you register is a function, either a lambda, class method or regular function. The system you are proposing implies that you have a good understanding of OPP in order to be able to use these, which is not necesarily the case for a lot of OF’s novice users.

As for the encapsulation issue, yes, I have written code that is fully encapsulated and it is a pain in the ass when there are some classes taht are not fully encapsulated. The thing is that I don’t see the point in having something that is supposed to be fully encapsulated yet you are able to access an internal component through a function that returns a pointer to it.
maybe you will not like my answer, but I will recommend you then to not writing fully encapsulated code when using OF. I can not give you a better answer and I don’t know the exact reason as why it is this way. maybe @zach @theo @arturo @bakercp could give you a better answer.

1 Like

Hello. I’m facing light issues when I change the default glVersion to 3.2.
is this second setup supposed to solve the problem?
I don’t know what “MainEditor” is, but I changed it with ofApp() and my main looks like this:

int main()
{
	ofGLFWWindowSettings settings;
	settings.setGLVersion(3, 2);
	settings.setSize(500, 500);
	settings.resizable = false;

	ofCreateWindow(settings);
	ofApp *mainEditorPtr = new ofApp();
	ofRunApp(mainEditorPtr);
}

The app is just drawing a sphere with a lightPoint at {0,0,200}. It works with settings.setGLVersion(2, 1);
image

But with 3,2:
image

Hey try using an ofMaterial with openGL 3.x, and you may also have to set the normals of the sphere but not sure. OpenGL 3.x has the programmable pipeline, so there are some big differences in how 3D things are rendered.

I’m trying to integrate shaders from Shadertoy and they all require 3.x it seems…

However switching to 3.x breaks some basic functionality mentioned earlier. That includes line thickness and alphaMasks…

So there is no backward compatibility between openGL 3.x and 2.x ?

Line thickness in the programmable renderer ( OpenGL 3 onwards ), is not supported unfortunately.
This is something that just doesn’t exist at the OpenGL level. There are a couple of different options for thick lines:

For Alpha mask there should be a way to do that with the OpenGL 3 renderer.
I’ll reply in the other thread you were discussing it in.

Cheers!
Theo

1 Like

Hello,

Line thickness is a big loss for me…

Using ofxFatLine is not really an option. It’s way too slow - on large polygons it’s taking 10-12ms bringing the application to it’s knees from 30fps to 22fps.

Will look into ofxStrip, but I doubt it will be any better.

So that leaves me with the vector shader… :-/

Thanks
M

In case it’s helpful Ive had good luck using Cairo to draw thick lines in OF into a texture. It’s a 2d renderer that’s already in OF and it’s pretty great at very thick lines. You can render to pixels and upload to texture. Happy to share a small example if useful.

Try ofxStrip - we use it for realtime applications all the time.

A couple of things that could help speed things up regardless of the approach.

Try:

ofPolyline poly;//this is your normal outline 
//add verts here 
poly.setClosed(true); //set closed so things don't get weird if its a closed loop 
auto lowPoly = poly.getResampledBySpacing(3.0);

and then feed in the low poly verts to ofxStrip.

Play with the spacing amount. The higher the spacing the less smooth it will look, but the faster it will be.

@theo

I sort of managed to make it working!

Here is my code

for (unsigned int i = 0; i < contourFinder.blobs.size(); i++) {
	ofPolyline cur;
	cur.addVertices(contourFinder.blobs[i].pts);
	cur.setClosed(true); 
	resampled.push_back(cur.getResampledByCount(resample).getSmoothed(smooth));

	ofxStrip strip;
	strip.generate(resampled[i].getVertices(), 10, ofPoint(255, 255, 255));
	myStrips.push_back(strip);
}

and here is the result

There is this strange opening as if contour is not closed.
Yet contour is closed as you can see in the code…
Any ideas of what it might be ?

Also I’m unsure what does “ofPoint upVec” parameter means… ?

Thanks
M

Oh nice!
I think to fix the issue of the gap. Maybe do this.

auto poly = cur.getResampledByCount(resample).getSmoothed(smooth);
poly.addVertex(poly[0]); //add the first point to really close the loop 
resampled.push_back(poly);

The upVec is mostly for 3D uses ie: should the surface of the strip be facing the camera. or the y vector etc.

In this case you would want your upvec to be: (0, 0, 1), so your wide strip is facing the camera