1

I recently began programming a simulation for one of my high school classes. I have never worked in c++ before so I really should've done some practice programming first. Bear in mind this means my program is quite disorganized due to a rocky foundation. I have been trying to solve this error for almost two weeks now. So this post is my last resort. If I can't figure it out after this I will postpone it until I have more experience and just try to re-write it.

I have isolated the problem to a part of a method that blurs the image using a gaussian kernel. It iterates through all x and y values. For each pixel, it also iterates through dx and dy. (x + dx, y + dy) becomes the new coordinates where I read the value out of an image buffer, divide it by the correct amount, compound those 9 values from the kernel, then add that value to a new image buffer. I then replace all the values in the original buffer with the new ones.

And although the blur-ing works for the first frame: Frame 0

By only the third frame, it is completely unrecognizable: Frame 2

Eventually, the image settles from its noise-like state and looks something like this: Frame 75

Brace yourself for the ugly code that is about to come...

void simulate(agent group[groupsize], int frames) {
    for (int framenumber = 0; framenumber < frames; framenumber++) {
        for (int agentIndex = 0; agentIndex < groupsize; agentIndex++)
        {
            group[agentIndex].update();
            int x = floor(group[agentIndex].xPos);
            int y = floor(group[agentIndex].yPos);
            imgBuffer = imgptr + getIndex(x,y);
            *imgBuffer = byteMax;
        }
        imgBuffer = imgptr;
        for (int y = 0; y < h; y++)
        {
            for (int x = 0; x < w; x++)
            {
                int index = 0;
                unsigned char val = byteZero;
                for (int dy = -1; dy <= 1; dy++)
                {
                    for (int dx = -1; dx <= 1; dx++)
                    {
                        index = getIndex(x + dx, y + dy);
                        if (0 < index && index < imgSize) {
                            imgBuffer = imgptr + index;
                            int shift = abs(dx) + abs(dy) + 2;
                            val += (*imgBuffer >> shift);
                        }
                    }
                }
                *tempBuffer = val;
                tempBuffer++;
            }

        }
        imgBuffer = imgptr;
        tempBuffer = tempptr;
        for (int i = 0; i < imgSize; i++)
        {
            *imgBuffer = *tempBuffer;
            if (*imgBuffer > fadeAmt) {
                *imgBuffer -= fadeAmt;
            }
            imgBuffer++;
            tempBuffer++;
        }
        imgBuffer = imgptr;
        tempBuffer = tempptr;
        writePPM(imgBuffer, w, h, framenumber);
    }
}

It comes down to the fact that I am inexperienced with c++. If you can help at all, whether that be gut reactions to the example frames or probable solutions, I would greatly appreciate it. I will be monitoring this post throughout the day(even though I should be paying attention in class LOL) so if you have any questions, I will answer them as fast as humanly possible.

I have tried more things than I can count. Almost all give slight variations to the examples above, yet never fully fix the issue.

  • On first glance, there's not enough code here to say. What is the exact datatype of `imgBuffer`? Since you are right-shifting values from its contents, you should ensure it is an unsigned type. Is `getIndex` a function or a macro? Can you show the definition? Are `imgptr` and `tempptr` _definitely_ pointing to different memory space? Small possibly-relevant note on your "fade": if the value is `<= fadeAmt` would you not want to set it to zero? Not doing so could cause streaking if your "agents" are moving and the `fadeAmt` is reasonably large. – paddy Apr 06 '22 at 05:11
  • imgBuffer is an unsigned char. getIndex is a function that evaluates y*w+x imgptr and tempptr are the original addresses of imgBuffer and tempBuffer respectively. The fading is so that trails don’t last too long. fadeAmt in these examples is 2 and the reason I chose to only subtract when *imgBuffer > fadeAmt is because I don’t want it to go below 0 and become 255. – Malachy Crossan Apr 06 '22 at 05:45
  • Again I’m not sure that anything I’m doing is the right way to do it so if you have suggestions I will most likely take them to heart. I can also update this tomorrow with the rest of the code needed to understand this once I’m back on my computer. – Malachy Crossan Apr 06 '22 at 05:48
  • And what is `imgSize`? Is it set to `y * x`? If it's zero or something, that could explain the compounding effect with no fades occurring. Or it could be simply that a fade value of 2 is way too small. The best thing to do is a process of elimination to selectively isolate the issue. Try commenting-out your "fade" section or zero the memory of your image buffer at the beginning of each frame. Observe the effect. Try commenting-out your blurring convolution. Again, observe. Try various combinations. Test your `writePPM` function to ensure it's behaving correctly. There are many things to try. – paddy Apr 06 '22 at 07:22
  • 1
    One other thing to mention is that all your code assumes the image rows are not padded with extra empty bytes. If your PPM output has some kind of memory alignment requirement that's not being met, this could cause the output to be skewed. Consider a simple test where you overwrite your blur result with a simple checkerboard pattern. _e.g._ https://godbolt.org/z/6PvPEYs4z -- if the image you get is not a checkerboard, then there's probably an alignment issue. – paddy Apr 06 '22 at 08:02
  • 'imgSize' is width by height. I have tried many values for the fade amount. Changing it pretty much makes the image brighter and darker(because the agents have no velocity right now). I thought that file padding might be the problem but, I researched the file format extensively and it looks as thought there is no padding necessary. I was also able to create a checkerboard with no problems. My theory is that somepoint in the program an int is being converted to a uChar which might mean that 3 bytes which is sizeof(int) - sizeof(uChar) are placed where they shouldn't be. – Malachy Crossan Apr 06 '22 at 17:13
  • Well, I've given you some strategies to consider. Debugging is like science. Approach all of your code, all your data, all your program state with the assumption that none of it works, and then _prove_ through testing each individual part. Disprove every theory you have about what might be happening. Break apart every relevant step and examine the data you have to ensure it is how you expected. – paddy Apr 06 '22 at 20:08

0 Answers0