From 4598f9307014d602e52ad37b18c4dae887b32593 Mon Sep 17 00:00:00 2001
From: C09 <100433934+CI09@users.noreply.github.com>
Date: Sun, 10 Nov 2024 17:29:53 +0100
Subject: [PATCH 1/5] Begin implementing primitive multicellular matrix
---
src/microbe_stage/IMembraneDataSource.cs | 8 +-
src/microbe_stage/MembraneShapeGenerator.cs | 37 +++++++--
.../systems/MicrobeVisualsSystem.cs | 78 ++++++++++++++++++-
3 files changed, 114 insertions(+), 9 deletions(-)
diff --git a/src/microbe_stage/IMembraneDataSource.cs b/src/microbe_stage/IMembraneDataSource.cs
index 1a160cda79b..72065a3feba 100644
--- a/src/microbe_stage/IMembraneDataSource.cs
+++ b/src/microbe_stage/IMembraneDataSource.cs
@@ -18,14 +18,18 @@ public interface IMembraneDataSource
///
public struct MembraneGenerationParameters : IMembraneDataSource
{
- public MembraneGenerationParameters(Vector2[] hexPositions, int hexPositionCount, MembraneType type)
+ public MembraneGenerationParameters(Vector2[] hexPositions, int hexPositionCount, MembraneType type, Vector2[]? multicellularPositions, Vector2? thisCellPosition)
{
HexPositions = hexPositions;
+ MulticellularPositions = multicellularPositions;
+ CellPositionInMulticellular = thisCellPosition;
HexPositionCount = hexPositionCount;
Type = type;
}
public Vector2[] HexPositions { get; }
+ public Vector2[]? MulticellularPositions { get; }
+ public Vector2? CellPositionInMulticellular { get; }
public int HexPositionCount { get; }
public MembraneType Type { get; }
@@ -108,7 +112,7 @@ public static MembranePointData GetOrComputeMembraneShape(IReadOnlyList, which should be
/// checked for existing data before computing new data)
///
- public MembranePointData GenerateShape(Vector2[] hexPositions, int hexCount, MembraneType membraneType)
+ public MembranePointData GenerateShape(Vector2[] hexPositions, int hexCount, MembraneType membraneType,
+ Vector2[]? cellPositions, Vector2? thisCellPosition)
{
// The length in pixels (probably not accurate?) of a side of the square that bounds the membrane.
// Half the side length of the original square that is compressed to make the membrane.
@@ -109,7 +110,7 @@ public MembranePointData GenerateShape(Vector2[] hexPositions, int hexCount, Mem
// ReSharper restore PossibleLossOfFraction
// Get new membrane points for vertices2D
- GenerateMembranePoints(hexPositions, hexCount, membraneType);
+ GenerateMembranePoints(hexPositions, hexCount, membraneType, cellPositions, thisCellPosition);
// This makes a copy of the vertices so the data is safe to modify in further calls to this method
return new MembranePointData(hexPositions, hexCount, membraneType, vertices2D);
@@ -117,12 +118,13 @@ public MembranePointData GenerateShape(Vector2[] hexPositions, int hexCount, Mem
public MembranePointData GenerateShape(ref MembraneGenerationParameters parameters)
{
- return GenerateShape(parameters.HexPositions, parameters.HexPositionCount, parameters.Type);
+ return GenerateShape(parameters.HexPositions, parameters.HexPositionCount, parameters.Type,
+ parameters.MulticellularPositions, parameters.CellPositionInMulticellular);
}
public MembranePointData GenerateShape(IMembraneDataSource parameters)
{
- return GenerateShape(parameters.HexPositions, parameters.HexPositionCount, parameters.Type);
+ return GenerateShape(parameters.HexPositions, parameters.HexPositionCount, parameters.Type, null, null);
}
///
@@ -464,7 +466,8 @@ private static ArrayMesh BuildEngulfMesh(Vector2[] vertices2D, int vertexCount,
return generatedMesh;
}
- private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, MembraneType membraneType)
+ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, MembraneType membraneType,
+ Vector2[]? cellPositions, Vector2? thisCellPosition)
{
// Move all the points in the source buffer close to organelles
// This operation used to be iterative but this is now a much faster version that moves things all the way in
@@ -479,6 +482,30 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
startingBuffer[i] = closestOrganelle + movement;
}
+ // Multicellular matrix
+ if (thisCellPosition != null && cellPositions != null)
+ {
+ for (int i = 0, end = startingBuffer.Count; i < end; ++i)
+ {
+ // Make into constant unless you will forget
+ var multicellularHexDistanceMultiplier = 20;
+
+ Vector2 movement = default;
+
+ foreach (var cellPosition in cellPositions)
+ {
+ // Not normalizing due to need to keep proportions
+ var multicellularDirection = (cellPosition * multicellularHexDistanceMultiplier)
+ - (thisCellPosition * multicellularHexDistanceMultiplier + startingBuffer[i]);
+
+ if (multicellularDirection != null)
+ movement += multicellularDirection.Value;
+ }
+
+ startingBuffer[i] = startingBuffer[i] + movement;
+ }
+ }
+
float circumference = 0.0f;
for (int i = 0, end = startingBuffer.Count; i < end; ++i)
diff --git a/src/microbe_stage/systems/MicrobeVisualsSystem.cs b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
index 1e80e9b86d0..05175ccfa6f 100644
--- a/src/microbe_stage/systems/MicrobeVisualsSystem.cs
+++ b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
@@ -11,6 +11,7 @@
using DefaultEcs;
using DefaultEcs.System;
using Godot;
+using HarmonyLib;
using World = DefaultEcs.World;
///
@@ -136,8 +137,17 @@ protected override void Update(float delta, in Entity entity)
ref var materialStorage = ref entity.Get();
+ MembranePointData? data = null;
+
// Background thread membrane generation
- var data = GetMembraneDataIfReadyOrStartGenerating(ref cellProperties, ref organelleContainer);
+ if (entity.Has())
+ {
+ data = GetMulticellularMembraneDataIfReadyOrStartGenerating(ref cellProperties, ref organelleContainer, ref entity.Get());
+ }
+ else
+ {
+ data = GetMembraneDataIfReadyOrStartGenerating(ref cellProperties, ref organelleContainer);
+ }
if (data == null)
{
@@ -258,7 +268,71 @@ protected override void PostUpdate(float state)
}
}
- membranesToGenerate.Enqueue(new MembraneGenerationParameters(hexes, hexCount, cellProperties.MembraneType));
+ membranesToGenerate.Enqueue(new MembraneGenerationParameters(hexes, hexCount, cellProperties.MembraneType, null, null));
+
+ // Immediately start some jobs to give background threads something to do while the main thread is busy
+ // potentially setting up other visuals
+ StartMembraneGenerationJobs();
+
+ return null;
+ }
+
+ private MembranePointData? GetMulticellularMembraneDataIfReadyOrStartGenerating(ref CellProperties cellProperties,
+ ref OrganelleContainer organelleContainer, ref EarlyMulticellularSpeciesMember multicellular)
+ {
+ // TODO: should we consider the situation where a membrane was requested on the previous update but is not
+ // ready yet? This causes extra memory usage here in those cases.
+ var hexes = MembraneComputationHelpers.PrepareHexPositionsForMembraneCalculations(
+ organelleContainer.Organelles!.Organelles, out var hexCount);
+
+ var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType);
+
+ var cachedMembrane = ProceduralDataCache.Instance.ReadMembraneData(hash);
+
+ if (cachedMembrane != null)
+ {
+ // TODO: hopefully this can't get into a permanent loop where 2 conflicting membranes want to
+ // re-generate on each game update cycle
+ if (!cachedMembrane.MembraneDataFieldsEqual(hexes, hexCount, cellProperties.MembraneType))
+ {
+ CacheableDataExtensions.OnCacheHashCollision(hash);
+ cachedMembrane = null;
+ }
+ }
+
+ if (cachedMembrane != null)
+ {
+ // Membrane was ready now
+ return cachedMembrane;
+ }
+
+ // Need to generate a new membrane
+
+ lock (pendingGenerationsOfMembraneHashes)
+ {
+ if (!pendingGenerationsOfMembraneHashes.Add(hash))
+ {
+ // Already queued, don't need to queue again
+
+ // Return the unnecessary array that there won't be a cache entry to hold to the pool
+ ArrayPool.Shared.Return(hexes);
+
+ return null;
+ }
+ }
+
+ List positions = new List();
+
+ foreach (var cell in multicellular.Species.Cells)
+ {
+ var cartesian = Hex.AxialToCartesian(cell.Position);
+ positions.AddItem(new Vector2(cartesian.X, cartesian.Z));
+ }
+
+ var thisCartesian = Hex.AxialToCartesian(multicellular.Species.Cells[multicellular.MulticellularBodyPlanPartIndex].Position);
+ var thisVector2 = new Vector2(thisCartesian.X, thisCartesian.Z);
+
+ membranesToGenerate.Enqueue(new MembraneGenerationParameters(hexes, hexCount, cellProperties.MembraneType, positions.ToArray(), thisVector2));
// Immediately start some jobs to give background threads something to do while the main thread is busy
// potentially setting up other visuals
From 710b2258732c4ecbeb9cbb5e79e46eee11383fbb Mon Sep 17 00:00:00 2001
From: C09 <100433934+CI09@users.noreply.github.com>
Date: Mon, 11 Nov 2024 15:14:17 +0100
Subject: [PATCH 2/5] Attempt at fixing constant membrane re-generation
---
src/microbe_stage/IMembraneDataSource.cs | 22 ++++++++++++++--
src/microbe_stage/MembranePointData.cs | 8 +++++-
src/microbe_stage/MembraneShapeGenerator.cs | 10 ++++---
.../systems/MicrobeVisualsSystem.cs | 26 +++++++++++--------
4 files changed, 48 insertions(+), 18 deletions(-)
diff --git a/src/microbe_stage/IMembraneDataSource.cs b/src/microbe_stage/IMembraneDataSource.cs
index 72065a3feba..8bd5cf952cf 100644
--- a/src/microbe_stage/IMembraneDataSource.cs
+++ b/src/microbe_stage/IMembraneDataSource.cs
@@ -9,6 +9,9 @@
public interface IMembraneDataSource
{
public Vector2[] HexPositions { get; }
+
+ public Vector2[]? MulticellularPositions { get; }
+
public int HexPositionCount { get; }
public MembraneType Type { get; }
}
@@ -150,11 +153,11 @@ public static long ComputeMembraneDataHash(this IMembraneDataSource dataSource)
public static bool MembraneDataFieldsEqual(this IMembraneDataSource dataSource, IMembraneDataSource other)
{
- return dataSource.MembraneDataFieldsEqual(other.HexPositions, other.HexPositionCount, other.Type);
+ return dataSource.MembraneDataFieldsEqual(other.HexPositions, other.HexPositionCount, other.Type, other.MulticellularPositions);
}
public static bool MembraneDataFieldsEqual(this IMembraneDataSource dataSource, Vector2[] otherPoints,
- int otherPointCount, MembraneType otherType)
+ int otherPointCount, MembraneType otherType, Vector2[]? multicellularPositions)
{
if (!dataSource.Type.Equals(otherType))
return false;
@@ -166,6 +169,21 @@ public static bool MembraneDataFieldsEqual(this IMembraneDataSource dataSource,
var sourcePoints = dataSource.HexPositions;
+ if (dataSource.MulticellularPositions != null)
+ {
+ if (!dataSource.MulticellularPositions.Equals(multicellularPositions))
+ {
+ return false;
+ }
+ GD.Print("elo");
+ }
+ else
+ {
+ if (multicellularPositions != null)
+ return false;
+ GD.Print("olelo");
+ }
+
for (int i = 0; i < count; ++i)
{
if (sourcePoints[i] != otherPoints[i])
diff --git a/src/microbe_stage/MembranePointData.cs b/src/microbe_stage/MembranePointData.cs
index 65da4bad70a..238176bb14c 100644
--- a/src/microbe_stage/MembranePointData.cs
+++ b/src/microbe_stage/MembranePointData.cs
@@ -23,11 +23,12 @@ public sealed class MembranePointData : IMembraneDataSource, ICacheableData
private bool disposed;
public MembranePointData(Vector2[] hexPositions, int hexPositionCount, MembraneType type,
- IReadOnlyList verticesToCopy)
+ IReadOnlyList verticesToCopy, Vector2[]? multicellularPositions)
{
HexPositions = hexPositions;
Type = type;
HexPositionCount = hexPositionCount;
+ MulticellularPositions = multicellularPositions;
// Setup mesh to be generated (on the main thread) only when required
finalMesh = new Lazy<(ArrayMesh Mesh, int SurfaceIndex)>(() =>
@@ -82,6 +83,11 @@ public MembranePointData(Vector2[] hexPositions, int hexPositionCount, MembraneT
///
public Vector2[] HexPositions { get; }
+ ///
+ /// Positions of other cells in multicellular organism
+ ///
+ public Vector2[]? MulticellularPositions { get; }
+
public int HexPositionCount { get; }
public MembraneType Type { get; }
diff --git a/src/microbe_stage/MembraneShapeGenerator.cs b/src/microbe_stage/MembraneShapeGenerator.cs
index e5a545fa83c..555d72e546b 100644
--- a/src/microbe_stage/MembraneShapeGenerator.cs
+++ b/src/microbe_stage/MembraneShapeGenerator.cs
@@ -112,8 +112,10 @@ public MembranePointData GenerateShape(Vector2[] hexPositions, int hexCount, Mem
// Get new membrane points for vertices2D
GenerateMembranePoints(hexPositions, hexCount, membraneType, cellPositions, thisCellPosition);
+ GD.Print(cellPositions == null);
+
// This makes a copy of the vertices so the data is safe to modify in further calls to this method
- return new MembranePointData(hexPositions, hexCount, membraneType, vertices2D);
+ return new MembranePointData(hexPositions, hexCount, membraneType, vertices2D, cellPositions);
}
public MembranePointData GenerateShape(ref MembraneGenerationParameters parameters)
@@ -483,12 +485,12 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
}
// Multicellular matrix
- if (thisCellPosition != null && cellPositions != null)
+ /*if (thisCellPosition != null && cellPositions != null)
{
for (int i = 0, end = startingBuffer.Count; i < end; ++i)
{
// Make into constant unless you will forget
- var multicellularHexDistanceMultiplier = 20;
+ var multicellularHexDistanceMultiplier = 1;
Vector2 movement = default;
@@ -504,7 +506,7 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
startingBuffer[i] = startingBuffer[i] + movement;
}
- }
+ }*/
float circumference = 0.0f;
diff --git a/src/microbe_stage/systems/MicrobeVisualsSystem.cs b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
index 05175ccfa6f..7c1d019181d 100644
--- a/src/microbe_stage/systems/MicrobeVisualsSystem.cs
+++ b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
@@ -240,7 +240,7 @@ protected override void PostUpdate(float state)
{
// TODO: hopefully this can't get into a permanent loop where 2 conflicting membranes want to
// re-generate on each game update cycle
- if (!cachedMembrane.MembraneDataFieldsEqual(hexes, hexCount, cellProperties.MembraneType))
+ if (!cachedMembrane.MembraneDataFieldsEqual(hexes, hexCount, cellProperties.MembraneType, null))
{
CacheableDataExtensions.OnCacheHashCollision(hash);
cachedMembrane = null;
@@ -285,6 +285,16 @@ protected override void PostUpdate(float state)
var hexes = MembraneComputationHelpers.PrepareHexPositionsForMembraneCalculations(
organelleContainer.Organelles!.Organelles, out var hexCount);
+ List positions = new List();
+
+ foreach (var cell in multicellular.Species.Cells)
+ {
+ var cartesian = Hex.AxialToCartesian(cell.Position);
+ positions.AddItem(new Vector2(cartesian.X, cartesian.Z));
+ }
+
+ var positionsArray = positions.ToArray();
+
var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType);
var cachedMembrane = ProceduralDataCache.Instance.ReadMembraneData(hash);
@@ -293,10 +303,12 @@ protected override void PostUpdate(float state)
{
// TODO: hopefully this can't get into a permanent loop where 2 conflicting membranes want to
// re-generate on each game update cycle
- if (!cachedMembrane.MembraneDataFieldsEqual(hexes, hexCount, cellProperties.MembraneType))
+ if (!cachedMembrane.MembraneDataFieldsEqual(hexes, hexCount, cellProperties.MembraneType, positionsArray))
{
CacheableDataExtensions.OnCacheHashCollision(hash);
cachedMembrane = null;
+
+ GD.Print("uhm");
}
}
@@ -321,18 +333,10 @@ protected override void PostUpdate(float state)
}
}
- List positions = new List();
-
- foreach (var cell in multicellular.Species.Cells)
- {
- var cartesian = Hex.AxialToCartesian(cell.Position);
- positions.AddItem(new Vector2(cartesian.X, cartesian.Z));
- }
-
var thisCartesian = Hex.AxialToCartesian(multicellular.Species.Cells[multicellular.MulticellularBodyPlanPartIndex].Position);
var thisVector2 = new Vector2(thisCartesian.X, thisCartesian.Z);
- membranesToGenerate.Enqueue(new MembraneGenerationParameters(hexes, hexCount, cellProperties.MembraneType, positions.ToArray(), thisVector2));
+ membranesToGenerate.Enqueue(new MembraneGenerationParameters(hexes, hexCount, cellProperties.MembraneType, positionsArray, thisVector2));
// Immediately start some jobs to give background threads something to do while the main thread is busy
// potentially setting up other visuals
From fc34db9edd999c25afc7a8fa86a3acc994bfd477 Mon Sep 17 00:00:00 2001
From: C09 <100433934+CI09@users.noreply.github.com>
Date: Wed, 13 Nov 2024 18:33:05 +0100
Subject: [PATCH 3/5] Make multicellular matrix data flow work
---
src/microbe_stage/IMembraneDataSource.cs | 21 ++++++++++------
src/microbe_stage/MembraneShapeGenerator.cs | 25 ++++++++-----------
.../systems/MicrobeVisualsSystem.cs | 8 +++---
3 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/src/microbe_stage/IMembraneDataSource.cs b/src/microbe_stage/IMembraneDataSource.cs
index 8bd5cf952cf..9cca39bb36c 100644
--- a/src/microbe_stage/IMembraneDataSource.cs
+++ b/src/microbe_stage/IMembraneDataSource.cs
@@ -1,6 +1,7 @@
using System;
using System.Buffers;
using System.Collections.Generic;
+using System.Linq;
using Godot;
///
@@ -96,7 +97,7 @@ public static MembranePointData GetOrComputeMembraneShape(IReadOnlyList 0);
}
public static bool MembraneDataFieldsEqual(this IMembraneDataSource dataSource, IMembraneDataSource other)
@@ -171,17 +174,21 @@ public static bool MembraneDataFieldsEqual(this IMembraneDataSource dataSource,
if (dataSource.MulticellularPositions != null)
{
- if (!dataSource.MulticellularPositions.Equals(multicellularPositions))
+ if (multicellularPositions == null)
+ return false;
+
+ if (!dataSource.MulticellularPositions.SequenceEqual(multicellularPositions))
{
return false;
}
- GD.Print("elo");
}
else
{
if (multicellularPositions != null)
+ {
return false;
- GD.Print("olelo");
+
+ }
}
for (int i = 0; i < count; ++i)
diff --git a/src/microbe_stage/MembraneShapeGenerator.cs b/src/microbe_stage/MembraneShapeGenerator.cs
index 555d72e546b..9dc7e95b25f 100644
--- a/src/microbe_stage/MembraneShapeGenerator.cs
+++ b/src/microbe_stage/MembraneShapeGenerator.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using Godot;
using Array = Godot.Collections.Array;
@@ -485,28 +486,24 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
}
// Multicellular matrix
- /*if (thisCellPosition != null && cellPositions != null)
+ if (thisCellPosition != null && cellPositions != null)
{
+ // Make into constant unless you will forget
+ var multicellularHexDistanceMultiplier = 10f;
+
+
+
for (int i = 0, end = startingBuffer.Count; i < end; ++i)
{
- // Make into constant unless you will forget
- var multicellularHexDistanceMultiplier = 1;
+
- Vector2 movement = default;
+ var movement = thisCellPosition.Value;
- foreach (var cellPosition in cellPositions)
- {
- // Not normalizing due to need to keep proportions
- var multicellularDirection = (cellPosition * multicellularHexDistanceMultiplier)
- - (thisCellPosition * multicellularHexDistanceMultiplier + startingBuffer[i]);
-
- if (multicellularDirection != null)
- movement += multicellularDirection.Value;
- }
+ GD.Print(movement);
startingBuffer[i] = startingBuffer[i] + movement;
}
- }*/
+ }
float circumference = 0.0f;
diff --git a/src/microbe_stage/systems/MicrobeVisualsSystem.cs b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
index 7c1d019181d..932a968a603 100644
--- a/src/microbe_stage/systems/MicrobeVisualsSystem.cs
+++ b/src/microbe_stage/systems/MicrobeVisualsSystem.cs
@@ -232,7 +232,7 @@ protected override void PostUpdate(float state)
var hexes = MembraneComputationHelpers.PrepareHexPositionsForMembraneCalculations(
organelleContainer.Organelles!.Organelles, out var hexCount);
- var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType);
+ var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType, false);
var cachedMembrane = ProceduralDataCache.Instance.ReadMembraneData(hash);
@@ -290,12 +290,12 @@ protected override void PostUpdate(float state)
foreach (var cell in multicellular.Species.Cells)
{
var cartesian = Hex.AxialToCartesian(cell.Position);
- positions.AddItem(new Vector2(cartesian.X, cartesian.Z));
+ positions.Add(new Vector2(cartesian.X, cartesian.Z));
}
var positionsArray = positions.ToArray();
- var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType);
+ var hash = MembraneComputationHelpers.ComputeMembraneDataHash(hexes, hexCount, cellProperties.MembraneType, true);
var cachedMembrane = ProceduralDataCache.Instance.ReadMembraneData(hash);
@@ -307,8 +307,6 @@ protected override void PostUpdate(float state)
{
CacheableDataExtensions.OnCacheHashCollision(hash);
cachedMembrane = null;
-
- GD.Print("uhm");
}
}
From b94ded6b1f2f3d2a033a4dbe72c354c3622ca329 Mon Sep 17 00:00:00 2001
From: dligr
Date: Sat, 16 Nov 2024 16:49:47 +0300
Subject: [PATCH 4/5] Project membrane vertices onto Voronoi edges
---
src/microbe_stage/MembraneShapeGenerator.cs | 77 +++++++++++++++------
1 file changed, 57 insertions(+), 20 deletions(-)
diff --git a/src/microbe_stage/MembraneShapeGenerator.cs b/src/microbe_stage/MembraneShapeGenerator.cs
index 9dc7e95b25f..d5d7b4302b0 100644
--- a/src/microbe_stage/MembraneShapeGenerator.cs
+++ b/src/microbe_stage/MembraneShapeGenerator.cs
@@ -485,26 +485,6 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
startingBuffer[i] = closestOrganelle + movement;
}
- // Multicellular matrix
- if (thisCellPosition != null && cellPositions != null)
- {
- // Make into constant unless you will forget
- var multicellularHexDistanceMultiplier = 10f;
-
-
-
- for (int i = 0, end = startingBuffer.Count; i < end; ++i)
- {
-
-
- var movement = thisCellPosition.Value;
-
- GD.Print(movement);
-
- startingBuffer[i] = startingBuffer[i] + movement;
- }
- }
-
float circumference = 0.0f;
for (int i = 0, end = startingBuffer.Count; i < end; ++i)
@@ -576,5 +556,62 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
vertices2D[i] = point + movement;
}
+
+ var average = Vector2.Zero;
+
+ foreach (var vertex in vertices2D)
+ {
+ average += vertex;
+ }
+
+ average /= vertices2D.Count;
+
+ // Multicellular matrix
+ if (thisCellPosition != null && cellPositions != null)
+ {
+ // Make into constant unless you will forget
+ var multicellularHexDistanceMultiplier = 10f;
+
+ for (int i = 0; i < vertices2D.Count; ++i)
+ {
+ var relativeVertex = vertices2D[i] - average;
+
+ float minMultiplier = float.MaxValue;
+
+ foreach (var cellPos in cellPositions)
+ {
+ if (cellPos == thisCellPosition)
+ continue;
+
+ // Coordinates of such a point on the Voronoi edge, that a line from the cell's center to this
+ // point is perpendicular to the edge.
+ var edge = (cellPos + thisCellPosition.Value) * 0.5f;
+
+ var relativeEdge = (edge - thisCellPosition.Value) * 2.0f;
+
+ float dotProduct = relativeVertex.Dot(relativeEdge);
+
+ // If the dotproduct is less that this (arbitrary) value, then this edge faces away
+ // from our vertex, so it doesn't need to be considered
+ if (dotProduct <= 0.5f)
+ continue;
+
+ // The vertex pos, when multiplied by this, should be placed at the edge
+ float multiplier = relativeEdge.LengthSquared() / dotProduct;
+
+ if (multiplier < minMultiplier)
+ minMultiplier = multiplier;
+ }
+
+ vertices2D[i] = average + relativeVertex * minMultiplier;
+ }
+
+ for (int i = 0, end = startingBuffer.Count; i < end; ++i)
+ {
+ var movement = thisCellPosition.Value;
+
+ startingBuffer[i] = startingBuffer[i] + movement;
+ }
+ }
}
}
From 06d2cdbceb0f4c9c67754e1cacf423eb0681ee2c Mon Sep 17 00:00:00 2001
From: dligr
Date: Sat, 16 Nov 2024 20:54:04 +0300
Subject: [PATCH 5/5] Fix wrong projection
---
src/microbe_stage/MembraneShapeGenerator.cs | 23 ++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/microbe_stage/MembraneShapeGenerator.cs b/src/microbe_stage/MembraneShapeGenerator.cs
index d5d7b4302b0..6087a7c6634 100644
--- a/src/microbe_stage/MembraneShapeGenerator.cs
+++ b/src/microbe_stage/MembraneShapeGenerator.cs
@@ -570,12 +570,13 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
if (thisCellPosition != null && cellPositions != null)
{
// Make into constant unless you will forget
- var multicellularHexDistanceMultiplier = 10f;
+ var verticeDistanceMultiplier = 0.8f;
for (int i = 0; i < vertices2D.Count; ++i)
{
var relativeVertex = vertices2D[i] - average;
+ bool facesAnEdge = false;
float minMultiplier = float.MaxValue;
foreach (var cellPos in cellPositions)
@@ -591,19 +592,31 @@ private void GenerateMembranePoints(Vector2[] hexPositions, int hexCount, Membra
float dotProduct = relativeVertex.Dot(relativeEdge);
- // If the dotproduct is less that this (arbitrary) value, then this edge faces away
- // from our vertex, so it doesn't need to be considered
- if (dotProduct <= 0.5f)
+ // If the dotproduct is less that this value, then this edge faces a direction different
+ // than that of the vertex, so it doesn't need to be considered
+ if (dotProduct <= 0.0f)
continue;
// The vertex pos, when multiplied by this, should be placed at the edge
float multiplier = relativeEdge.LengthSquared() / dotProduct;
if (multiplier < minMultiplier)
+ {
minMultiplier = multiplier;
+ facesAnEdge = true;
+ }
}
- vertices2D[i] = average + relativeVertex * minMultiplier;
+ if (!facesAnEdge)
+ {
+ minMultiplier = 1.0f;
+ }
+ else if (minMultiplier > 3.0f)
+ {
+ minMultiplier = 1.0f;
+ }
+
+ vertices2D[i] = average + relativeVertex * minMultiplier * verticeDistanceMultiplier;
}
for (int i = 0, end = startingBuffer.Count; i < end; ++i)