// Copyright (C) 2017 Rémi Bèges // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include namespace Nz { namespace { static constexpr std::array m_functionScales = { { 1.f / float(M_SQRT2), 0.5f / float(M_SQRT2), 0.5f / float(M_SQRT2), 0.5f / float(M_SQRT2) } }; } Worley::Worley() : m_function(WorleyFunction_F1) { } Worley::Worley(unsigned int seed) : Worley() { SetSeed(seed); Shuffle(); } float Worley::Get(float x, float y, float scale) const { std::map featurePoints; float xc, yc; int x0, y0; float fractx, fracty; xc = x * scale; yc = y * scale; x0 = fastfloor(xc); y0 = fastfloor(yc); fractx = xc - static_cast(x0); fracty = yc - static_cast(y0); featurePoints.clear(); SquareTest(x0,y0,xc,yc,featurePoints); std::size_t functionIndex = static_cast(m_function); auto it = featurePoints.begin(); std::advance(it, functionIndex); if(fractx < it->first) SquareTest(x0 - 1,y0,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if(1.f - fractx < it->first) SquareTest(x0 + 1,y0,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if(fracty < it->first) SquareTest(x0,y0 - 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if (1.f - fracty < it->first) SquareTest(x0,y0 + 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if (fractx < it->first && fracty < it->first) SquareTest(x0 - 1, y0 - 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if (1.f - fractx < it->first && fracty < it->first) SquareTest(x0 + 1, y0 - 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if (fractx < it->first && 1.f - fracty < it->first) SquareTest(x0 - 1, y0 + 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); if(1.f - fractx < it->first && 1.f - fracty < it->first) SquareTest(x0 + 1, y0 + 1,xc,yc,featurePoints); it = featurePoints.begin(); std::advance(it, functionIndex); return it->first * m_functionScales[functionIndex]; } float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*scale*/) const { throw std::runtime_error("Worley 3D not available yet."); } float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*w*/, float /*scale*/) const { throw std::runtime_error("Worley 4D not available yet."); } void Worley::Set(WorleyFunction func) { m_function = func; } void Worley::SquareTest(int xi, int yi, float x, float y, std::map& featurePoints) const { int ii = xi & 255; int jj = yi & 255; std::size_t seed = m_permutations[ii + m_permutations[jj]]; //On initialise notre rng avec seed std::minstd_rand0 randomNumberGenerator(static_cast(seed)); //On prend un nombre de points à déterminer dans le cube, compris entre 1 et 8 std::size_t m = (seed & 7) + 1; //On calcule les emplacements des différents points for(std::size_t i(0) ; i < m; ++i) { Nz::Vector2f featurePoint; featurePoint.x = (randomNumberGenerator() & 1023) / 1023.f + static_cast(xi); featurePoint.y = (randomNumberGenerator() & 1023) / 1023.f + static_cast(yi); // TODO : Check order is correct float distance = std::sqrt((featurePoint.x - x) * (featurePoint.x - x) + (featurePoint.y - y) * (featurePoint.y - y)); //Insertion dans la liste triée featurePoints[distance] = featurePoint; } } }