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; } } }
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(); }