Hej, napisałem w C++/SFML dla odprężenia mały program generujący znany fraktal, może nie jest to duży projekt ale uznałem że uzyskany efekt jest dość ciekawy:
oto kod programu:
#include <SFML/Graphics.hpp>
#include <vector>
#include <array>
//-----------------------------------------------------------------------------------
void generateTriangles(int deepth, std::array<sf::Vector2f, 3> vertex, std::vector<sf::Vertex>& points) {
if (deepth <= 0) return;
sf::Vector2f rs = (vertex[0] + vertex[1]) / 2.f;
sf::Vector2f bs = (vertex[1] + vertex[2]) / 2.f;
sf::Vector2f ls = (vertex[2] + vertex[0]) / 2.f;
points.emplace_back(rs, sf::Color(0, 0, 0, 255));
points.emplace_back(bs, sf::Color(0, 0, 0, 200));
points.emplace_back(ls, sf::Color(0, 0, 0, 145));
generateTriangles(deepth - 1, { vertex[1], bs, rs }, points);
generateTriangles(deepth - 1, { bs, vertex[2], ls }, points);
generateTriangles(deepth - 1, { rs, ls, vertex[0] }, points);
}
//-----------------------------------------------------------------------------------
constexpr unsigned SurfaceWidth = 900u;
constexpr unsigned SurfaceHeight = 900u;
//-----------------------------------------------------------------------------------
int main() {
sf::RenderWindow window(sf::VideoMode(SurfaceWidth,SurfaceHeight), "window", sf::Style::Close);
window.setKeyRepeatEnabled(false);
///----------------------------------------------------------------------------
std::array<sf::Vector2f, 3> startedVertex = {
(sf::Vector2f(0.f, 0.f) + sf::Vector2f(float(window.getSize().x), 0.f) / 2.f ),
sf::Vector2f(float(window.getSize().x), float(window.getSize().y)),
sf::Vector2f(0.f, float(window.getSize().y))
}; // masę rzutowań na float by uniknąć ostrzeżeń...
std::vector<sf::Vertex> triangle;
triangle.emplace_back(startedVertex[0], sf::Color(2, 225, 119, 255));
triangle.emplace_back(startedVertex[1], sf::Color(2, 225, 119, 255));
triangle.emplace_back(startedVertex[2], sf::Color(2, 225, 119, 255));
generateTriangles(7, { startedVertex[0], startedVertex[1], startedVertex[2] }, triangle);
///----------------------------------------------------------------------------
sf::RenderTexture surface;
surface.create(SurfaceWidth, SurfaceHeight);
surface.setSmooth(true);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::S) { //screenshot
surface.clear(sf::Color::Black);
surface.draw(&triangle[0], triangle.size(), sf::Triangles);
surface.display();
surface.getTexture().copyToImage().saveToFile("result.jpg");
}
}
}
window.clear(sf::Color(0, 0, 0));
window.draw(&triangle[0], triangle.size(), sf::Triangles);
window.display();
}
}
Algorytm jest rekurencyjny, na początku tworzymy duży trójkąt ( jego trzy wierzchołki ) a następnie już w funkcji mniejszy trójkąt mający swoje wierzchołki w połowie boków większego. Pozostaną wtedy 3 mniejsze figury, dla każdej wywołujemy funkcje ponownie. Dla efektu wewnętrzne trójkąty mają różne stopnie przeźroczystości dla swoich wierzchołków.
Czy mógłbym coś poprawić? Zrobić łatwiej/wydajniej?
Chciałbym zrobić też animację niekończącego się przybliżenia ( jak tu ).
Jak jest najlepsza metoda żeby to zrobić? Myślę o czymś takim żeby wykonać trójkąt bardzo szczegółowy ( do np. 8 poziomu rekurencji ). Przybliżać do pewnego momentu ( aż na ekranie będzie widoczny tylko jeden "pod-trójkąt trójkątów" ;) ) a potem znowu w mgnieniu oka oddalić na sam początek.
Będę wdzięczny za wszelkie wskazówki, zaznaczam że pierwszy raz bawię się fraktalami i jest to do tej pory dla mnie mega frajda ;)