From 1de157e2b02072f5efc473c0b15042ab3fb682fc Mon Sep 17 00:00:00 2001 From: Cupiii Date: Sun, 20 Mar 2022 21:36:42 +0100 Subject: [PATCH 1/5] Orientation Calculation more verbose and some documentation --- .../VisualPinball.Unity/VPT/Ball/BallData.cs | 22 +++++++++++++++++++ .../VPT/Ball/BallDisplacementSystem.cs | 5 ++++- .../VPT/Ball/BallMovementSystem.cs | 21 +++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs index 66018dbb7..2e3d1ca8b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs @@ -26,7 +26,24 @@ internal struct BallData : IComponentData public float3 Position; public float3 EventPosition; // m_lastEventPos public float3 Velocity; + + /// + /// AngularVelocity + /// * Set to 0 at start + /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) + /// (which is not used anywhere) + /// * Used to get tangential velocity due to rotation when rolling / colliding on surfaces (alsways added to normal velocity) + /// (in BallData.SurfaceVelocity(in BallData ball, in float3 surfP)) + /// * Calculated from AngularMomentum / inertia + /// (In BallDisplacementSystem.OnUpdate()) + /// (Where Inertia is a "constant" based on radius and mass (2/5 m r^2)) + /// public float3 AngularVelocity; + /// + /// AngularMomentum + /// * set to 0 at Start. + /// * When a survace applies an impule, it applies it to velocity and to angMom. () + /// public float3 AngularMomentum; public float3x3 Orientation; public float Radius; @@ -72,7 +89,12 @@ public float CollisionRadiusSqr { } } + /// + /// Calculates Moment of Inertia for a Ball + /// https://en.wikipedia.org/wiki/Moment_of_inertia#Examples_2 + /// public float Inertia => 2.0f / 5.0f * Radius * Radius * Mass; + public float InvMass => 1f / Mass; public void ApplySurfaceImpulse(in float3 rotI, in float3 impulse) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs index 9ac1cd938..8e92e938d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs @@ -1,4 +1,4 @@ -// Visual Pinball Engine +// Visual Pinball Engineball.Orientation // Copyright (C) 2022 freezy and VPE Team // // This program is free software: you can redistribute it and/or modify @@ -56,7 +56,10 @@ protected override void OnUpdate() ball.Orientation += addedOrientation; math.orthonormalize(ball.Orientation); + // https://docs.unity.cn/Packages/com.unity.mathematics@1.2/api/Unity.Mathematics.math.orthonormalize.html#Unity_Mathematics_math_orthonormalize_Unity_Mathematics_float3x3_ + // angular momentum = drehimpuls / Schwung, Impulsmomemt + // angular velocity = Winkelgeschwindigkeit ball.AngularVelocity = ball.AngularMomentum / inertia; marker.End(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs index 738d639cf..90fe14819 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs @@ -60,8 +60,20 @@ protected override void OnUpdate() var zHeight = !ball.IsFrozen ? ball.Position.z : ball.Position.z - ball.Radius; var or = ball.Orientation; + var vpright = new Vector3(or.c0.x, or.c1.x, or.c2.x); + var vpfront = new Vector3(or.c0.y, or.c1.y, or.c2.y); + var vptop = new Vector3(or.c0.z, or.c1.z, or.c2.z); + Debug.Log("c0: (" + or.c0.x + ", " + or.c0.y + ", " + or.c0.z + ")"); + Debug.Log("c1: (" + or.c1.x + ", " + or.c1.y + ", " + or.c1.z + ")"); + Debug.Log("c2: (" + or.c2.x + ", " + or.c2.y + ", " + or.c2.z + ")"); var ballTransform = _player.Balls[entity].transform; ballTransform.localPosition = new Vector3(ball.Position.x, ball.Position.y, zHeight); + Vector3.OrthoNormalize(ref vptop, ref vpfront, ref vpright); + + var unitytop = new Vector3(vptop.x, vptop.z, vptop.y); + var unityfront = new Vector3(vpfront.x, vpfront.z, vpfront.y); + + Vector3.OrthoNormalize(ref unitytop, ref unityfront); // Following is the transistion from VP-Physics Ball Orientation to the Unity Ball-Orientation. // following statements: when looking at the backglass: @@ -81,7 +93,14 @@ protected override void OnUpdate() //1st iteration by (looks strange, but less strange) (cupiii) //ballTransform.localRotation = Quaternion.LookRotation(new Vector3(or.c0.x*-1, or.c1.x*-1, or.c2.x), new Vector3(or.c0.z*-1, or.c1.z*-1, or.c2.z)); //newest iteration (hopefully correct)) - ballTransform.localRotation = Quaternion.LookRotation(new Vector3(or.c0.z*1f, or.c2.z*1f, or.c1.z*1f), new Vector3(or.c0.y*1f, or.c2.y*1f, or.c1.y*1f)); + + // Better Ways than skew matrix: + // https://gamedev.stackexchange.com/questions/108920/applying-angular-velocity-to-quaternion + // https://stackoverflow.com/questions/23503151/how-to-update-quaternion-based-on-3d-gyro-data + // https://stackoverflow.com/questions/12053895/converting-angular-velocity-to-quaternion-in-opencv + + ballTransform.localRotation = Quaternion.LookRotation(unityfront, unitytop); + marker.End(); From 070c2282b181689a217332873029afe2ae40768a Mon Sep 17 00:00:00 2001 From: Cupiii Date: Mon, 21 Mar 2022 19:18:19 +0100 Subject: [PATCH 2/5] Some more Comments --- .../VisualPinball.Unity/VPT/Ball/BallData.cs | 29 +++++++++++++++---- .../VPT/Ball/BallDisplacementSystem.cs | 18 ++++++++++++ .../VPT/Ball/BallMovementSystem.cs | 1 - 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs index 2e3d1ca8b..b3574cf97 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs @@ -29,20 +29,39 @@ internal struct BallData : IComponentData /// /// AngularVelocity - /// * Set to 0 at start + /// * Set to 0 at Manual Roll /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) /// (which is not used anywhere) - /// * Used to get tangential velocity due to rotation when rolling / colliding on surfaces (alsways added to normal velocity) - /// (in BallData.SurfaceVelocity(in BallData ball, in float3 surfP)) + /// * Is set to zero At RotatorComponent. Possibly an error and should be AngularVelocity + /// (in UpdateRotation(float angleDeg)) /// * Calculated from AngularMomentum / inertia /// (In BallDisplacementSystem.OnUpdate()) /// (Where Inertia is a "constant" based on radius and mass (2/5 m r^2)) + /// * Used to get tangential velocity due to rotation when rolling / colliding on surfaces (alsways added to normal velocity) + /// (in BallData.SurfaceVelocity(in BallData ball, in float3 surfP)) + /// public float3 AngularVelocity; /// /// AngularMomentum - /// * set to 0 at Start. - /// * When a survace applies an impule, it applies it to velocity and to angMom. () + /// * Set to 0 at Manual Roll + /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) + /// * Set to 0 at every new ball + /// (in Ballmanager.CreateEntity(GameObject ballGo, int id, in float3 worldPos, in float3 localPos, in float3 localVel, in float scale, in float mass, in float radius, in Entity kickerEntity) + /// * Set to 0 in KickerApi, KickerCollider and RotatorComponent + /// (in several places) + /// * Calculated when a survace applies an impulse, it applies it to velocity (div by mass) and to angMom fully. + /// (ApplySurfaceImpulse(in float3 rotI, in float3 impulse)) + /// (Where rotI seems to be the Rotation impulse and impulse is the (non angular)velocity (makes sense to divide by mass) + /// (angularMomenmtom = rotI;) + /// * used to calculate Angular Velocity (ball.AngularVelocity = ball.AngularMomentum / inertia;) + /// (in BalldisplacementSystem.OnUpdate()) + /// * used to add and thus calculate Orientation + /// (in BalldisplacementSystem.OnUpdate()) + /// skewSymmetricMatrix is created from the Angular Momentum divided by Inertia + /// The original orientation is multiplied with the skewSymmetric Matrix + /// and added to the old Orientation to form new orientation + /// /// public float3 AngularMomentum; public float3x3 Orientation; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs index 8e92e938d..db28c8a5e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs @@ -56,6 +56,7 @@ protected override void OnUpdate() ball.Orientation += addedOrientation; math.orthonormalize(ball.Orientation); + NormalizeOrientation(ball.Orientation); // https://docs.unity.cn/Packages/com.unity.mathematics@1.2/api/Unity.Mathematics.math.orthonormalize.html#Unity_Mathematics_math_orthonormalize_Unity_Mathematics_float3x3_ // angular momentum = drehimpuls / Schwung, Impulsmomemt @@ -67,6 +68,23 @@ protected override void OnUpdate() }).Run(); } + private void NormalizeOrientation(float3x3 orientation) + { + float lengthX, lengthY, lengthZ = 0f; + lengthX = math.sqrt(orientation.c0.x * orientation.c0.x + orientation.c1.x * orientation.c1.x + orientation.c2.x * orientation.c2.x); + lengthY = math.sqrt(orientation.c0.y * orientation.c0.y + orientation.c1.y * orientation.c1.y + orientation.c2.y * orientation.c2.y); + lengthZ = math.sqrt(orientation.c0.z * orientation.c0.z + orientation.c1.z * orientation.c1.z + orientation.c2.z * orientation.c2.z); + orientation.c0.x /= lengthX; + orientation.c1.x /= lengthX; + orientation.c2.x /= lengthX; + orientation.c0.y /= lengthY; + orientation.c1.y /= lengthY; + orientation.c2.y /= lengthY; + orientation.c0.z /= lengthZ; + orientation.c1.z /= lengthZ; + orientation.c2.z /= lengthZ; + } + private static float3x3 CreateSkewSymmetric(in float3 pv3D) { return new float3x3( diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs index 90fe14819..909f2a55f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs @@ -69,7 +69,6 @@ protected override void OnUpdate() var ballTransform = _player.Balls[entity].transform; ballTransform.localPosition = new Vector3(ball.Position.x, ball.Position.y, zHeight); Vector3.OrthoNormalize(ref vptop, ref vpfront, ref vpright); - var unitytop = new Vector3(vptop.x, vptop.z, vptop.y); var unityfront = new Vector3(vpfront.x, vpfront.z, vpfront.y); From f4009845452c1b6c168bc9f6c0ead2a6d0c300f0 Mon Sep 17 00:00:00 2001 From: Cupiii Date: Mon, 21 Mar 2022 21:06:18 +0100 Subject: [PATCH 3/5] NaN-Ball-Orientation-Fix and some comments on angularVelocity and angularMomentum --- .../VisualPinball.Unity/VPT/Ball/BallData.cs | 6 +-- .../VPT/Ball/BallDisplacementSystem.cs | 52 +++++++++++-------- .../VPT/Ball/BallMovementSystem.cs | 11 ++-- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs index b3574cf97..acb94ab29 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs @@ -28,7 +28,8 @@ internal struct BallData : IComponentData public float3 Velocity; /// - /// AngularVelocity + /// AngularVelocity - german: Winkelgeschwindigkeit + /// * Set to 0 at Manual Roll /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) /// (which is not used anywhere) @@ -39,11 +40,10 @@ internal struct BallData : IComponentData /// (Where Inertia is a "constant" based on radius and mass (2/5 m r^2)) /// * Used to get tangential velocity due to rotation when rolling / colliding on surfaces (alsways added to normal velocity) /// (in BallData.SurfaceVelocity(in BallData ball, in float3 surfP)) - /// public float3 AngularVelocity; /// - /// AngularMomentum + /// AngularMomentum - german: drehimpuls, Impulsmomemt /// * Set to 0 at Manual Roll /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) /// * Set to 0 at every new ball diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs index db28c8a5e..337b79bdc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs @@ -56,11 +56,38 @@ protected override void OnUpdate() ball.Orientation += addedOrientation; math.orthonormalize(ball.Orientation); - NormalizeOrientation(ball.Orientation); - // https://docs.unity.cn/Packages/com.unity.mathematics@1.2/api/Unity.Mathematics.math.orthonormalize.html#Unity_Mathematics_math_orthonormalize_Unity_Mathematics_float3x3_ - // angular momentum = drehimpuls / Schwung, Impulsmomemt - // angular velocity = Winkelgeschwindigkeit + // after Othonomalization, the Orientation vectors also have to be normalized - this is not done by othonomalize, since the skew matrix creates quite lengthy vectors. + // in fact, they dont have to be normalized, but just shortened, so we can abs-add the x, y and z together and just divide by the sum. + // This saves three qrts in the game loop per ball. + float lengthX, lengthY, lengthZ; + /* Correct normalization would be: + * lengthX = math.sqrt(ball.Orientation.c0.x * ball.Orientation.c0.x + ball.Orientation.c0.y * ball.Orientation.c0.y + ball.Orientation.c0.z * ball.Orientation.c0.z); + * lengthY = math.sqrt(ball.Orientation.c1.x * ball.Orientation.c1.x + ball.Orientation.c1.y * ball.Orientation.c1.y + ball.Orientation.c1.z * ball.Orientation.c1.z); + * lengthZ = math.sqrt(ball.Orientation.c2.x * ball.Orientation.c2.x + ball.Orientation.c2.y * ball.Orientation.c2.y + ball.Orientation.c2.z * ball.Orientation.c2.z); + */ + lengthX = math.abs(ball.Orientation.c0.x) + math.abs(ball.Orientation.c0.y) + math.abs(ball.Orientation.c0.z); + lengthY = math.abs(ball.Orientation.c1.x) + math.abs(ball.Orientation.c1.y) + math.abs(ball.Orientation.c1.z); + lengthZ = math.abs(ball.Orientation.c2.x) + math.abs(ball.Orientation.c2.y) + math.abs(ball.Orientation.c2.z); + if (lengthX != 0f) + { + ball.Orientation.c0.x /= lengthX; + ball.Orientation.c0.y /= lengthX; + ball.Orientation.c0.z /= lengthX; + } + if (lengthY != 0f) + { + ball.Orientation.c1.x /= lengthY; + ball.Orientation.c1.y /= lengthY; + ball.Orientation.c1.z /= lengthY; + } + if (lengthZ != 0f) + { + ball.Orientation.c2.x /= lengthZ; + ball.Orientation.c2.y /= lengthZ; + ball.Orientation.c2.z /= lengthZ; + } + ball.AngularVelocity = ball.AngularMomentum / inertia; marker.End(); @@ -68,23 +95,6 @@ protected override void OnUpdate() }).Run(); } - private void NormalizeOrientation(float3x3 orientation) - { - float lengthX, lengthY, lengthZ = 0f; - lengthX = math.sqrt(orientation.c0.x * orientation.c0.x + orientation.c1.x * orientation.c1.x + orientation.c2.x * orientation.c2.x); - lengthY = math.sqrt(orientation.c0.y * orientation.c0.y + orientation.c1.y * orientation.c1.y + orientation.c2.y * orientation.c2.y); - lengthZ = math.sqrt(orientation.c0.z * orientation.c0.z + orientation.c1.z * orientation.c1.z + orientation.c2.z * orientation.c2.z); - orientation.c0.x /= lengthX; - orientation.c1.x /= lengthX; - orientation.c2.x /= lengthX; - orientation.c0.y /= lengthY; - orientation.c1.y /= lengthY; - orientation.c2.y /= lengthY; - orientation.c0.z /= lengthZ; - orientation.c1.z /= lengthZ; - orientation.c2.z /= lengthZ; - } - private static float3x3 CreateSkewSymmetric(in float3 pv3D) { return new float3x3( diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs index 909f2a55f..eae1b485c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs @@ -58,16 +58,17 @@ protected override void OnUpdate() // calculate/adapt height of ball var zHeight = !ball.IsFrozen ? ball.Position.z : ball.Position.z - ball.Radius; + var ballTransform = _player.Balls[entity].transform; + ballTransform.localPosition = new Vector3(ball.Position.x, ball.Position.y, zHeight); + var or = ball.Orientation; var vpright = new Vector3(or.c0.x, or.c1.x, or.c2.x); var vpfront = new Vector3(or.c0.y, or.c1.y, or.c2.y); var vptop = new Vector3(or.c0.z, or.c1.z, or.c2.z); - Debug.Log("c0: (" + or.c0.x + ", " + or.c0.y + ", " + or.c0.z + ")"); - Debug.Log("c1: (" + or.c1.x + ", " + or.c1.y + ", " + or.c1.z + ")"); - Debug.Log("c2: (" + or.c2.x + ", " + or.c2.y + ", " + or.c2.z + ")"); - var ballTransform = _player.Balls[entity].transform; - ballTransform.localPosition = new Vector3(ball.Position.x, ball.Position.y, zHeight); + // Debug.Log("c0: (" + or.c0.x + ", " + or.c0.y + ", " + or.c0.z + ")"); + // Debug.Log("c1: (" + or.c1.x + ", " + or.c1.y + ", " + or.c1.z + ")"); + // Debug.Log("c2: (" + or.c2.x + ", " + or.c2.y + ", " + or.c2.z + ")"); Vector3.OrthoNormalize(ref vptop, ref vpfront, ref vpright); var unitytop = new Vector3(vptop.x, vptop.z, vptop.y); var unityfront = new Vector3(vpfront.x, vpfront.z, vpfront.y); From d78531c177a7f0276da98f7091fc66225fc0c2e3 Mon Sep 17 00:00:00 2001 From: Cupiii Date: Tue, 22 Mar 2022 18:25:29 +0100 Subject: [PATCH 4/5] Typos and reference to ravarcades ImGUI-Debug-Addon --- VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs | 2 +- .../VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs index acb94ab29..e64f1c14e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallData.cs @@ -32,7 +32,7 @@ internal struct BallData : IComponentData /// * Set to 0 at Manual Roll /// (in BallManualRoll(in Entity entity, in float3 targetWorldPosition) - /// (which is not used anywhere) + /// (which is not used anywhere in this Project, but is at least used in Ravarcade's ImGui Physics Debugger - Addon) /// * Is set to zero At RotatorComponent. Possibly an error and should be AngularVelocity /// (in UpdateRotation(float angleDeg)) /// * Calculated from AngularMomentum / inertia diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs index 337b79bdc..a20d7d805 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallDisplacementSystem.cs @@ -57,9 +57,9 @@ protected override void OnUpdate() ball.Orientation += addedOrientation; math.orthonormalize(ball.Orientation); - // after Othonomalization, the Orientation vectors also have to be normalized - this is not done by othonomalize, since the skew matrix creates quite lengthy vectors. + // after Orthonormalization, the orientation vectors also have to be normalized - this is not done by othonomalize, since the skew matrix creates quite lengthy vectors. // in fact, they dont have to be normalized, but just shortened, so we can abs-add the x, y and z together and just divide by the sum. - // This saves three qrts in the game loop per ball. + // This saves three sqrts in the game loop per ball. float lengthX, lengthY, lengthZ; /* Correct normalization would be: * lengthX = math.sqrt(ball.Orientation.c0.x * ball.Orientation.c0.x + ball.Orientation.c0.y * ball.Orientation.c0.y + ball.Orientation.c0.z * ball.Orientation.c0.z); From 0ca680acf74b6242b569abc139028c3eae336944 Mon Sep 17 00:00:00 2001 From: Cupiii Date: Tue, 22 Mar 2022 18:51:14 +0100 Subject: [PATCH 5/5] NAN-Fix Gave hint to Orthonormalize-code in vp for future performance upgrades. --- .../VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs index eae1b485c..5a343a223 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallMovementSystem.cs @@ -99,6 +99,9 @@ protected override void OnUpdate() // https://stackoverflow.com/questions/23503151/how-to-update-quaternion-based-on-3d-gyro-data // https://stackoverflow.com/questions/12053895/converting-angular-velocity-to-quaternion-in-opencv + // also implementing VP's "Orthonormalize" Code - although it does not really orthonormalize could give a performance benefit: + // https://github.com/vpinball/vpinball/blob/be08b04d61096272df97bd45e6f0682043228a73/math/matrix.h#L208 + ballTransform.localRotation = Quaternion.LookRotation(unityfront, unitytop);