Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="equation"></param>
        /// <param name="sizex"></param>
        /// <param name="sizey"></param>
        /// <param name="discTexture"></param>
        /// <param name="backgroundTexture"></param>
        /// <param name="cameraTilt"></param>
        /// <param name="trace">If true, the steps of RungeKutta integration will be stored in a list, so that they can be studied after.</param>
        public RayTracer(KerrBlackHoleEquation equation, int sizex, int sizey, Bitmap discTexture, Bitmap backgroundTexture, double cameraTilt, double cameraYaw, bool trace = false)
        {
            this.equation          = equation;
            this.sizex             = sizex;
            this.sizey             = sizey;
            this.discTexture       = discTexture;
            this.backgroundTexture = backgroundTexture;
            this.cameraTilt        = cameraTilt;
            this.trace             = trace;
            this.cameraYaw         = cameraYaw;

            lock (backgroundTexture)
            {
                this.backgroundMap = new SphericalMapping(backgroundTexture.Width, backgroundTexture.Height);
            }

            lock (discTexture)
            {
                this.discMap = new DiscMapping(equation.Rmstable, equation.Rdisk, discTexture.Width, discTexture.Height);
            }

            if (trace)
            {
                this.RayPoints = new List <Tuple <double, double, double> >();
            }
        }
Ejemplo n.º 2
0
        public unsafe bool Hit(double *y, double *prevY, double *dydx, double hdid, KerrBlackHoleEquation equation, ref Color color, ref bool stop, bool debug)
        {
            double tempX = 0, tempY = 0, tempZ = 0;

            Util.ToCartesian(y[0], y[1], y[2], ref tempX, ref tempY, ref tempZ);

            double distance = Math.Sqrt((tempX - centerX) * (tempX - centerX)
                                        + (tempY - centerY) * (tempY - centerY)
                                        + (tempZ - centerZ) * (tempZ - centerZ));

            if (distance < radius)
            {
                // Restore Y to its previous values, and perform the binary intersection search.
                Util.memcpy((IntPtr)y, (IntPtr)prevY, equation.N * sizeof(double));

                IntersectionSearch(y, dydx, hdid, equation);

                // transform impact coordinates to cartesian coordinates relative to center of sphere.
                Util.ToCartesian(y[0], y[1], y[2], ref tempX, ref tempY, ref tempZ);

                var impact           = new Vector3((float)tempX, (float)tempY, (float)tempZ);
                var impactFromCenter = Vector3.Normalize(impact - center);

                // and now transform to spherical coordinates relative to center of sphere.
                double tempR = 0, tempTheta = 0, tempPhi = 0;
                // hack: rejigger axes to make textures appear right side up.
                Util.ToSpherical(-impactFromCenter.X, impactFromCenter.Z, impactFromCenter.Y, ref tempR, ref tempTheta, ref tempPhi);

                color = Util.AddColor(GetColor(tempR, tempTheta, tempPhi), color);

                stop = true;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 3
0
        public unsafe bool Hit(double *y, double *prevY, double *dydx, double hdid, KerrBlackHoleEquation equation, ref Color color, ref bool stop, bool debug)
        {
            // Remember what side of the theta-plane we're currently on, so that we can detect
            // whether we've crossed the plane after stepping.
            int side = prevY[1] > Math.PI / 2 ? 1 : prevY[1] < Math.PI / 2 ? -1 : 0;

            // Did we cross the theta (horizontal) plane?
            bool success = false;

            if ((y[1] - Math.PI / 2) * side <= 0)
            {
                // remember the current values of Y, so that we can restore them after the intersection search.
                double *yCurrent = stackalloc double[equation.N];
                Util.memcpy((IntPtr)yCurrent, (IntPtr)y, equation.N * sizeof(double));

                //  Overwrite Y with its previous values, and perform the binary intersection search.
                Util.memcpy((IntPtr)y, (IntPtr)prevY, equation.N * sizeof(double));

                IntersectionSearch(y, dydx, hdid, equation);

                // Is the ray within the accretion disk?
                if ((y[0] >= radiusInner) && (y[0] <= radiusOuter))
                {
                    color = Util.AddColor(GetColor(side, y[0], y[1], y[2]), color);

                    stop    = false;
                    success = true;
                }

                // ...and reset Y to its original current values.
                Util.memcpy((IntPtr)y, (IntPtr)yCurrent, equation.N * sizeof(double));
            }
            return(success);
        }
Ejemplo n.º 4
0
        public unsafe bool Hit(double *y, double *prevY, double *dydx, double hdid, KerrBlackHoleEquation equation, ref Color color, ref bool stop, bool debug)
        {
            // Has the ray fallen past the horizon?
            if (y[0] < equation.Rhor)
            {
                Color col = Color.Black;
                if (checkered)
                {
                    var m1 = Util.DoubleMod(y[2], 1.04719); // Pi / 3
                    var m2 = Util.DoubleMod(y[1], 1.04719); // Pi / 3
                    if ((m1 < 0.52359) ^ (m2 < 0.52359))    // Pi / 6
                    {
                        col = Color.Green;
                    }
                }
                else if (textureBitmap != null)
                {
                    int xPos, yPos;
                    textureMap.Map(y[0], y[1], -y[2], out xPos, out yPos);

                    col = Color.FromArgb(textureBitmap[yPos * textureWidth + xPos]);
                }
                color = Util.AddColor(col, color);
                stop  = true;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 5
0
        public KerrRayTracer(KerrBlackHoleEquation equation, int sizex, int sizey, List <IHitable> hitables,
                             double cameraTilt, double cameraYaw, bool trace = false)
        {
            this.equation   = equation;
            this.sizex      = sizex;
            this.sizey      = sizey;
            this.cameraTilt = cameraTilt;
            this.cameraYaw  = cameraYaw;
            this.hitables   = hitables;

            this.trace = trace;
            if (trace)
            {
                RayPoints = new List <Tuple <double, double, double> >();
            }
        }
Ejemplo n.º 6
0
        public Scene(Vector3 CameraPosition, Vector3 CameraLookAt, Vector3 UpVector, float Fov, List <IHitable> hitables, float CurvatureCoeff, float AngularMomentum)
        {
            this.CameraPosition = CameraPosition;
            this.CameraLookAt   = CameraLookAt;
            this.UpVector       = UpVector;
            this.hitables       = hitables;
            this.Fov            = Fov;

            double tempR = 0, tempTheta = 0, tempPhi = 0;

            Util.ToSpherical(CameraPosition.X, CameraPosition.Y, CameraPosition.Z, ref tempR, ref tempTheta, ref tempPhi);
            CameraDistance  = tempR;
            CameraAngleVert = tempTheta;
            CameraAngleHorz = tempPhi - 0.1;

            SchwarzschildEquation = new SchwarzschildBlackHoleEquation(CurvatureCoeff);
            KerrEquation          = new KerrBlackHoleEquation(CameraDistance, CameraAngleHorz, CameraAngleVert, AngularMomentum);
        }
Ejemplo n.º 7
0
        public unsafe bool Hit(double *y, double *prevY, double *dydx, double hdid, KerrBlackHoleEquation equation, ref Color color, ref bool stop, bool debug)
        {
            // Has the ray escaped to infinity?
            if (y[0] > equation.R0)
            {
                // Restore Y to its previous values, and perform the binary intersection search.
                Util.memcpy((IntPtr)y, (IntPtr)prevY, equation.N * sizeof(double));

                IntersectionSearch(y, dydx, hdid, equation);

                int xPos, yPos;
                textureMap.Map(y[0], y[1], y[2] + textureOffset, out xPos, out yPos);

                color = Util.AddColor(Color.FromArgb(textureBitmap[yPos * textureWidth + xPos]), color);
                stop  = true;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 8
0
        protected unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation)
        {
            double hlower = 0.0;
            double tempX = 0, tempY = 0, tempZ = 0;

            equation.Function(y, dydx);

            while ((y[0] > equation.Rhor) && (y[0] < equation.R0))
            {
                double *yout = stackalloc double[equation.N];
                double *yerr = stackalloc double[equation.N];

                double hdiff = hupper - hlower;

                if (Math.Abs(hdiff) < 1e-7)
                {
                    RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr);

                    Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double));
                    return;
                }

                double hmid = (hupper + hlower) / 2;

                RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr);

                Util.ToCartesian(yout[0], yout[1], yout[2], ref tempX, ref tempY, ref tempZ);
                double distance = Math.Sqrt((tempX - centerX) * (tempX - centerX)
                                            + (tempY - centerY) * (tempY - centerY)
                                            + (tempZ - centerZ) * (tempZ - centerZ));

                if (distance > radius)
                {
                    hlower = hmid;
                }
                else
                {
                    hupper = hmid;
                }
            }
        }
Ejemplo n.º 9
0
        private unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation)
        {
            double hlower = 0.0;

            equation.Function(y, dydx);

            while ((y[0] > equation.Rhor) && (y[0] < equation.R0 * 2))
            {
                double *yout = stackalloc double[equation.N];
                double *yerr = stackalloc double[equation.N];

                double hdiff = hupper - hlower;

                if (Math.Abs(hdiff) < 1e-7)
                {
                    RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr);

                    Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double));
                    return;
                }

                double hmid = (hupper + hlower) / 2;

                RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr);

                if (yout[0] < equation.R0)
                {
                    hlower = hmid;
                }
                else
                {
                    hupper = hmid;
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Use Runge-Kutta steps to find intersection with horizontal plane of the scene.
        /// This is necessary to stop integrating when the ray hits the accretion disc.
        /// </summary>
        private unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation)
        {
            double hlower = 0.0;

            int side;

            if (y[1] > Math.PI / 2)
            {
                side = 1;
            }
            else if (y[1] < Math.PI / 2)
            {
                side = -1;
            }
            else
            {
                // unlikely, but needs to handle a situation when ray hits the plane EXACTLY
                return;
            }

            equation.Function(y, dydx);

            while ((y[0] > equation.Rhor) && (y[0] < equation.R0) && (side != 0))
            {
                double *yout = stackalloc double[equation.N];
                double *yerr = stackalloc double[equation.N];

                double hdiff = hupper - hlower;

                if (Math.Abs(hdiff) < 1e-7)
                {
                    RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr);

                    Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double));

                    return;
                }

                double hmid = (hupper + hlower) / 2;

                RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr);

                if (side * (yout[1] - Math.PI / 2) > 0)
                {
                    hlower = hmid;
                }
                else
                {
                    hupper = hmid;
                }
            }
        }