Hello, I recently was making a Mandelbrot Fractal viewer, and I came upon a very weird problem. Only one fourth of the buffer loads, more specifically the top-right fourth of the screen. This is the code (
The SFML window is in InitState.cpp and the Bitmap with pixel-buffer is used in files InitState.hpp/cpp and Fractal.hpp/cpp):
main.cpp:#include "ProgramEngine.hpp"
#include "ProgramState.hpp"
#include "InitState.hpp"
int main(int argc, char** argv)
{
ProgramEngine program;
InitState initState;
program.init();
program.changeState(&initState);
while (program.isRunning())
{
program.handleEvents();
program.update();
program.draw();
}
program.cleanUp();
return 0;
}
ProgramEngine.hpp:#ifndef PROGRAM_ENGINE_HPP
#define PROGRAM_ENGINE_HPP
#include <vector>
class ProgramState;
class ProgramEngine
{
public:
void init();
void cleanUp();
void changeState(ProgramState* state);
void pushState(ProgramState* state);
void popState();
void handleEvents();
void update();
void draw();
bool isRunning();
void quit();
std::vector<ProgramState*> states;
bool running;
};
#endif
ProgramEngine.cpp:#include "ProgramEngine.hpp"
#include "ProgramState.hpp"
void ProgramEngine::init()
{
running = true;
}
void ProgramEngine::cleanUp()
{
for (std::vector<ProgramState*>::iterator i = states.begin(); i != states.end(); i++)
{
(*i)->cleanUp();
}
states.clear();
}
void ProgramEngine::changeState(ProgramState* state)
{
for (std::vector<ProgramState*>::iterator i = states.begin(); i != states.end(); i++)
{
(*i)->cleanUp();
}
states.clear();
states.push_back(state);
state->init();
}
void ProgramEngine::pushState(ProgramState* state)
{
states.push_back(state);
state->init();
}
void ProgramEngine::popState()
{
states.back()->cleanUp();
states.pop_back();
}
void ProgramEngine::handleEvents()
{
for (std::vector<ProgramState*>::iterator i = states.begin(); i != states.end(); i++)
{
(*i)->handleEvents(this);
}
}
void ProgramEngine::update()
{
for (std::vector<ProgramState*>::iterator i = states.begin(); i != states.end(); i++)
{
(*i)->update(this);
}
}
void ProgramEngine::draw()
{
for (std::vector<ProgramState*>::iterator i = states.begin(); i != states.end(); i++)
{
(*i)->draw(this);
}
}
bool ProgramEngine::isRunning()
{
return running;
}
void ProgramEngine::quit()
{
running = false;
}
ProgramState.hpp:#ifndef PROGRAM_STATE_HPP
#define PROGRAM_STATE_HPP
class ProgramEngine;
class ProgramState
{
public:
virtual void init() = 0;
virtual void cleanUp() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
virtual void handleEvents(ProgramEngine* program) = 0;
virtual void update(ProgramEngine* program) = 0;
virtual void draw(ProgramEngine* program) = 0;
void changeState(ProgramEngine* program, ProgramState* state);
};
#endif
ProgramState.cpp:#include "ProgramEngine.hpp"
#include "ProgramState.hpp"
void ProgramState::changeState(ProgramEngine* program, ProgramState* state)
{
program->changeState(state);
}
InitState.hpp:#ifndef INIT_STATE_HPP
#define INIT_STATE_HPP
#include <SFML\System.hpp>
#include <SFML\Window.hpp>
#include <SFML\Graphics.hpp>
#include <SFML\OpenGL.hpp>
#include "ProgramEngine.hpp"
#include "ProgramState.hpp"
#include "Fractal.hpp"
class Bitmap;
class InitState :public ProgramState
{
public:
void init();
void cleanUp();
void pause();
void resume();
void handleEvents(ProgramEngine* program);
void update(ProgramEngine* program);
void draw(ProgramEngine* program);
private:
sf::RenderWindow* window;
sf::Clock* clock;
Bitmap* bitmap;
long previousTime;
double delta;
Fractal* mandelbrot;
};
#endif
InitState.cpp:#include "InitState.hpp"
#include "Preprocessor.hpp"
#include "Bitmap.h"
void InitState::init()
{
window = new sf::RenderWindow(sf::VideoMode(800, 600, 32U), "Test");
bitmap = new Bitmap(800, 600);
clock = new sf::Clock();
mandelbrot = new Fractal(bitmap, sf::Vector2u(800, 600));
glEnable(GL_TEXTURE_2D);
previousTime = clock->getElapsedTime().asMicroseconds();
srand(time(NULL));
window->setActive(false);
}
void InitState::cleanUp()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
delete window;
delete clock;
delete bitmap;
delete mandelbrot;
}
void InitState::pause()
{
}
void InitState::resume()
{
}
void InitState::handleEvents(ProgramEngine* program)
{
sf::Event event;
while (window->pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
program->quit();
break;
}
}
}
void InitState::update(ProgramEngine* program)
{
long currentTime = clock->getElapsedTime().asMicroseconds();
delta = (currentTime - previousTime) / 1000000.0;
previousTime = currentTime;
}
void InitState::draw(ProgramEngine* program)
{
window->setActive(true);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bitmap->clear(0x000000ff);
mandelbrot->compute();
bitmap->displayPixels();
window->display();
window->setActive(false);
}
Fractal.hpp:#ifndef FRACTAL_HPP
#define FRACTAL_HPP
#include <SFML\System.hpp>
#include <SFML\Window.hpp>
#include <SFML\Graphics.hpp>
#include <SFML\OpenGL.hpp>
class Bitmap;
class Fractal
{
public:
Fractal(Bitmap* _bitmap, sf::Vector2u fractal_size);
void compute();
private:
sf::Vector2i getOriginPixel(sf::Vector2u window_size);
private:
Bitmap* bitmap;
sf::Vector2u size;
sf::Vector2f position;
double leftBound;
double rightBound;
double sizeUnits;
double pixelSize;
double zoom;
double prevZoom;
int iterations;
};
#endif
Fractal.cpp:#include "Fractal.hpp"
#include "Bitmap.h"
#include <cmath>
Fractal::Fractal(Bitmap* _bitmap, sf::Vector2u fractal_size)
{
bitmap = _bitmap;
size = fractal_size;
leftBound = -2.5;
rightBound = 1.5;
sizeUnits = abs(leftBound - rightBound);
position = sf::Vector2f((leftBound + rightBound)/2, 0);
zoom = 1.0;
iterations = 256;
}
void Fractal::compute()
{
for (unsigned int pixelY = 1; pixelY <= size.y; pixelY++)
{
for (unsigned int pixelX = 1; pixelX <= size.x; pixelX++)
{
pixelSize = (sizeUnits / (double)(size.x)) / zoom;
double a = ((double)(pixelX - getOriginPixel(size).x) * pixelSize) + (double)(position.x);
double b = ((double)(getOriginPixel(size).y - pixelY) * pixelSize) + (double)(position.y);
double xtemp = 0;
double x = 0;
double y = 0;
int i;
for (i = 1; (i <= iterations) && ((x*x + y*y) < 4); i++)
{
xtemp = pow(x, 2) - pow(y, 2) + a;
y = 2 * x*y + b;
x = xtemp;
//xtemp = pow(x, 6) - 15 * pow(x, 4)*pow(y, 2) + 15 * pow(x, 2)*pow(y, 4) - pow(y, 6) + a;
//y = 6 * pow(x, 5)*y - 20 * pow(x, 3)*pow(y, 3) + 6 * x*pow(y, 5) + b;
//x = xtemp;
}
if (i == iterations)
{
bitmap->drawPixel(pixelX, pixelY, 0x00, 0x00, 0x00, 0xff);
}
if (i < iterations)
{
unsigned char colorlinear = ((i * 0xff) / (iterations / (iterations / 64))) % 0x100;
bitmap->drawPixel(pixelX, pixelY, round(colorlinear / 2), colorlinear, 0x00, 0xff);
}
}
}
}
sf::Vector2i Fractal::getOriginPixel(sf::Vector2u window_size)
{
sf::Vector2i origin(ceil(window_size.x / 2), ceil(window_size.y / 2));
return origin;
}
Bitmap.h:#ifndef SFML_OPENGL_BITMAP_H
#define SFML_OPENGL_BITMAP_H
class Bitmap
{
public:
Bitmap(int width, int height) //Konstruktor klasy Bitmap
:buffer_width(width), buffer_height(height)
{
buffer = new unsigned char [height*(4 * width)];
}
void clear(const unsigned int& colorRGBA) //Czyszczenie buffera bitmapy wybranym kolorem RGBA
{
unsigned char r = (colorRGBA & 0xff000000) >> 24;
unsigned char g = (colorRGBA & 0x00ff0000) >> 16;
unsigned char b = (colorRGBA & 0x0000ff00) >> 8;
unsigned char a = (colorRGBA & 0x000000ff) >> 0;
for (int y = 0; y < buffer_height; y++)
{
for (int x = 0; x < buffer_width; x++)
{
buffer[y*(buffer_width * 4) + (x * 4) + 0] = r;
buffer[y*(buffer_width * 4) + (x * 4) + 1] = g;
buffer[y*(buffer_width * 4) + (x * 4) + 2] = b;
buffer[y*(buffer_width * 4) + (x * 4) + 3] = a;
}
}
}
void clear(const unsigned char& r, const unsigned char& g, const unsigned char& b, const unsigned char& a = 0xff)
//Czyszczenie buffera bitmapy wybranym kolorem RGBA, rozpisane argument po argumencie
{
for (int y = 0; y < buffer_height; y++)
{
for (int x = 0; x < buffer_width; x++)
{
buffer[y*(buffer_width * 4) + (x * 4) + 0] = r;
buffer[y*(buffer_width * 4) + (x * 4) + 1] = g;
buffer[y*(buffer_width * 4) + (x * 4) + 2] = b;
buffer[y*(buffer_width * 4) + (x * 4) + 3] = a;
}
}
}
void clearGray(const unsigned char& grayscale) //Czyszczenie buffera bitmapy wybranym odcieniem szarości
{
for (int y = 0; y < buffer_height; y++)
{
for (int x = 0; x < buffer_width; x++)
{
buffer[y*(buffer_width * 4) + (x * 4) + 0] = grayscale;
buffer[y*(buffer_width * 4) + (x * 4) + 1] = grayscale;
buffer[y*(buffer_width * 4) + (x * 4) + 2] = grayscale;
buffer[y*(buffer_width * 4) + (x * 4) + 3] = 0xff;
}
}
}
void drawPixel(int x, int y, const unsigned int& colorRGBA) //Rysowanie piksela na ekranie
{
unsigned char r = (colorRGBA & 0xff000000) >> 24;
unsigned char g = (colorRGBA & 0x00ff0000) >> 16;
unsigned char b = (colorRGBA & 0x0000ff00) >> 8;
unsigned char a = (colorRGBA & 0x000000ff) >> 0;
if (x >= buffer_width) { x = buffer_width - 1; }
if (y >= buffer_height) { y = buffer_height - 1; }
if (x <= 0) { x = 0; }
if (y <= 0) { y = 0; }
y = buffer_height - y - 1;
buffer[y*(buffer_width * 4) + (x * 4) + 0] = r;
buffer[y*(buffer_width * 4) + (x * 4) + 1] = g;
buffer[y*(buffer_width * 4) + (x * 4) + 2] = b;
buffer[y*(buffer_width * 4) + (x * 4) + 3] = a;
}
void drawPixel(int x, int y, const unsigned char& r, const unsigned char& g,
const unsigned char& b, const unsigned char& a = 0xff) //Rysowanie piksela na ekranie
{
if (x >= buffer_width) { x = buffer_width - 1; }
if (y >= buffer_height) { y = buffer_height - 1; }
if (x <= 0) { x = 0; }
if (y <= 0) { y = 0; }
y = buffer_height - y - 1;
buffer[y*(buffer_width * 4) + (x * 4) + 0] = r;
buffer[y*(buffer_width * 4) + (x * 4) + 1] = g;
buffer[y*(buffer_width * 4) + (x * 4) + 2] = b;
buffer[y*(buffer_width * 4) + (x * 4) + 3] = a;
}
void displayPixels() //Kopiowanie buffera bitmapy do buffera OpenGL
{
glDrawPixels(buffer_width, buffer_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
public:
int buffer_width;
int buffer_height;
private:
unsigned char* buffer;
}; //END OF: class Bitmap
#endif
Thank you for help!