#include "ai.h"
#include <cmath>
AI_SHADER_NODE_EXPORT_METHODS(apChaosMosaic)

enum apChaosMosaicParams {
	p_input,
	p_tile
};

struct ShaderData
{
	int tile;
};

node_parameters 
{
	AiParameterRGB("input", 0, 0, 0);
	AiParameterInt("tile", 10);
}

node_initialize
{
	ShaderData *data = (ShaderData *)AiMalloc(sizeof(ShaderData));
	AiNodeSetLocalData(node, data);
}

node_update
{
	ShaderData *data = (ShaderData *)AiNodeGetLocalData(node);
	data->tile = AiNodeGetInt(node, "tile");
}

node_finish
{
	ShaderData *data = (ShaderData *)AiNodeGetLocalData(node);
	AiFree(data);
}

shader_evaluate
{
	ShaderData *data = (ShaderData *)AiNodeGetLocalData(node);
	float x, y;
	x = fmod(sg->u, 1);
	y = fmod(sg->v, 1);

	float xi = floor(x*data->tile);
	float yi = floor(y*data->tile);

	AtVector p(sg->u, sg->v, 0);

	float xp = AiCellNoise4(p, xi*data->tile + yi);
	float yp = AiCellNoise4(p, xi*data->tile + yi + data->tile*data->tile);
	float xoffset = fmod(fmod(x, 1.0 / data->tile) + xp, 1);
	float yoffset = fmod(fmod(y, 1.0 / data->tile) + yp, 1);

	sg->u = xoffset;
	sg->v = yoffset;

	sg->out.RGB() = AiShaderEvalParamRGB(p_input);
	return;
}

node_loader
{
	if (i > 0)
	return false;

	node->methods = apChaosMosaic;
	node->output_type = AI_TYPE_RGB;
	node->name = "apChaosMosaic";
	node->node_type = AI_NODE_SHADER;
	strcpy(node->version, AI_VERSION);
	return true;
}
