Esempio n. 1
0
        public static void CopyGeometryAndMaterials(this SCNNode node)
        {
            // this copies the material, but not the lod
            if (node.Geometry != null)
            {
                node.UpdateGeometry(node.Geometry.CopyGeometryAndMaterials());

                if (node.Geometry.LevelsOfDetail != null)
                {
                    var lodsNew = new List <SCNLevelOfDetail>();
                    foreach (var lod in node.Geometry.LevelsOfDetail)
                    {
                        if (lod.Geometry != null)
                        {
                            var lodGeometryCopy = lod.Geometry.CopyGeometryAndMaterials();
                            lodsNew.Add(SCNLevelOfDetail.CreateWithScreenSpaceRadius(lodGeometryCopy, lod.ScreenSpaceRadius));
                        }
                    }

                    node.Geometry.LevelsOfDetail = lodsNew.ToArray();
                }
            }

            foreach (var child in node.ChildNodes)
            {
                child.CopyGeometryAndMaterials();
            }
        }
Esempio n. 2
0
        // We load all nodes as references which means they share the same
        // geometry and materials.  For team colors, we need to set geometry overrides
        // and so need unique geometry with shadable overrides for each node created.

        public static void CopyGeometryForPaintColors(this SCNNode node)
        {
            // neutral blocks also need to be tinted
            if (node.Geometry != null && !string.IsNullOrEmpty(node.Name))
            {
                // does this copy the LOD as well ?
                if (node.Geometry.Copy() is SCNGeometry geometryCopy)
                {
                    SetupPaintColorMask(geometryCopy, node.Name);

                    // this may already done by the copy() above, but just be safe
                    if (node.Geometry.LevelsOfDetail != null)
                    {
                        var lodsNew = new List <SCNLevelOfDetail>();
                        foreach (var lod in node.Geometry.LevelsOfDetail)
                        {
                            if (lod.Geometry != null)
                            {
                                if (lod.ScreenSpaceRadius > 0)
                                {
                                    if (lod.Geometry.Copy() is SCNGeometry lodGeometryCopy)
                                    {
                                        lodGeometryCopy.SetupPaintColorMask(node.Name);
                                        lodsNew.Add(SCNLevelOfDetail.CreateWithScreenSpaceRadius(lodGeometryCopy, lod.ScreenSpaceRadius));
                                    }
                                }
                                else
                                {
                                    if (lod.Geometry.Copy() is SCNGeometry lodGeometryCopy)
                                    {
                                        SetupPaintColorMask(lodGeometryCopy, node.Name);
                                        lodsNew.Add(SCNLevelOfDetail.CreateWithWorldSpaceDistance(lodGeometryCopy, lod.WorldSpaceDistance));
                                    }
                                }
                            }
                        }

                        geometryCopy.LevelsOfDetail = lodsNew.ToArray();
                    }

                    // set the new geometry and LOD
                    node.UpdateGeometry(geometryCopy);
                }
            }

            foreach (var child in node.ChildNodes)
            {
                child.CopyGeometryForPaintColors();
            }
        }
Esempio n. 3
0
        public static void FixLevelsOfDetail(this SCNNode node, float screenSpaceRadius, bool showLOD)
        {
            // find the boundingRadius of the node, and scale to that
            var lods = node?.Geometry?.LevelsOfDetail;

            if (lods != null)
            {
                var lodsNew = new List <SCNLevelOfDetail>();
                foreach (var lod in lods)
                {
                    if (lod.Geometry != null)
                    {
                        if (showLOD)
                        {
                            // visualize the lod
                            var lodGeometryCopy = lod.Geometry.CopyGeometryAndMaterials();

                            // override the emission
                            // this is not removed currently
                            foreach (var material in lodGeometryCopy.Materials)
                            {
                                material.Emission.Contents = UIColor.Red;
                            }

                            lodsNew.Add(SCNLevelOfDetail.CreateWithScreenSpaceRadius(lodGeometryCopy, screenSpaceRadius));
                        }
                        else
                        {
                            lodsNew.Add(SCNLevelOfDetail.CreateWithScreenSpaceRadius(lod.Geometry, screenSpaceRadius));
                        }
                    }
                }

                node.Geometry.LevelsOfDetail = lodsNew.ToArray();
            }

            foreach (var child in node.ChildNodes)
            {
                child.FixLevelsOfDetail(screenSpaceRadius, showLOD);
            }
        }
Esempio n. 4
0
		public override void PresentStep (int index, PresentationViewController presentationViewController)
		{
			switch (index) {
			case 0:
				// Hide everything (in case the user went backward)
				for (var i = 1; i < 4; i++) {
					var teapot = GroundNode.FindChildNode ("Teapot" + i, true);
					teapot.Opacity = 0.0f;
				}
				break;
			case 1:
				// Move the camera and adjust the clipping plane
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 3;
				presentationViewController.CameraNode.Position = new SCNVector3 (0, 0, 200);
				presentationViewController.CameraNode.Camera.ZFar = 500.0f;
				SCNTransaction.Commit ();
				break;
			case 2:
				// Revert to original position
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				presentationViewController.CameraNode.Position = new SCNVector3 (0, 0, 0);
				presentationViewController.CameraNode.Camera.ZFar = 100.0f;
				SCNTransaction.Commit ();
				break;
			case 3:
				var numberNodes = new SCNNode[] { AddNumberNode ("64k", -17),
					AddNumberNode ("6k", -9),
					AddNumberNode ("3k", -1),
					AddNumberNode ("1k", 6.5f),
					AddNumberNode ("256", 14)
				};
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;

				// Move the camera and the text
				presentationViewController.CameraHandle.Position = new SCNVector3 (presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y + 6, presentationViewController.CameraHandle.Position.Z);
				TextManager.TextNode.Position = new SCNVector3 (TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y + 6, TextManager.TextNode.Position.Z);

				// Show the remaining resolutions
				for (var i = 0; i < 5; i++) {
					var numberNode = numberNodes [i];
					numberNode.Position = new SCNVector3 (numberNode.Position.X, 7, -5);

					var teapot = GroundNode.FindChildNode ("Teapot" + i, true);
					teapot.Opacity = 1.0f;
					teapot.Rotation = new SCNVector4 (0, 0, 1, (float)(Math.PI / 4));
					teapot.Position = new SCNVector3 ((i - 2) * 8, 5, teapot.Position.Z);
				}

				SCNTransaction.Commit ();
				break;
			case 4:
				presentationViewController.ShowsNewInSceneKitBadge (true);

				// Remove the numbers
				RemoveNumberNodes ();

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
					// Add some text and code
				TextManager.SetSubtitle ("SCNLevelOfDetail");

				TextManager.AddCode ("#var lod1 = SCNLevelOfDetail.#CreateWithWorldSpaceDistance# (aGeometry, aDistance); \n"
				+ "geometry.#LevelsOfDetail# = new SCNLevelOfDetail { lod1, lod2, ..., lodn };#");

				// Animation the merge
				for (int i = 0; i < 5; i++) {
					var teapot = GroundNode.FindChildNode ("Teapot" + i, true);

					teapot.Opacity = i == 0 ? 1.0f : 0.0f;
					teapot.Rotation = new SCNVector4 (0, 0, 1, 0);
					teapot.Position = new SCNVector3 (0, -5, teapot.Position.Z);
				}

				// Move the camera and the text
				presentationViewController.CameraHandle.Position = new SCNVector3 (presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y - 3, presentationViewController.CameraHandle.Position.Z);
				TextManager.TextNode.Position = new SCNVector3 (TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y - 3, TextManager.TextNode.Position.Z);

				SCNTransaction.Commit ();
				break;
			case 5:
				presentationViewController.ShowsNewInSceneKitBadge (false);

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 3;
				// Change the lighting to remove the front light and rise the main light
				presentationViewController.UpdateLightingWithIntensities (new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.3f });
				presentationViewController.RiseMainLight (true);

				// Remove some text
				TextManager.FadeOutText (SlideTextManager.TextType.Title);
				TextManager.FadeOutText (SlideTextManager.TextType.Subtitle);
				TextManager.FadeOutText (SlideTextManager.TextType.Code);
				SCNTransaction.Commit ();

				// Retrieve the main teapot
				var maintTeapot = GroundNode.FindChildNode ("Teapot0", true);

				// The distances to use for each LOD
				var distances = new float [4] { 30, 50, 90, 150 };

				// An array of SCNLevelOfDetail instances that we will build
				var levelsOfDetail = new SCNLevelOfDetail[4];
				for (var i = 1; i < 5; i++) {
					var teapotNode = GroundNode.FindChildNode ("Teapot" + i, true);
					var teapot = teapotNode.Geometry;

					// Unshare the material because we will highlight the different levels of detail with different colors in the next step
					teapot.FirstMaterial = (SCNMaterial)teapot.FirstMaterial.Copy ();

					// Build the SCNLevelOfDetail instance
					var levelOfDetail = SCNLevelOfDetail.CreateWithWorldSpaceDistance (teapot, distances [i - 1]);
					levelsOfDetail [i - 1] = levelOfDetail;
				}

				maintTeapot.Geometry.LevelsOfDetail = levelsOfDetail;

				// Duplicate and move the teapots
				var startTime = CAAnimation.CurrentMediaTime ();
				var delay = 0.2;

				var rowCount = 9;
				var columnCount = 12;

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 0;
				// Change the far clipping plane to be able to see far away
				presentationViewController.CameraNode.Camera.ZFar = 1000.0;

				for (var j = 0; j < columnCount; j++) {
					for (var i = 0; i < rowCount; i++) {
						// Clone
						var clone = maintTeapot.Clone ();
						maintTeapot.ParentNode.AddChildNode (clone);

						// Animate
						var animation = CABasicAnimation.FromKeyPath ("position");
						animation.Additive = true;
						animation.Duration = 1.0;
						animation.To = NSValue.FromVector (new SCNVector3 ((i - rowCount / 2.0f) * 12.0f, 5 + (columnCount - j) * 15.0f, 0));
						animation.From = NSValue.FromVector (new SCNVector3 (0, 0, 0));
						animation.BeginTime = startTime + delay; // desynchronize

						// Freeze at the end of the animation
						animation.RemovedOnCompletion = false;
						animation.FillMode = CAFillMode.Forwards;

						clone.AddAnimation (animation, new NSString ("cloneAnimation"));

						// Animate the hidden property to automatically show the node when the position animation starts
						animation = CABasicAnimation.FromKeyPath ("hidden");
						animation.Duration = delay + 0.01;
						animation.FillMode = CAFillMode.Both;
						animation.From = new NSNumber (1);
						animation.To = new NSNumber (0);
						clone.AddAnimation (animation, new NSString ("cloneAnimation2"));

						delay += 0.05;
					}
				}
				SCNTransaction.Commit ();

				// Animate the camera while we duplicate the nodes
				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1.0 + rowCount * columnCount * 0.05;

				var position = presentationViewController.CameraHandle.Position;
				presentationViewController.CameraHandle.Position = new SCNVector3 (position.X, position.Y + 5, position.Z);
				presentationViewController.CameraPitch.Rotation = new SCNVector4 (1, 0, 0, presentationViewController.CameraPitch.Rotation.W - ((float)(Math.PI / 4) * 0.1f));
				SCNTransaction.Commit ();
				break;
			case 6:
				// Highlight the levels of detail with colors
				var teapotChild = GroundNode.FindChildNode ("Teapot0", true);
				var colors = new NSColor[] { NSColor.Red, NSColor.Orange, NSColor.Yellow, NSColor.Green };

				SCNTransaction.Begin ();
				SCNTransaction.AnimationDuration = 1;
				for (var i = 0; i < 4; i++) {
					var levelOfDetail = teapotChild.Geometry.LevelsOfDetail [i];
					levelOfDetail.Geometry.FirstMaterial.Multiply.Contents = colors [i];
				}
				SCNTransaction.Commit ();
				break;
			}
		}
Esempio n. 5
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                // Hide everything (in case the user went backward)
                for (var i = 1; i < 4; i++)
                {
                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);
                    teapot.Opacity = 0.0f;
                }
                break;

            case 1:
                // Move the camera and adjust the clipping plane
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 3;
                presentationViewController.CameraNode.Position    = new SCNVector3(0, 0, 200);
                presentationViewController.CameraNode.Camera.ZFar = 500.0f;
                SCNTransaction.Commit();
                break;

            case 2:
                // Revert to original position
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                presentationViewController.CameraNode.Position    = new SCNVector3(0, 0, 0);
                presentationViewController.CameraNode.Camera.ZFar = 100.0f;
                SCNTransaction.Commit();
                break;

            case 3:
                var numberNodes = new SCNNode[] { AddNumberNode("64k", -17),
                                                  AddNumberNode("6k", -9),
                                                  AddNumberNode("3k", -1),
                                                  AddNumberNode("1k", 6.5f),
                                                  AddNumberNode("256", 14) };
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;

                // Move the camera and the text
                presentationViewController.CameraHandle.Position = new SCNVector3(presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y + 6, presentationViewController.CameraHandle.Position.Z);
                TextManager.TextNode.Position = new SCNVector3(TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y + 6, TextManager.TextNode.Position.Z);

                // Show the remaining resolutions
                for (var i = 0; i < 5; i++)
                {
                    var numberNode = numberNodes [i];
                    numberNode.Position = new SCNVector3(numberNode.Position.X, 7, -5);

                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);
                    teapot.Opacity  = 1.0f;
                    teapot.Rotation = new SCNVector4(0, 0, 1, (float)(Math.PI / 4));
                    teapot.Position = new SCNVector3((i - 2) * 8, 5, teapot.Position.Z);
                }

                SCNTransaction.Commit();
                break;

            case 4:
                presentationViewController.ShowsNewInSceneKitBadge(true);

                // Remove the numbers
                RemoveNumberNodes();

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Add some text and code
                TextManager.SetSubtitle("SCNLevelOfDetail");

                TextManager.AddCode("#var lod1 = SCNLevelOfDetail.#CreateWithWorldSpaceDistance# (aGeometry, aDistance); \n"
                                    + "geometry.#LevelsOfDetail# = new SCNLevelOfDetail { lod1, lod2, ..., lodn };#");

                // Animation the merge
                for (int i = 0; i < 5; i++)
                {
                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);

                    teapot.Opacity  = i == 0 ? 1.0f : 0.0f;
                    teapot.Rotation = new SCNVector4(0, 0, 1, 0);
                    teapot.Position = new SCNVector3(0, -5, teapot.Position.Z);
                }

                // Move the camera and the text
                presentationViewController.CameraHandle.Position = new SCNVector3(presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y - 3, presentationViewController.CameraHandle.Position.Z);
                TextManager.TextNode.Position = new SCNVector3(TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y - 3, TextManager.TextNode.Position.Z);

                SCNTransaction.Commit();
                break;

            case 5:
                presentationViewController.ShowsNewInSceneKitBadge(false);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 3;
                // Change the lighting to remove the front light and rise the main light
                presentationViewController.UpdateLightingWithIntensities(new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.3f });
                presentationViewController.RiseMainLight(true);

                // Remove some text
                TextManager.FadeOutText(SlideTextManager.TextType.Title);
                TextManager.FadeOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FadeOutText(SlideTextManager.TextType.Code);
                SCNTransaction.Commit();

                // Retrieve the main teapot
                var maintTeapot = GroundNode.FindChildNode("Teapot0", true);

                // The distances to use for each LOD
                var distances = new float[] { 30, 50, 90, 150 };

                // An array of SCNLevelOfDetail instances that we will build
                var levelsOfDetail = new SCNLevelOfDetail[4];
                for (var i = 1; i < 5; i++)
                {
                    var teapotNode = GroundNode.FindChildNode("Teapot" + i, true);
                    var teapot     = teapotNode.Geometry;

                    // Unshare the material because we will highlight the different levels of detail with different colors in the next step
                    teapot.FirstMaterial = (SCNMaterial)teapot.FirstMaterial.Copy();

                    // Build the SCNLevelOfDetail instance
                    var levelOfDetail = SCNLevelOfDetail.CreateWithWorldSpaceDistance(teapot, distances [i - 1]);
                    levelsOfDetail [i - 1] = levelOfDetail;
                }

                maintTeapot.Geometry.LevelsOfDetail = levelsOfDetail;

                // Duplicate and move the teapots
                var startTime = CAAnimation.CurrentMediaTime();
                var delay     = 0.2;

                var rowCount    = 9;
                var columnCount = 12;

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0;
                // Change the far clipping plane to be able to see far away
                presentationViewController.CameraNode.Camera.ZFar = 1000.0;

                for (var j = 0; j < columnCount; j++)
                {
                    for (var i = 0; i < rowCount; i++)
                    {
                        // Clone
                        var clone = maintTeapot.Clone();
                        maintTeapot.ParentNode.AddChildNode(clone);

                        // Animate
                        var animation = CABasicAnimation.FromKeyPath("position");
                        animation.Additive  = true;
                        animation.Duration  = 1.0;
                        animation.To        = NSValue.FromVector(new SCNVector3((i - rowCount / 2.0f) * 12.0f, 5 + (columnCount - j) * 15.0f, 0));
                        animation.From      = NSValue.FromVector(new SCNVector3(0, 0, 0));
                        animation.BeginTime = startTime + delay;                         // desynchronize

                        // Freeze at the end of the animation
                        animation.RemovedOnCompletion = false;
                        animation.FillMode            = CAFillMode.Forwards;

                        clone.AddAnimation(animation, new NSString("cloneAnimation"));

                        // Animate the hidden property to automatically show the node when the position animation starts
                        animation          = CABasicAnimation.FromKeyPath("hidden");
                        animation.Duration = delay + 0.01;
                        animation.FillMode = CAFillMode.Both;
                        animation.From     = new NSNumber(1);
                        animation.To       = new NSNumber(0);
                        clone.AddAnimation(animation, new NSString("cloneAnimation2"));

                        delay += 0.05;
                    }
                }
                SCNTransaction.Commit();

                // Animate the camera while we duplicate the nodes
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0 + rowCount * columnCount * 0.05;

                var position = presentationViewController.CameraHandle.Position;
                presentationViewController.CameraHandle.Position = new SCNVector3(position.X, position.Y + 5, position.Z);
                presentationViewController.CameraPitch.Rotation  = new SCNVector4(1, 0, 0, presentationViewController.CameraPitch.Rotation.W - ((float)(Math.PI / 4) * 0.1f));
                SCNTransaction.Commit();
                break;

            case 6:
                // Highlight the levels of detail with colors
                var teapotChild = GroundNode.FindChildNode("Teapot0", true);
                var colors      = new NSColor[] { NSColor.Red, NSColor.Orange, NSColor.Yellow, NSColor.Green };

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                for (var i = 0; i < 4; i++)
                {
                    var levelOfDetail = teapotChild.Geometry.LevelsOfDetail [i];
                    levelOfDetail.Geometry.FirstMaterial.Multiply.Contents = colors [i];
                }
                SCNTransaction.Commit();
                break;
            }
        }
Esempio n. 6
0
        public CatapultInteraction(IInteractionDelegate @delegate)
        {
            this.Delegate  = @delegate;
            this.dummyBall = SCNNodeExtensions.LoadSCNAsset("projectiles_ball_8k");

            // stri the geometry out of a low-lod model, assume it doesn't have an lod
            if (this.dummyBall.Geometry != null)
            {
                var lod = SCNNodeExtensions.LoadSCNAsset("projectiles_ball");
                if (lod.Geometry != null)
                {
                    lod.Geometry.Materials = this.dummyBall.Geometry.Materials;

                    // this radius will be replaced by fixLevelsOfDetail
                    // when the level is placed
                    this.dummyBall.Geometry.LevelsOfDetail = new SCNLevelOfDetail[] { SCNLevelOfDetail.CreateWithScreenSpaceRadius(lod.Geometry, 100f) };
                }
            }
        }