예제 #1
0
        public async Task Start()
        {
            _logger.LogInformation("Animation thread started");

            // Hackish way to measure time ...
            float       totalTime   = 0;
            const float target_fps  = 60;
            int         threadDelay = (int)Math.Ceiling(1 / target_fps);

            while (!_cancellationTokenManager.IsCancellationRequested)
            {
                // Update triangle vertex positions and send to update channel
                // so that their positions are updated and vertex buffers are refreshed

                var angleDegrees = totalTime / 2.0;

                var angle = MathHelper.DegreesToRadians(angleDegrees);
                var modelTransformMatrix = Matrix4.CreateRotationZ((float)angle);

                // Rotate the triangle by updating vertex positions, which will update the vertex buffers on
                // the renderer
                var assetionBatch = new AssertionBatch
                {
                    Assertions = new IAssertion[]
                    {
                        new Vertex(0, new Coordinate3d(-0.33f, 0.0f, 0.0f).Transform(modelTransformMatrix)),
                        new Vertex(1, new Coordinate3d(0.33f, 0.0f, 0.0f).Transform(modelTransformMatrix)),
                        new Vertex(2, new Coordinate3d(0.0f, 0.33f, 0.0f).Transform(modelTransformMatrix)),
                        new Vertex(4, new Coordinate3d(0.66f, -0.33f, 0.0f).Transform(modelTransformMatrix)),
                        new Vertex(5, new Coordinate3d(0.0f, -0.33f, 0.0f).Transform(modelTransformMatrix)),
                        new Vertex(7, new Coordinate3d(-0.66f, -0.33f, 0.0f).Transform(modelTransformMatrix))
                    }
                };
                await _scene.AssertionUpdatesChannel.Writer.WriteAsync(assetionBatch, _cancellationTokenManager.Token);

                await Task.Delay(threadDelay);

                totalTime += threadDelay;
            }
        }
예제 #2
0
        public async Task StartAssertionProducer()
        {
            var    currentLocation = new FileInfo(typeof(SceneLoader).Assembly.Location);
            string image           = $"{Uri.UriSchemeFile}://{currentLocation.Directory}/snail.jpg";
            string image2          = $"{Uri.UriSchemeFile}://{currentLocation.Directory}/snail_2.jpg";

            var batch0 = new AssertionBatch
            {
                Assertions = new IAssertion[]
                {
                    // Define vertices
                    new Vertex(0, new Coordinate3d(-0.33f, 0.0f, 0.0f)),
                    new Vertex(1, new Coordinate3d(0.33f, 0.0f, 0.0f)),
                    new Vertex(2, new Coordinate3d(0.0f, 0.33f, 0.0f)),
                    new Vertex(4, new Coordinate3d(0.66f, -0.33f, 0.0f)),
                    new Vertex(5, new Coordinate3d(0.0f, -0.33f, 0.0f)),
                    new Vertex(7, new Coordinate3d(-0.66f, -0.33f, 0.0f))
                }
            };

            // Send the assertions to the rendering system
            await _scene.AssertionUpdatesChannel.Writer.WriteAsync(batch0, _cancellationTokenManager.Token);

            var batch1 = new AssertionBatch
            {
                Assertions = new IAssertion[]
                {
                    // Initial setup
                    new ClearColor(0.1f, 0.1f, 0.2f),
                    Constants.DefaultCameraOrientation,
                    new CameraProjectionPerspective(90, 0.3f, 3),

                    // Images
                    new Texture(100, image),
                    new Texture(200, image2),

                    // Top triangle
                    new Triangle(3, (0, 1, 2)),
                    new TexCoords((3, 0), 100, 0f, 0.2f),
                    new TexCoords((3, 1), 100, 1f, 0.2f),
                    new TexCoords((3, 2), 100, 0.5f, 0.7f),

                    // Bottom right triangle
                    new Triangle(6, (4, 5, 1)),
                    new TexCoords((6, 4), 200, 0.8f, 0.5f),
                    new TexCoords((6, 5), 200, -0.2f, 0.5f),
                    new TexCoords((6, 1), 200, 0.3f, 1f),

                    // Bottom left triangle
                    new Triangle(8, (5, 7, 0)),
                    new SurfaceColor((8, 7), new (1.0f, 0.0f, 0.0f, 1.0f)),
                    new SurfaceColor((8, 5), new (0.0f, 1.0f, 0.0f, 1.0f)),
                    new SurfaceColor((8, 0), new (0.0f, 0.0f, 1.0f, 1.0f))
                }
            };

            // Send the assertions to the rendering system
            await _scene.AssertionUpdatesChannel.Writer.WriteAsync(batch1, _cancellationTokenManager.Token);

            // Render second test batch
            var batch2 = new AssertionBatch
            {
                Assertions = new IAssertion[]
                {
                    // Define vertices
                    new Vertex(9, new Coordinate3d(-0.33f, 0.0f, -1.0f)),
                    new Vertex(10, new Coordinate3d(0.33f, 0.0f, -1.0f)),
                    new Vertex(11, new Coordinate3d(0.0f, -0.33f, -1.0f)),

                    // Bottom left triangle
                    new Triangle(12, (9, 10, 11)),
                    new SurfaceColor((12, 9), new (1.0f, 1.0f, 0.0f, 1.0f)),
                    new SurfaceColor((12, 10), new (0.0f, 1.0f, 1.0f, 1.0f)),
                    new SurfaceColor((12, 11), new (1.0f, 0.0f, 1.0f, 1.0f))
                }
            };

            // Send the assertions to the rendering system
            await _scene.AssertionUpdatesChannel.Writer.WriteAsync(batch2, _cancellationTokenManager.Token);
        }
예제 #3
0
        /// <summary>
        /// Generates scene graph updates for renderer.
        /// </summary>
        public async IAsyncEnumerable <IRenderCommand> Process(AssertionBatch assertionBatch)
        {
            var knownUpdateObjects = new List <ObjectIdentityBase>();

            foreach (var assertion in assertionBatch.Assertions)
            {
                if (assertion is GetPickingInfo getPickingInfo)
                {
                    yield return(new RenderCommands.RequestPickingInfo(getPickingInfo.ScreenX, getPickingInfo.ScreenY));
                }
                else if (assertion is Core.Assertions.ClearColor clearColor)
                {
                    _sceneGraph.RgbClearColor = new (clearColor.Red, clearColor.Green, clearColor.Blue, 1.0f);
                    yield return(new RenderCommands.ClearColor(_sceneGraph.RgbClearColor));
                }
                else if (assertion is CameraProjectionPerspective projectionPerspective)
                {
                    // Projection matrix is set in uniforms
                    yield return(new RenderCommands.SetProjectionMatrix(_sceneGraph, projectionPerspective.FieldOfViewVerticalDegrees,
                                                                        projectionPerspective.NearPlane, projectionPerspective.FarPlane));
                }
                else if (assertion is CameraOrientation cameraOrientation)
                {
                    // View matrix is set in uniforms
                    _sceneGraph.ViewMatrix = cameraOrientation.ToMatrix();
                }
                else if (assertion is Core.Assertions.Vertex assertionVertex)
                {
                    if (!_sceneGraph.Vertices.TryGetValue(assertionVertex.VertexId, out Core.Scene.Vertex vertex))
                    {
                        vertex = new Core.Scene.Vertex(_sceneGraph, assertionVertex.VertexId);
                        _sceneGraph.Vertices[assertionVertex.VertexId] = vertex;
                    }
                    if (assertionVertex.Coordinates != default)
                    {
                        vertex.Coordinates = assertionVertex.Coordinates;
                        knownUpdateObjects.Add(vertex);
                    }
                }
                else if (assertion is Core.Assertions.Triangle triangle)
                {
                    var newTriangle = new Core.Scene.Triangle(_sceneGraph, triangle.TriangleId)
                    {
                        VertexIds = triangle.VertexIds
                    };
                    _partialObjectsWatchList.AddLast(newTriangle);
                    _sceneGraph.Triangles[triangle.TriangleId] = newTriangle;
                }
                else if (assertion is Core.Assertions.GrabScreenshot)
                {
                    yield return(new RenderCommands.GrabScreenshot(_renderWindow, _cancellationTokenManager));
                }
                else if (assertion is Core.Assertions.Texture texture)
                {
                    // Pre-load texture to avoid doing this in the function setting OpenGL state
                    var loadedImage = await _imageLoader.LoadImage(new Uri(texture.Uri));

                    _sceneGraph.Textures[texture.TextureId] = new Core.Scene.Texture(_sceneGraph, texture.TextureId, loadedImage.BufferRgba,
                                                                                     loadedImage.Width, loadedImage.Height);
                }
                else if (assertion is TexCoords texCoords)
                {
                    _sceneGraph.SurfaceVertexTexCoords[texCoords.ObjectIdentifier] = texCoords;
                }
                else if (assertion is SurfaceColor surfaceColor)
                {
                    _sceneGraph.SurfaceVertexColors[surfaceColor.ObjectIdentifier] = surfaceColor;
                }
                else
                {
                    throw new ArgumentException($"Unknown assertion type: {assertion.GetType()}");
                }
            }

            // Split objects into new and update lists
            var newRenderTriangles = new List <Core.Scene.Triangle>();

            // Get known complete geometry
            LinkedListNode <Core.Scene.Triangle> currentNode = _partialObjectsWatchList.First;

            while (currentNode != null)
            {
                if (_bufferManager.HasExistingTriangleBuffer(currentNode.Value))
                {
                    knownUpdateObjects.Add(currentNode.Value);
                    currentNode = currentNode.Next;
                    continue;
                }

                if (!currentNode.Value.HasMinimumRenderInfo)
                {
                    currentNode = currentNode.Next;
                    continue;
                }

                newRenderTriangles.Add(currentNode.Value);
                var next = currentNode.Next;
                _partialObjectsWatchList.Remove(currentNode);
                currentNode = next;
            }

            if (newRenderTriangles.Any())
            {
                yield return(_bufferManager.CreateRenderCommands(newRenderTriangles));
            }

            if (knownUpdateObjects.Any())
            {
                foreach (var reloadCommand in _bufferManager.CreateReloadCommands(knownUpdateObjects))
                {
                    yield return(reloadCommand);
                }
            }
        }