forked from Unity-Technologies/EntityComponentSystemSamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSplineBakingSystem.cs
More file actions
102 lines (81 loc) · 3.88 KB
/
Copy pathSplineBakingSystem.cs
File metadata and controls
102 lines (81 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
namespace Graphical.Splines
{
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
public partial struct SplineBakingSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<ExecuteSplines>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var bakingOnlyEntities = new NativeList<Entity>(state.WorldUpdateAllocator);
foreach (var (spline, splineBakingData, bufferEntity, bufferPosition) in
SystemAPI.Query<RefRW<Spline>, RefRO<SplineBakingData>, DynamicBuffer<SplineControlPointEntity>,
DynamicBuffer<SplineControlPointPosition>>())
{
bakingOnlyEntities.AddRange(bufferEntity.Reinterpret<Entity>().AsNativeArray());
using var bakedPoints = BakePoints(state.WorldUpdateAllocator,
bufferPosition.Reinterpret<float3>().AsNativeArray(),
splineBakingData.ValueRO.Subdivisions);
using var blobBuilder = new BlobBuilder(state.WorldUpdateAllocator);
ref var splineData = ref blobBuilder.ConstructRoot<SplineData>();
var pointsBuilder = blobBuilder.Allocate(ref splineData.Points, bakedPoints.Length);
var distanceBuilder = blobBuilder.Allocate(ref splineData.Distance, bakedPoints.Length + 1);
var previous = bakedPoints[0];
var distance = 0f;
for (int i = 0; i < bakedPoints.Length; i += 1)
{
pointsBuilder[i] = bakedPoints[i];
distance += math.distance(previous, bakedPoints[i]);
distanceBuilder[i] = distance;
previous = bakedPoints[i];
}
distance += math.distance(previous, bakedPoints[0]);
distanceBuilder[bakedPoints.Length] = distance;
spline.ValueRW.Data = blobBuilder.CreateBlobAssetReference<SplineData>(Allocator.Persistent);
}
state.EntityManager.AddComponent<BakingOnlyEntity>(bakingOnlyEntities.AsArray());
}
NativeList<float3> BakePoints(Allocator allocator, NativeArray<float3> controlPoints, int subdivisions)
{
float3 RingBufferAt(int index)
{
index %= controlPoints.Length;
if (index < 0) index += controlPoints.Length;
return controlPoints[index];
}
var baked = new NativeList<float3>(allocator);
baked.Add(controlPoints[0]);
for (int i = 0; i < controlPoints.Length; i += 1)
{
float3 p0 = RingBufferAt(i - 1);
float3 p1 = RingBufferAt(i);
float3 p2 = RingBufferAt(i + 1);
float3 p3 = RingBufferAt(i + 2);
float t0 = 0;
float t1 = t0 + math.distance(p0, p1);
float t2 = t1 + math.distance(p1, p2);
float t3 = t2 + math.distance(p2, p3);
for (int j = 0; j < subdivisions; j += 1)
{
float t = math.lerp(t1, t2, (1 + j) / (float)subdivisions);
float3 a1 = ((t1 - t) * p0 + (t - t0) * p1) / (t1 - t0);
float3 a2 = ((t2 - t) * p1 + (t - t1) * p2) / (t2 - t1);
float3 a3 = ((t3 - t) * p2 + (t - t2) * p3) / (t3 - t2);
float3 b1 = ((t2 - t) * a1 + (t - t0) * a2) / (t2 - t0);
float3 b2 = ((t3 - t) * a2 + (t - t1) * a3) / (t3 - t1);
float3 c = ((t2 - t) * b1 + (t - t1) * b2) / (t2 - t1);
baked.Add(c);
}
}
return baked;
}
}
}