#pragma once

#include "util.h"

inline float PerlinRand(DWORD&seed)
{
	seed = seed * 1103515245 + 12345; 
	return (( seed & 0x7fffffff) % (0x1fffffff+1)) / (float)0x1fffffff;  
}

void PerlinInit(float*rv,const DWORD size,DWORD seed);

void PerlinCloudize(float*data,int size,float CS,float CC);
void PerlinScale(float*data,int size,float s);
void PerlinAdd(float*data,int size,float add);

class Perlin1D
{
	DWORD m_Seed;
	DWORD m_Size;
	float *m_RV;

public:
	Perlin1D(DWORD size,DWORD seed){m_Size = size;m_RV = new float[m_Size];m_Seed = seed;PerlinInit(m_RV,m_Size,m_Seed);}
	~Perlin1D(void){SAFEDELETEARRAY(m_RV);}

	void SetSeed(DWORD seed){m_Seed = seed; PerlinInit(m_RV,m_Size,m_Seed);}

	void BuildMap(float*outdata,DWORD size,float strength,DWORD oct);
	float GetP(float x);
};


class Perlin2D
{
	DWORD m_Seed;
	DWORD m_XSize,m_YSize;
	float *m_RV;

public:
	Perlin2D(DWORD xsize,DWORD ysize,DWORD seed){m_XSize = xsize;m_YSize = ysize;m_RV = new float[m_XSize*m_YSize];m_Seed = seed;PerlinInit(m_RV,m_XSize*m_YSize,m_Seed);}
	~Perlin2D(void){SAFEDELETEARRAY(m_RV);}

	void SetSeed(DWORD seed){m_Seed = seed; PerlinInit(m_RV,m_XSize*m_YSize,m_Seed);}

	void BuildMap(float*outdata,DWORD xsize,DWORD ysize,float strength,DWORD noct);
	void AddOct(float*data,const DWORD&xsize,const DWORD&ysize,const float&strength,DWORD oct);
	
	float GetP(const float&x,const float&y);
};

class Perlin3D
{
	DWORD m_XSize,m_YSize;
	DWORD m_ZSize;
	Perlin2D** m_P;

public:
	Perlin3D(DWORD xsize,DWORD ysize,DWORD zsize,DWORD seed);
	~Perlin3D(void);

	void BuildFrame(float*outdata, float t, DWORD xsize, DWORD ysize, DWORD baseoct, DWORD octcount);
	
	float GetP(const float x, const float y, const float z);
};