public void CommonApplicationDidFinishLaunching(Action completionHandler)
        {
            Scene.ShowsStatistics = true;
            Scene.BackgroundColor = AppKit.NSColor.Black;

            NSProgress progress = NSProgress.FromTotalUnitCount(10);

            DispatchQueue queue = DispatchQueue.GetGlobalQueue(DispatchQueuePriority.Default);

            queue.DispatchSync(() => {
                progress.BecomeCurrent(2);
                var ui = new InGameScene(Scene.Bounds.Size);

                DispatchQueue.MainQueue.DispatchAsync(() =>
                                                      Scene.OverlayScene = ui
                                                      );

                progress.ResignCurrent();
                progress.BecomeCurrent(3);

                GameSimulation gameSim = GameSimulation.Sim;
                gameSim.GameUIScene    = ui;

                progress.ResignCurrent();
                progress.BecomeCurrent(3);

                SCNTransaction.Flush();

                // Preload
                Scene.Prepare(gameSim, new Func <bool> (() =>
                                                        true
                                                        ));
                progress.ResignCurrent();
                progress.BecomeCurrent(1);

                // Game Play Specific Code
                gameSim.GameUIScene.GameStateDelegate = gameSim.GameLevel;
                gameSim.GameLevel.ResetLevel();
                gameSim.SetGameState(GameState.PreGame);

                progress.ResignCurrent();
                progress.BecomeCurrent(1);

                DispatchQueue.MainQueue.DispatchAsync(() => {
                    Scene.Scene = gameSim;
                    Scene.WeakSceneRendererDelegate = gameSim;

                    if (completionHandler != null)
                    {
                        completionHandler();
                    }
                });

                progress.ResignCurrent();
            });
        }
        // Preload the next slide
        private void PrepareSlide(int slideIndex)
        {
            // Retrieve the slide to preload
            var slide = GetSlide(slideIndex, true);

            if (slide != null)
            {
                SCNTransaction.Flush();                  // make sure that all pending transactions are flushed otherwise objects not added yet to the scene graph would not be preloaded

                // Preload the node tree
                // ((SCNView)View).Prepare (slide.contentNode, null);

                // Preload the floor image if any
                if (slide.FloorImageName != null)
                {
                    NSImage image;
                    try {
                        image = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/" + slide.FloorImageName, "png"));
                    } catch (Exception) {
                        image = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/" + slide.FloorImageName, "jpg"));
                    }

                    // Create a container for this image to be able to preload it
                    var material = SCNMaterial.Create();
                    material.Diffuse.Contents  = image;
                    material.Diffuse.MipFilter = SCNFilterMode.Linear; // we also want to preload mipmaps

                    SCNTransaction.Flush();                            //make this material ready before warming up

                    // Preload
                    //((SCNView)View).Prepare (material, null);

                    // Don't release the material now, otherwise we will loose what we just preloaded
                    slide.FloorWarmupMaterial = material;
                }
            }
        }
Example #3
0
        private void BuildVisualizationsOfNode(SCNNode node, ref SCNNode verticesNode, ref SCNNode normalsNode)
        {
            // A material that will prevent the nodes from being lit
            var noLightingMaterial = SCNMaterial.Create();

            noLightingMaterial.LightingModelName = SCNLightingModel.Constant;

            var normalMaterial = SCNMaterial.Create();

            normalMaterial.LightingModelName = SCNLightingModel.Constant;
            normalMaterial.Diffuse.Contents  = NSColor.Red;

            // Create nodes to represent the vertex and normals
            var positionVisualizationNode = SCNNode.Create();
            var normalsVisualizationNode  = SCNNode.Create();

            // Retrieve the vertices and normals from the model
            var positionSource = node.Geometry.GetGeometrySourcesForSemantic(SCNGeometrySourceSemantic.Vertex) [0];
            var normalSource   = node.Geometry.GetGeometrySourcesForSemantic(SCNGeometrySourceSemantic.Normal) [0];

            // Get vertex and normal bytes
            var vertexBufferByte = (byte[])positionSource.Data.ToArray();
            var vertexBuffer     = new float[vertexBufferByte.Length / 4];

            Buffer.BlockCopy(vertexBufferByte, 0, vertexBuffer, 0, vertexBufferByte.Length);

            var normalBufferByte = (byte[])normalSource.Data.ToArray();
            var normalBuffer     = new float[normalBufferByte.Length / 4];

            Buffer.BlockCopy(normalBufferByte, 0, normalBuffer, 0, normalBufferByte.Length);

            // Iterate and create geometries to represent the positions and normals
            for (var i = 0; i < positionSource.VectorCount; i++)
            {
                // One new node per normal/vertex
                var vertexNode = SCNNode.Create();
                var normalNode = SCNNode.Create();

                // Attach one sphere per vertex
                var sphere = SCNSphere.Create(0.5f);
                sphere.SegmentCount  = 4;                // use a small segment count for better performances
                sphere.FirstMaterial = noLightingMaterial;
                vertexNode.Geometry  = sphere;

                // And one pyramid per normal
                var pyramid = SCNPyramid.Create(0.1f, 0.1f, 8);
                pyramid.FirstMaterial = normalMaterial;
                normalNode.Geometry   = pyramid;

                // Place the position node
                var componentsPerVector = positionSource.ComponentsPerVector;
                vertexNode.Position = new SCNVector3(vertexBuffer [i * componentsPerVector], vertexBuffer [i * componentsPerVector + 1], vertexBuffer [i * componentsPerVector + 2]);

                // Place the normal node
                normalNode.Position = vertexNode.Position;

                // Orientate the normal
                var up         = new Vector3(0, 0, 1);
                var normalVec  = new Vector3(normalBuffer [i * 3], normalBuffer [i * 3 + 1], normalBuffer [i * 3 + 2]);
                var axis       = Vector3.Normalize(Vector3.Cross(up, normalVec));
                var dotProduct = Vector3.Dot(up, normalVec);
                normalNode.Rotation = new SCNVector4(axis.X, axis.Y, axis.Z, NMath.Acos(dotProduct));

                // Add the nodes to their parent
                positionVisualizationNode.AddChildNode(vertexNode);
                normalsVisualizationNode.AddChildNode(normalNode);
            }

            // We must flush the transaction in order to make sure that the parametric geometries (sphere and pyramid)
            // are up-to-date before flattening the nodes
            SCNTransaction.Flush();

            // Flatten the visualization nodes so that they can be rendered with 1 draw call
            verticesNode = positionVisualizationNode.FlattenedClone();
            normalsNode  = normalsVisualizationNode.FlattenedClone();
        }