override public Matrix4x4 GetMetric(Vector4 stpiw, Vector4 pstpiw) { Vector4 origin = transform.position; //We assume all input space-time-position-in-world vectors are Cartesian. //The Schwarzschild metric is most naturally expressed in spherical coordinates. //So, let's just convert to spherical to get the conformal factor: Vector4 cartesianPos = stpiw - origin; Vector4 sphericalPos = cartesianPos.Cartesian4ToSpherical4(); //Assume that spherical transform of input are Lemaître coordinates, since they "co-move" with the gravitational pull of the black hole: double rho = cartesianPos.magnitude; double tau = cartesianPos.w; //Convert to usual Schwarzschild solution r: double r = Math.Pow(Math.Pow(3.0 / 2.0 * (rho - SRelativityUtil.c * tau), 2) * radius, 1.0 / 3.0); //At the center of the coordinate system is a singularity, at the Schwarzschild radius is an event horizon, // so we need to cut-off the interior metric at some point, for numerical sanity if (r <= radiusCutoff) { Matrix4x4 minkowski = Matrix4x4.identity; minkowski.m33 = SRelativityUtil.cSqrd; minkowski.m00 = -1; minkowski.m11 = -1; minkowski.m22 = -1; return(minkowski); } else { double schwarzFac = 1 - radius / r; double playerR = ((Vector3)(pstpiw - origin)).magnitude; double playerSchwarzFac = 1; if (playerR > radiusCutoff) { playerSchwarzFac = 1 - radius / playerR; } double sqrtRDivRs = Math.Sqrt(r / radius); double denomFac = (sqrtRDivRs - 1.0 / sqrtRDivRs) * (sqrtRDivRs - 1.0 / sqrtRDivRs); //Here's the value of the conformal factor at this distance in spherical coordinates with the orig at zero: Matrix4x4 sphericalMetric = Matrix4x4.zero; //(For the metric, rather than the conformal factor, the time coordinate would have its sign flipped relative to the spatial components, // either positive space and negative time, or negative time and positive space.) sphericalMetric[3, 3] = (float)(SRelativityUtil.cSqrd * playerSchwarzFac * (r - radius) / (radius * denomFac)); sphericalMetric[0, 0] = (float)(-schwarzFac / (denomFac * playerSchwarzFac)); sphericalMetric[1, 1] = (float)(-r * r); sphericalMetric[2, 2] = (float)(-r * r * Mathf.Pow(Mathf.Sin(sphericalPos.y), 2)); //A particular useful "tensor" (which we can think of loosely here as "just a matrix") called the "Jacobian" // lets us convert the "metric tensor" (and other tensors) between coordinate systems, like from spherical back to Cartesian: Matrix4x4 jacobian = Matrix4x4.identity; double x = cartesianPos.x; double y = cartesianPos.y; double z = cartesianPos.z; rho = Math.Sqrt(x * x + y * y + z * z); double sqrtXSqrYSqr = Math.Sqrt(x * x + y * y); if (rho != 0 && sqrtXSqrYSqr != 0) { // This is the Jacobian from spherical to Cartesian coordinates: jacobian.m00 = (float)(x / rho); jacobian.m01 = (float)(y / rho); jacobian.m02 = (float)(z / rho); jacobian.m10 = (float)(x * z / (rho * rho * sqrtXSqrYSqr)); jacobian.m11 = (float)(y * z / (rho * rho * sqrtXSqrYSqr)); jacobian.m20 = (float)(-y / (x * x + y * y)); jacobian.m21 = (float)(x / (x * x + y * y)); jacobian.m12 = (float)(-sqrtXSqrYSqr / (rho * rho)); jacobian.m22 = 0; jacobian.m33 = 1; //To convert the coordinate system of the metric (or the "conformal factor," in this case,) we multiply this way by the Jacobian and its transpose. //(*IMPORTANT NOTE: I'm assuming this "conformal factor" transforms like a true tensor, which not all matrices are. I need to do more research to confirm that // it transforms the same way as the metric, but given that the conformal factor maps from Minkowski to another metric, I think this is a safe bet.) return(jacobian.transpose * sphericalMetric * jacobian); } else { sphericalMetric.m22 = sphericalMetric.m00; sphericalMetric.m00 = 1; sphericalMetric.m11 = 1; return(sphericalMetric); } } }