public void OnBeforeSerialize()
        {
            var cube = new CubemapHelper {
                cubemap = cubemap
            };

            m_SerializedCubemap = EditorJsonUtility.ToJson(cube, true);
        }
Exemplo n.º 2
0
        //https://stackoverflow.com/questions/34250742/converting-a-cubemap-into-equirectangular-panorama
        //https://github.com/adamb70/Python-Spherical-Projection/blob/master/cube2equi.py
        //https://stackoverflow.com/questions/11504584/cubic-to-equirectangular-projection-algorithm
        private Bitmap ConvertToEquirectangular(CubemapImages cubeMap)
        {
            CubemapHelper.FillAnyNullWithBlanks(cubeMap);
            CubemapHelper.UpsizeAnyPartials(cubeMap);

            DirectBitmap[] faces = ResizeAndConverCubeToDirectBitmap(cubeMap);

            int cubeFaceWidth  = faces[0].Width;
            int cubeFaceHeight = cubeFaceWidth;

            // this block is to calculate a size that has a comparable pixel density to that of the combined input images
            int factor          = 256;
            int nearestMultiple = 0;
            {
                int cubePixelCount      = cubeFaceHeight * cubeFaceWidth;
                int totalCubePixelCount = cubePixelCount * 6;

                int sizeToGetComparablePixelDensity = (int)Math.Sqrt(totalCubePixelCount / 2);
                nearestMultiple =
                    (int)Math.Round(
                        (sizeToGetComparablePixelDensity / (double)factor),
                        MidpointRounding.AwayFromZero
                        ) * factor;
            }
            int outputHeight = nearestMultiple + factor; // round it up
            int outputWidth  = outputHeight * 2;

            // make the projection a multiple of the width of the combined images
            int scale_factor     = 4;
            int projectionWidth  = (cubeFaceWidth * 4) * scale_factor;
            int projectionHeight = projectionWidth / 2;

            DirectBitmap equiTexture = new DirectBitmap(projectionWidth, projectionHeight);

            //Normalised UV texture coordinates, from 0 to 1, starting at lower left corner
            double u_coordinate;
            double v_coordinate;
            //Polar coordinates
            double latitude;
            double longitude;
            //Unit vector
            double x, y, z;
            double xAxis, yAxis, zAxis;
            double largestComponent;

            double[] vector = new double[3];

            Color color;
            Point pixelCoord;

            double normX;
            double normY;

            //int modulousFactorX = outputWidth / 16;
            //int modulousFactorY = outputHeight / 8;
            //bool horizontalMarker = false;
            //bool verticalMarker = false;

            for (int heightIndex = 0; heightIndex < equiTexture.Height; heightIndex++)
            {
                //verticalMarker = heightIndex % modulousFactorX == 0;

                v_coordinate = 1 - ((double)heightIndex / equiTexture.Height);
                latitude     = v_coordinate * Math.PI;

                for (int widthIndex = 0; widthIndex < equiTexture.Width; widthIndex++)
                {
                    //horizontalMarker = widthIndex % modulousFactorY == 0;

                    u_coordinate = ((double)widthIndex / equiTexture.Width);
                    longitude    = u_coordinate * 2 * Math.PI;

                    //assuming Y+ is up, X+ is right, Z+ is front

                    //Calculate unit vector
                    x = Math.Sin(longitude) * Math.Sin(latitude) * -1;
                    y = Math.Cos(latitude);
                    z = Math.Cos(longitude) * Math.Sin(latitude) * -1;

                    vector[0]        = Math.Abs(x);
                    vector[1]        = Math.Abs(y);
                    vector[2]        = Math.Abs(z);
                    largestComponent = vector.Max();
                    // PROBLEM : there are cases where the vertical boundary between cube faces
                    // results in both the x and z components to be equivalent
                    // so both axis return a 1, which

                    //Vector Parallel to the unit vector that lies on one of the cube faces
                    xAxis = x / largestComponent;
                    yAxis = y / largestComponent;
                    zAxis = z / largestComponent;

                    //bool debug = true;
                    //if (debug && verticalMarker && horizontalMarker)
                    //{
                    //    MessageBox.Show(
                    //        "h:" + heightIndex + " w:" + widthIndex +
                    //        "\r\nlat:" + latitude + " long:" + longitude +
                    //        "\r\nx:" + x + " y:" + y + " z:" + z
                    //        );
                    //    color = Color.Purple;
                    //}

                    if (xAxis == 1)
                    {
                        //Right
                        normX      = (((zAxis + 1f) / 2f) - 1f);
                        normY      = (((yAxis + 1f) / 2f));
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[4].Width, faces[4].Height);
                        color      = faces[4].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else if (xAxis == -1)
                    {
                        //Left
                        normX      = ((zAxis + 1) / 2);
                        normY      = ((yAxis + 1) / 2);
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[3].Width, faces[3].Height);
                        color      = faces[3].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else if (yAxis == -1)
                    {
                        //Up
                        normX      = ((xAxis + 1f) / 2f);
                        normY      = ((zAxis + 1f) / 2f);
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[5].Width, faces[5].Height);
                        color      = faces[5].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else if (yAxis == 1)
                    {
                        //Down
                        normX      = ((xAxis + 1f) / 2f);
                        normY      = (((zAxis + 1f) / 2f) - 1f);
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[1].Width, faces[1].Height);
                        color      = faces[1].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else if (zAxis == 1)
                    {
                        //Front
                        normX      = ((xAxis + 1f) / 2f);
                        normY      = ((yAxis + 1f) / 2f);
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[2].Width, faces[2].Height);
                        color      = faces[2].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else if (zAxis == -1)
                    {
                        //Back
                        normX      = (((xAxis + 1f) / 2f) - 1f);
                        normY      = ((yAxis + 1f) / 2f);
                        pixelCoord = GetPixelCoordinates(normX, normY, faces[0].Width, faces[0].Height);
                        color      = faces[0].GetPixel(pixelCoord.X, pixelCoord.Y);
                    }
                    else
                    {
                        throw new Exception("Unknown face, something went wrong");
                    }

                    equiTexture.SetPixel(widthIndex, heightIndex, color);
                }
            }
            var downscaled = ResizeImage(equiTexture.Bitmap, equiTexture.Width / scale_factor, equiTexture.Height / scale_factor);

            return(downscaled);
        }