public void ResetTrails(bool forceReset = false) { if (!forceReset && _onlyResetWhenComplete) { _trailResetQueued = true; } else { _trailResetQueued = false; if (_trailState != null) { NBodyC.DestroyGalaxy(_trailState); _trailState = null; } _trailState = NBodyC.Clone(mainState); _trails.Clear(); unsafe { BlackHole *src = mainState->blackHoles; for (int i = 0; i < mainState->numBlackHoles; i++, src++) { _trails[src->id] = new TrailRecord(); } } } }
private unsafe void updateShaderConstants() { simulateMat.SetFloat("_MinDiscRadius", minDiscRadius); simulateMat.SetFloat("_MaxDiscRadius", maxDiscRadius); simulateMat.SetFloat("_MaxDiscHeight", maxDiscHeight); { BlackHole *src = mainState->blackHoles; for (int i = 0; i < mainState->numBlackHoles; i++, src++) { Vector4 planet = src->position; planet.w = src->mass; _vectorArray[i] = planet; } simulateMat.SetVectorArray("_Planets", _vectorArray); } { BlackHole *src = mainState->blackHoles; for (int i = 0; i < mainState->numBlackHoles; i++, src++) { _matrixArray[i] = Matrix4x4.Rotate(src->rotation); } simulateMat.SetMatrixArray("_PlanetRotations", _matrixArray); } simulateMat.SetInt("_PlanetCount", mainState->numBlackHoles); simulateMat.SetFloat("_Force", starGravConstant); simulateMat.SetFloat("_FuzzValue", fuzzValue); }
private void Update() { if (Input.GetKeyDown(resetKeycode)) { ResetSimulation(); } if ((loop && mainState->time > loopTime) || respawnMode) { ResetSimulation(); return; } Random.InitState(Time.frameCount); _seed = Random.Range(int.MinValue, int.MaxValue); if (simulate) { stepSimulation(); } if (_enableTrails) { using (new ProfilerSample("Simulate Trails")) { if (_profileTrails) { var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Reset(); stopwatch.Start(); const int FRAMES_TO_TEST = 1000; for (int i = 0; i < FRAMES_TO_TEST; i++) { NBodyC.StepGalaxy(_trailState); } double seconds = stopwatch.ElapsedTicks / (double)System.Diagnostics.Stopwatch.Frequency; double framesPerSecond = FRAMES_TO_TEST / seconds; _trailFramerate = framesPerSecond; Debug.Log("#####: " + _trailFramerate); } else { int simTime = 0; while (_trailState->frames < mainState->frames + _maxTrailLength) { NBodyC.StepGalaxy(_trailState); unsafe { BlackHole * src = _trailState->blackHoles; TrailRecord trail; for (int j = 0; j < _trailState->numBlackHoles; j++, src++) { if (!_trails.TryGetValue(src->id, out trail)) { trail = new TrailRecord() { startFrame = _trailState->frames }; _trails[src->id] = trail; } trail.queue.PushBack(src->position); } } simTime++; if (simTime >= _trailUpdateRate) { break; } } } } //Build and display trail mesh //but only if it's already reached its max length if (_trailState->frames - mainState->frames >= _trailShowLength) { using (new ProfilerSample("Display Trails")) { _trailVerts.Clear(); _trailIndices.Clear(); using (new ProfilerSample("Build Vertex List")) { foreach (var pair in _trails) { for (int i = 0; i < pair.Value.queue.Count; i++) { if (i != 0) { _trailIndices.Add(_trailVerts.Count); _trailIndices.Add(_trailVerts.Count - 1); } _trailVerts.Add(pair.Value.queue[i]); } } } int[] indexArray; using (new ProfilerSample("Build Index Array")) { indexArray = ArrayPool <int> .Spawn(_trailIndices.Count); for (int i = 0; i < _trailIndices.Count; i++) { indexArray[i] = _trailIndices[i]; } for (int i = _trailIndices.Count; i < indexArray.Length; i++) { indexArray[i] = 0; } } using (new ProfilerSample("Upload Mesh")) { _trailMesh.Clear(); _trailMesh.SetVertices(_trailVerts); _trailMesh.SetIndices(indexArray, MeshTopology.Lines, 0); ArrayPool <int> .Recycle(indexArray); indexArray = null; } if (_trailResetQueued) { ResetTrails(forceReset: true); } } } _trailPropertyBlock.SetColor("_Color", _trailColor); Graphics.DrawMesh(_trailMesh, galaxyRenderer.displayAnchor.localToWorldMatrix, _trailMaterial, 0, null, 0, _trailPropertyBlock); } //Render the black holes themselves unsafe { BlackHole *prevSrc = prevState->blackHoles; BlackHole *mainSrc = mainState->blackHoles; float fraction = Mathf.InverseLerp(prevState->time, mainState->time, simulationTime); for (int j = 0; j < mainState->numBlackHoles; j++, prevSrc++, mainSrc++) { Vector3 position = Vector3.Lerp(prevSrc->position, mainSrc->position, fraction); galaxyRenderer.DrawBlackHole(position); } } }
public unsafe void ResetSimulation() { if (mainState != null) { NBodyC.DestroyGalaxy(mainState); mainState = null; } if (prevState != null) { NBodyC.DestroyGalaxy(prevState); prevState = null; } if (_trailState != null) { NBodyC.DestroyGalaxy(_trailState); _trailState = null; } _trails.Clear(); _trailMesh.Clear(); simulationTime = 0; mainState = NBodyC.CreateGalaxy(blackHoleCount); mainState->time = 0; mainState->frames = 0; _initialBlackHoleCount = blackHoleCount; { Random.InitState(_seed); BlackHole *dst = mainState->blackHoles; int nextId = 1; for (int i = 0; i < blackHoleCount; i++, dst++) { Vector3 position = Random.onUnitSphere * blackHoleSpawnRadius; *dst = new BlackHole() { position = position, velocity = Vector3.Slerp(Vector3.zero - position, Random.onUnitSphere, initialDirVariance).normalized *blackHoleVelocity, mass = Random.Range(1 - blackHoleMassVariance, 1 + blackHoleMassVariance), id = nextId, rotation = Random.rotationUniform }; nextId = nextId << 1; } } Texture2D tex = new Texture2D(2048, 1, TextureFormat.RFloat, mipmap: false, linear: true); for (int i = 0; i < tex.width; i++) { float t = 1 - i / 2047f; t = Mathf.Pow(t, pow); tex.SetPixel(i, 0, new Color(t, 0, 0, 0)); //tex.SetPixel(i, 0, new Color(radiusDistribution.Evaluate(i / 2048.0f), 0, 0, 0)); } tex.Apply(); tex.filterMode = FilterMode.Bilinear; tex.wrapMode = TextureWrapMode.Clamp; simulateMat.SetTexture("_RadiusDistribution", tex); updateShaderConstants(); { BlackHole *src = mainState->blackHoles; for (int i = 0; i < mainState->numBlackHoles; i++, src++) { _vectorArray[i] = src->velocity; } simulateMat.SetVectorArray("_PlanetVelocities", _vectorArray); } { BlackHole *src = mainState->blackHoles; _floatArray.Fill(0); for (int i = 0; i < mainState->numBlackHoles; i++, src++) { _floatArray[i] = Mathf.Lerp(1, src->mass, blackHoleMassAffectsDensity); } simulateMat.SetFloatArray("_PlanetDensities", _floatArray); simulateMat.SetFloat("_TotalDensity", _floatArray.Query().Fold((a, b) => a + b)); } { BlackHole *src = mainState->blackHoles; for (int i = 0; i < mainState->numBlackHoles; i++, src++) { _floatArray[i] = Mathf.Lerp(1, src->mass, blackHoleMassAffectsSize); } simulateMat.SetFloatArray("_PlanetSizes", _floatArray); } GL.LoadPixelMatrix(0, 1, 0, 1); prevPos.DiscardContents(); currPos.DiscardContents(); RenderBuffer[] buffer = new RenderBuffer[2]; buffer[0] = prevPos.colorBuffer; buffer[1] = currPos.colorBuffer; Graphics.SetRenderTarget(buffer, prevPos.depthBuffer); simulateMat.SetPass(1); GL.Begin(GL.QUADS); GL.TexCoord2(0, 0); GL.Vertex3(0, 0, 0); GL.TexCoord2(1, 0); GL.Vertex3(1, 0, 0); GL.TexCoord2(1, 1); GL.Vertex3(1, 1, 0); GL.TexCoord2(0, 1); GL.Vertex3(0, 1, 0); GL.End(); prevState = NBodyC.Clone(mainState); prevState->time = mainState->time - 1.0f / REFERENCE_FRAMERATE; ResetTrails(forceReset: true); if (OnReset != null) { OnReset(); } }