Files
com.misaki.art-tools/Runtime/Cloner/Effector/RandomEffector.cs
Misaki 4a15d63447 Fix error amd Update features.
Changed Span<PointData> to ReadOnlySpan<PointData> on method Operate in EffectorBase.cs
Changed the return type of method Operate in EffectorBase.cs from void to PointDate
Added FieldHelper and BlendField function to make the blending work.
2024-09-18 19:49:32 +09:00

127 lines
4.2 KiB
C#

using System;
using Unity.Mathematics;
using UnityEngine;
using Random = Unity.Mathematics.Random;
namespace Misaki.ArtTool
{
public class RandomEffector : EffectorBase
{
public float2 minMax = new(-1.0f, 1.0f);
public bool synchronized;
public uint seed = 123456;
public TransformSpace transformSpace;
public bool isEnablePosition;
public float3 positionMinMax;
public bool isEnableRotation;
public float3 rotationMinMax;
public bool isEnableScale;
public bool isAbsoluteScale;
public bool isUniformScale;
public float3 scaleMinMax;
public float uniformScaleMinMax;
public override PointData Operate(int index, float4x4 nodeWorldMatrix, ReadOnlySpan<PointData> points)
{
var currentPoint = points[index];
if (!isEnablePosition && !isEnableRotation && !isEnableScale)
{
return currentPoint;
}
Random random;
if (synchronized)
{
random = Random.CreateFromIndex(seed);
}
else
{
if (index > uint.MaxValue - seed)
{
random = Random.CreateFromIndex(seed - (uint)index);
}
else
{
random = Random.CreateFromIndex(seed + (uint)index);
}
}
MatrixHelper.DecomposeMatrix(currentPoint.matrix, out var position, out var rotation, out var scale);
var weight = CalculateFieldsWeight(position);
if (weight == 0)
{
return currentPoint;
}
if (isEnablePosition)
{
var newPosition = random.NextFloat3(positionMinMax * minMax.x, positionMinMax * minMax.y);
switch (transformSpace)
{
case TransformSpace.Effector:
newPosition = math.mul(effectorMatrix, new float4(newPosition, 0.0f)).xyz;
break;
case TransformSpace.Object:
newPosition = math.mul(currentPoint.matrix, new float4(newPosition, 0.0f)).xyz;
break;
default:
break;
}
position = math.lerp(position, position + newPosition, weight);
}
if (isEnableRotation)
{
var angle = random.NextFloat3(rotationMinMax * minMax.x, rotationMinMax * minMax.y);
switch (transformSpace)
{
case TransformSpace.Effector:
angle = math.mul(effectorMatrix, new float4(angle, 0.0f)).xyz;
break;
case TransformSpace.Object:
angle = math.mul(currentPoint.matrix, new float4(angle, 0.0f)).xyz;
break;
default:
break;
}
var newRotation = quaternion.Euler(math.radians(angle));
rotation = Quaternion.Lerp(rotation, math.mul(rotation, newRotation), weight);
}
if (isEnableScale)
{
float3 newScale;
if (isUniformScale)
{
var minScale = isAbsoluteScale ? uniformScaleMinMax : 1.0f + (uniformScaleMinMax - 1.0f) * minMax.x;
var maxScale = isAbsoluteScale ? 0.0f : 1.0f + (uniformScaleMinMax - 1.0f) * minMax.y;
newScale = random.NextFloat(minScale, maxScale);
}
else
{
var minScale = isAbsoluteScale ? scaleMinMax : 1.0f + ((scaleMinMax - 1.0f) * minMax.x);
var maxScale = isAbsoluteScale ? 0.0f : 1.0f + ((scaleMinMax - 1.0f) * minMax.y);
newScale = random.NextFloat3(minScale, maxScale);
}
scale = math.lerp(scale, scale + newScale, weight);
}
currentPoint.matrix = float4x4.TRS(position, rotation, scale);
return currentPoint;
}
}
}