// End the game if the object has its initial orientation with a 10 degree tolerance.
        void EndGameOnCorrectOrientation()
        {
            if (!gameNodes.HasValue || !gameStarted)
            {
                return;
            }

            var gNodes = gameNodes.Value;

            var transform = gNodes.Object.Transform;
            var unitX     = new SCNVector4(1, 0, 0, 0);
            var unitY     = new SCNVector4(0, 1, 0, 0);

            var tX = SCNVector4.Transform(unitX, transform);
            var tY = SCNVector4.Transform(unitY, transform);

            float toleranceDegree = 10;
            var   max_cos_angle   = Math.Cos(toleranceDegree * Math.PI / 180);
            var   cos_angleX      = SCNVector4.Dot(unitX, tX);
            var   cos_angleY      = SCNVector4.Dot(unitY, tY);

            if (cos_angleX >= max_cos_angle && cos_angleY >= max_cos_angle)
            {
                EndGame();
            }
        }
示例#2
0
        public static SCNMatrix4 ToSCNMatrix4(this NMatrix4 self)
        {
            var row0 = new SCNVector4(self.M11, self.M12, self.M13, self.M14);
            var row1 = new SCNVector4(self.M21, self.M22, self.M23, self.M24);
            var row2 = new SCNVector4(self.M31, self.M32, self.M33, self.M34);
            var row3 = new SCNVector4(self.M41, self.M42, self.M43, self.M44);

            return(new SCNMatrix4(row0, row1, row2, row3));
        }
        private void ApplyRandomTorque(SCNPhysicsBody physicsBody, float maxTorque)
        {
            var randomAxis = new SCNVector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());

            randomAxis = SCNVector3.Normalize(randomAxis);

            var randomTorque = new SCNVector4(randomAxis, (float)(random.NextDouble() * 2d - 1d) * maxTorque);

            physicsBody.ApplyTorque(randomTorque, true);
        }
示例#4
0
        public static SCNVector4 Lerp(SCNVector4 vectorStart, SCNVector4 vectorEnd, nfloat t)
        {
            var v = new SCNVector4(
                vectorStart.X + ((vectorEnd.X - vectorStart.X) * t),
                vectorStart.Y + ((vectorEnd.Y - vectorStart.Y) * t),
                vectorStart.Z + ((vectorEnd.Z - vectorStart.Z) * t),
                vectorStart.W + ((vectorEnd.W - vectorStart.W) * t)
                );

            return(v);
        }
示例#5
0
		public static SCNVector4 Lerp (SCNVector4 vectorStart, SCNVector4 vectorEnd, nfloat t)
		{
			var v = new SCNVector4 (
				        vectorStart.X + ((vectorEnd.X - vectorStart.X) * t),
				        vectorStart.Y + ((vectorEnd.Y - vectorStart.Y) * t),
				        vectorStart.Z + ((vectorEnd.Z - vectorStart.Z) * t),
				        vectorStart.W + ((vectorEnd.W - vectorStart.W) * t)
			        );

			return v;
		}
示例#6
0
        /// Matrix-Vector multiplication.  Keep in mind that matrix types are named
        /// `FloatNxM` where `N` is the number of *columns* and `M` is the number of
        /// *rows*, so we multiply a `Float3x2 * Float3` to get a `Float2`, for
        /// example.
        internal static SCNVector4 Times(this SCNMatrix4 self, SCNVector4 vec)
        {
            Func <SCNVector4, float>        elementSum    = v => v.X + v.Y + v.Z + v.W;
            Func <SCNVector4, float, float> rowTimesVecEl = (row, s) => elementSum(SCNVector4.Multiply(row, s));
            var x = rowTimesVecEl(self.Row0, vec.X);
            var y = rowTimesVecEl(self.Row1, vec.Y);
            var z = rowTimesVecEl(self.Row2, vec.Z);
            var w = rowTimesVecEl(self.Row3, vec.W);

            return(new SCNVector4(x, y, z, w));
        }
示例#7
0
        void AssertEqual(SCNVector4 vector, string message, pfloat m1, pfloat m2, pfloat m3, pfloat m4)
        {
            if (m1 == vector.X && m2 == vector.Y && m3 == vector.Z && m4 == vector.W)
            {
                return;
            }

            var expectedString = vector.ToString();
            var actualString   = $"({m1}, {m2}, {m3}, {m4})";

            Assert.Fail($"Expected vector:\n{expectedString}\nActual vector:\n{actualString}\n{message}");
        }
示例#8
0
        internal static SCNVector3?UnprojectPointLocal(this ARSCNView self, CGPoint point, NMatrix4 planeTransform)
        {
            var result = self.Unproject(point, planeTransform);
            // Convert the result into the plane's local coordinate system.
            var pt            = new SCNVector4(result.X, result.Y, result.Z, 1);
            var invertedPlane = planeTransform.ToSCNMatrix4();

            invertedPlane.Invert();
            var localResult = invertedPlane.Times(pt);

            return(localResult.Xyz);
        }
示例#9
0
        public void Vector()
        {
            var v = new SCNVector4();
            var u = SCNVector4.UnitX;

#if !XAMCORE_2_0
            // that was possible in classic - but will now trigger a CS0198
            SCNVector4.UnitX = v;
#else
            u.X = 2;
#endif
            Assert.That(SCNVector4.UnitX, Is.Not.EqualTo(u), "UnitX");

            u = SCNVector4.UnitY;
#if !XAMCORE_2_0
            // that was possible in classic - but will now trigger a CS0198
            SCNVector4.UnitY = v;
#else
            u.Y = 2;
#endif
            Assert.That(SCNVector4.UnitY, Is.Not.EqualTo(u), "UnitY");

            u = SCNVector4.UnitZ;
#if !XAMCORE_2_0
            // that was possible in classic - but will now trigger a CS0198
            SCNVector4.UnitZ = v;
#else
            u.Z = 2;
#endif
            Assert.That(SCNVector4.UnitZ, Is.Not.EqualTo(u), "UnitZ");

            u = SCNVector4.UnitW;
#if !XAMCORE_2_0
            // that was possible in classic - but will now trigger a CS0198
            SCNVector4.UnitW = v;
#else
            u.W = 2;
#endif
            Assert.That(SCNVector4.UnitW, Is.Not.EqualTo(u), "UnitW");

            u = SCNVector4.Zero;
#if !XAMCORE_2_0
            // that was possible in classic - but will now trigger a CS0198
            SCNVector4.Zero = v;
            Assert.That(SCNVector4.Zero, Is.EqualTo(u), "Zero");
#else
            u.W = 2;
            Assert.That(SCNVector4.Zero, Is.Not.EqualTo(u), "Zero");
#endif
        }
示例#10
0
        public static SCNMatrix4 Normalize(this SCNMatrix4 matrix)
        {
            // for row-major matrixes only
            var normalized = matrix;

            var row0 = SCNVector4.Normalize(matrix.Row0);
            var row1 = SCNVector4.Normalize(matrix.Row1);
            var row2 = SCNVector4.Normalize(matrix.Row2);

            normalized.Row0 = row0;
            normalized.Row1 = row1;
            normalized.Row2 = row2;

            return(normalized);
        }
示例#11
0
        private void UpdateCatapultStable()
        {
            if (!this.Disabled)
            {
                // Catapult will be unstable when the physics settles, therefore we do not update catapult's stability status
                if (GameTime.TimeSinceLevelStart > CatapultPhysicsSettleTime)
                {
                    // Cannot use simdVelocity on client since simdVelocity could be high from physicsSync interacting with local physics engine
                    if (!this.lastPosition.HasValue)
                    {
                        this.lastPosition = this.Base.PresentationNode.WorldPosition;
                        return;
                    }

                    var position = this.Base.PresentationNode.WorldPosition;
                    var speed    = ((position - this.lastPosition.Value) / (float)GameTime.DeltaTime).Length;
                    this.lastPosition = position;

                    // Base below table?
                    // Base tilted? base's up vector must maintain some amount of y to be determined as stable
                    var transform = this.Base.PresentationNode.Transform;
                    transform.Transpose();
                    var baseUp = SCNVector4.Normalize(transform.Column1);
                    if (position.Y < -1f || Math.Abs(baseUp.Y) < MinStableTiltBaseUpY)
                    {
                        // Switch to knocked mode
                        if (!this.isCatapultKnocked)
                        {
                            this.catapultKnockedStartTime = GameTime.Time;
                        }

                        this.isCatapultKnocked = true;
                        this.isCatapultStable  = false;
                        return;
                    }

                    this.isCatapultKnocked = false;

                    // Base could be moving although the catapult is not knocked
                    this.isCatapultStable = speed < MaxSpeedToCountAsStable;
                }
            }
        }
示例#12
0
        public static SCNMatrix4 Interpolate(SCNMatrix4 scnm0, SCNMatrix4 scnmf, nfloat factor)
        {
            SCNVector4 p0 = scnm0.Row3;
            SCNVector4 pf = scnmf.Row3;

            var q0 = scnm0.ToQuaternion();
            var qf = scnmf.ToQuaternion();

            SCNVector4    pTmp = Lerp(p0, pf, factor);
            SCNQuaternion qTmp = SCNQuaternion.Slerp(q0, qf, (float)factor);
            SCNMatrix4    rTmp = qTmp.ToMatrix4();

            SCNMatrix4 transform = new SCNMatrix4(
                rTmp.M11, rTmp.M12, rTmp.M13, 0.0f,
                rTmp.M21, rTmp.M22, rTmp.M23, 0.0f,
                rTmp.M31, rTmp.M32, rTmp.M33, 0.0f,
                pTmp.X, pTmp.Y, pTmp.Z, 1.0f
                );

            return(transform);
        }
示例#13
0
        private void UpdateTransform(SCNVector3 position, ARCamera camera)
        {
            // Add to list of recently visited positions
            RecentFocusSquarePositions[recentFocusSquarePositionIndex] = position;
            // Increment current position, rolling over to beginning
            recentFocusSquarePositionIndex = ++recentFocusSquarePositionIndex % RecentFocusSquarePositions.Length;
            // Note that we don't really care about "current position" as we just average all the positions

            // Move to average of recent positions to avoid jitter
            var average = Utilities.AverageVector3List(RecentFocusSquarePositions);

            Position = average;
            this.SetUniformScale(ScaleBasedOnDistance(camera));

            // Correct y rotation of camera square
            if (camera != null)
            {
                var tilt       = (float)Math.Abs(camera.EulerAngles.X);
                var threshold1 = (float)(Math.PI / 2f * 0.65f);
                var threshold2 = (float)(Math.PI / 2f * 0.75f);
                var yaw        = (float)Math.Atan2(camera.Transform.M11, camera.Transform.M12);
                var angle      = 0f;

                if (tilt >= 0 && tilt < threshold1)
                {
                    angle = camera.EulerAngles.Y;
                }
                else if (threshold1 < threshold2)
                {
                    var relativeInRange = Math.Abs((tilt - threshold1) / (threshold2 / threshold1));
                    var normalizedY     = Normalize(camera.EulerAngles.Y, yaw);
                    angle = normalizedY * (1 - relativeInRange) + yaw * relativeInRange;
                }
                else
                {
                    angle = yaw;
                }
                Rotation = new SCNVector4(0, 1, 0, angle);
            }
        }
示例#14
0
        unsafe void UpdatePose()
        {
            float[] mPoseBuffer    = new float[16];
            int     mTrackingState = 0;

            fixed(float *ptr = &mPoseBuffer[0])
            {
                // R T
                // 0 1
                int bufferSize = 16;

                mTrackingState = SDPlugin.SixDegreesSDK_GetPose(ptr, bufferSize);
            }

            switch (mTrackingState)
            {
            case (int)SDPlugin.SDTrackingQuality.Good:
            case (int)SDPlugin.SDTrackingQuality.Limited:
            {
                if (mTrackingState > 0)
                {
                    // Update camera pose
                    var        row0       = new SCNVector4(mPoseBuffer[0], mPoseBuffer[1], mPoseBuffer[2], mPoseBuffer[3]);
                    var        row1       = new SCNVector4(mPoseBuffer[4], mPoseBuffer[5], mPoseBuffer[6], mPoseBuffer[7]);
                    var        row2       = new SCNVector4(mPoseBuffer[8], mPoseBuffer[9], mPoseBuffer[10], mPoseBuffer[11]);
                    var        row3       = new SCNVector4(mPoseBuffer[12], mPoseBuffer[13], mPoseBuffer[14], mPoseBuffer[15]);
                    SCNMatrix4 poseMatrix = new SCNMatrix4(row0, row1, row2, row3);
                }

                break;
            }

            case (int)SDPlugin.SDTrackingQuality.None:
            default:
            {
                break;
            }
            }
        }
示例#15
0
        public static SCNVector4 Multiply(this SCNMatrix4 matrix, SCNVector4 vector)
        {
            var x = matrix.Column0.X * vector.X;
            var y = matrix.Column0.Y * vector.X;
            var z = matrix.Column0.Z * vector.X;
            var w = matrix.Column0.W * vector.X;

            x += matrix.Column1.X * vector.Y;
            y += matrix.Column1.Y * vector.Y;
            z += matrix.Column1.Z * vector.Y;
            w += matrix.Column1.W * vector.Y;

            x += matrix.Column2.X * vector.Z;
            y += matrix.Column2.Y * vector.Z;
            z += matrix.Column2.Z * vector.Z;
            w += matrix.Column2.W * vector.Z;

            x += matrix.Column3.X * vector.W;
            y += matrix.Column3.Y * vector.W;
            z += matrix.Column3.Z * vector.W;
            w += matrix.Column3.W * vector.W;

            return(new SCNVector4(x, y, z, w));
        }
示例#16
0
        public void Vector()
        {
            var v = new SCNVector4();
            var u = SCNVector4.UnitX;

            u.X = 2;
            Assert.That(SCNVector4.UnitX, Is.Not.EqualTo(u), "UnitX");

            u   = SCNVector4.UnitY;
            u.Y = 2;
            Assert.That(SCNVector4.UnitY, Is.Not.EqualTo(u), "UnitY");

            u   = SCNVector4.UnitZ;
            u.Z = 2;
            Assert.That(SCNVector4.UnitZ, Is.Not.EqualTo(u), "UnitZ");

            u   = SCNVector4.UnitW;
            u.W = 2;
            Assert.That(SCNVector4.UnitW, Is.Not.EqualTo(u), "UnitW");

            u   = SCNVector4.Zero;
            u.W = 2;
            Assert.That(SCNVector4.Zero, Is.Not.EqualTo(u), "Zero");
        }
		// End the game if the object has its initial orientation with a 10 degree tolerance.
		void EndGameOnCorrectOrientation ()
		{
			if (!gameNodes.HasValue || !gameStarted)
				return;

			var gNodes = gameNodes.Value;

			var transform = gNodes.Object.Transform;
			var unitX = new SCNVector4 (1, 0, 0, 0);
			var unitY = new SCNVector4 (0, 1, 0, 0);

			var tX = SCNVector4.Transform (unitX, transform);
			var tY = SCNVector4.Transform (unitY, transform);

			float toleranceDegree = 10;
			var max_cos_angle = Math.Cos (toleranceDegree * Math.PI / 180);
			var cos_angleX = SCNVector4.Dot (unitX, tX);
			var cos_angleY = SCNVector4.Dot (unitY, tY);

			if (cos_angleX >= max_cos_angle && cos_angleY >= max_cos_angle)
				EndGame ();
		}
示例#18
0
 public static bool AlmostEqual(this SCNVector4 self, SCNVector4 value, float tolerance)
 {
     return((self - value).Length <= tolerance);
 }
示例#19
0
 public static bool HasNaN(this SCNVector4 self)
 {
     return(float.IsNaN(self.X) || float.IsNaN(self.Y) || float.IsNaN(self.Z) || float.IsNaN(self.W));
 }
示例#20
0
        private SCNVector3 ComputeBallPosition(CameraInfo cameraInfo)
        {
            var cameraRay = cameraInfo.Ray;

            // These should be based on the projectile radius.
            // This affects centering of ball, and can hit near plane of camera
            // This is always centering to one edge of screen independent of screen orient
            // We always want the ball at the bottom of the screen.
            var distancePullToCamera = 0.21f;
            var ballShiftDown        = 0.2f;

            var targetBallPosition = cameraRay.Position + cameraRay.Direction * distancePullToCamera;

            var cameraDown = -SCNVector4.Normalize(cameraInfo.Transform.Column1).Xyz;

            targetBallPosition += cameraDown * ballShiftDown;

            // Clamp to only the valid side
            var pullWorldPosition = this.pullOrigin.WorldPosition;

            if (pullWorldPosition.Z < 0f)
            {
                targetBallPosition.Z = Math.Min(targetBallPosition.Z, pullWorldPosition.Z);
            }
            else
            {
                targetBallPosition.Z = Math.Max(targetBallPosition.Z, pullWorldPosition.Z);
            }

            // Clamp to cone/circular core
            var yDistanceFromPull       = Math.Max(0f, pullWorldPosition.Y - targetBallPosition.Y);
            var minBallDistanceFromPull = 0.5f;
            var pullBlockConeSlope      = 1.0f;
            var pullBlockConeRadius     = yDistanceFromPull / pullBlockConeSlope;
            var pullBlockCoreRadius     = Math.Max(minBallDistanceFromPull, pullBlockConeRadius);

            // if pull is in the core, move it out.
            var pullWorldPositionGrounded  = new SCNVector3(pullWorldPosition.X, 0f, pullWorldPosition.Z);
            var targetPullPositionGrounded = new SCNVector3(targetBallPosition.X, 0f, targetBallPosition.Z);
            var targetInitialToTargetPull  = targetPullPositionGrounded - pullWorldPositionGrounded;

            if (pullBlockCoreRadius > targetInitialToTargetPull.Length)
            {
                var moveOutDirection = SCNVector3.Normalize(targetInitialToTargetPull);
                var newTargetPullPositionGrounded = pullWorldPositionGrounded + moveOutDirection * pullBlockCoreRadius;
                targetBallPosition = new SCNVector3(newTargetPullPositionGrounded.X, targetBallPosition.Y, newTargetPullPositionGrounded.Z);
            }

            // only use the 2d distance, so that user can gauage stretch indepdent of mtch
            var distance2D = targetBallPosition - pullWorldPosition;
            var stretchY   = Math.Abs(distance2D.Y);

            distance2D.Y = 0f;

            var stretchDistance = distance2D.Length;

            this.stretch = DigitExtensions.Clamp((double)stretchDistance, this.properties.MinStretch, this.properties.MaxStretch);

            // clamp a little bit farther than maxStretch
            // can't let the strap move back too far right now
            var clampedStretchDistance = (float)(1.1d * this.properties.MaxStretch);

            if (stretchDistance > clampedStretchDistance)
            {
                targetBallPosition = (clampedStretchDistance / stretchDistance) * (targetBallPosition - pullWorldPosition) + pullWorldPosition;
                stretchDistance    = clampedStretchDistance;
            }

            // Make this optional, not required.  You're often at max stretch.
            // Also have a timer for auto-launch.  This makes it very difficuilt to test
            // storing state in member data
            this.IsPulledTooFar = stretchDistance > (float)(this.properties.MaxStretch) || stretchY > (float)(this.properties.MaxStretch);

            return(targetBallPosition);
        }
示例#21
0
 public static void SetFloat4(this SCNGeometry geometry, string uniform, SCNVector4 value)
 {
     geometry.SetValueForKey(NSValue.FromVector(value), new NSString(uniform));
 }
示例#22
0
        public void Draw(MTKView view)
        {
            if (!SDPlugin.IsSDKReady)
            {
                return;
            }

            // Update sizes
            if (backgroundTextureSize.Width == 0 && backgroundTextureSize.Height == 0)
            {
                var size = MakeBackgroundTextureSize();
                backgroundTextureSize = size;
                UpdateMTKViewFrame();
            }

            // Draw meshes
            if (SDPlugin.ShowMesh)
            {
                MeshController.Update();
            }

            // Get pose and tracking quality
            var localOrientation = UIApplication.SharedApplication.StatusBarOrientation;

            float[] mPoseBuffer     = new float[16];
            int     trackingQuality = 0;

            unsafe
            {
                fixed(float *ptr = &mPoseBuffer[0])
                {
                    // R T
                    // 0 1
                    int bufferSize = 16;

                    trackingQuality = SDPlugin.SixDegreesSDK_GetPose(ptr, bufferSize);
                }
            }

            if (trackingQuality > 0)
            {
                // Update camera pose
                var        row0       = new SCNVector4(mPoseBuffer[0], mPoseBuffer[1], mPoseBuffer[2], mPoseBuffer[3]);
                var        row1       = new SCNVector4(mPoseBuffer[4], mPoseBuffer[5], mPoseBuffer[6], mPoseBuffer[7]);
                var        row2       = new SCNVector4(mPoseBuffer[8], mPoseBuffer[9], mPoseBuffer[10], mPoseBuffer[11]);
                var        row3       = new SCNVector4(mPoseBuffer[12], mPoseBuffer[13], mPoseBuffer[14], mPoseBuffer[15]);
                SCNMatrix4 poseMatrix = new SCNMatrix4(row0, row1, row2, row3);

                CameraNode.WorldTransform = poseMatrix;

                // Update camera projection
                var projectionTransform = MakeProjectionMatrix(localOrientation);
                CameraNode.Camera.ProjectionTransform = projectionTransform;
            }

            // Update vertex factory
            if (vertexFactory.IsComplete == false || orientation != localOrientation)
            {
                vertexFactory.Update(localOrientation, backgroundTextureSize);
            }
            orientation = localOrientation;

            // Draw background texture
            var texturePtr = SDPlugin.SixDegreesSDK_GetBackgroundTexture();

            if (texturePtr != IntPtr.Zero)
            {
                var obj = ObjCRuntime.Runtime.GetINativeObject <IMTLTexture>(texturePtr, false);
                Draw((IMTLTexture)obj);
            }

            if (commandQueue != null)
            {
                var    commandBuffer   = commandQueue.CommandBuffer();
                var    currentDrawable = mtkView.CurrentDrawable;
                double CurrentTime     = CAAnimation.CurrentMediaTime();
                var    screenScale     = UIScreen.MainScreen.Scale;
                var    viewport        = new CGRect(x: 0, y: 0,
                                                    width: mtkView.Frame.Width * screenScale,
                                                    height: mtkView.Frame.Height * screenScale);

                var renderPassDescriptor = MTLRenderPassDescriptor.CreateRenderPassDescriptor();
                renderPassDescriptor.ColorAttachments[0].Texture     = currentDrawable.Texture;
                renderPassDescriptor.ColorAttachments[0].LoadAction  = MTLLoadAction.Load;
                renderPassDescriptor.ColorAttachments[0].StoreAction = MTLStoreAction.Store;

                renderer.Render(CurrentTime,
                                viewport,
                                commandBuffer,
                                renderPassDescriptor);

                commandBuffer.PresentDrawable(currentDrawable);
                commandBuffer.Commit();
            }
        }