예제 #1
0
        public override void RotateWithEvent(NSEvent theEvent)
        {
            base.RotateWithEvent(theEvent);
            var r = SCNQuaternion.FromAxisAngle(new SCNVector3(0, 0, 1), -theEvent.Rotation / 180);

            r.Normalize();
            Trackball.Rotate(r);
        }
예제 #2
0
        /// <summary>
        /// Computes the tangent position of the rope based on a given fixture
        /// </summary>
        private SCNVector3 TangentPosition(SCNVector3 fixture)
        {
            var r     = this.ballRadius;
            var d     = fixture - this.ballPosition;
            var alpha = (float)Math.Acos(r / d.Length);

            d = this.ballRadius * SCNVector3.Normalize(d);
            var rot       = SCNQuaternion.FromAxisAngle(this.UpVector, fixture == this.FixturePositionL ? -alpha : alpha);
            var d_rotated = rot.Act(d);

            return(d_rotated + this.ballPosition);
        }
예제 #3
0
        public SlingShotSimulation(SCNNode rootNode, int count, float segmentRadius) : base()
        {
            this.InitializeHelpers();

            for (var i = 0; i < count; i++)
            {
                var isStatic   = (i < this.BoneInset) || (i >= count - this.BoneInset);
                var quaternion = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, 0);

                var transform = new SimulatedTransform(SCNVector3.Zero, quaternion, SCNVector3.Zero, !isStatic);
                this.simulatedTransforms.Add(transform);
            }
        }
예제 #4
0
        private void Setup(NVector3 extent)
        {
            // Translate and rotate line nodes to the correct transform
            var halfX = extent.X / 2;
            var halfY = extent.Y / 2;
            var halfZ = extent.Z / 2;

            // Two helper functions to isolate the allocations and casts
            Action <SCNNode, float, float, float> xlat = (node, extentX, extentY, extentZ) => node.LocalTranslate(new SCNVector3(extentX, extentY, extentZ));

            Action <SCNNode, float, float, float, Axis> xlatAndRot = (node, extentX, extentY, extentZ, axis) =>
            {
                xlat(node, extentX, extentY, extentZ);
                node.LocalRotate(SCNQuaternion.FromAxisAngle(axis.Normal().ToSCNVector3(), (float)-Math.PI / 2));
            };

            var halfWidth  = extent.X / 2;
            var halfHeight = extent.Y / 2;
            var halfDepth  = extent.Z / 2;

            xlatAndRot(lineNodes[0], 0, -halfHeight, -halfDepth, Axis.Z);
            xlatAndRot(lineNodes[1], -halfWidth, -halfHeight, 0, Axis.X);
            xlatAndRot(lineNodes[2], 0, -halfHeight, halfDepth, Axis.Z);
            xlatAndRot(lineNodes[3], halfWidth, -halfHeight, 0, Axis.X);
            xlat(lineNodes[4], -extent.X, 0, -halfDepth);
            xlat(lineNodes[5], -halfWidth, 0, halfDepth);
            xlat(lineNodes[6], halfWidth, 0, -halfDepth);
            xlat(lineNodes[7], halfWidth, 0, halfDepth);
            xlatAndRot(lineNodes[8], 0, halfHeight, -halfDepth, Axis.Z);
            xlatAndRot(lineNodes[9], -halfWidth, halfHeight, 0, Axis.X);
            xlatAndRot(lineNodes[10], 0, halfHeight, halfDepth, Axis.Z);
            xlatAndRot(lineNodes[11], halfWidth, halfHeight, 0, Axis.X);

            // Assign geometries
            lineNodes[0].Geometry  = Cylinder(extent.X);
            lineNodes[1].Geometry  = Cylinder(extent.Z);
            lineNodes[2].Geometry  = Cylinder(extent.X);
            lineNodes[3].Geometry  = Cylinder(extent.Z);
            lineNodes[4].Geometry  = Cylinder(extent.Y);
            lineNodes[5].Geometry  = Cylinder(extent.Y);
            lineNodes[6].Geometry  = Cylinder(extent.Y);
            lineNodes[7].Geometry  = Cylinder(extent.Y);
            lineNodes[8].Geometry  = Cylinder(extent.X);
            lineNodes[9].Geometry  = Cylinder(extent.Z);
            lineNodes[10].Geometry = Cylinder(extent.X);
            lineNodes[11].Geometry = Cylinder(extent.Z);
        }
예제 #5
0
        public void CreateFlagSimulationFromNode(SCNNode node)
        {
            var meshData  = new ClothSimMetalNode(this.device, Width, Height);
            var clothNode = SCNNode.FromGeometry(meshData.Geometry);

            var flag = node.FindChildNode("flagStaticWave", true);

            if (flag != null)
            {
                var boundingBoxMax = SCNVector3.Zero;
                var boundingBoxMin = SCNVector3.Zero;
                flag.GetBoundingBox(ref boundingBoxMin, ref boundingBoxMax);
                var existingFlagBV = boundingBoxMax - boundingBoxMin;

                var rescaleToMatchSizeMatrix = SCNMatrix4.Scale(existingFlagBV.X / (float)Width);

                var rotation       = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, (float)Math.PI / 2f);
                var localTransform = rescaleToMatchSizeMatrix * SCNMatrix4.Rotate(rotation.ToQuaternion());

                localTransform.Transpose();
                var currentTransform = SCNMatrix4.Transpose(flag.Transform);
                var newTransform     = currentTransform * localTransform;

                clothNode.Transform = SCNMatrix4.Transpose(newTransform);// flag.Transform * localTransform;
                if (clothNode.Geometry != null)
                {
                    clothNode.Geometry.FirstMaterial = flag.Geometry?.FirstMaterial;
                    if (clothNode.Geometry.FirstMaterial != null)
                    {
                        clothNode.Geometry.FirstMaterial.DoubleSided = true;
                    }
                }

                flag.ParentNode.ReplaceChildNode(flag, clothNode);
                clothNode.Geometry.SetupPaintColorMask("flag_flagA");
                clothNode.SetPaintColors();
                clothNode.FixNormalMaps();

                this.clothData.Add(new ClothData(clothNode, meshData));
            }
        }
예제 #6
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Perform any additional setup after loading the view, typically from a nib.
            var scene = new SCNScene();

            var rnd = new Random();

            Func <int, int, bool, float> random = (min, max, clamp) => {
                float num = (float)((double)rnd.Next(min, max) * rnd.NextDouble());
                if (!clamp)
                {
                    return(num);
                }
                else if (num < 1.0f)
                {
                    return(1.0f);
                }
                else
                {
                    return(num);
                }
            };

            Enumerable.Range(0, 200).Select <int, int> ((i) => Building(
                                                            random(2, 5, true),
                                                            random(2, 5, true),
                                                            random(2, 10, true),
                                                            random(-20, 20, false),
                                                            random(-20, 20, false),
                                                            scene,
                                                            rnd
                                                            )).ToArray();

            //Lights!
            var lightNode = new SCNNode()
            {
                Light    = new SCNLight(),
                Position = new SCNVector3(30.0F, 20.0F, 60.0F)
            };

            lightNode.Light.LightType = SCNLightType.Omni;
            scene.RootNode.AddChildNode(lightNode);

            var ambientLightNode = new SCNNode()
            {
                Light = new SCNLight()
            };

            ambientLightNode.Light.LightType = SCNLightType.Ambient;
            ambientLightNode.Light.Color     = UIColor.DarkGray;
            scene.RootNode.AddChildNode(ambientLightNode);

            //Camera!
            var cameraNode = new SCNNode()
            {
                Camera = new SCNCamera()
            };

            scene.RootNode.AddChildNode(cameraNode);
            cameraNode.Position = new SCNVector3(0.0F, 10.0F, 20.0F);

            var targetNode = new SCNNode()
            {
                Position = new SCNVector3(00.0F, 1.5F, 0.0F)
            };

            scene.RootNode.AddChildNode(targetNode);

            var lc = SCNLookAtConstraint.Create(targetNode);

            cameraNode.Constraints = new[] { lc };

            var scnView = new SCNView(UIScreen.MainScreen.Bounds)
            {
                Scene = scene,
                AllowsCameraControl = true,
                ShowsStatistics     = true,
                BackgroundColor     = UIColor.FromRGB(52, 152, 219)
            };

            var floorNode = new SCNNode {
                Geometry = new SCNPlane {
                    Height = 40.0F,
                    Width  = 40.0F
                },
                Position = SCNVector3.Zero
            };

            var pi2 = Math.PI / 2.0;

            floorNode.Orientation = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, (float)(0.0 - pi2));

            scene.RootNode.AddChildNode(floorNode);

            var material = new SCNMaterial();

            material.Diffuse.Contents            = UIImage.FromFile("Content/road.jpg");
            material.Diffuse.ContentsTransform   = SCNMatrix4.Scale(new SCNVector3(10.0f, 10.0f, 1.0f));
            material.Diffuse.MinificationFilter  = SCNFilterMode.Linear;
            material.Diffuse.MagnificationFilter = SCNFilterMode.Linear;
            material.Diffuse.MipFilter           = SCNFilterMode.Linear;
            material.Diffuse.WrapS     = SCNWrapMode.Repeat;
            material.Diffuse.WrapT     = SCNWrapMode.Repeat;
            material.Specular.Contents = UIColor.Gray;

            floorNode.Geometry.FirstMaterial = material;

            this.View = scnView;
        }
예제 #7
0
        internal BoundingBoxSide(PositionName position, NVector3 extent, UIColor color = null) : base()
        {
            if (color == null)
            {
                color = Utilities.AppYellow;
            }
            Tiles      = new List <Tile>();
            this.color = color;
            this.face  = position;

            // inline Swift setup() and setupExtensions() functions
            size = Size(extent);

            var   yAxis       = Axis.Y.Normal().ToSCNVector3();
            var   xAxis       = Axis.X.Normal().ToSCNVector3();
            var   zAxis       = Axis.Z.Normal().ToSCNVector3();
            float halfTurn    = (float)Math.PI;
            float quarterTurn = (float)Math.PI / 2;

            switch (face)
            {
            case PositionName.Front:
                LocalTranslate(new SCNVector3(0, 0, extent.Z / 2));
                break;

            case PositionName.Back:
                LocalTranslate(new SCNVector3(0, 0, -extent.Z / 2));
                LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, halfTurn));
                break;

            case PositionName.Left:
                LocalTranslate(new SCNVector3(-extent.X / 2, 0, 0));
                LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, -quarterTurn));
                break;

            case PositionName.Right:
                LocalTranslate(new SCNVector3(extent.X / 2, 0, 0));
                LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, quarterTurn));
                break;

            case PositionName.Bottom:
                LocalTranslate(new SCNVector3(0, -extent.Y / 2, 0));
                LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn));
                break;

            case PositionName.Top:
                LocalTranslate(new SCNVector3(0, extent.Y / 2, 0));
                LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, -quarterTurn));
                break;
            }

            for (int index = 0; index < 12; index++)
            {
                var line = new SCNNode();
                line.Geometry = Cylinder(lineThickness, extensionLength);
                if (index < 4)
                {
                    xAxisExtLines.Add(line);
                    line.LocalRotate(SCNQuaternion.FromAxisAngle(zAxis, -quarterTurn));
                    if (index == 2 || index == 3)
                    {
                        line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn));
                    }
                    xAxisExtNode.AddChildNode(line);
                }
                else if (index < 8)
                {
                    yAxisExtLines.Add(line);
                    if (index == 5 || index == 7)
                    {
                        line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn));
                    }
                    yAxisExtNode.AddChildNode(line);
                }
                else
                {
                    zAxisExtLines.Add(line);
                    line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, -quarterTurn));
                    zAxisExtNode.AddChildNode(line);
                }
            }

            UpdateExtensions();
            HideXAxisExtensions();
            HideYAxisExtensions();
            HideZAxisExtensions();

            AddChildNode(xAxisExtNode);
            AddChildNode(yAxisExtNode);
            AddChildNode(zAxisExtNode);
        }
예제 #8
0
        public SlingShotPose ComputeInputPose()
        {
            // note the -1 here differs from other usage
            var data = new SlingShotPose {
                UpVector = -this.UpVector                            /* negated because the strap Y-axis points down */
            };

            var startBend            = this.CurrentLengthL / this.CurrentTotalLength;
            var endBend              = 1f - this.CurrentLengthR / this.CurrentTotalLength;
            var leatherOnStraights   = this.OriginalLeatherLength - this.CurrentLengthOnBall;
            var segmentAStart        = 0f;
            var segmentAEnd          = this.CurrentLengthL - leatherOnStraights * 0.5f;
            var segmentCStart        = segmentAEnd + this.OriginalLeatherLength;
            var segmentCEnd          = this.CurrentTotalLength;
            var originalLeatherRange = this.OriginalLeatherLength / this.OriginalTotalLength;
            var currentLeatherRange  = this.OriginalLeatherLength / this.CurrentTotalLength;

            for (var i = 0; i < this.SimulatedTransformCount; i++)
            {
                var l = this.OriginalTotalLength * (float)i / (float)(this.SimulatedTransformCount - 1f);
                var u = l / this.OriginalTotalLength;

                // remap the u value depending on the material (rubber vs leather)
                var isRubber = Math.Abs(0.5f - u) > originalLeatherRange * 0.5f;
                if (isRubber)
                {
                    if (u < 0.5f)
                    {
                        u = u / (0.5f - originalLeatherRange * 0.5f);
                        u = (segmentAStart + (segmentAEnd - segmentAStart) * u) / this.CurrentTotalLength;
                    }
                    else
                    {
                        u = 1f - (1f - u) / (0.5f - originalLeatherRange * 0.5f);
                        u = (segmentCStart + (segmentCEnd - segmentCStart) * u) / this.CurrentTotalLength;
                    }
                }
                else
                {
                    u = (startBend + endBend) * 0.5f - (0.5f - u) * (currentLeatherRange / originalLeatherRange);
                }

                var p = SCNVector3.Zero;
                var t = SCNVector3.UnitX;
                if (u < startBend)
                {
                    // left straight
                    var value = u / startBend;
                    p = SimdExtensions.Mix(this.FixturePositionL,
                                           this.TangentPositionL,
                                           new SCNVector3(value, value, value)); // left rubber band
                    t = SCNVector3.Normalize(this.TangentPositionL - this.FixturePositionL);
                }
                else if (u > endBend)
                {
                    // right straight
                    var value = (1f - u) / (1f - endBend);
                    p = SimdExtensions.Mix(this.FixturePositionR,
                                           this.TangentPositionR,
                                           new SCNVector3(value, value, value)); // right rubber band
                    t = SCNVector3.Normalize(this.FixturePositionR - this.TangentPositionR);
                }
                else
                {
                    // on the ball
                    var upv = this.UpVector;
                    var rot = SCNQuaternion.FromAxisAngle(upv, -this.BetaAngle * (u - startBend) / (endBend - startBend));
                    p = this.ballPosition + rot.Act(this.TangentPositionL - this.ballPosition);
                    t = SCNVector3.Cross(upv, SCNVector3.Normalize(this.ballPosition - p));
                }

                data.Positions.Add(p);
                data.Tangents.Add(t);
                data.Lengths.Add(l);
            }

            return(data);
        }