/// <summary> /// A direction interpolated between the two given directions. /// </summary> /// <param name="slon">Start longitude.</param> /// <param name="slat">Start latitude.</param> /// <param name="elon">End longitude.</param> /// <param name="elat">End latitude.</param> /// <param name="t">Interpolation.</param> /// <param name="lon">Output longitude.</param> /// <param name="lat">Output latitude.</param> public virtual void InterpolateDirection(double slon, double slat, double elon, double elat, double t, ref double lon, ref double lat) { var s = new Vector3d(Math.Cos(slon) * Math.Cos(slat), Math.Sin(slon) * Math.Cos(slat), Math.Sin(slat)); var e = new Vector3d(Math.Cos(elon) * Math.Cos(elat), Math.Sin(elon) * Math.Cos(elat), Math.Sin(elat)); var v = (s * (1.0 - t) + e * t).Normalized(); lat = Functions.Safe_Asin(v.z); lon = Math.Atan2(v.y, v.x); }
public override void Move(Vector3d oldp, Vector3d p, double speed) { var oldPosition = oldp.Normalized(); var position = p.Normalized(); var oldlat = Functions.Safe_Asin(oldPosition.z); var oldlon = Math.Atan2(oldPosition.y, oldPosition.x); var lat = Functions.Safe_Asin(position.z); var lon = Math.Atan2(position.y, position.x); base.position.X -= (lon - oldlon) * speed * Math.Max(1.0, worldPosition.Magnitude() - Radius); base.position.Y -= (lat - oldlat) * speed * Math.Max(1.0, worldPosition.Magnitude() - Radius); }
public override void MoveForward(double distance) { // NOTE : co - x; so - y; ca - z; sa - w; var oa = CalculatelongitudeLatitudeVector(position.X, position.Y); var po = new Vector3d(oa.x * oa.z, oa.y * oa.z, oa.w) * Radius; var px = new Vector3d(-oa.y, oa.x, 0.0); var py = new Vector3d(-oa.x * oa.w, -oa.y * oa.w, oa.z); var pd = (po - px * Math.Sin(position.Phi) * distance + py * Math.Cos(position.Phi) * distance).Normalized(); position.X = Math.Atan2(pd.y, pd.x); position.Y = Functions.Safe_Asin(pd.z); }
public override double Interpolate(Position from, Position to, double t) { var s = new Vector3d(Math.Cos(from.X) * Math.Cos(from.Y), Math.Sin(from.X) * Math.Cos(from.Y), Math.Sin(from.Y)); var e = new Vector3d(Math.Cos(to.X) * Math.Cos(to.Y), Math.Sin(to.X) * Math.Cos(to.Y), Math.Sin(to.Y)); var distance = Math.Max(Functions.Safe_Acos(s.Dot(e)) * Radius, 1e-3); t = Math.Min(t + Math.Min(0.1, 5000.0 / distance), 1.0); var T = 0.5 * Math.Atan(4.0 * (t - 0.5)) / Math.Atan(4.0 * 0.5) + 0.5; var W = 10.0; InterpolateDirection(from.X, from.Y, to.X, to.Y, T, ref position.X, ref position.Y); InterpolateDirection(from.Phi, from.Theta, to.Phi, to.Theta, T, ref position.Phi, ref position.Theta); position.Distance = from.Distance * (1.0 - t) + to.Distance * t + distance * (Math.Exp(-W * (t - 0.5) * (t - 0.5)) - Math.Exp(-W * 0.25)); return(t); }
public override Matrix4x4d LocalToDeformedDifferential(Vector3d localPoint, bool clamp = false) { if (!Functions.IsFinite(localPoint.x) || !Functions.IsFinite(localPoint.y) || !Functions.IsFinite(localPoint.z)) { return(Matrix4x4d.identity); } var point = new Vector2d(localPoint); if (clamp) { point.x = point.x - Math.Floor((point.x + R) / (2.0 * R)) * 2.0 * R; point.y = point.y - Math.Floor((point.y + R) / (2.0 * R)) * 2.0 * R; } var r2 = R * R; var l = point.x * point.x + point.y * point.y + r2; var c0 = 1.0 / Math.Sqrt(l); var c1 = c0 * R / l; return(new Matrix4x4d((point.y * point.y + r2) * c1, -point.x * point.y * c1, point.x * c0, R * point.x * c0, -point.x * point.y * c1, (point.x * point.x + r2) * c1, point.y * c0, R * point.y * c0, -point.x * R * c1, -point.y * R * c1, R * c0, (r2) * c0, 0.0, 0.0, 0.0, 1.0)); }
public override void UpdateNode() { TerrainMaterial.renderQueue = (int)ParentBody.RenderQueue + ParentBody.RenderQueueOffset; // NOTE : Body shape dependent... LocalToWorld = Matrix4x4d.ToMatrix4x4d(ParentBody.transform.localToWorldMatrix) * FaceToLocal; TangentFrameToWorld = new Matrix3x3d(LocalToWorld.m[0, 0], LocalToWorld.m[0, 1], LocalToWorld.m[0, 2], LocalToWorld.m[1, 0], LocalToWorld.m[1, 1], LocalToWorld.m[1, 2], LocalToWorld.m[2, 0], LocalToWorld.m[2, 1], LocalToWorld.m[2, 2]); LocalToCamera = GodManager.Instance.View.WorldToCameraMatrix * LocalToWorld; LocalToScreen = GodManager.Instance.View.CameraToScreenMatrix * LocalToCamera; var invLocalToCamera = LocalToCamera.Inverse(); DeformedCameraPosition = invLocalToCamera * Vector3d.zero; DeformedFrustumPlanes = Frustum3d.GetFrustumPlanes(LocalToScreen); // NOTE : Extract frustum planes from LocalToScreen matrix... LocalCameraPosition = Deformation.DeformedToLocal(DeformedCameraPosition); DeformedLocalToTangent = Deformation.DeformedToTangentFrame(GodManager.Instance.View.WorldCameraPosition) * LocalToWorld * Deformation.LocalToDeformedDifferential(LocalCameraPosition); var m = Deformation.LocalToDeformedDifferential(LocalCameraPosition, true); var left = DeformedFrustumPlanes[0].xyz.Normalized(); var right = DeformedFrustumPlanes[1].xyz.Normalized(); var fov = (float)Functions.Safe_Acos(-left.Dot(right)); SplitDistance = SplitFactor * Screen.width / 1024.0f * Mathf.Tan(40.0f * Mathf.Deg2Rad) / Mathf.Tan(fov / 2.0f); DistanceFactor = (float)Math.Max(new Vector3d(m.m[0, 0], m.m[1, 0], m.m[2, 0]).Magnitude(), new Vector3d(m.m[0, 1], m.m[1, 1], m.m[2, 1]).Magnitude()); if (SplitDistance < 1.1f || SplitDistance > 128.0f || !Functions.IsFinite(SplitDistance)) { SplitDistance = 1.1f; } var splitDistanceBlending = SplitDistance + 1.0f; DistanceBlending = new Vector2(splitDistanceBlending, 2.0f * SplitDistance - splitDistanceBlending); // Initializes data structures for horizon occlusion culling if (UseHorizonCulling && LocalCameraPosition.z <= TerrainQuadRoot.ZMax) { var deformedDirection = invLocalToCamera * Vector3d.forward; var localDirection = (Deformation.DeformedToLocal(deformedDirection) - LocalCameraPosition).Normalized(); LocalCameraDirection = new Matrix2x2d(localDirection.y, -localDirection.x, -localDirection.x, -localDirection.y); for (var i = 0; i < HORIZON_SIZE; ++i) { Horizon[i] = float.NegativeInfinity; } } if (ParentBody.UpdateLOD) { TerrainQuadRoot.UpdateLOD(); } SetUniforms(TerrainMaterial); }