Membrane stretch#7084
Conversation
Smoothing
|
The lead programmer for Thrive is currently on vacation until 2026-07-13. Until then other programmers will try to make pull request reviews, but please be patient if your PR is not getting reviewed. PRs may be merged after multiple programmers have approved the changes (especially making sure to ensure style guide conformance and gameplay testing are good). If there are no active experienced programmers who can perform merges, PRs may need to wait until the lead programmer is back to be merged. |
|
Is this still experimental or, should this be marked as a draft or is this ready for review? |
| { | ||
| public Vector2[] HexPositions { get; } | ||
| public int HexPositionCount { get; } | ||
| public Vector2[]? MulticellularPositions { get; } |
There was a problem hiding this comment.
Adding all of this extra data makes this a ton heavier, enough so that I fear for the efficiency of the overall design being able to handle things...
There was a problem hiding this comment.
What exactly do you mean by "being able to handle things"? I unfortunatelly need all of this data to make good membrane stretch generation. What would you propose here instead?
There was a problem hiding this comment.
The way I made the hashing and finding stuff is that I bedgrudginly accepted that the game has to hash the full list of positions, and that works fine now. But this PR increases the amount of hashing effort 5x, and makes membranes unique based on colony position, meaning that the overall caching system for membranes might not even make sense. So by adding a lot of heavy weight to the membrane caching system might hinder it so much that the entire concept needs to be rethought.
I suggested a few things to try to make it lighter (by using a single list, and only verifying some properties), but there might be a fundamental limit that causes problems with doing so much new stuff in the membrane caching and generation.
its ready for review |
| continue; | ||
|
|
||
| var cell = multicellular.Species.ModifiableGameplayCells[i]; | ||
| var cellPosistion = Hex.AxialToCartesian(cell.Position); |
There was a problem hiding this comment.
| var cellPosistion = Hex.AxialToCartesian(cell.Position); | |
| var cellPosition = Hex.AxialToCartesian(cell.Position); |
Typo
| var positionsArray = cellsPositions.ToArray(); | ||
| var rotationsArray = cellsOrientations.ToArray(); |
There was a problem hiding this comment.
For memory efficiency, these should absolutely be avoided.
If temporary memory is needed I think these should use array buffer renting.
Or having read the generation request data, I think we should have just a single array with structs in it and those structs then would hold all data related to the other cells rather than spreading it across like 5 or so arrays as they are currently.
There was a problem hiding this comment.
I guess that also applies to the dictionaries with lists as values, right?
I dont quite understand what you mean by array with structs in it - why structs would be better in this case then classes? they would constantly be copied across all the method calls, wouldn't they?
Anyway, I will try to improve it, either using the arrayPool or somehow implementing the struct concept
There was a problem hiding this comment.
I guess that also applies to the dictionaries with lists as values, right?
Yes.
I dont quite understand what you mean by array with structs in it - why structs would be better in this case then classes? they would constantly be copied across all the method calls, wouldn't they?
In C# structs are value types, which means that ArrayStruct[] and List<ArrayStruct> both allocate only one continuous segment of memory. Whereas a list of class objects first allocates the list memory and then each class separately this causes memory fragmentation and major slowdown as the CPU prefetch doesn't work. So a list of classes is a memory performance nightmare in comparison to an array. Even better would be being able to rent arrays from the global array buffer and only needing to not return the array when actually generating a new membrane, this would take most of the load off from using a cached copy of data.
Anyway, I will try to improve it, either using the arrayPool or somehow implementing the struct concept
Yes, I think this would be a very key optimization.
I thought about using stackalloc originally but I couldn't figure out a way to use it because when you fill it and hash it, and find out that the membrane is not cached, then you need to make a second array you can actually give to the membrane generation object. So if our cache hit rate is low the extra copy from the stackalloc array to the array that can be given to the membrane object to hold, will be a major performance drain (and stackalloc wouldn't help), but I haven't extensively tested so I'm not actually sure if this problem is real.
|
|
||
| var sourcePoints = dataSource.HexPositions; | ||
|
|
||
| if (dataSource.MulticellularPositions != null || multicellularPositions != null) |
There was a problem hiding this comment.
This looks quite bad in terms of new performance drain, so I would only keep the most important comparison and put all else behind a #if DEBUG condition check to still help catch bugs but not eat up runtime performance for players.
Brief Description of What This PR Does
Extends membrane in multicellular colonies to other cell neighbours.
Membrane is generated in 2 passes - first normally like for single cell expect without applying membrane waviness. Then in the second pass, which is currently performed on a single thread, gets cells neighbours.,calculates the position of middle point between these cell, creates tangent lines to the cell coming from that point and casts vertices onto these lines checking if the are not accidentally inside other neighbours' membrane. After that a smoothing is applied.
Note: membrane stretching in a colony is sequential for each cell, not asynchronous. It's because it needs other cells' membranes (both original and stretched) to avoid overlaps. Also during calculations both current and neighbours membranes are modified to avoid cases where one cell's vertices are modified and second's not because of overlaps. The code makes sure that either both stretch or none do.
Unfortunately there are list allocations for rotated and shifted neighbours vertices. Maybe I should use array pool there?
Related Issues
Progress Checklist
Note: before starting this checklist the PR should be marked as non-draft.
break existing features:
https://wiki.revolutionarygamesstudio.com/wiki/Testing_Checklist
(this is important as to not waste the time of Thrive team
members reviewing this PR). This includes gameplay testing by the PR author.
styleguide.
Before merging all CI jobs should finish on this PR without errors, if
there are automatically detected style issues they should be fixed by
the PR author. Merging must follow our
styleguide.