Skip to content

Commit 818cc09

Browse files
authored
Merge pull request #107 from Nytra/metaballsUpdates
Improve performance of metaballs
2 parents 46fcef0 + 7be45ef commit 818cc09

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

ProjectObsidian/Components/Mesh/MetaballMesh.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Elements.Core;
33
using FrooxEngine;
44
using System.Collections.Generic;
5+
using System.Linq;
56

67
namespace Obsidian
78
{
@@ -17,6 +18,8 @@ public class MetaballMesh : ProceduralMesh
1718
private float3 _fieldSize;
1819
private int _resolution;
1920
private List<MetaballPoint> _subscribedPoints = new();
21+
private List<MetaballPoint> _subscribedPointsCopy;
22+
private bool _scheduleRangeDatasRecompute;
2023
protected override void OnStart()
2124
{
2225
Points.Changed += OnListChange;
@@ -30,6 +33,7 @@ protected override void OnStart()
3033
_subscribedPoints.Add(point);
3134
}
3235
}
36+
_scheduleRangeDatasRecompute = true;
3337
}
3438

3539
protected override void OnAwake()
@@ -58,21 +62,25 @@ private void OnListChange(IChangeable change)
5862
_subscribedPoints.Add(point);
5963
}
6064
}
65+
_scheduleRangeDatasRecompute = true;
6166
MarkChangeDirty();
6267
}
6368

6469
private void OnPointChange(IChangeable change)
6570
{
71+
_scheduleRangeDatasRecompute = true;
6672
MarkChangeDirty();
6773
}
6874

6975
private void OnPointDestroyed(IDestroyable destroy)
7076
{
77+
_scheduleRangeDatasRecompute = true;
7178
MarkChangeDirty();
7279
}
7380

7481
private void OnWorldTransformChanged(Slot s)
7582
{
83+
_scheduleRangeDatasRecompute = true;
7684
MarkChangeDirty();
7785
}
7886

@@ -81,6 +89,7 @@ protected override void PrepareAssetUpdateData()
8189
_threshold = Threshold.Value;
8290
_fieldSize = FieldSize.Value;
8391
_resolution = Resolution.Value;
92+
_subscribedPointsCopy = _subscribedPoints.ToList();
8493
}
8594

8695
protected override void ClearMeshData()
@@ -96,11 +105,13 @@ protected override void UpdateMeshData(MeshX meshx)
96105
shape = new MetaballShape(meshx);
97106
}
98107

99-
shape.Points = _subscribedPoints;
108+
shape.Points = _subscribedPointsCopy;
100109
shape.OriginSlot = Slot;
101110
shape.Threshold = _threshold;
102111
shape.FieldSize = _fieldSize;
103112
shape.Resolution = _resolution;
113+
shape.scheduleRangeDatasRecompute = _scheduleRangeDatasRecompute;
114+
_scheduleRangeDatasRecompute = false;
104115

105116
meshx.Clear();
106117
shape.Update();

ProjectObsidian/Components/Mesh/MetaballShape.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,50 @@ public class MetaballShape : MeshXShape
1919

2020
private int vertIndex;
2121

22+
public bool scheduleRangeDatasRecompute;
23+
24+
private class RangeData
25+
{
26+
public float effectiveRange;
27+
public float3 position;
28+
}
29+
30+
private List<RangeData> rangeDatas = new();
31+
2232
public MetaballShape(MeshX mesh) : base(mesh)
2333
{
2434
}
2535

36+
private void ComputeRangeData()
37+
{
38+
if (rangeDatas.Count != Points.Count)
39+
{
40+
rangeDatas.Clear();
41+
for (int i = 0; i < Points.Count; i++)
42+
rangeDatas.Add(new RangeData());
43+
}
44+
int j = 0;
45+
foreach (var point in Points) // reading from data model here might be bad?
46+
{
47+
var data = rangeDatas[j];
48+
if (point == null || point.IsRemoved)
49+
{
50+
data.effectiveRange = 0;
51+
}
52+
else
53+
{
54+
data.effectiveRange = point.Radius.Value + point.Strength.Value; // this formula may need tweaking?
55+
data.position = OriginSlot.GlobalPointToLocal(point.Slot.GlobalPosition);
56+
}
57+
j++;
58+
}
59+
scheduleRangeDatasRecompute = false;
60+
}
61+
2662
public float SampleField(float3 point)
2763
{
2864
float value = 0;
29-
foreach (var metaball in Points)
65+
foreach (var metaball in Points) // reading from data model here might be bad?
3066
{
3167
if (metaball == null || metaball.IsRemoved) continue;
3268
value += metaball.GetValue(point, OriginSlot);
@@ -149,6 +185,10 @@ private float3 InterpolateVertex(float3[] corners, float[] values, int edgeIndex
149185

150186
private void Generate(MeshX mesh)
151187
{
188+
// might be better to do this in PrepareAssetUpdateData?
189+
if (scheduleRangeDatasRecompute)
190+
ComputeRangeData();
191+
152192
float3 step = FieldSize / Resolution;
153193

154194
for (int x = 0; x < Resolution - 1; x++)
@@ -158,6 +198,19 @@ private void Generate(MeshX mesh)
158198
for (int z = 0; z < Resolution - 1; z++)
159199
{
160200
float3 cubePos = new float3(x, y, z) * step - FieldSize * 0.5f;
201+
202+
bool anyIn = false;
203+
foreach (var rangeData in rangeDatas)
204+
{
205+
if (rangeData.effectiveRange == 0) continue;
206+
if (MathX.DistanceSqr(cubePos, rangeData.position) < MathX.Pow(rangeData.effectiveRange, 2f))
207+
{
208+
anyIn = true;
209+
break;
210+
}
211+
}
212+
if (!anyIn) continue;
213+
161214
MarchCube(cubePos, step);
162215
}
163216
}

0 commit comments

Comments
 (0)