Advertisement
JontePonte

sim draft

Nov 19th, 2024
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.42 KB | None | 0 0
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using TMPro;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.VisualScripting;
  8. using UnityEngine;
  9. using UnityEngine.Profiling;
  10. using Unity.Mathematics;
  11. using UnityEngine.Serialization;
  12. using Debug = UnityEngine.Debug;
  13. using Random = UnityEngine.Random;
  14.  
  15. public class Simulation : MonoBehaviour
  16. {
  17.     public struct Particle
  18.     {
  19.         public float2 position, velocity;
  20.         public float mass;
  21.         public Color color;
  22.     }
  23.     public int particleCount;
  24.     public float radius;
  25.     public float mass;
  26.     public float timeScale;
  27.     [Range(1, 2)]
  28.     public float centerConcentration;
  29.     public float galaxySize;
  30.     public Gradient velocityGradient;
  31.    
  32.     [Range(0, 1)] public float approximationThreshold;
  33.     [Range(0, 1)] public float approximationSmoothing;
  34.     public int treeSize;
  35.  
  36.     [Header("")]
  37.     public bool centerAttraction;
  38.     public float centerMass;
  39.  
  40.     public float particleForce;
  41.  
  42.     public Material material;
  43.  
  44.     NativeArray<Particle> particles;
  45.     NativeArray<Particle> renderParticles;
  46.     QuadTree quadTree;
  47.     new ParticleRenderer renderer;
  48.     Particle center;
  49.     TextMeshProUGUI latency;
  50.     System.Random random;
  51.     NativeArray<Color> sampledGradient;
  52.     QuadTree[,] trees;
  53.  
  54.     JobHandle handle;
  55.  
  56.     public static int HalfScreenSize = 7;
  57.  
  58.     void Start()
  59.     {
  60.         center = new Particle
  61.         {
  62.             position = Vector2.zero,
  63.             velocity = Vector2.zero,
  64.             mass = centerMass
  65.         };
  66.        
  67.         random = new System.Random(0);
  68.         particles = new NativeArray<Particle>(particleCount + 1, Allocator.Persistent);
  69.         renderParticles = new NativeArray<Particle>(particleCount + 1, Allocator.Persistent);
  70.         particles[0] = center;
  71.         trees = new QuadTree[treeSize, treeSize];
  72.         sampledGradient = SampleGradient(velocityGradient, 256);
  73.  
  74.         for (int i = 1; i < particleCount; i++)
  75.         {
  76.             particles[i] = ParticlePositionAndVelocity();
  77.         }
  78.  
  79.         //latency = GameObject.Find("Latency").GetComponent<TextMeshProUGUI>();
  80.         renderer = new(particles, material, radius);
  81.         quadTree = new();
  82.     }
  83.  
  84.     Particle ParticlePositionAndVelocity()
  85.     {
  86.         Particle particle;
  87.         while (true)
  88.         {
  89.             // Generate radius using a quadratic distribution for higher central density
  90.             float radius = Mathf.Pow(Random.value, centerConcentration) * galaxySize; // Adjust power for density control
  91.             float angle = Random.Range(0f, Mathf.PI * 2f); // Uniform angle
  92.  
  93.             // Convert polar coordinates to Cartesian
  94.             Vector2 pos = new Vector2(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle));
  95.             float centerDist = pos.magnitude;
  96.  
  97.             // Calculate circular orbit velocity
  98.             float force = Mathf.Sqrt(centerMass / centerDist) * particleForce;
  99.             Vector2 tangentDirection = new Vector2(-pos.y, pos.x).normalized; // Tangential direction
  100.             Vector2 velocity = tangentDirection * force;
  101.  
  102.             // Skip if position is too close to the center to avoid instabilities
  103.             float noise = Mathf.PerlinNoise((pos.x + 1000) * 4, (pos.y + 1000) * 4);
  104.             if (centerDist > 0.2f && (noise > .8f || random.NextDouble() < .1f))
  105.             {
  106.                 particle = new Particle
  107.                 {
  108.                     position = pos,
  109.                     velocity = velocity,
  110.                     mass = mass,
  111.                     color = velocityGradient.Evaluate(noise + 1 - centerDist / galaxySize)
  112.                 };
  113.                 break;
  114.             }
  115.         }
  116.  
  117.         return particle;
  118.     }
  119.    
  120.     void FixedUpdate()
  121.     {
  122.         float startTime = Time.realtimeSinceStartup;
  123.        
  124.         handle.Complete();
  125.         Profiler.BeginSample("UpdatePositions");
  126.         UpdatePositions(Time.fixedDeltaTime * timeScale);
  127.         Profiler.EndSample();
  128.         for (int i = 0; i < particles.Length; i++)
  129.         {
  130.             renderParticles[i] = particles[i];
  131.         }
  132.         RebuildQuadTree();
  133.         ScheduleAccelerationJob(Time.fixedDeltaTime * timeScale);
  134.  
  135.         //latency.text = Mathf.RoundToInt(Time.realtimeSinceStartup - startTime) * 1000f + " ms";
  136.     }
  137.  
  138.     void Update()
  139.     {
  140.         renderer.Render(renderParticles);
  141.     }
  142.  
  143.     void OnDestroy()
  144.     {
  145.         handle.Complete();
  146.         renderer.ReleaseBuffers();
  147.         particles.Dispose();
  148.         renderParticles.Dispose();
  149.         sampledGradient.Dispose();
  150.     }
  151.  
  152.     void RebuildQuadTree()
  153.     {
  154.         quadTree = new();
  155.         Profiler.BeginSample("Insert");
  156.         InsertJob job = new()
  157.         {
  158.             particles = particles,
  159.             nodes = quadTree.nodes
  160.         };
  161.         job.Schedule().Complete();
  162.         Profiler.EndSample();
  163.         Profiler.BeginSample("Propagate");
  164.         quadTree.Propagate();
  165.         Profiler.EndSample();
  166.     }
  167.  
  168.     void ScheduleAccelerationJob(float deltaTime)
  169.     {
  170.         AccelerationJob job = new()
  171.         {
  172.             nodes = quadTree.nodes,
  173.             particles = particles,
  174.             theta = approximationThreshold,
  175.             epsilon = approximationSmoothing,
  176.             deltaTime = deltaTime
  177.         };
  178.         handle = job.Schedule(particles.Length, 64);
  179.     }
  180.    
  181.     void UpdatePositions(float deltaTime)
  182.     {
  183.         float minPosX = -HalfScreenSize + radius;
  184.         float maxPosX = HalfScreenSize - radius;
  185.         float minPosY = -HalfScreenSize + radius;
  186.         float maxPosY = HalfScreenSize - radius;
  187.  
  188.         UpdateParticlesJob job = new()
  189.         {
  190.             particles = particles,
  191.             gradient = sampledGradient,
  192.             gradientResolution = sampledGradient.Length,
  193.             deltaTime = deltaTime,
  194.             minPosX = minPosX,
  195.             maxPosX = maxPosX,
  196.             minPosY = minPosY,
  197.             maxPosY = maxPosY,
  198.             rng = new Unity.Mathematics.Random(1)
  199.         };
  200.         job.Schedule(particles.Length, 64).Complete();
  201.     }
  202.    
  203.     NativeArray<Color> SampleGradient(Gradient gradient, int resolution)
  204.     {
  205.         NativeArray<Color> gradientArray = new(resolution, Allocator.Persistent);
  206.  
  207.         for (int i = 0; i < resolution; i++)
  208.         {
  209.             gradientArray[i] = gradient.Evaluate((float)i / resolution);
  210.         }
  211.  
  212.         return gradientArray;
  213.     }
  214. }
  215.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement