CapturePanorama.CapturePanorama.CubemapToEquirectangularCpuGeneralCase C# (CSharp) Method

CubemapToEquirectangularCpuGeneralCase() private method

private CubemapToEquirectangularCpuGeneralCase ( uint cameraPixels, byte pixelValues, int stride, int panoramaWidth, int panoramaHeight, int ssaaFactor, float startTime, float processingTimePerFrame, float maxWidth, float maxHeight, int numPixelsAveraged, int startX, int startY, int endX, int endY ) : IEnumerator
cameraPixels uint
pixelValues byte
stride int
panoramaWidth int
panoramaHeight int
ssaaFactor int
startTime float
processingTimePerFrame float
maxWidth float
maxHeight float
numPixelsAveraged int
startX int
startY int
endX int
endY int
return IEnumerator
        private IEnumerator CubemapToEquirectangularCpuGeneralCase(uint[] cameraPixels, byte[] pixelValues, int stride, int panoramaWidth, int panoramaHeight, int ssaaFactor, float startTime, float processingTimePerFrame, float maxWidth, float maxHeight, int numPixelsAveraged,
            int startX, int startY, int endX, int endY)
        {
            for (int y = startY; y < endY; y++)
            for (int x = startX; x < endX; x++)
            {
                int rTotal = 0, gTotal = 0, bTotal = 0, aTotal = 0;
                for (int ySsaa = y * ssaaFactor; ySsaa < (y + 1) * ssaaFactor; ySsaa++)
                for (int xSsaa = x * ssaaFactor; xSsaa < (x + 1) * ssaaFactor; xSsaa++)
                {
                    float xcoord = (float)xSsaa / (panoramaWidth * ssaaFactor);
                    float ycoord = (float)ySsaa / (panoramaHeight * ssaaFactor);

                    float latitude = (ycoord - 0.5f) * Mathf.PI;
                    float longitude = (xcoord * 2.0f - 1.0f) * Mathf.PI;

                    // Equivalent to: Vector3 equirectRayDirection =
                    //     Quaternion.Euler(-latitude * 360/(2*Mathf.PI), longitude * 360/(2*Mathf.PI), 0.0f) * new Vector3(0, 0, 1);
                    float cosLat = Mathf.Cos(latitude);
                    Vector3 equirectRayDirection = new Vector3(
                        cosLat * Mathf.Sin(longitude), -Mathf.Sin(latitude), cosLat * Mathf.Cos(longitude));

                    float distance = 0.0f;
                    CubemapFace face;
                    float u, v;

                    {
                        distance = 1.0f / equirectRayDirection.y;
                        u = equirectRayDirection.x * distance; v = equirectRayDirection.z * distance;
                        if (equirectRayDirection.y > 0.0f)
                        {
                            face = CubemapFace.PositiveY;
                        }
                        else
                        {
                            face = CubemapFace.NegativeY;
                            u = -u;
                        }
                    }

                    if (Mathf.Abs(u) > 1.0f || Mathf.Abs(v) > 1.0f)
                    {
                        distance = 1.0f / equirectRayDirection.x;
                        u = -equirectRayDirection.z * distance; v = equirectRayDirection.y * distance;
                        if (equirectRayDirection.x > 0.0f)
                        {
                            face = CubemapFace.PositiveX;
                            v = -v;
                        }
                        else
                        {
                            face = CubemapFace.NegativeX;
                        }
                    }
                    if (Mathf.Abs(u) > 1.0f || Mathf.Abs(v) > 1.0f)
                    {
                        distance = 1.0f / equirectRayDirection.z;
                        u = equirectRayDirection.x * distance; v = equirectRayDirection.y * distance;
                        if (equirectRayDirection.z > 0.0f)
                        {
                            face = CubemapFace.PositiveZ;
                            v = -v;
                        }
                        else
                        {
                            face = CubemapFace.NegativeZ;
                        }
                    }

                    u = (u + 1.0f) / 2.0f;
                    v = (v + 1.0f) / 2.0f;

                    // Boundary: should blend between cubemap views, but for now just grab color
                    // of nearest pixel in selected cubemap view
                    u = Mathf.Min(u, maxWidth);
                    v = Mathf.Min(v, maxHeight);

                    Color32 c = GetCameraPixelBilinear(cameraPixels, (int)face, u, v);
                    rTotal += c.r; gTotal += c.g; bTotal += c.b; aTotal += c.a;
                }

                int baseIdx = stride * (panoramaHeight - 1 - y) + x * 4;
                pixelValues[baseIdx + 0] = (byte)(bTotal / numPixelsAveraged);
                pixelValues[baseIdx + 1] = (byte)(gTotal / numPixelsAveraged);
                pixelValues[baseIdx + 2] = (byte)(rTotal / numPixelsAveraged);
                pixelValues[baseIdx + 3] = (byte)(aTotal / numPixelsAveraged);

                if ((x & 0xFF) == 0 && Time.realtimeSinceStartup - startTime > processingTimePerFrame)
                {
                    yield return null; // Wait until next frame
                    startTime = Time.realtimeSinceStartup;
                }
            }
        }