/*public void OrbitTargetUpDownNatural( double theta_degrees ) * { * float fn = Forward.Val % NaturalUp.Val; * if( ( theta_degrees < 0.0 && fn >= 0.95f ) || ( theta_degrees > 0.0 && fn <= -0.95f ) ) return; * * double theta = theta_degrees * Math.PI / 180.0; * Vec3f posreltar = Position.Val - Target.Val; * Vec3f right = Forward.Val ^ NaturalUp.Val; * float dist = (Target.Val - Position.Val).Length; * * Properties.DeferPropertyChanged = true; * bIgnoreChanges = true; * Position.Set( Target.Val + Vec3f.Normalize( VecExtensions.RotateVectorAroundAxis( posreltar, right, (float) theta ) ) * dist ); * Up.Set( VecExtensions.RotateVectorAroundAxis( Up.Val, right, (float) theta ) ); * bIgnoreChanges = false; * Target.Set( Target.Val ); * Properties.DeferPropertyChanged = false; * }*/ public void OrbitTargetUpDown(double theta_degrees, bool clampflips) { double theta = theta_degrees * Math.PI / 180.0; Quatf newrot = qrot * Quatf.AxisAngleToQuatf(GetRight(), (float)theta); if (clampflips) { // prevent camera from flipping over! Vec3f newup = Vec3f.Normalize(newrot.Rotate(Vec3f.Y)); float dot = FMath.PI / 2.0f - Vec3f.AngleBetween(newup, NaturalUp.Val); if (dot < 0) { Vec3f newforward = Vec3f.Normalize(newrot.Rotate(-Vec3f.Z)); Vec3f newright = newforward ^ newup; float sign = -Math.Sign(newforward % NaturalUp.Val); newrot = newrot * Quatf.RotAxisAngleToQuatf(newright, dot * sign); } } Set(Target.Val, newrot, dist); }