Source code for augraphy.utilities.meshgenerator

"""
Version: 0.0.1
*********************************



References:

- Perlin Noise: https://iq.opengenus.org/perlin-noise/

*********************************


"""
import math
import random


class Vector2:
    """
    Gives a 2D vector based on the input parameters.
    """

    def __init__(self, x, y):
        """
        Constructor Method that initializes the x and y components of the vector.
        """
        self.x = x
        self.y = y

    def dot(self, other):
        """
        Method that returns the dot product of the vector and another 'Vector2' object
        """
        return self.x * other.x + self.y * other.y


[docs] class Noise: """ Generates 2D Perlin Noise, a type of gradient noise used to create natural looking textures, animations, and procedural meshes. This code generates smooth, continuous Perlin Noise Values that can be used for variety of applications in computer graphics and simulations. """ def __init__(self): """ Constructor method which creates the permutation table """ self.permutation = self.makePermutation()
[docs] def shuffle(self, arrayToShuffle): """ Randomly shuffles array of integers from 0 to 255 :param: arrayToShuffle :type: A list of integers """ for e in range(len(arrayToShuffle) - 1, 0, -1): index = math.floor(random.random() * (e + 1)) temp = arrayToShuffle[e] arrayToShuffle[e] = arrayToShuffle[index] arrayToShuffle[index] = temp
[docs] def makePermutation(self): """ Generates a permutation table, a randomly shuffled array of integers from 0 to 255. """ permutation = [] for i in range(256): permutation.append(i) self.shuffle(permutation) for i in range(256): permutation.append(permutation[i]) return permutation
[docs] def getConstantVector(self, v): """ Used to generate the gradient in Perlin Noise Algorithm. The vector points in four of the cardinal directions. Returns one the four pre-defined 'Vector2' objects based on the last two bits of the input integer 'v'. :param v: Input integer from the permutation table :type v: int """ # v is the value from the permutation table h = v & 3 if h == 0: return Vector2(1.0, 1.0) elif h == 1: return Vector2(-1.0, 1.0) elif h == 2: return Vector2(-1.0, -1.0) else: return Vector2(1.0, -1.0)
[docs] def fade(self, t): """ Returns a smooth interpolation curve between 0 and 1 :param t: Distance vector coordinate :type t: float """ return ((6 * t - 15) * t + 10) * t * t * t
[docs] def lerp(self, t, a1, a2): """ Based on the Linear Interpolation Function that returns a value linearly interpolated between a1 and a2 based on the input parameter 't'. It is a smoothening functions. :param t: Distance vector coordinate :type t: float :param a1: Dot product result from Gradient Vector and Distance Vector :type a1: float :param a2: Dot product result from Gradient Vector and Distaince Vector :type a2: float """ return a1 + t * (a2 - a1)
[docs] def noise2D(self, x, y): """ Generates a noise mesh based on x and y coordinates given as an input. It performs the following steps: 1. Calculates the integer grid coordinates of the bottom-left corner of the cell containing the input point, as well as the fractional offesets from that corner to the input point. 2. Computes the dot product between the gradient vectors at each of the cell's four corners and the vectors pointing from those corners to the input point. 3. Applies the fade and lerp function to interpolate(smoothening function) between these dot products and computes the final noise value at the input point. """ X = math.floor(x) & 255 Y = math.floor(y) & 255 # calculating the distance vectors xf = x - math.floor(x) yf = y - math.floor(y) topRight = Vector2(xf - 1.0, yf - 1.0) topLeft = Vector2(xf, yf - 1.0) bottomRight = Vector2(xf - 1.0, yf) bottomLeft = Vector2(xf, yf) # calculating the gradient vector based on the permutation table valueTopRight = self.permutation[self.permutation[X + 1] + Y + 1] valueTopLeft = self.permutation[self.permutation[X] + Y + 1] valueBottomRight = self.permutation[self.permutation[X + 1] + Y] valueBottomLeft = self.permutation[self.permutation[X] + Y] # the gradient vectors coordinates in the top right, top left, bottom right and bottom left dotTopRight = topRight.dot(self.getConstantVector(valueTopRight)) dotTopLeft = topLeft.dot(self.getConstantVector(valueTopLeft)) dotBottomRight = bottomRight.dot(self.getConstantVector(valueBottomRight)) dotBottomLeft = bottomLeft.dot(self.getConstantVector(valueBottomLeft)) # applying fade function to the distance coordinates u = self.fade(xf) v = self.fade(yf) # applying linear interpolation and returning the smoothened function return self.lerp(u, self.lerp(v, dotBottomLeft, dotTopLeft), self.lerp(v, dotBottomRight, dotTopRight))