#ifndef VERTEX_MODIFIER_TWIST_H
#define VERTEX_MODIFIER_TWIST_H

#include <shaders/materials/commons_curves.glsl>

struct VertexModifierTwistParams
{
	mat4 transform_world_to_local;
	mat4 transform_local_to_world;
	mat4 transform_local;
	mat4 transform_local_inv;
	mat4 transform_parent;
	mat4 transform_parent_inv;

	vec3 axis;
	float angle;
	vec3 position;
	int blend_mode; // 0 - angle blend 1 - coords blend
	vec3 radius;
	int falloff_curve_idx;
	int falloff_inverse;
};

void vertex_modifier_twist_apply(VertexModifierTwistParams params, in out VertexInput vtx_input)
{
	// for influence move object to the noise modifier local space
	vec3 modifier_position = vec3(0.0);

	vec3 base_pos = vtx_input.pos;

	// move to modifier local space
	vec3 influence_pos = vector_transform_by_mat43(vtx_input.pos, params.transform_parent_inv * params.transform_local_inv * transform_params.mModel); // <- when disconnected, globals
	vec3 noise_pos = influence_pos;

	noise_pos = vector_transform_by_mat43(noise_pos, params.transform_local);

	vec3 rel_coords;
	vec3 influence_rel_coords;

	rel_coords = base_pos;
	influence_rel_coords = influence_pos;

	float influence = length( (influence_rel_coords - modifier_position) / params.radius);
	
	if (influence <= 1.0)
	{
		if (params.falloff_inverse == 0)
			influence = 1.0 - influence;

		influence = curve_sample(params.falloff_curve_idx, influence);

		// transform axis to proper coordinate systme
		vec3 axis = params.axis;
		axis = vector_transform_by_mat33(axis, params.transform_parent_inv * params.transform_local_inv * transform_params.mModel);

		// angle is 'position' (t) along rotation axis (projection)
		float t = dot(influence_rel_coords - modifier_position, axis);
		float angle = params.angle * t;
		if (params.blend_mode == 0)
			angle *= influence;

		vec3 local_coords = vtx_input.pos - modifier_position - t * axis;
		vec3 new_pos = modifier_position + t * axis + vector_rotate_by_quaternion(local_coords, vec4(-axis * sin(angle * 0.5f), cos(angle * 0.5)));

		// because rotation angle is not uniform it is not enough to just rotate the normal. need to build derivatives and transform...
		//vec3 new_norm = vector_rotate_by_quaternion(vtx_input.norm, vec4(-axis * sin(angle * 0.5), cos(angle * 0.5)));

		if (params.blend_mode == 0)
			vtx_input.pos = new_pos;
		else
			vtx_input.pos = mix(vtx_input.pos, new_pos, influence);
		//vtx_input.pos = new_pos;
		//vtx_input.norm = normalize(new_norm);
	}
}


#endif