private void Render(Stream stream, int width, int height, ParameterBinding rp, ProgressToken token) { // get relative rotation amount var rotXDiff = rp.RotationX - _lastRotX; var rotYDiff = rp.RotationY - _lastRotY; var rotZDiff = rp.RotationZ - _lastRotZ; _lastRotX = rp.RotationX; _lastRotY = rp.RotationY; _lastRotZ = rp.RotationZ; // rotation // get new *relative* world q var rotationDiff = Matrix.RotationYawPitchRoll(rotYDiff, rotXDiff, rotZDiff); // transform world q into local rotation q var fullRotation = _lastRotation*rotationDiff; _lastRotation = fullRotation; // get the world projection matrix fullRotation.Transpose(); // set the camera zoom _scene.Camera.Scale = 1 / rp.Zoom; if (stream.CanWrite) { stream.Position = 0; // generate checkpoints var tenPercent = (width*height)/10; var list = Enumerable.Range(1, 9).Select(i => i*tenPercent).ToList(); int p = 0; for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var color = TraceRay(fullRotation, x, height - y, width, height); stream.WriteByte(color.B); stream.WriteByte(color.G); stream.WriteByte(color.R); stream.WriteByte(color.A); if (token != null && list.Contains(++p)) { token.Value += 10; } } } stream.Flush(); } }
public async Task<WriteableBitmap> RenderAsync(int width, int height, ParameterBinding rp, ProgressToken token) { var wb = new WriteableBitmap(width, height); var stream = wb.PixelBuffer.AsStream(); await Task.Run(() => Render(stream, width, height, rp, token)); if (token != null) { token.Value = 100; } return wb; }
public MainViewModel(IProgressAggregator progress) : base(progress) { _sceneRenderer = new SceneRenderer(); RenderWidth = 400; RenderHeight = 300; RenderCommand = new AsyncDelegateCommand(Render); AnimateCommand = new AsyncDelegateCommand(Animate); RenderParameters = new ParameterBinding(UiDispatcher); AnimationParameters = new ParameterBinding(UiDispatcher); }
/// <summary> /// Linearly nterpolates between this binding and the provided one /// </summary> /// <param name="end">Binding to interpolate to</param> /// <param name="frame">current frame</param> /// <param name="totalFrames">final frame</param> /// <returns></returns> public ParameterBinding Interpolate(ParameterBinding end, int frame, int totalFrames) { float ratio = (float)frame/totalFrames; var interpolated = new ParameterBinding(end.Dispatcher) { RotationX = Lerp(RotationX, end.RotationX, ratio), RotationY = Lerp(RotationY, end.RotationY, ratio), RotationZ = Lerp(RotationZ, end.RotationZ, ratio), Zoom = Lerp(Zoom, end.Zoom, ratio) }; return interpolated; }
public async Task<List<WriteableBitmap>> Animate(int renderWidth, int renderHeight, TimeSpan length, ProgressToken token, ParameterBinding start, ParameterBinding end) { const int parallelism = 1; // TODO change _lastRot variables so animations can be rendered in parallel var totalFrames = (int)length.TotalSeconds*AnimationFps; var frames = new List<WriteableBitmap>(); for (var frame = 0; frame < totalFrames; frame += parallelism) { var frameBindings = Enumerable.Range(frame, parallelism).Select(i => start.Interpolate(end, i, totalFrames)); var renderTasks = frameBindings.Select(b => RenderAsync(renderWidth, renderHeight, b, null)); var rendered = await Task.WhenAll(renderTasks); frames.AddRange(rendered); if (token != null) { token.Value = (int)((float)frame / totalFrames * 100); } } return frames; }