-
Notifications
You must be signed in to change notification settings - Fork 0
/
InstDysonShellLayer.cs
297 lines (256 loc) · 9.96 KB
/
InstDysonShellLayer.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
using System;
using System.Collections.Generic;
using UnityEngine;
namespace SphereOpt
{
public class InstDysonShellLayer
{
public struct HexProgressData
{
public float progress;
}
public static int HEXPROGRESSDATA_STRIDE = 4;
public struct PolygonData {
public Vector3 pos;
public Vector3 normal;
}
public static int POLYGONDATA_STRIDE = 24;
public struct HexData
{
public Vector3 pos;
public int shellIndex;
public int nodeIndex;
public float vertFillOrder;
public int closestPolygon;
public uint axialCoords_xy;
}
public static int HEXDATA_STRIDE = 32;
public struct ShellData
{
public int color;
public uint state;
public int progressBaseIndex;
public int polyCount;
public int polygonIndex;
public Vector3 center;
public int protoId;
public int clockwise;
}
public static int SHELLDATA_STRIDE = 40;
public int layerId;
public HexProgressData[] hexProgressPool;
public List<HexData> hexPool;
public ShellData[] shellPool;
public PolygonData[] polygonPool;
public float gridSize;
public int gridScale;
public float radius;
public int progressBaseCursor;
public int polygonCursor;
public int cachedHexCount = -1;
private ComputeBuffer hexProgressBuffer;
private ComputeBuffer hexBuffer;
private ComputeBuffer shellBuffer;
private ComputeBuffer polygonBuffer;
public bool hexProgressBufferIsDirty = true;
public bool hexBufferIsDirty = true;
public bool shellBufferIsDirty = true;
public bool polygonBufferIsDirty = true;
public MaterialPropertyBlock props = new MaterialPropertyBlock();
private static readonly int Radius = Shader.PropertyToID("_Radius");
private static readonly int Scale = Shader.PropertyToID("_Scale");
private static readonly int GridSize = Shader.PropertyToID("_GridSize");
private static readonly int CellSize = Shader.PropertyToID("_CellSize");
private static readonly int LayerId = Shader.PropertyToID("_LayerId");
private static readonly int HexBuffer = Shader.PropertyToID("_HexBuffer");
private static readonly int HexProgressBuffer = Shader.PropertyToID("_HexProgressBuffer");
private static readonly int ShellBuffer = Shader.PropertyToID("_ShellBuffer");
private static readonly int PolygonBuffer = Shader.PropertyToID("_PolygonBuffer");
public InstDysonShellLayer(int layerId)
{
this.layerId = layerId;
hexProgressPool = new HexProgressData[64];
hexPool = new List<HexData>();
shellPool = new ShellData[11];
polygonPool = new PolygonData[64];
hexProgressBuffer = new ComputeBuffer(64, HEXPROGRESSDATA_STRIDE);
shellBuffer = new ComputeBuffer(11, SHELLDATA_STRIDE);
polygonBuffer = new ComputeBuffer(64, POLYGONDATA_STRIDE);
SetProps();
}
public void Free()
{
if (polygonBuffer != null)
{
polygonBuffer.Release();
polygonBuffer = null;
}
polygonPool = null;
if (hexProgressBuffer != null)
{
hexProgressBuffer.Release();
hexProgressBuffer = null;
}
hexProgressPool = null;
if (shellBuffer != null)
{
shellBuffer.Release();
shellBuffer = null;
}
shellPool = null;
if (hexBuffer != null)
{
hexBuffer.Release();
hexBuffer = null;
}
hexPool.Clear();
hexPool = null;
progressBaseCursor = 0;
polygonCursor = 0;
cachedHexCount = -1;
props = null;
layerId = 0;
}
public void SetCapacityPolygonPool(int nextCount)
{
var newCap = polygonPool.Length + nextCount * 32;
var destinationArray = new PolygonData[newCap];
if (polygonPool != null)
{
Array.Copy(polygonPool, destinationArray, polygonPool.Length);
}
polygonPool = destinationArray;
polygonBuffer?.Release();
polygonBuffer = new ComputeBuffer(newCap, POLYGONDATA_STRIDE);
props.SetBuffer(PolygonBuffer, polygonBuffer);
polygonBufferIsDirty = true;
}
public int AddPolygonData(List<VectorLF3> polygon, VectorLF3[] polyn, bool clockwise) {
if (polygonCursor + polygon.Count >= polygonPool.Length) SetCapacityPolygonPool(polygon.Count);
for (var i = 0; i < polygon.Count; i++)
{
polygonPool[polygonCursor + i].pos = polygon[i];
polygonPool[polygonCursor + i].normal = polyn[i];
}
polygonBufferIsDirty = true;
var polyIndex = polygonCursor;
polygonCursor += polygon.Count;
return polyIndex;
}
public void SetCapacityShellPool(int newCap)
{
var destinationArray = new ShellData[newCap];
if (shellPool != null)
{
Array.Copy(shellPool, destinationArray, shellPool.Length);
}
shellPool = destinationArray;
shellBuffer?.Release();
shellBuffer = new ComputeBuffer(newCap, SHELLDATA_STRIDE);
props.SetBuffer(ShellBuffer, shellBuffer);
shellBufferIsDirty = true;
}
public void AddShellData(int shellId, ShellData shellData)
{
if (shellId >= shellPool.Length) SetCapacityShellPool(shellId + 16);
shellPool[shellId] = shellData;
shellBufferIsDirty = true;
}
public void SetCapacityHexProgressPool(int newCap)
{
var destinationArray = new HexProgressData[newCap];
if (hexProgressPool != null)
{
Array.Copy(hexProgressPool, destinationArray, hexProgressPool.Length);
}
hexProgressPool = destinationArray;
hexProgressBuffer?.Release();
hexProgressBuffer = new ComputeBuffer(newCap, HEXPROGRESSDATA_STRIDE);
props.SetBuffer(HexProgressBuffer, hexProgressBuffer);
hexProgressBufferIsDirty = true;
}
public void AddHexProgressData(int hexProgressIndex, HexProgressData hexProgressData)
{
if (hexProgressIndex >= hexProgressPool.Length) SetCapacityHexProgressPool(hexProgressIndex + 128);
hexProgressPool[hexProgressIndex] = hexProgressData;
hexProgressBufferIsDirty = true;
}
public void UpdateHexProgress(int shellIndex, int nodeIndex, float progress)
{
hexProgressPool[shellPool[shellIndex].progressBaseIndex + nodeIndex].progress = progress;
hexProgressBufferIsDirty = true;
}
public void SyncBufferData()
{
if (hexProgressBufferIsDirty)
{
hexProgressBuffer.SetData(hexProgressPool);
hexProgressBufferIsDirty = false;
}
if (hexBufferIsDirty)
{
if (hexBuffer == null || hexBuffer.count != hexPool.Count)
{
hexBuffer?.Release();
hexBuffer = new ComputeBuffer(hexPool.Count, HEXDATA_STRIDE);
props.SetBuffer(HexBuffer, hexBuffer);
}
hexBuffer.SetData(hexPool);
hexBufferIsDirty = false;
}
if (shellBufferIsDirty)
{
shellBuffer.SetData(shellPool);
shellBufferIsDirty = false;
}
if (polygonBufferIsDirty)
{
polygonBuffer.SetData(polygonPool);
polygonBufferIsDirty = false;
}
}
public void SetProps()
{
props.SetFloat(Radius, radius);
props.SetFloat(Scale, gridScale);
props.SetFloat(GridSize, gridSize);
props.SetFloat(CellSize, 0.94f);
props.SetFloat(LayerId, layerId);
props.SetBuffer(HexBuffer, hexBuffer);
props.SetBuffer(HexProgressBuffer, hexProgressBuffer);
props.SetBuffer(ShellBuffer, shellBuffer);
props.SetBuffer(PolygonBuffer, polygonBuffer);
}
public void RemoveDysonShell(int shellId)
{
hexPool.RemoveAll(x => x.shellIndex == shellId);
hexBufferIsDirty = true;
hexProgressBufferIsDirty = true;
var pbi = shellPool[shellId].polygonIndex;
for (int i = 0; i < shellPool[shellId].polyCount; i++)
{
polygonPool[pbi + i].pos = Vector3.zero;
polygonPool[pbi + i].normal = Vector3.zero;
}
polygonBufferIsDirty = true;
//TODO: shouldn't have to do this? leave as is?
shellPool[shellId].center = Vector3.zero;
shellPool[shellId].state = 0;
shellPool[shellId].color = 0;
shellPool[shellId].polyCount = 0;
shellPool[shellId].progressBaseIndex = 0;
shellPool[shellId].polygonIndex = 0;
shellBufferIsDirty = true;
}
public void UpdateState(int shellId, uint shellState)
{
shellPool[shellId].state = shellState;
shellBufferIsDirty = true;
}
public void UpdateColor(int shellId, Color32 shellColor)
{
shellPool[shellId].color = (shellColor.a << 24) | (shellColor.b << 16) | (shellColor.g << 8) | shellColor.r;
shellBufferIsDirty = true;
}
}
}