diff --git a/Makefile b/Makefile index ab21da2..3a0e14f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ SRCDIR = src TMPDIR = build TARGET = gross #FILES = Chromosome Fitness Generation main -FILES = Genes Chromosome +FILES = Genes Chromosome Fitness main #SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES)) OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES)) diff --git a/src/Fitness.cpp b/src/Fitness.cpp index 36dab02..12617d4 100644 --- a/src/Fitness.cpp +++ b/src/Fitness.cpp @@ -4,36 +4,21 @@ -Fitness::Fitness(sf::Texture target) : +sf::Color Fitness::backgroundColor = sf::Color::White; + + +Fitness::Fitness() : dummy(sf::TriangleFan, 4) { - this->target = target; - sf::Vector2u targetSize = this->target.getSize(); - this->tex.create(targetSize.x, targetSize.y); - - this->horizontal = targetSize.x >= targetSize.y; - if (this->horizontal) { - targetSize.x = 1; - } else { - targetSize.y = 1; - } - - this->comp.create(targetSize.x, targetSize.y); -// this->comp.setSmooth(true); - - this->dummy[0] = sf::Vertex(sf::Vector2f(0, 0), sf::Color::Red ); - this->dummy[1] = sf::Vertex(sf::Vector2f(targetSize.x, 0), sf::Color::Yellow); - this->dummy[2] = sf::Vertex(sf::Vector2f(targetSize), sf::Color::Green ); - this->dummy[3] = sf::Vertex(sf::Vector2f(0, targetSize.y), sf::Color::Blue ); } bool Fitness::loadShader(std::string filename) { - this->compshdr.loadFromFile(filename, sf::Shader::Fragment); - if (this->compshdr.isAvailable()) { - this->compshdr.setUniform("base", this->target); - this->compshdr.setUniform("curr", this->tex.getTexture()); + this->shaderLoaded = this->compshdr.loadFromFile(filename, sf::Shader::Fragment); + if (this->shaderLoaded) { + this->compshdr.setUniform("base", this->target.getTexture()); + this->compshdr.setUniform("curr", this->chromosome.getTexture()); this->compshdr.setUniform("size", sf::Vector2f(this->target.getSize())); this->compshdr.setUniform("horizontal", this->horizontal); return true; @@ -43,13 +28,94 @@ bool Fitness::loadShader(std::string filename) } -unsigned long long Fitness::of(const Chromosome& chr) +bool Fitness::loadTarget(std::string filename) { - // first, render chr to a texture, so we can just compare two textures - this->tex.clear(); - this->tex.draw(chr); - this->tex.display(); + // so create() isn't called twice on the same RenderTextures +// if (this->targetLoaded) { + // TODO: Test if this is necessary + + // DANGER ZONE :P + // First call destructor of object, then create new instance of object + // because the RenderTexture doesn't support this->target = RenderTexture(); + + // Do not separate these lines! +// this->target.~RenderTexture(); +// new (&this->target) sf::RenderTexture(); + + // Do not separate these lines! +// this->comp.~RenderTexture(); +// new (&this->comp) sf::RenderTexture(); + + // Do not separate these lines! +// this->chromosome.~RenderTexture(); +// new (&this->chromosome) sf::RenderTexture(); +// } + this->targetLoaded = false; + + // load the image + sf::Texture tex; + if (!tex.loadFromFile("tom-face.png")) { + return false; + } + + // create render textures in the needed size + sf::Vector2u targetSize = tex.getSize(); + if (!this->target.create(targetSize.x, targetSize.y)) { + return false; + } + if (!this->chromosome.create(targetSize.x, targetSize.y)) { + return false; + } + + // render target image to render texture + sf::Sprite spr(tex); + this->target.clear(Fitness::backgroundColor); + this->target.draw(spr); + this->target.display(); + + // do "horizontal" stuff + this->horizontal = targetSize.x >= targetSize.y; + if (this->horizontal) { + targetSize.x = 1; + } else { + targetSize.y = 1; + } + + // create render texture needed for computing fitness + if (!this->comp.create(targetSize.x, targetSize.y)) { + return false; + } + + // set dummy vertices to comp dimensions + // the colors don't matter, so why not rainbow 'em? + this->dummy[0] = sf::Vertex(sf::Vector2f(0, 0), sf::Color::Red ); + this->dummy[1] = sf::Vertex(sf::Vector2f(targetSize.x, 0), sf::Color::Yellow); + this->dummy[2] = sf::Vertex(sf::Vector2f(targetSize), sf::Color::Green ); + this->dummy[3] = sf::Vertex(sf::Vector2f(0, targetSize.y), sf::Color::Blue ); + + // update shader uniforms + if (this->shaderLoaded) { + this->compshdr.setUniform("size", sf::Vector2f(this->target.getSize())); + this->compshdr.setUniform("horizontal", this->horizontal); + } + + // Yay, loading sucessful! + this->targetLoaded = true; + return true; +} + + +void Fitness::render(const Chromosome& chr) +{ + this->chromosome.clear(Fitness::backgroundColor); + this->chromosome.draw(chr); + this->chromosome.display(); +} + + +unsigned long long Fitness::compute() +{ // compare the two textures using the SUPER ADVANCED shader this->comp.clear(sf::Color::Blue); this->comp.draw(this->dummy, &this->compshdr); @@ -59,22 +125,30 @@ unsigned long long Fitness::of(const Chromosome& chr) sf::Image image = this->comp.getTexture().copyToImage(); sf::Vector2u size = image.getSize(); + // TODO: Deal with horizontal-ness properly (not this ↓ ugly) unsigned long long fitness = 0; if (this->horizontal) { for (unsigned int y=0; yrender(chr); + return this->compute(); +} diff --git a/src/Fitness.hpp b/src/Fitness.hpp index 58004d3..bfb626c 100644 --- a/src/Fitness.hpp +++ b/src/Fitness.hpp @@ -8,18 +8,28 @@ class Fitness { public: - Fitness(sf::Texture target); + static sf::Color backgroundColor; + + Fitness(); bool loadShader(std::string filename); + bool loadTarget(std::string filename); - unsigned long long of(const Chromosome& chr); + void render(const Chromosome& chr); + unsigned long long compute(); + + unsigned long long of(const Chromosome& chr); // uses render and compute + + sf::RenderTexture target; // contains image to compare against + sf::RenderTexture chromosome; // contains the Chromosome to be evaluated - sf::Texture target; // base image to compare against - sf::RenderTexture tex; // big RenderWindow containg the Chromosome to be evaluated sf::RenderTexture comp; // smaller RenderWindow which is downloaded as Image - sf::VertexArray dummy; bool horizontal; private: + bool shaderLoaded = false; + bool targetLoaded = false; + sf::Shader compshdr; // shader to perform pixel-wise image diff with + sf::VertexArray dummy; // something to render so that the shader is run on every pixel };