-
Notifications
You must be signed in to change notification settings - Fork 2
Home
HastyNoise uses cmake and hunter (cmake package handler) for compilation. HastyNoise is also a package in hunter so if you are already using cmake/hunter adding HastyNoise to your application is as simple as adding the following to you CMakeLists.txt file and generating with cmake. HastyNoise will be downloaded and compiled then linked into you application.
hunter_add_package(HastyNoise)
find_package(HastyNoise CONFIG REQUIRED)
add_executable(hastynoise_test main.cpp)
target_link_libraries(hastynoise_test HastyNoise::hastyNoise)
If you would like to compile HastyNoise manually then you will need cmake 3.1+ then you can clone the repo and run cmake inside the repo directory
cmake -H. -Bbuild -G "Visual Studio 14 2015 Win64" //for MSVS 2015
// or cmake -H. -Bbuild -G "Visual Studio 15 2017 Win64" //for MSVS 2017
cmake --build build
cmake -H. -Bbuild
cmake --build build
Additional cmake options that can be added to the cmake commandline via -D{option}
HN_BUILD_APP - (default:OFF) build test app for performance and confirmation testing
HN_PREVIEW_APP - (default:ON) builds preview app
HN_FAST_INVSQRT - (default:OFF) Uses fast but approximate invsqrt for non SIMD function calls
Example
//turn on test app and build (on windows using MSVS 2015)
cmake -H. -Bbuild -G "Visual Studio 15 2017 Win64" -DHN_BUILD_APP=ON
cmake --build build
HastyNoise is relatively easy to use.
The first thing you need to do is to load the shared libraries for each of the SIMD levels. This is done by calling loadSimd
with the directory where the shared libs are stored. If the libraries are next the to exe this can be done like this:
HastyNoise::loadSimd("./");
Next find out the highest level of performance that the CPU can handle, this is done by calling
size_t fastestSimd=HastyNoise::GetFastestSIMD();
This will check the CPU features and return the highest supported level of SIMD. Right now the function returns a size_t which has been cast from HastNoise::SIMDType, likely in the next version it will just return a HastNoise::SIMDType.
Next you will need to create a noise generator; there are 2 functions for this either one that returns a raw pointer to a Noise
object which you will then own and need to manually delete or one that will return a std::unique_ptr.
HastyNoise::NoiseSIMD *noise=HastyNoise::CreateNoise(seed, fastestSimd);
or
std::unique_ptr<HastyNoise::NoiseSIMD> noise=HastyNoise::CreateNoise(seed, fastestSimd);
The std::unique_ptr version is inline so there is no issue with cross boundary issues between the libs.
Once the generator has been created you can set all the settings on the class that you need using the following class members.
void SetSeed(int seed);
void SetNoiseType(NoiseType noiseType);
void SetFrequency(float frequency);
//Used only with NoiseType::ValueFractal, NoiseType::PerlinFractal, NoiseType::SimplexFractal, NoiseType::CubicFractal
void SetFractalType(FractalType fractalType);
void SetFractalOctaves(int octaves);
void SetFractalLacunarity(float lacunarity);
void SetFractalGain(float gain);
//Used only with NoiseType::Cellular
void SetCellularDistanceFunction(CellularDistance cellularDistance);
void SetCellularReturnType(CellularReturnType cellularReturnType)
Since HastyNoise is handling everything through SIMD the buffers that it is working on are expected to be aligned based on the level of SIMD used. The easiest way to handle this is to just call GetEmptySet
.
inline FloatBuffer GetEmptySet(size_t size, size_t simdLevel);
inline FloatBuffer GetEmptySet(size_t xSize, size_t ySize, size_t zSize, size_t simdLevel);
This will return a FloatBuffer that is just a std::unique_ptr with a special deleter. FloatBuffer will allocate the proper aligned memory and the special deleter will handle deleting the aligned memory.
If you would like to handle the memory manually you can get the proper size by calling
size_t AlignedSize(size_t size, size_t simdLevel);
After we have the generator and a buffer for the noise we can call
noise->FillSet(noiseBuffer.get(), 0, 0, 0, noiseSizeX, noiseSizeY, 1);
The first argument is a array of floats; followed by startX, startY, startZ, and then sizeX, sizeY, sizeZ. In general the API calls are expecting to generate 3D noise, however if you just want 2D put 1 in for sizeZ and 1D put 1 in for sizeY as well.
All of the above is wrapped up into the function
FloatBuffer GetNoiseSet(int xStart, int yStart, int zStart, int xSize, int ySize, int zSize, float scaleModifier);
however it will generate a new noise buffer each time it is called and will be a bottleneck for anything needing to generate often.
The other way to get noise is to create a VectorSet and have it filled. The VectorSet allows you to arbitrarily chose the indexes that the noise will be created from. In the FillSet case it will fill linearly from start to start+size base on the scaleModifier. With vector set you can set the x,y,z points the generator will fill from.