It seems I don't understand C++ loops and/or pointers

So in my ofApp.h I declare ofImage imageTiles[20]; and then I have this code:

void ofApp::setup() {
    for (int i = 0; i < 20; i++) {
        imageTiles[i].grabScreen(0, 0, ofGetWidth()/5, ofGetHeight()/4);
        imageTiles[i].setColor(ofColor(ofRandom(255), ofRandom(255), ofRandom(255)));
    }
}

void ofApp::draw() {
    int x = 0;
    int y = 0;
    for (ofImage image : imageTiles) {
        phongSphere(&image, 1, ofVec3f(), ofColor(255,0,0));
        image.draw(x, y);
        x += image.getWidth();
        if (x >= ofGetWidth() - 1) {
            y += image.getHeight();
            x = 0;
        }
    }
}

Which gives me the desired image:

But when I exchange the for loop in my draw function to this, everything breaks:

    for (int i = 0; i < 20; i++) {
        imageTiles[i].draw(x, y);
        x += imageTiles[i].getWidth();
        if (x >= ofGetWidth() - 1) {
            y += imageTiles[i].getHeight();
            x = 0;
        }
    }

I then get a solid coloured screen.

Can somebody explain to me what’s going on here, and why these two loops aren’t equivalent? It seems I fundamentally misunderstand something about pointers or references and how these loops access my ofImage objects.

Hi

At face value I would say the loop is correct.

This makes me wonder what else might be going on, the bug may be somewhere else, or the images have a larger width/height than u expect.

You can pass draw dimension with like image.draw(x, y, 50, 50), see if that changes anything and double check the image dimensions are what u expect.

You may also want to make sure you’re calling ofClear() in draw every frame and have alphablending off, although I dont think that matters here.

Otherwise post the full code and we can take a closer look

What does the phongSphere() function do?
What happens if you put it back in the loop?

Hi,
there is a big difference between those two for loops, as

 for (ofImage image : imageTiles) {

will create a copy of each image. to avoid such you need to use a reference as it follows.

 for (ofImage& image : imageTiles) {

(yes, it is just adding that & )

Then when using

 for (int i = 0; i < 20; i++) {

nothing assures me that the array actually has 20 elements.
I’d recomment you to use an std:vector instead of a plain array. As the vector will allow you to check its size within the for loop. only thing you need to add is to resize it or push elements into it in the setup.
Also, I dont see the usefulness of calling grabScreen if you then set the image’s color to a random one. If you are using grabScreen simply to generate the image of the passed size it will be a lot more efficient and clearer if you use allocate instead
so it should look more or less like

// in ofApp.h
/
vector<ofImage> imageTiles;
//ofImage imageTiles[20]; // comment or remove this line

ofApp.cpp

void ofApp::setup() {
imageTiles.resize(20);
    for (int i = 0; i < imageTiles.size(); i++) {
        imageTiles[i].allocate( ofGetWidth()/5, ofGetHeight()/4, OF_IMAGE_COLOR);

        imageTiles[i].setColor(ofColor(ofRandom(255), ofRandom(255), ofRandom(255)));
    }
}

void ofApp::draw() {
    int x = 0;
    int y = 0;
    for (ofImage& image : imageTiles) {
        phongSphere(&image, 1, ofVec3f(), ofColor(255,0,0));
        image.draw(x, y);
        x += image.getWidth();
        if (x >= ofGetWidth() - 1) {
            y += image.getHeight();
            x = 0;
        }
    }
// now it is equivalent to the following commented code.
//  	for (int i = 0; i < imageTiles.size(); i++) {
//        imageTiles[i].draw(x, y);
//        x += imageTiles[i].getWidth();
//        if (x >= ofGetWidth() - 1) {
//            y += imageTiles[i].getHeight();
//            x = 0;
//        }
//    }



}
2 Likes