|
| 1 | +#include <noiz/noise3.hpp> |
| 2 | +#include <noiz/processing.hpp> |
| 3 | + |
| 4 | +#include <argument_parsing.hpp> |
| 5 | + |
| 6 | + |
| 7 | +#include <charconv> |
| 8 | +#include <filesystem> |
| 9 | +#include <format> |
| 10 | +#include <iostream> |
| 11 | +#include <vector> |
| 12 | +#include <fstream> |
| 13 | + |
| 14 | +constexpr int32_t constant_base_resolution = 128; |
| 15 | +constexpr int32_t constant_max_resolution_factor = 32; |
| 16 | + |
| 17 | +struct Config { |
| 18 | + noiz::Seed seed{noiz::detail::Generator::make_random_seed()}; |
| 19 | + noiz::GridExtent3 grid_extent{constant_base_resolution, constant_base_resolution, constant_base_resolution}; // NOLINT |
| 20 | + float step{0.1f}; // NOLINT |
| 21 | + int image_size_factor{1}; |
| 22 | + |
| 23 | + // syntax: [count] [step] |
| 24 | + auto parse_args(Args args) -> bool { |
| 25 | + if (!args.next_as(step, "step")) { return false; } |
| 26 | + if (!args.next_as(image_size_factor, "image_size_factor")) { return false; } |
| 27 | + if (image_size_factor < 0 || image_size_factor > constant_max_resolution_factor) { |
| 28 | + std::cerr << std::format("invalid image size factor: '{}'\n", image_size_factor); |
| 29 | + return false; |
| 30 | + } |
| 31 | + if (!args.args.empty()) { |
| 32 | + return false; |
| 33 | + } |
| 34 | + grid_extent.x *= image_size_factor; |
| 35 | + grid_extent.y *= image_size_factor; |
| 36 | + grid_extent.z *= image_size_factor; |
| 37 | + return true; |
| 38 | + } |
| 39 | +}; |
| 40 | + |
| 41 | +// pulls noise from noiz::lib, writes a pixel to ppm file |
| 42 | +class Point_Cloud { |
| 43 | + public: |
| 44 | + explicit Point_Cloud(int image_size_factor) : image_size{static_cast<uint16_t>(constant_base_resolution * image_size_factor)} {} |
| 45 | + |
| 46 | + void build_and_write_object_with_noise(noiz::Noise3f& noise, float const& step) const { |
| 47 | + |
| 48 | + std::ofstream out_file{"hybrid_multifractal_noise.obj", std::ios::binary}; |
| 49 | + |
| 50 | + float vertex_z; |
| 51 | + float vertex_y; |
| 52 | + |
| 53 | + noiz::Processor3f noise_processor{noise}; |
| 54 | + |
| 55 | + for(int z = 0; z < image_size; z++){ |
| 56 | + vertex_z = (static_cast<float>(z) / static_cast<float>(image_size)) - 0.5f; |
| 57 | + |
| 58 | + for (int y = 0; y < image_size; y++) { |
| 59 | + vertex_y = (static_cast<float>(y) / static_cast<float>(image_size)) - 0.5f; |
| 60 | + for(int x = 0; x < image_size; x++) { |
| 61 | + // add noise at point |
| 62 | + //raw noise |
| 63 | +#if 0 //raw noise |
| 64 | + const float noise_value = noise.at(noiz::Vec3f{.x = static_cast<float>(x) * step, .y = static_cast<float>(y) * step, .z = static_cast<float>(z) * step}); |
| 65 | + if(noise_value > 0.0f){ //this should render a half of the points with raw noise |
| 66 | + |
| 67 | + //no point in assigning x here? just write it directly to |
| 68 | + out_file << "v " << ((static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f) << " " << vertex_y << " " << vertex_z << '\n'; |
| 69 | + } |
| 70 | +#else //hybrid multi fractal noise |
| 71 | + const float noise_value = noise_processor.hybrid_multi_fractal_processing( |
| 72 | + noiz::Vec3f{.x = static_cast<float>(x) * step, .y = static_cast<float>(y) * step, .z = static_cast<float>(z) * step} |
| 73 | + ); |
| 74 | + if(noise_value > 2.0f){ //this should render a half of the points with hmf noise |
| 75 | + |
| 76 | + //no point in assigning x here? just write it directly to |
| 77 | + out_file << std::format("v {} {} {} '\n", (static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f, vertex_y, vertex_z); |
| 78 | + //out_file << "v " << ((static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f) << " " << vertex_y << " " << vertex_z << '\n'; |
| 79 | + } |
| 80 | +#endif |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + out_file.close(); |
| 85 | + } |
| 86 | + |
| 87 | + private: |
| 88 | + uint16_t image_size; |
| 89 | +}; |
| 90 | + |
| 91 | +auto main(int argc, char** argv) -> int { |
| 92 | + auto config = Config{}; |
| 93 | + |
| 94 | + // skip exe name (argv[0]) |
| 95 | + auto const args = Args{std::span{argv, static_cast<std::size_t>(argc)}.subspan(1)}; |
| 96 | + |
| 97 | + // handle --help |
| 98 | + if (!args.args.empty() && args.args.front() == std::string_view{"--help"}) { |
| 99 | + std::cout << std::format("Usage: {} [step(=0.1)] [image_size_factor(=1)]\n", std::filesystem::path{*argv}.stem().string()); |
| 100 | + std::cout << "\t output image resolution is 128x128, with each dimension multiplied by image_size_factor, maximum scaling factor is 32[image size of 4096]" << std::endl; |
| 101 | + return EXIT_SUCCESS; |
| 102 | + } |
| 103 | + |
| 104 | + // parse args, if any |
| 105 | + if (!config.parse_args(args)) { |
| 106 | + std::cout << args.args.front() << std::endl; |
| 107 | + return EXIT_FAILURE; |
| 108 | + } |
| 109 | + |
| 110 | + |
| 111 | + auto noise = noiz::Noise3f{noiz::Seed{config.seed}, config.grid_extent}; |
| 112 | + |
| 113 | + // build and write noise to image |
| 114 | + auto point_cloud = Point_Cloud{config.image_size_factor}; |
| 115 | + point_cloud.build_and_write_object_with_noise(noise, config.step); |
| 116 | +} |
0 commit comments