Kizeko
Kizeko

Reputation: 11

I'm trying to port a 1D perlin noise tutorial on C++

I'm trying to port a 1D perlin noise tutorial on C++ using SFMl lib : (tutorial link in javascript) https://codepen.io/Tobsta/post/procedural-generation-part-1-1d-perlin-noise

However this doesn't work, i don't get any error but this is what i get : https://i.sstatic.net/TPMYY.png . basically a straight line

And this is what i should get : https://i.sstatic.net/9J8FG.png

Here's the ported code from the above link :

TerrainBorder constructor:

TerrainBorder::TerrainBorder(sf::RenderWindow &window) {

    M = 4294967296;
    A = 1664525;
    C = 1;

    std::random_device rd;
    std::mt19937 rng(rd());
    std::uniform_int_distribution<int> dist(0, M);

    Z = floor(dist(rng) * M);
    x = 0;
    y = window.getSize().y / 2.0f;
    amp = 100;
    wl = 100;
    fq = 1.0f / wl;
    a = rand();
    b = rand();

    ar = sf::VertexArray(sf::Points);
}

Functions:

double TerrainBorder::rand()
{
    Z =  (A * Z + C) % M;
    return Z / M - 0.5;
}

double TerrainBorder::interpolate(double pa, double pb , double px) {
    double ft = px * PI,
           f = (1 - cos(ft)) * 0.5;
    return pa * (1 - f) + pb * f;
}

void TerrainBorder::drawPoints(sf::RenderWindow &window) {
    while (x < window.getSize().x) {

        if (static_cast<int> (x) % wl == 0) {
            a = b;
            b = rand();
            y = window.getSize().y / 2 + a * amp;
        } else {
            y = window.getSize().y / 2 + interpolate(a, b, static_cast<int> (x) 
            % wl / wl) * amp;
        }
        ar.append(sf::Vertex(sf::Vector2f(x, y)));
        x += 1;
    }
}

Then i'm drawing the sf::VectorArray (which contains all the sf::Vertex in the game loop

Upvotes: 0

Views: 947

Answers (2)

Kizeko
Kizeko

Reputation: 11

i solved my problem ty for the answer anyway :) I had to deal with types problems :p

I figured out that :

double c = x % 100 / 100;
std::cout << c << std::endl; // 0

!=

double c = x % 100;
std::cout << c / 100 << std::endl; // Some numbers depending on x

If it can help anyone in the future :)

Upvotes: 1

Bob__
Bob__

Reputation: 12779

C++ requires a careful choice for the types of the numeric variables, to avoid overflows and unexpected conversions.

The snippet shown in OP's question doesn't specify the types of M, A and Z, but uses a std::uniform_int_distribution of int, while M is initialized with a value that's out of the range of an int in most implementations.

It's also worth to be noted that the Standard Library already provides a std::linear_congruential_engine:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 rng(rd());

    // Calculate the first value
    constexpr std::size_t M = 4294967296;
    std::uniform_int_distribution<std::size_t> ui_dist(0, M);
    std::size_t Z = ui_dist(rng); 

    // Initialize the engine
    static std::linear_congruential_engine<std::size_t, 1664525, 1, M> lcg_dist(Z);

    // Generate the values
    for (int i = 0; i < 10; ++i)
    {
        Z = lcg_dist();
        std::cout << Z / double(M) << '\n'; // <- To avoid an integer division
    }
}

Upvotes: 0

Related Questions