Assorted questions while porting code from P5 to OF

As a learning excercise I’ve been porting some Processing code examples (from my Generative Typography tutorial) to OpenFrameworks. Of course I’ve run into troubles, but I’ve googled my way to success so far. That is, the code examples seem to be running fine and have more or less the same visual end result as the Processing originals. However, before continuing with porting more examples, I’d like to ask a few questions concerning the correctness of my ported code. The respective code examples can be found here:

So far I have the following questions:

  1. Is there a quick way to have smoother ofEllipses? For example in the AggregateDrawing example, the resulting image quality in OF seems slightly lower than in Processing. I believe ofEnableAntiAliasing() is on by default (and does make it look better) and ofEnableSmoothing() doesn’t work on ellipses. I found that there is multisampling for FBO’s, but is there a similar command for ofApp’s main canvas? The ofAppGlutWindow code snippet does not seem to work anymore in the current version of OF.

  2. My intention in the AggregateParticles and FlowField examples was to pass references via the Particle class constructor. My question is if I did this correctly.

  3. The FlowField example runs fine with maxParticles set to 250, but when I set it to 1000, I get the following out-of-memory error: terminate called after throwing an instance of ‘std::bad_alloc’. In the task manager it seems only a fraction of my 32GB of memory is used. Is this is a problem with the available memory to the app or the way the Particles are added to the vector? How can I fix this and prevent these kind of memory problems?

In general I’d like to hear if there are any obvious mistakes in these ported code examples or perhaps there are better ways of doing something. Thanks! :smile:

1 Like

@amnon is great to hear that youa are porting this tutorial, because is a great to tool to teach people intrinsics of processing :smile:

A few comments about flow field example:

  1. While is justa a convention, usually all caps variables are used for constants defined in the code (see for example OF_* values)… for regular variables can be confusing for some people.

  2. Are you using a while in the update to fill the particle system, you can isolate that in a separate function that is called only when needed (for example in the setup or after clear particles) .

  3. the std:bad_alloc error usually is because you are pointing to an element of an array or vector that doesn’t exist in memory. Seems to be related to mouse click clear() in the particle system while you are updating or drawing particles. To avoid this I usually use a boolean and I clear and refill the particle system in the update, only while the boolean is true, and the update the boolean to false. As is not relevant to change until next iteration of the update/draw loop, it doesn’t make a difference.

Thank you for your suggestions @drakko. I have implemented all of them.

Indeed it is a good thing to adhere to conventions, especially with code examples because they will teach new users and should be clear to existing users. I am already applying the OF formatting style to all my files, so I will remember your remark with regard to variable names. I have now changed this it in all my examples.

I have added a resetParticles() method, that is called in the update() method when a bReset boolean is set to true. The possible problem you indicate (clearing and updating/drawing simultaneously), can no longer happen as a result of this changed code. However it does not solve the initial problem. In the adapted app, when I set maxParticles to 1000, the program still crashes immediately with the bad_alloc error.

ok I will try tomorrow to see why the error still happening…

BTW, translating the hamesh example will be a real challenge :wink:

@amnon I messed around with it for a second - something you were doing was causing the pixels to be copied repeatedly and it was probably stressing out your video memory

I changed it to pointers and was able to get it up to 10000 without crashing

https://github.com/jvcleave/OF_GenerativeTypography/commit/f81aff6681d5e8a29bb0b8fec32d6044349cdf89

Hi there!

Regarding the drawing quality, I usually go for FBO’s. But, with my computer, I don’t see much difference with OF’s MSAA. Even if it’s set to it’s max, which is 8x.

Therefor, I do it manually, 2x. And I get nicer results.


I would also recommend you to do ofClear() before you draw something into the FBO. As an example, my GPU is getting older and older, so I get crazy glitches and noise if I don’t clear it before-hand.

And if you are going to draw big circles, don’t forget ofSetCircleResolution().

Thanks so much for all your responses.

@drakko Definitely :smile: I’m saving those for last and hopefully there are some useful ofxaddons to help out…

@jvcleave Wow, I studied your code, very useful to see this solution. Indeed it runs smoothly with 10000 for me as well. I see you changed both the particle system and the ofPixels to use pointers. With regard to the ofPixels variable inside each Particle. Is a pointer the only way to prevent copies? I thought the & reference operator in the Particle’s constructor ensured objects to be copied by reference (but apparantly it didn’t work so well)?

@hubris Thanks for those tips. So by manual, do you mean make the FBO twice the size that it is drawn? And then you add an ofScale() call before the drawing I suppose? I will test how the MSAA and manual option look on my system. The visual result is definitely much nicer in your comparison image. Yes, I saw the ofClear() call in @jvcleave’s adapted code as well. Will remember this for all future FBO uses.

@amnon

You may be able to pass the pixels by reference - I would mess around with it a bit as I did it fairly quickly.

When you push_back in a vector the entire object is copied so I think you are basically running the Particle constructor twice

By using pointers I was insuring the Particle was only created once . As you may have seen when you call vector.clear() you have to manually delete the pointers or you will leak. With references the deconstructor will automatically be called.

All right, I’ve looked some more into the topic of passing references via the constructor.

I was doing this:

class OldClass {
    public:
        OldClass(Object & newObj){
            obj = newObj;
        }
    private:
        Object obj;
}

Where I should be doing this:

class NewClass {
    public:
        NewClass(const Object & newObj) : objReference(newObj){
        }
    private:
        const Object & objReference;
}

The original code most likely just made a copy. The adapted code initializes the class member variable as a reference. In fact a const reference, so one that cannot be changed.

The problem of this copy-by-reference solution (besides being syntactically complex) is that it appears to be incompatible with a vector of objects. It only works with a vector of pointers to objects. For the purpose of new users, it would be overly complicated to have an example with both references and pointers. So I’m thinking I will go with the all pointer solution provided by @jvcleave.

To be continued… :sunglasses:

Ok you were close I think

With your original code you may just need to change this in Particle.h

ofPixels pix;

to

ofPixels& pix;

I personally try to keep my Constructors parameter free and just use them to set default values - I would have done something like

Particle particle;
particle.setup(pix, color, drawMode);
particles.push_back(particle);

What was bothering me about using pointers with your Class is that it was never set to NULL - I would have done that in the parameter-less constructor

Particle::Particle()
{
    pix = NULL;
}

Already tried that before, but I end up with more errors (uninitialized reference member, non-static reference member can’t use default assignment operator) and warnings than I’d like to. I do like the parameter-less constructor approach. I’ll take that into account when refactoring my classes.

All right, with all the initial questions answered and many useful suggestions given, I have refactored and cleaned up my existing code examples. Now I will focus on adding/porting more examples from the tutorial and also add a general OF multisampling example in the GettingStarted category. Thanks for all your help so far!

Hey everyone,

I am making good progress with porting the Generative Typography examples from P5 to OF! :smiley:

I do have a few new questions. Perhaps someone can shed some light on these issues.

  1. I am unable to port the AvailableFonts example. It seems there is no equivalent in OpenFrameworks for Processing’s PFont.list() method and no straightforward cross-platform alternative in C++ to get all the available fonts on a system. Is this a correct conclusion?

  2. I have started porting the PDF examples. The WavesPDF example (using ofPath) creates a correct PDF, which looks identical to what is drawn on the screen. However the CirclePacking example (using ofEllipse) creates a PDF, where there is a straight line in each ellipse. When I use the ofEllipse method in the OF-included pdfExample, I get the same incorrect result. Using ofSetCircleResolution() does not solve this. I have not found an issue on GitHub about this possible bug. Am I doing something wrong or can someone confirm this is a bug?

  3. As a workaround for problem 2 I tried switching to ofPath.circle, but unfortunately that also shows a straight line in each ellipse. In fact, with ofPath, you can already see this issue in the application (and also in the exported PDF). There is no issue on GitHub about this possible bug either. Am I doing something wrong or can someone confirm this is a bug?

Edit
The image below shows the bug as described in problem 2. Top shows the drawn image in the application. Bottom shows the exported PDF with a straight line in each ellipse. At the time of writing, the code that produces this result can be found here on GitHub.

Hi ammon!

Regarding your PDF export issues, I don’t think you are doing anything wrong. ofCircle and ofEllipse and drawn in the same way in OF, but are not exported, using Cairo, in the same way. So, you get that wrong output.

I know nothing about Cairo (the only thing I did was check the OF source). But, since you are using the same width-height ratio, you can simply use ofCircle. It’s just a temporary solution, of course.

Edit: I was going to add an issue to Git, but I noticed you already did. Great! :slight_smile:

Thank you very much for the confirmation @hubris and for the alternative solution. I didn’t know of ofCircle, but it’s even shorter and doesn’t have the bug, so it’s a much better choice. I have updated the example in the repo to use ofCircle and now the PDF export works fine. Excellent! :smile:

Hopefully in time (the PDF export of) ofEllipse can be fixed as well…

Update:

The ofEllipse export to PDF issue is now solved for OF 0.9 (current master branch).

Well, that worked out nicely. Thanks!

I’m currently working on some of the trickier-to-port examples. I need some help again with porting the ReactionDiffusion example. I’ve uploaded my progress so far to GitHub. One of the main changes is using vectors instead of arrays. The good news is that the ported example runs without errors and the basic image and type is somewhat distinguishable. The bad news is that the reaction-diffusion simulation isn’t working correctly and the application is slower than in Processing. I suspect these problems are most likely in the Rd.cpp file. I’ve been doublechecking some things using cout, such as the neighbour map, copying one vector into another, but these seem to be working correctly. And most of the code / input values are the same as in the original code example.

What could I be doing wrong? Hints & suggestions appreciated! :smile:

Links:

I didn’t run it but I am guessing that this is copying the image

I would try changing it to this

void Rd::getImage(ofImage& image, ofColor c1, ofColor c2){
	for(int y = 0; y < image.height; y++){
		for(int x = 0; x < image.width; x++){
			int index = x + y * w;
			ofColor c = c1;
			c.lerp(c2, A[index] * A[index]);
			image.setColor(x, y, c);
		}
	}
	image.update();
}

and calling it like this

rd.getImage(result, fg_color, bg_color);

Thanks for your suggestion! :smile: I changed the code accordingly (updated version now on GitHub).

Despite this improvement, the two issues mentioned above remain unsolved though:

  1. Reaction-diffusion simulation not working correctly.
  2. Slow framerate. Measured fps with 25 simulation steps: P5 = 26 vs. OF = 6.