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.
127 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|
|
} |