forked from stella3d/job-system-cookbook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RayBoundsIntersection.cs
142 lines (115 loc) · 4.17 KB
/
RayBoundsIntersection.cs
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;
public class RayBoundsIntersection : BaseJobObjectExample
{
NativeArray<Bounds> m_NativeBounds;
NativeArray<int> m_RayIntersectionResults;
RayIntersectionJob m_RayIntersectionJob;
RayIntersectionListJob m_RayIntersectionListJob;
JobHandle m_RayIntersectionJobHandle;
JobHandle m_RayIntersectionListJobHandle;
protected virtual void Start()
{
m_NativeBounds = new NativeArray<Bounds>(m_ObjectCount, Allocator.Persistent);
m_RayIntersectionResults = new NativeArray<int>(m_ObjectCount, Allocator.Persistent);
m_Objects = SetupUtils.PlaceRandomCubes(m_ObjectCount, m_ObjectPlacementRadius);
for (int i = 0; i < m_ObjectCount; i++)
{
m_Renderers[i] = m_Objects[i].GetComponent<Renderer>();
m_NativeBounds[i] = m_Renderers[i].bounds;
}
}
// assemble an array representing which input Bounds in the parallel array was intersected
struct RayIntersectionJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<Bounds> boundsArray;
// we can't use bools in NativeArray<T>, since the type must be blittable,
// so i'm representing boolean results as 0 or 1
[WriteOnly]
public NativeArray<int> results;
public Ray ray;
public void Execute(int i)
{
if (boundsArray[i].IntersectRay(ray))
results[i] = 1;
else
results[i] = 0;
}
}
// use a non-parallel job to assemble a friendlier results array
struct RayIntersectionListJob : IJob
{
[ReadOnly]
public NativeArray<Bounds> boundsArray;
[ReadOnly]
public NativeArray<int> boundsIntersected;
[WriteOnly]
public NativeArray<Bounds> results;
public void Execute()
{
int resultIndex = 0;
for (int i = 0; i < boundsArray.Length; i++)
{
if (resultIndex == results.Length)
break;
if (boundsIntersected[i] == 1)
{
results[resultIndex] = boundsArray[i];
resultIndex++;
}
}
}
}
public void Update()
{
// generate a new Ray to test against every frame
var point = UnityEngine.Random.insideUnitSphere;
var testRay = new Ray(Vector3.zero - point, Vector3.right + Vector3.up + point);
m_RayIntersectionJob = new RayIntersectionJob()
{
ray = testRay,
results = m_RayIntersectionResults,
boundsArray = m_NativeBounds
};
// instead of keeping a results array between frames and clearing it, here we
// use the TempJob allocator for an array we'll dispose quickly (within 4 frames)
var results = new NativeArray<Bounds>(new Bounds[10], Allocator.TempJob);
m_RayIntersectionListJob = new RayIntersectionListJob()
{
boundsIntersected = m_RayIntersectionResults,
boundsArray = m_NativeBounds,
results = results
};
m_RayIntersectionJobHandle = m_RayIntersectionJob.Schedule(m_NativeBounds.Length, 64);
m_RayIntersectionListJobHandle = m_RayIntersectionListJob.Schedule(m_RayIntersectionJobHandle);
}
public void LateUpdate()
{
m_RayIntersectionListJobHandle.Complete();
var results = m_RayIntersectionListJob.results;
var resultCount = GetResultCount(results);
if (resultCount > 0)
Debug.Log(resultCount + " total intersections, first result: " + results[0]);
// make sure to dispose any temp allocations made for this job
m_RayIntersectionListJob.results.Dispose();
}
public int GetResultCount(NativeArray<Bounds> bounds)
{
var zeroBounds = new Bounds();
for (int i = 0; i < bounds.Length; i++)
{
if (bounds[i] == zeroBounds)
{
return i;
}
}
return 0;
}
private void OnDestroy()
{
m_NativeBounds.Dispose();
m_RayIntersectionResults.Dispose();
}
}