public void Initialize(List <RedLine> lines) { Clear(); if (lines.Count == 0) { return; } //max size for init var redshapes = new GenericVertex[lines.Count * ShapeSize * 3][]; ResourceSync initsync = new ResourceSync(); int vertcount = 0; System.Threading.Tasks.Parallel.For(0, lines.Count, (idx) => { var acc = GetAccelDecor(lines[idx]); redshapes[idx] = acc; System.Threading.Interlocked.Add(ref vertcount, acc.Length); }); GenericVertex[] verts = new GenericVertex[vertcount]; _indices.EnsureCapacity(vertcount); _indices.UnsafeSetCount(vertcount); int shapepos = 0; for (int idx = 0; idx < lines.Count; idx++) { var acc = redshapes[idx]; var entry = new accelentry() { start = shapepos, shapes = acc.Length / ShapeSize }; for (int i = 0; i < acc.Length; i++) { verts[shapepos] = acc[i]; _indices.unsafe_array[shapepos] = shapepos; shapepos++; } _lookup.Add(lines[idx].ID, entry); } _vertcount = verts.Length; _accelbuffer.Bind(); EnsureVBOSize(verts.Length, false); _accelbuffer.SetData(verts, 0, 0, verts.Length); _accelbuffer.Unbind(); _accelibo.Bind(); EnsureIBOSize(_indices.Count, false); _accelibo.SetData(_indices.unsafe_array, 0, 0, _indices.Count); _accelibo.Unbind(); }
/// <summary> /// The meat of the recompute engine, updating hit test and the /// cached frames. /// </summary> private void ThreadUnsafeRunFrames(int start, int count) { var steps = new Rider[count]; var collisionlist = new List <LinkedList <int> >(count); Rider current = _frames[start - 1]; int framecount = _frames.Count; var bones = _track.Bones; using (changesync.AcquireWrite()) { // we use the savedcells buffer exactly so runframes can // be completely consistent with the track state at the // time of running // we could also get a lock on the track grid, but that would // block user input on the track until we finish running. _savedcells.Clear(); } using (var sync = changesync.AcquireRead()) { _hittest.MarkFirstInvalid(start); for (int i = 0; i < count; i++) { int currentframe = start + i; var collisions = new LinkedList <int>(); current = current.Simulate( _savedcells, bones, _activetriggers, collisions); steps[i] = current; collisionlist.Add(collisions); // 10 seconds of frames, // couldnt hurt to check? if ((i + 1) % 400 == 0) { sync.ReleaseWaiting(); } } _hittest.AddFrames(collisionlist); } if (start + count > framecount) { _frames.EnsureCapacity(start + count); _frames.UnsafeSetCount(start + count); } for (int i = 0; i < steps.Length; i++) { _frames.unsafe_array[start + i] = steps[i]; } FrameInvalidated?.Invoke(this, start); }
public virtual Vector2d GetFrameCamera(int frame) { if (_zoom != _cachezoom) { _cachezoom = _zoom; _prevframe = -1; _framecache.UnsafeSetCount(1); } EnsureFrame(frame); var offset = CalculateOffset(frame); _prevframe = frame; _prevcamera = offset; return(_frames[frame].RiderCenter + offset); }
/// <summary> /// The meat of the recompute engine, updating hit test and the /// cached frames. /// </summary> private void ThreadUnsafeRunFrames(int start, int count) { var steps = new frameinfo[count]; var collisionlist = new List <LinkedList <int> >(count); frameinfo current = _frames[start - 1]; int framecount = _frames.Count; var bones = _track.Bones; using (changesync.AcquireWrite()) { // we use the savedcells buffer exactly so runframes can // be completely consistent with the track state at the // time of running // we could also get a lock on the track grid, but that would // block user input on the track until we finish running. _savedcells.Clear(); } using (var sync = changesync.AcquireRead()) { _hittest.MarkFirstInvalid(start); for (int i = 0; i < count; i++) { int currentframe = start + i; var collisions = new LinkedList <int>(); var oldtrigid = current.TriggerLineID; var zoom = current.Rider = current.Rider.Simulate( _savedcells, bones, ref current.TriggerLineID, collisions, frameid: currentframe); if (current.TriggerLineID != oldtrigid) { current.TriggerHitFrame = currentframe; } if (current.TriggerLineID != -1) { var std = (StandardLine)_track.LineLookup[current.TriggerLineID]; Debug.Assert(std.Trigger != null, "Trigger line proc on line with no trigger"); var delta = currentframe - current.TriggerHitFrame; if (!std.Trigger.Activate(delta, ref current.Zoom)) { current.TriggerLineID = -1; current.TriggerHitFrame = -1; } } steps[i] = current; collisionlist.Add(collisions); // 10 seconds of frames, // couldnt hurt to check? if ((i + 1) % 400 == 0) { sync.ReleaseWaiting(); } } _hittest.AddFrames(collisionlist); } if (start + count > framecount) { _frames.EnsureCapacity(start + count); _frames.UnsafeSetCount(start + count); } for (int i = 0; i < steps.Length; i++) { _frames.unsafe_array[start + i] = steps[i]; } FrameInvalidated?.Invoke(this, start); }
/// <summary> /// Clears the renderer and initializes it with new lines. /// </summary> public void InitializeTrack(Track track) { AutoArray <GameLine> scenery = new AutoArray <GameLine>(track.SceneryLines); scenery.UnsafeSetCount(track.SceneryLines); AutoArray <GameLine> phys = new AutoArray <GameLine>(track.BlueLines); AutoArray <GameLine> accel = new AutoArray <GameLine>(track.RedLines); var sorted = track.GetSortedLines(); using (_sync.AcquireWrite()) { _lineactions.Clear(); _physvbo.Clear(); _sceneryvbo.Clear(); _accelvbo.Clear(); _bluedecorator.Clear(); _acceldecorator.Clear(); _physlines.Clear(); _scenerylines.Clear(); _accellines.Clear(); RequiresUpdate = true; int scenerycount = 0; for (int i = 0; i < sorted.Length; i++) { var line = sorted[i]; switch (line.Type) { case LineType.Scenery: scenery.unsafe_array[scenery.Count - (1 + scenerycount++)] = line; break; case LineType.Blue: phys.Add(line); break; case LineType.Red: accel.Add(line); break; } } Debug.Assert(scenerycount == scenery.Count, "Predicted scenery count was not accurate"); if (scenery.Count != 0) { LineVertex[] sceneryverts = new LineVertex[scenery.Count * linesize]; System.Threading.Tasks.Parallel.For(0, scenery.Count, (index) => { int counter = 0; var verts = (GenerateLine(scenery[index], false)); foreach (var vert in verts) { sceneryverts[index * linesize + counter++] = vert; } }); _scenerylines = _sceneryvbo.AddLines( scenery, sceneryverts); } if (phys.Count != 0) { LineVertex[] physverts = new LineVertex[phys.Count * linesize]; System.Threading.Tasks.Parallel.For(0, phys.Count, (index) => { int counter = 0; var verts = (GenerateLine(phys[index], false)); foreach (var vert in verts) { physverts[index * linesize + counter++] = vert; } }); _physlines = _physvbo.AddLines( phys, physverts); _bluedecorator.Initialize(phys); } if (accel.Count != 0) { LineVertex[] accelverts = new LineVertex[accel.Count * linesize]; System.Threading.Tasks.Parallel.For(0, accel.Count, (index) => { int counter = 0; var verts = (GenerateLine(accel[index], false)); foreach (var vert in verts) { accelverts[index * linesize + counter++] = vert; } }); _accellines = _accelvbo.AddLines( accel, accelverts); _acceldecorator.Initialize(accel); } RequiresUpdate = true; } }
/// <summary> /// The meat of the recompute engine, updating hit test and the /// cached frames. /// </summary> public void ThreadUnsafeRunFrames(int start, int count) { var steps = new frameinfo[count]; var collisionlist = new List <LinkedList <int> >(count); frameinfo current = _frames[start - 1]; int framecount = _frames.Count; var bones = _track.Bones; using (changesync.AcquireWrite()) { // we use the savedcells buffer exactly so runframes can // be completely consistent with the track state at the // time of running // we could also get a lock on the track grid, but that would // block user input on the track until we finish running. _savedcells.Clear(); } using (var sync = changesync.AcquireRead()) { _hittest.MarkFirstInvalid(start); GameTrigger[] triggers = new GameTrigger[GameTrigger.TriggerTypes]; for (int i = 0; i < count; i++) { int currentframe = start + i; var collisions = new LinkedList <int>(); current.Rider = current.Rider.Simulate( _savedcells, bones, collisions, frameid: currentframe); if (GetTriggersForFrame(triggers, currentframe)) { var zoomtrigger = triggers[(int)TriggerType.Zoom]; if (zoomtrigger != null) { var delta = currentframe - zoomtrigger.Start; zoomtrigger.ActivateZoom(delta, ref current.Zoom); } var bgtrigger = triggers[(int)TriggerType.BGChange]; if (bgtrigger != null) { var delta = currentframe - bgtrigger.Start; Constants.StaticTriggerBGColor = _frames[start - 1].BGColor; bgtrigger.ActivateBG(delta, currentframe, ref Constants.StaticTriggerBGColor, ref Constants.TriggerBGColor, ref current.BGColor); } var linetrigger = triggers[(int)TriggerType.LineColor]; if (linetrigger != null) { var delta = currentframe - linetrigger.Start; Constants.StaticTriggerLineColorChange = _frames[start - 1].LineColor; linetrigger.ActivateLine(delta, ref Constants.StaticTriggerLineColorChange, ref Constants.TriggerLineColorChange, currentframe, ref current.LineColor); } } steps[i] = current; collisionlist.Add(collisions); // 10 seconds of frames, // couldnt hurt to check? if ((i + 1) % 400 == 0) { sync.ReleaseWaiting(); } } _hittest.AddFrames(collisionlist); } if (start + count > framecount) { _frames.EnsureCapacity(start + count); _frames.UnsafeSetCount(start + count); } for (int i = 0; i < steps.Length; i++) { _frames.unsafe_array[start + i] = steps[i]; } FrameInvalidated?.Invoke(this, start); }