Switch points generation from managed thread to unmanaged thread; Change Spline to NativeSpline; Add converter for DistributionMode and update cloner editor ui; Add MeshData type for object distribution calculation; Add ObjectDistributionSetting and ObjectDistributionCalculation(Vertex and Edge Mode);
This commit is contained in:
@@ -3,10 +3,13 @@ using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Splines;
|
||||
using Random = Unity.Mathematics.Random;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
@@ -22,6 +25,9 @@ namespace Misaki.ArtTool
|
||||
public bool autoGenerate;
|
||||
public bool isRenderInstancing;
|
||||
|
||||
public MeshFilter inputMeshFilter;
|
||||
public ObjectDistributionSetting objectDistributionSetting;
|
||||
public SplineContainer inputSplineContainer;
|
||||
public SplineDistributionSetting splineDistributionSetting;
|
||||
public LinearDistributionSetting linearDistributionSetting;
|
||||
public GridDistributionSetting gridDistributionSetting;
|
||||
@@ -128,16 +134,37 @@ namespace Misaki.ArtTool
|
||||
switch (distributionMode)
|
||||
{
|
||||
case DistributionMode.Object:
|
||||
|
||||
if (inputMeshFilter == null)
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
objectDistributionSetting.meshData = new(inputMeshFilter, Allocator.TempJob);
|
||||
|
||||
break;
|
||||
case DistributionMode.Spline:
|
||||
|
||||
if (inputSplineContainer == null)
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
splineDistributionSetting.splineWorldMatrix = inputSplineContainer.transform.localToWorldMatrix;
|
||||
splineDistributionSetting.nativeSpline = new(inputSplineContainer.Spline, Allocator.TempJob);
|
||||
splineDistributionSetting.splineLength = splineDistributionSetting.nativeSpline.CalculateLength(splineDistributionSetting.splineWorldMatrix);
|
||||
|
||||
_pointSize = splineDistributionSetting.DistributionCount;
|
||||
break;
|
||||
|
||||
case DistributionMode.Linear:
|
||||
_pointSize = (int)linearDistributionSetting.count;
|
||||
break;
|
||||
|
||||
case DistributionMode.Grid:
|
||||
_pointSize = gridDistributionSetting.DistributionCount;
|
||||
break;
|
||||
|
||||
case DistributionMode.Radial:
|
||||
break;
|
||||
case DistributionMode.Honeycomb:
|
||||
@@ -146,6 +173,12 @@ namespace Misaki.ArtTool
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate a empty native spline to avoid job error
|
||||
if (distributionMode != DistributionMode.Spline)
|
||||
{
|
||||
splineDistributionSetting.nativeSpline = new(new List<BezierKnot>(), false, transform.localToWorldMatrix, Allocator.TempJob);
|
||||
}
|
||||
|
||||
if (_pointSize == 0)
|
||||
{
|
||||
return;
|
||||
@@ -161,68 +194,66 @@ namespace Misaki.ArtTool
|
||||
effectorData.effector.Initialize();
|
||||
}
|
||||
|
||||
if (distributionMode == DistributionMode.Spline && splineDistributionSetting.spline != null)
|
||||
{
|
||||
splineDistributionSetting.splineWorldMatrix = splineDistributionSetting.spline.transform.localToWorldMatrix;
|
||||
splineDistributionSetting.splineLength = splineDistributionSetting.spline.CalculateLength();
|
||||
}
|
||||
|
||||
var worldMatrix = transform.localToWorldMatrix;
|
||||
Parallel.For(0, _pointSize, i =>
|
||||
//for (var i = 0; i < _pointSize; i++)
|
||||
{
|
||||
var pointMatrix = float4x4.identity;
|
||||
var isValid = true;
|
||||
switch (distributionMode)
|
||||
{
|
||||
case DistributionMode.Object:
|
||||
break;
|
||||
case DistributionMode.Spline:
|
||||
Distribution.SplineDistribution(i, _pointSize, splineDistributionSetting, out pointMatrix, out isValid);
|
||||
break;
|
||||
case DistributionMode.Linear:
|
||||
Distribution.LinearDistribution(i, linearDistributionSetting, out pointMatrix, out isValid);
|
||||
break;
|
||||
case DistributionMode.Grid:
|
||||
Distribution.GridDistribution(i, gridDistributionSetting, out pointMatrix, out isValid);
|
||||
break;
|
||||
case DistributionMode.Radial:
|
||||
break;
|
||||
case DistributionMode.Honeycomb:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pointMatrix = math.mul(worldMatrix, pointMatrix);
|
||||
|
||||
_points[i].matrix = pointMatrix;
|
||||
_points[i].isValid = isValid;
|
||||
//}
|
||||
});
|
||||
|
||||
//var pointsArray = new NativeArray<PointData>(_pointSize, Allocator.Temp);
|
||||
|
||||
//var pointsGenerationJob = new PointsGenerationJob()
|
||||
//Parallel.For(0, _pointSize, i =>
|
||||
////for (var i = 0; i < _pointSize; i++)
|
||||
//{
|
||||
// worldMatrix = worldMatrix,
|
||||
// pointSize = _pointSize,
|
||||
// var pointMatrix = float4x4.identity;
|
||||
// var isValid = true;
|
||||
// switch (distributionMode)
|
||||
// {
|
||||
// case DistributionMode.Object:
|
||||
// break;
|
||||
// case DistributionMode.Spline:
|
||||
// Distribution.SplineDistribution(i, _pointSize, splineDistributionSetting, out pointMatrix, out isValid);
|
||||
// break;
|
||||
// case DistributionMode.Linear:
|
||||
// Distribution.LinearDistribution(i, linearDistributionSetting, out pointMatrix, out isValid);
|
||||
// break;
|
||||
// case DistributionMode.Grid:
|
||||
// Distribution.GridDistribution(i, gridDistributionSetting, out pointMatrix, out isValid);
|
||||
// break;
|
||||
// case DistributionMode.Radial:
|
||||
// break;
|
||||
// case DistributionMode.Honeycomb:
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// distributionMode = distributionMode,
|
||||
// pointMatrix = math.mul(worldMatrix, pointMatrix);
|
||||
|
||||
// splineDistributionSetting = splineDistributionSetting,
|
||||
// linearDistributionSetting = linearDistributionSetting,
|
||||
// gridDistributionSetting = gridDistributionSetting,
|
||||
// _points[i].matrix = pointMatrix;
|
||||
// _points[i].isValid = isValid;
|
||||
// //}
|
||||
//});
|
||||
|
||||
// points = pointsArray
|
||||
//};
|
||||
// Since NativeSpline is not available in managed thread, we have to use jobs
|
||||
var pointsArray = new NativeArray<PointData>(_points.Length, Allocator.TempJob);
|
||||
var pointsGenerationJob = new PointsGenerationJob()
|
||||
{
|
||||
worldMatrix = worldMatrix,
|
||||
pointSize = _pointSize,
|
||||
|
||||
//var handle = pointsGenerationJob.ScheduleBatch(_pointSize, 64);
|
||||
//handle.Complete();
|
||||
distributionMode = distributionMode,
|
||||
|
||||
//pointsArray.CopyTo(_points);
|
||||
//pointsArray.Dispose();
|
||||
splineDistributionSetting = splineDistributionSetting,
|
||||
linearDistributionSetting = linearDistributionSetting,
|
||||
gridDistributionSetting = gridDistributionSetting,
|
||||
|
||||
points = pointsArray
|
||||
};
|
||||
|
||||
var handle = pointsGenerationJob.Schedule(_pointSize, 64);
|
||||
handle.Complete();
|
||||
|
||||
pointsArray.CopyTo(_points);
|
||||
|
||||
pointsArray.Dispose();
|
||||
splineDistributionSetting.nativeSpline.Dispose();
|
||||
objectDistributionSetting.meshData.Dispose();
|
||||
|
||||
// Switch to managed thread for effectors because of interface
|
||||
Parallel.For(0, _pointSize, i =>
|
||||
{
|
||||
for (var e = 0; e < effectors.Count; e++)
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Misaki.ArtTool
|
||||
{
|
||||
var random = Random.CreateFromIndex((uint)index);
|
||||
|
||||
var localPosition = GetCubePosition(index, setting.count) * setting.spacing;
|
||||
var localPosition = ShapeHelper.GetCubePosition(index, setting.count) * setting.spacing;
|
||||
|
||||
switch (setting.shape)
|
||||
{
|
||||
@@ -17,13 +17,13 @@ namespace Misaki.ArtTool
|
||||
break;
|
||||
|
||||
case GridShape.Sphere:
|
||||
var isInsideSphere = ShapeHelper.IsInsideSphere(localPosition, 0.0f, setting.count * setting.spacing);
|
||||
var isInsideSphere = ShapeHelper.IsPointInsideSphere(localPosition, 0.0f, setting.count * setting.spacing);
|
||||
|
||||
isValid = isInsideSphere;
|
||||
break;
|
||||
|
||||
case GridShape.Cylinder:
|
||||
var isInsideCylinder = ShapeHelper.IsInsideCylinder(localPosition, 0.0f, setting.count * setting.spacing);
|
||||
var isInsideCylinder = ShapeHelper.IsPointInsideCylinder(localPosition, 0.0f, setting.count * setting.spacing);
|
||||
isValid = isInsideCylinder;
|
||||
break;
|
||||
default:
|
||||
@@ -38,18 +38,5 @@ namespace Misaki.ArtTool
|
||||
|
||||
localMatrix = float4x4.TRS(localPosition, quaternion.identity, new float3(1.0f));
|
||||
}
|
||||
|
||||
private static float3 GetCubePosition(int index, int3 size)
|
||||
{
|
||||
float3 localPosition;
|
||||
var yIndex = index / (size.x * size.z);
|
||||
var remain = index % (size.x * size.z);
|
||||
var zIndex = remain / size.x;
|
||||
var xIndex = remain % size.x;
|
||||
|
||||
localPosition = new float3(xIndex, yIndex, zIndex);
|
||||
localPosition -= (float3)(size - 1) * 0.5f;
|
||||
return localPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Runtime/Cloner/Distribution/ObjectDistribution.cs
Normal file
13
Runtime/Cloner/Distribution/ObjectDistribution.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
public static partial class Distribution
|
||||
{
|
||||
public static void ObjectDistribution(int index, ObjectDistributionSetting setting, out float4x4 localMatrix, out bool isValid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/Cloner/Distribution/ObjectDistribution.cs.meta
Normal file
2
Runtime/Cloner/Distribution/ObjectDistribution.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bed43825cb2cca49b6b7adfe693a5e2
|
||||
@@ -17,7 +17,6 @@ namespace Misaki.ArtTool
|
||||
return;
|
||||
}
|
||||
|
||||
var spline = setting.spline;
|
||||
float t;
|
||||
|
||||
if (setting.isSpacingMode)
|
||||
@@ -29,7 +28,7 @@ namespace Misaki.ArtTool
|
||||
t = pointIndex / (float)(pointSize - 1);
|
||||
}
|
||||
|
||||
if (SplineUtility.Evaluate(spline.Spline, t, out var position, out var normal, out var upVector))
|
||||
if (SplineUtility.Evaluate(setting.nativeSpline, t, out var position, out var normal, out var upVector))
|
||||
{
|
||||
var localRotation = quaternion.LookRotationSafe(normal, upVector);
|
||||
|
||||
|
||||
11
Runtime/Cloner/Enums/ObjectDistributionMode.cs
Normal file
11
Runtime/Cloner/Enums/ObjectDistributionMode.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
public enum ObjectDistributionMode
|
||||
{
|
||||
Surface,
|
||||
Volume,
|
||||
Vertex,
|
||||
Edge,
|
||||
PolygonCenter
|
||||
}
|
||||
}
|
||||
2
Runtime/Cloner/Enums/ObjectDistributionMode.cs.meta
Normal file
2
Runtime/Cloner/Enums/ObjectDistributionMode.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f378e3924b6a5c34fa1eab8b8c87dc4f
|
||||
@@ -11,7 +11,6 @@ namespace Misaki.ArtTool
|
||||
public static void Initialize()
|
||||
{
|
||||
var boolToDisplayGroup = new ConverterGroup("BoolToDisplayConvertor");
|
||||
|
||||
boolToDisplayGroup.AddConverter((ref bool v) => BoolToDisplayConverter.ConvertTo(v));
|
||||
boolToDisplayGroup.AddConverter((ref StyleEnum<DisplayStyle> v) => BoolToDisplayConverter.ConvertBack(v));
|
||||
|
||||
@@ -19,7 +18,6 @@ namespace Misaki.ArtTool
|
||||
|
||||
|
||||
var inverseBoolToDisplayGroup = new ConverterGroup("InverseBoolToDisplayConverter");
|
||||
|
||||
inverseBoolToDisplayGroup.AddConverter((ref bool v) => InverseBoolToDisplayConverter.ConvertTo(v));
|
||||
inverseBoolToDisplayGroup.AddConverter((ref StyleEnum<DisplayStyle> v) => InverseBoolToDisplayConverter.ConvertBack(v));
|
||||
|
||||
@@ -27,7 +25,6 @@ namespace Misaki.ArtTool
|
||||
|
||||
|
||||
var float2ToVector2Group = new ConverterGroup("Float2ToVector2Converter");
|
||||
|
||||
float2ToVector2Group.AddConverter((ref float2 v) => Float2ToVector2Converter.ConvertTo(v));
|
||||
float2ToVector2Group.AddConverter((ref Vector2 v) => Float2ToVector2Converter.ConvertBack(v));
|
||||
|
||||
@@ -35,11 +32,50 @@ namespace Misaki.ArtTool
|
||||
|
||||
|
||||
var float3ToVector3Group = new ConverterGroup("Float3ToVector3Converter");
|
||||
|
||||
float3ToVector3Group.AddConverter((ref float3 v) => Float3ToVector3Converter.ConvertTo(v));
|
||||
float3ToVector3Group.AddConverter((ref Vector3 v) => Float3ToVector3Converter.ConvertBack(v));
|
||||
|
||||
ConverterGroups.RegisterConverterGroup(float3ToVector3Group);
|
||||
|
||||
|
||||
var int2ToVector2IntGroup = new ConverterGroup("int2ToVector2IntConverter");
|
||||
int2ToVector2IntGroup.AddConverter((ref int2 v) => Int2ToVector2IntConverter.ConvertTo(v));
|
||||
int2ToVector2IntGroup.AddConverter((ref Vector2Int v) => Int2ToVector2IntConverter.ConvertBack(v));
|
||||
|
||||
ConverterGroups.RegisterConverterGroup(int2ToVector2IntGroup);
|
||||
|
||||
|
||||
var int3ToVector3IntGroup = new ConverterGroup("int3ToVector3IntConverter");
|
||||
int3ToVector3IntGroup.AddConverter((ref int3 v) => Int3ToVector3IntConverter.ConvertTo(v));
|
||||
int3ToVector3IntGroup.AddConverter((ref Vector3Int v) => Int3ToVector3IntConverter.ConvertBack(v));
|
||||
|
||||
ConverterGroups.RegisterConverterGroup(int3ToVector3IntGroup);
|
||||
|
||||
// Converter in ui-toolkit does not support converter parameters right now, we have to register all the types one by one
|
||||
var objectModeToDisplayStyleGroup = new ConverterGroup("ObjectModeToDisplayStyleConverter");
|
||||
objectModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.ObjectModeConvertTo(v));
|
||||
|
||||
var splineModeToDisplayStyleGroup = new ConverterGroup("SplineModeToDisplayStyleConverter");
|
||||
splineModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.SplineModeConvertTo(v));
|
||||
|
||||
var linearModeToDisplayStyleGroup = new ConverterGroup("LinearModeToDisplayStyleConverter");
|
||||
linearModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.LinearModeConvertTo(v));
|
||||
|
||||
var gridModeToDisplayStyleGroup = new ConverterGroup("GridModeToDisplayStyleConverter");
|
||||
gridModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.GridModeConvertTo(v));
|
||||
|
||||
var radialModeToDisplayStyleGroup = new ConverterGroup("RadialModeToDisplayStyleConverter");
|
||||
radialModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.RadialModeConvertTo(v));
|
||||
|
||||
var honeycombModeToDisplayStyleGroup = new ConverterGroup("HoneycombModeToDisplayStyleConverter");
|
||||
honeycombModeToDisplayStyleGroup.AddConverter((ref DistributionMode v) => DistributionModeToDisplayStyleConverter.HoneycombModeConvertTo(v));
|
||||
|
||||
ConverterGroups.RegisterConverterGroup(objectModeToDisplayStyleGroup);
|
||||
ConverterGroups.RegisterConverterGroup(splineModeToDisplayStyleGroup);
|
||||
ConverterGroups.RegisterConverterGroup(linearModeToDisplayStyleGroup);
|
||||
ConverterGroups.RegisterConverterGroup(gridModeToDisplayStyleGroup);
|
||||
ConverterGroups.RegisterConverterGroup(radialModeToDisplayStyleGroup);
|
||||
ConverterGroups.RegisterConverterGroup(honeycombModeToDisplayStyleGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,67 @@
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
public struct DistributionModeToDisplayStyleConverter
|
||||
{
|
||||
public static StyleEnum<DisplayStyle> ObjectModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Object)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
|
||||
public static StyleEnum<DisplayStyle> SplineModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Spline)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
|
||||
public static StyleEnum<DisplayStyle> LinearModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Linear)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
|
||||
public static StyleEnum<DisplayStyle> GridModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Grid)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
|
||||
public static StyleEnum<DisplayStyle> RadialModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Radial)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
|
||||
public static StyleEnum<DisplayStyle> HoneycombModeConvertTo(DistributionMode mode)
|
||||
{
|
||||
if (mode == DistributionMode.Honeycomb)
|
||||
{
|
||||
return DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
return DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
Runtime/Cloner/Helper/Converter/IntToVectorIntConverter.cs
Normal file
31
Runtime/Cloner/Helper/Converter/IntToVectorIntConverter.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
public struct Int2ToVector2IntConverter
|
||||
{
|
||||
public static Vector2Int ConvertTo(int2 value)
|
||||
{
|
||||
return new Vector2Int(value.x, value.y);
|
||||
}
|
||||
|
||||
public static int2 ConvertBack(Vector2Int value)
|
||||
{
|
||||
return new int2(value.x, value.y);
|
||||
}
|
||||
}
|
||||
|
||||
public struct Int3ToVector3IntConverter
|
||||
{
|
||||
public static Vector3Int ConvertTo(int3 value)
|
||||
{
|
||||
return new Vector3Int(value.x, value.y, value.z);
|
||||
}
|
||||
|
||||
public static int3 ConvertBack(Vector3Int value)
|
||||
{
|
||||
return new int3(value.x, value.y, value.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c271b5a6b3fadff498bc8f938e501eee
|
||||
@@ -31,7 +31,7 @@ namespace Misaki.ArtTool
|
||||
rotation = Quaternion.LookRotation(matrix.c2.xyz / scale.z, matrix.c1.xyz / scale.y);
|
||||
}
|
||||
|
||||
internal static void DecomposeMatrixListAsSpan(in IList<Matrix4x4> matrixList, Span<Vector3> positions, Span<Quaternion> rotations, Span<Vector3> scales)
|
||||
internal static void DecomposeMatrixListAsSpan(in List<Matrix4x4> matrixList, Span<Vector3> positions, Span<Quaternion> rotations, Span<Vector3> scales)
|
||||
{
|
||||
if (matrixList.Count != positions.Length || matrixList.Count != rotations.Length || matrixList.Count != scales.Length)
|
||||
{
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
internal static class ShapeHelper
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static float Linear01DistanceToSphereCenter(float3 pointPosition, float3 spherePosition, float3 sphereSize)
|
||||
{
|
||||
var x = (pointPosition.x - spherePosition.x) / sphereSize.x;
|
||||
var y = (pointPosition.y - spherePosition.y) / sphereSize.y;
|
||||
var z = (pointPosition.z - spherePosition.z) / sphereSize.z;
|
||||
|
||||
var normalizedDistance = math.sqrt(x * x + y * y + z * z);
|
||||
|
||||
return math.saturate(normalizedDistance);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool IsInsideSphere(float3 pointPosition, float3 spherePosition, float3 sphereSize)
|
||||
{
|
||||
sphereSize /= 2.0f;
|
||||
|
||||
var x = (pointPosition.x - spherePosition.x) / sphereSize.x;
|
||||
var y = (pointPosition.y - spherePosition.y) / sphereSize.y;
|
||||
var z = (pointPosition.z - spherePosition.z) / sphereSize.z;
|
||||
|
||||
return (x * x + y * y + z * z) <= 1.0f;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool IsInsideCylinder(float3 pointPosition, float3 cylinderPosition, float3 cylinderSize)
|
||||
{
|
||||
cylinderSize /= 2.0f;
|
||||
|
||||
var dx = (pointPosition.x - cylinderPosition.x) / cylinderSize.x;
|
||||
var dz = (pointPosition.z - cylinderPosition.z) / cylinderSize.z;
|
||||
var distanceSquared = dx * dx + dz * dz;
|
||||
|
||||
var withinRadius = distanceSquared <= 1.0f;
|
||||
|
||||
var withinHeight = pointPosition.y >= (cylinderPosition.y - cylinderSize.y) && pointPosition.y <= (cylinderPosition.y + cylinderSize.y);
|
||||
|
||||
return withinRadius && withinHeight;
|
||||
}
|
||||
|
||||
internal static bool IsInsideMesh(float3 pointPosition, float3 meshPosition, Mesh mesh)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Runtime/Cloner/Helper/ShapeHelperGetPosition.cs
Normal file
51
Runtime/Cloner/Helper/ShapeHelperGetPosition.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
internal static partial class ShapeHelper
|
||||
{
|
||||
internal static float3 GetCubePosition(int index, int3 size)
|
||||
{
|
||||
float3 localPosition;
|
||||
var yIndex = index / (size.x * size.z);
|
||||
var remain = index % (size.x * size.z);
|
||||
var zIndex = remain / size.x;
|
||||
var xIndex = remain % size.x;
|
||||
|
||||
localPosition = new float3(xIndex, yIndex, zIndex);
|
||||
localPosition -= (float3)(size - 1) * 0.5f;
|
||||
return localPosition;
|
||||
}
|
||||
|
||||
internal static bool GetMeshVertexPosition(int index, MeshData meshData, out float3 position)
|
||||
{
|
||||
if (!meshData.vertices.IsCreated || meshData.vertices.Length <= index)
|
||||
{
|
||||
position = float3.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
position = meshData.vertices[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool GetMeshEdgePosition(int index, MeshData meshData, out float3 position)
|
||||
{
|
||||
if (!meshData.edges.IsCreated || meshData.edges.Length <= index)
|
||||
{
|
||||
position = float3.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
var edge = meshData.edges[index];
|
||||
if (meshData.vertices.Length <= edge.x || meshData.vertices.Length <= edge.y)
|
||||
{
|
||||
position = float3.zero;
|
||||
return false;
|
||||
}
|
||||
|
||||
position = (meshData.vertices[edge.x] + meshData.vertices[edge.y]) / 2.0f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/Cloner/Helper/ShapeHelperGetPosition.cs.meta
Normal file
2
Runtime/Cloner/Helper/ShapeHelperGetPosition.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36c7b9b7309ef1c4681c47a09154d5e1
|
||||
82
Runtime/Cloner/Helper/ShapeHelperInsideCheck.cs
Normal file
82
Runtime/Cloner/Helper/ShapeHelperInsideCheck.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
internal static partial class ShapeHelper
|
||||
{
|
||||
internal static float Linear01DistanceToSphereCenter(float3 pointPosition, float3 spherePosition, float3 sphereSize)
|
||||
{
|
||||
var x = (pointPosition.x - spherePosition.x) / sphereSize.x;
|
||||
var y = (pointPosition.y - spherePosition.y) / sphereSize.y;
|
||||
var z = (pointPosition.z - spherePosition.z) / sphereSize.z;
|
||||
|
||||
var normalizedDistance = math.sqrt(x * x + y * y + z * z);
|
||||
|
||||
return math.saturate(normalizedDistance);
|
||||
}
|
||||
|
||||
internal static bool IsPointInsideSphere(float3 pointPosition, float3 spherePosition, float3 sphereSize)
|
||||
{
|
||||
sphereSize /= 2.0f;
|
||||
|
||||
var x = (pointPosition.x - spherePosition.x) / sphereSize.x;
|
||||
var y = (pointPosition.y - spherePosition.y) / sphereSize.y;
|
||||
var z = (pointPosition.z - spherePosition.z) / sphereSize.z;
|
||||
|
||||
return (x * x + y * y + z * z) <= 1.0f;
|
||||
}
|
||||
|
||||
internal static bool IsPointInsideCylinder(float3 pointPosition, float3 cylinderPosition, float3 cylinderSize)
|
||||
{
|
||||
cylinderSize /= 2.0f;
|
||||
|
||||
var dx = (pointPosition.x - cylinderPosition.x) / cylinderSize.x;
|
||||
var dz = (pointPosition.z - cylinderPosition.z) / cylinderSize.z;
|
||||
var distanceSquared = dx * dx + dz * dz;
|
||||
|
||||
var withinRadius = distanceSquared <= 1.0f;
|
||||
|
||||
var withinHeight = pointPosition.y >= (cylinderPosition.y - cylinderSize.y) && pointPosition.y <= (cylinderPosition.y + cylinderSize.y);
|
||||
|
||||
return withinRadius && withinHeight;
|
||||
}
|
||||
|
||||
internal static bool IsPointInsideMesh(float3 pointPosition, float3 meshPosition, MeshData meshData)
|
||||
{
|
||||
var windingNumber = 0;
|
||||
|
||||
for (var i = 0; i < meshData.triangles.Length; i += 3)
|
||||
{
|
||||
var v1 = meshData.vertices[meshData.triangles[i]];
|
||||
var v2 = meshData.vertices[meshData.triangles[i + 1]];
|
||||
var v3 = meshData.vertices[meshData.triangles[i + 2]];
|
||||
|
||||
if (IsPointInsideTriangle(pointPosition, v1, v2, v3))
|
||||
{
|
||||
windingNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
return windingNumber % 2 != 0;
|
||||
}
|
||||
|
||||
private static bool IsPointInsideTriangle(float3 point, float3 a, float3 b, float3 c)
|
||||
{
|
||||
var v0 = c - a;
|
||||
var v1 = b - a;
|
||||
var v2 = point - a;
|
||||
|
||||
var dot00 = math.dot(v0, v0);
|
||||
var dot01 = math.dot(v0, v1);
|
||||
var dot02 = math.dot(v0, v2);
|
||||
var dot11 = math.dot(v1, v1);
|
||||
var dot12 = math.dot(v1, v2);
|
||||
|
||||
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
|
||||
var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
|
||||
return (u >= 0) && (v >= 0) && (u + v < 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
@@ -10,7 +9,6 @@ namespace Misaki.ArtTool
|
||||
public int3 count;
|
||||
public float3 spacing;
|
||||
public GridShape shape;
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float fill;
|
||||
|
||||
public readonly int DistributionCount => count.x * count.y * count.z;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
[Serializable]
|
||||
public struct ObjectDistributionSetting
|
||||
{
|
||||
public MeshFilter meshFilter;
|
||||
public MeshData meshData;
|
||||
public ObjectDistributionMode mode;
|
||||
public int count;
|
||||
public uint seed;
|
||||
public bool alignNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Misaki.ArtTool
|
||||
[Serializable]
|
||||
public struct SplineDistributionSetting
|
||||
{
|
||||
public SplineContainer spline;
|
||||
public NativeSpline nativeSpline;
|
||||
|
||||
public int indexOffset;
|
||||
|
||||
@@ -26,14 +26,9 @@ namespace Misaki.ArtTool
|
||||
{
|
||||
get
|
||||
{
|
||||
if (spline == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isSpacingMode)
|
||||
{
|
||||
return Mathf.FloorToInt(spline.CalculateLength() / spacing) + 1;
|
||||
return Mathf.FloorToInt(splineLength / spacing) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
76
Runtime/Cloner/Models/MeshData.cs
Normal file
76
Runtime/Cloner/Models/MeshData.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.ArtTool
|
||||
{
|
||||
public struct MeshData : IDisposable
|
||||
{
|
||||
public Bounds bounds;
|
||||
public NativeArray<int> triangles;
|
||||
public NativeArray<float4> tangents;
|
||||
public NativeArray<float3> vertices;
|
||||
public NativeList<int2> edges;
|
||||
public int vertexCount;
|
||||
|
||||
public float4x4 worldMatrix;
|
||||
|
||||
public MeshData(MeshFilter meshFilter, Allocator allocator)
|
||||
{
|
||||
var mesh = meshFilter.sharedMesh;
|
||||
|
||||
bounds = mesh.bounds;
|
||||
|
||||
triangles = new(mesh.triangles.Length, allocator);
|
||||
for (var i = 0; i < triangles.Length; i++)
|
||||
{
|
||||
triangles[i] = mesh.triangles[i];
|
||||
}
|
||||
|
||||
tangents = new(mesh.tangents.Length, allocator);
|
||||
for (var i = 0; i < tangents.Length; i++)
|
||||
{
|
||||
tangents[i] = mesh.tangents[i];
|
||||
}
|
||||
|
||||
vertices = new(mesh.vertices.Length, allocator);
|
||||
for (var i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i] = mesh.vertices[i];
|
||||
}
|
||||
|
||||
vertexCount = mesh.vertexCount;
|
||||
|
||||
edges = new((int)(vertexCount * 1.5f), allocator);
|
||||
for (var i = 0; i < triangles.Length; i += 3)
|
||||
{
|
||||
AddEdge(edges, triangles[i], triangles[i + 1]);
|
||||
AddEdge(edges, triangles[i + 1], triangles[i + 2]);
|
||||
AddEdge(edges, triangles[i + 2], triangles[i]);
|
||||
}
|
||||
|
||||
worldMatrix = meshFilter.transform.localToWorldMatrix;
|
||||
|
||||
static void AddEdge(NativeList<int2> edges, int a, int b)
|
||||
{
|
||||
if (a < b)
|
||||
{
|
||||
edges.Add(new int2(a, b));
|
||||
}
|
||||
else
|
||||
{
|
||||
edges.Add(new int2(b, a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
triangles.Dispose();
|
||||
tangents.Dispose();
|
||||
vertices.Dispose();
|
||||
edges.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/Cloner/Models/MeshData.cs.meta
Normal file
2
Runtime/Cloner/Models/MeshData.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 211ceb887d371d946b4b6617e565d329
|
||||
Reference in New Issue
Block a user