Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1st, 3rd, 4th dimension #5

Merged
merged 10 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_subdirectory(histogram)
add_subdirectory(texture2d)
add_subdirectory(point-cloud)
2 changes: 0 additions & 2 deletions examples/common/argument_parsing.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#include <noiz/noise2.hpp>

#include <charconv>
#include <format>
#include <iostream>
Expand Down
16 changes: 16 additions & 0 deletions examples/point-cloud/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
project(noiz-point-cloud)

add_executable(${PROJECT_NAME})

target_link_libraries(${PROJECT_NAME} PRIVATE
noiz::noiz-lib
noiz::noiz-compile-options
)

target_sources(${PROJECT_NAME} PRIVATE
pointcloud.cpp
)

target_include_directories(${PROJECT_NAME} PRIVATE
../common
)
116 changes: 116 additions & 0 deletions examples/point-cloud/pointcloud.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include <noiz/noise3.hpp>
#include <noiz/processing.hpp>

#include <argument_parsing.hpp>


#include <charconv>
#include <filesystem>
#include <format>
#include <iostream>
#include <vector>
#include <fstream>

constexpr int32_t constant_base_resolution = 128;
constexpr int32_t constant_max_resolution_factor = 32;

struct Config {
noiz::Seed seed{noiz::detail::Generator::make_random_seed()};
noiz::GridExtent3 grid_extent{constant_base_resolution, constant_base_resolution, constant_base_resolution}; // NOLINT
float step{0.1f}; // NOLINT
int image_size_factor{1};

// syntax: [count] [step]
auto parse_args(Args args) -> bool {
if (!args.next_as(step, "step")) { return false; }
if (!args.next_as(image_size_factor, "image_size_factor")) { return false; }
if (image_size_factor < 0 || image_size_factor > constant_max_resolution_factor) {
std::cerr << std::format("invalid image size factor: '{}'\n", image_size_factor);
return false;
}
if (!args.args.empty()) {
return false;
}
grid_extent.x *= image_size_factor;
grid_extent.y *= image_size_factor;
grid_extent.z *= image_size_factor;
return true;
}
};

// pulls noise from noiz::lib, writes a pixel to ppm file
class Point_Cloud {
public:
explicit Point_Cloud(int image_size_factor) : image_size{static_cast<uint16_t>(constant_base_resolution * image_size_factor)} {}

void build_and_write_object_with_noise(noiz::Noise3f& noise, float const& step) const {

std::ofstream out_file{"hybrid_multifractal_noise.obj", std::ios::binary};

float vertex_z;
float vertex_y;

noiz::Processor3f noise_processor{noise};

for(int z = 0; z < image_size; z++){
vertex_z = (static_cast<float>(z) / static_cast<float>(image_size)) - 0.5f;

for (int y = 0; y < image_size; y++) {
vertex_y = (static_cast<float>(y) / static_cast<float>(image_size)) - 0.5f;
for(int x = 0; x < image_size; x++) {
// add noise at point
//raw noise
#if 0 //raw noise
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});
if(noise_value > 0.0f){ //this should render a half of the points with raw noise

//no point in assigning x here? just write it directly to
out_file << "v " << ((static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f) << " " << vertex_y << " " << vertex_z << '\n';
}
#else //hybrid multi fractal noise
const float noise_value = noise_processor.hybrid_multi_fractal_processing(
noiz::Vec3f{.x = static_cast<float>(x) * step, .y = static_cast<float>(y) * step, .z = static_cast<float>(z) * step}
);
if(noise_value > 2.0f){ //this should render a half of the points with hmf noise

//no point in assigning x here? just write it directly to
out_file << std::format("v {} {} {} '\n", (static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f, vertex_y, vertex_z);
//out_file << "v " << ((static_cast<float>(x) / static_cast<float>(image_size)) - 0.5f) << " " << vertex_y << " " << vertex_z << '\n';
}
#endif
}
}
}
out_file.close();
}

private:
uint16_t image_size;
};

auto main(int argc, char** argv) -> int {
auto config = Config{};

// skip exe name (argv[0])
auto const args = Args{std::span{argv, static_cast<std::size_t>(argc)}.subspan(1)};

// handle --help
if (!args.args.empty() && args.args.front() == std::string_view{"--help"}) {
std::cout << std::format("Usage: {} [step(=0.1)] [image_size_factor(=1)]\n", std::filesystem::path{*argv}.stem().string());
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;
return EXIT_SUCCESS;
}

// parse args, if any
if (!config.parse_args(args)) {
std::cout << args.args.front() << std::endl;
return EXIT_FAILURE;
}


auto noise = noiz::Noise3f{noiz::Seed{config.seed}, config.grid_extent};

// build and write noise to image
auto point_cloud = Point_Cloud{config.image_size_factor};
point_cloud.build_and_write_object_with_noise(noise, config.step);
}
20 changes: 19 additions & 1 deletion noiz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,25 @@ target_sources(${PROJECT_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS include FILES
include/noiz/noise2.hpp
include/noiz/seed.hpp
include/noiz/vec2.hpp
)


include/noiz/detail/data3.hpp
include/noiz/detail/grid3.hpp

include/noiz/cell3.hpp
include/noiz/index3.hpp
include/noiz/noise3.hpp
include/noiz/vec3.hpp


include/noiz/detail/data4.hpp
include/noiz/detail/grid4.hpp

include/noiz/cell4.hpp
include/noiz/index4.hpp
include/noiz/noise4.hpp
include/noiz/vec4.hpp
)

target_include_directories(${PROJECT_NAME} INTERFACE
include
Expand Down
31 changes: 31 additions & 0 deletions noiz/include/noiz/cell3.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once
#include <span>
#include "index3.hpp"
#include "vec3.hpp"

namespace noiz {
template <std::floating_point Type>
struct Corner3 {
Vec3<Type> location{};
Vec3<Type> gradient{};
};

template <typename Type>
struct TCell3 {
Type left_top_front{};
Type right_top_front{};
Type left_bottom_front{};
Type right_bottom_front{};

Type left_top_back{};
Type right_top_back{};
Type left_bottom_back{};
Type right_bottom_back{};
};

template <std::floating_point Type>
using Cell3 = TCell3<Vec3<Type>>;

template <std::floating_point Type>
using CornerCell3 = TCell3<Corner3<Type>>;
} // namespace noiz
24 changes: 24 additions & 0 deletions noiz/include/noiz/cell4.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once
#include <span>
#include "index4.hpp"
#include "vec4.hpp"

namespace noiz {
template <std::floating_point Type>
struct Corner4 {
Vec4<Type> location{};
Vec4<Type> gradient{};
};

template <typename Type>
struct TCell4 {
//16 is 2^4
std::array<Type, 16> corners{};
};

template <std::floating_point Type>
using Cell4 = TCell4<Vec4<Type>>;

template <std::floating_point Type>
using CornerCell4 = TCell4<Corner4<Type>>;
} // namespace noiz
58 changes: 58 additions & 0 deletions noiz/include/noiz/detail/data3.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once
#include "generator.hpp"
#include "grid3.hpp"

namespace noiz::detail {
template <std::floating_point Type>
auto make_populated_grid(Index3 const grid_extent, Seed seed = Generator::make_random_seed()) -> Grid3<Type> {
auto ret = make_grid3<Type>(grid_extent);
auto generator = Generator{seed};
for (auto& corner : ret.corners) { generator.next(corner.gradient); }
return ret;
}

template <std::floating_point Type>
constexpr auto compute_offsets(CornerCell3<Type> const& corner, Vec3<Type> const point) -> Cell3<Type> {
return Cell3<Type>{
.left_top_front = point - corner.left_top_front.location,
.right_top_front = point - corner.right_top_front.location,
.left_bottom_front = point - corner.left_bottom_front.location,
.right_bottom_front = point - corner.right_bottom_front.location,
.left_top_back = point - corner.left_top_back.location,
.right_top_back = point - corner.right_top_back.location,
.left_bottom_back = point - corner.left_bottom_back.location,
.right_bottom_back = point - corner.right_bottom_back.location,
};
}

template <std::floating_point Type>
constexpr auto compute_dot_products(CornerCell3<Type> const& corner, Cell3<Type> const& offset) -> TCell3<Type> {
return TCell3<Type>{
.left_top_front = dot(corner.left_top_front.gradient, offset.left_top_front),
.right_top_front = dot(corner.right_top_front.gradient, offset.right_top_front),
.left_bottom_front = dot(corner.left_bottom_front.gradient, offset.left_bottom_front),
.right_bottom_front = dot(corner.right_bottom_front.gradient, offset.right_bottom_front),

.left_top_back = dot(corner.left_top_back.gradient, offset.left_top_back),
.right_top_back = dot(corner.right_top_back.gradient, offset.right_top_back),
.left_bottom_back = dot(corner.left_bottom_back.gradient, offset.left_bottom_back),
.right_bottom_back = dot(corner.right_bottom_back.gradient, offset.right_bottom_back),
};
}

template <std::floating_point Type>
constexpr auto interpolate(Vec3<Type> const point, TCell3<Type> const& dot_products) -> Type {
auto const uvw = point.fract().fade();

auto const below_a = std::lerp(dot_products.left_top_front, dot_products.right_top_front, uvw.x);
auto const below_b = std::lerp(dot_products.left_bottom_front, dot_products.right_bottom_front, uvw.x);
auto const below = std::lerp(below_a, below_b, uvw.y);

auto const above_a = std::lerp(dot_products.left_top_back, dot_products.right_top_back, uvw.x);
auto const above_b = std::lerp(dot_products.left_bottom_back, dot_products.right_bottom_back, uvw.x);
auto const above = std::lerp(above_a, above_b, uvw.y);

//i might need to swap the position of below and above, not really sure
return std::lerp(below, above, uvw.z);
}
} // namespace noiz::detail
67 changes: 67 additions & 0 deletions noiz/include/noiz/detail/data4.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once
#include "generator.hpp"
#include "grid4.hpp"

namespace noiz::detail {
template <std::floating_point Type>
auto make_populated_grid(Index4 const grid_extent, Seed seed = Generator::make_random_seed()) -> Grid4<Type> {
auto ret = make_grid4<Type>(grid_extent);
auto generator = Generator{seed};
for (auto& corner : ret.corners) { generator.next(corner.gradient); }
return ret;
}

template <std::floating_point Type>
constexpr auto compute_offsets(CornerCell4<Type> const& corner, Vec4<Type> const point) -> Cell4<Type> {

Cell4<Type> ret;
for(uint8_t i = 0; i < 16; i++){
ret.corners[i] = point - corner.corners[i];
}
return ret;
}

template <std::floating_point Type>
constexpr auto compute_dot_products(CornerCell4<Type> const& corner, Cell4<Type> const& offset) -> TCell4<Type> {

TCell4<Type> ret;
for(int i = 0; i < 16; i++){
ret.corners[i] = dot(corner.corners[i].gradient, offset.corners[i]);
}
return ret;
}

template <std::floating_point Type>
constexpr auto interpolate(Vec4<Type> const point, TCell4<Type> const& dot_products) -> Type {
auto const cell_interpolated_position = point.fract().fade();

//1st dimension
auto const below_a = std::lerp(dot_products.corners[0], dot_products.corners[1], cell_interpolated_position.x);
//2nd dimension
auto const below_b = std::lerp(dot_products.corners[2], dot_products.corners[3], cell_interpolated_position.x);
auto const below = std::lerp(below_a, below_b, cell_interpolated_position.y);

//3rd dimension
auto const above_a = std::lerp(dot_products.corners[4], dot_products.corners[5], cell_interpolated_position.x);
auto const above_b = std::lerp(dot_products.corners[6], dot_products.corners[7], cell_interpolated_position.x);
auto const above = std::lerp(above_a, above_b, cell_interpolated_position.y);

auto const third_lerp_a = std::lerp(below, above, cell_interpolated_position.z);

//4th dimension
auto const fourth_below_a = std::lerp(dot_products.corners[8], dot_products.corners[9], cell_interpolated_position.x);
auto const fourth_below_b = std::lerp(dot_products.corners[10], dot_products.corners[11], cell_interpolated_position.x);
auto const fourth_below = std::lerp(fourth_below_a, fourth_below_b, cell_interpolated_position.y);

auto const fourth_above_a = std::lerp(dot_products.corners[12], dot_products.corners[13], cell_interpolated_position.x);
auto const fourth_above_b = std::lerp(dot_products.corners[14], dot_products.corners[15], cell_interpolated_position.x);
auto const fourth_above = std::lerp(fourth_above_a, fourth_above_b, cell_interpolated_position.y);

auto const third_lerp_b = std::lerp(fourth_below, fourth_above, cell_interpolated_position.z);



//i might need to swap the position of below and above, not really sure
return std::lerp(third_lerp_a, third_lerp_b, cell_interpolated_position.w);
}
} // namespace noiz::detail
Loading
Loading