Beispiel #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="f"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        private static Complex32 falpo(IComplex f, Complex32 a, Complex32 b, float eps = 1e-8f)
        {
            Complex32 x1 = a;
            Complex32 x2 = b;
            Complex32 fb = f(b);
            int       n  = 0;

            while (Maths.Abs(x2 - x1) > eps && n < short.MaxValue)
            {
                Complex32 xpoint  = x2 - (x2 - x1) * f(x2) / (f(x2) - f(x1));
                Complex32 fxpoint = f(xpoint);
                float     s       = fb.Real * fxpoint.Real;

                // sign
                if (s > 0)
                {
                    x2 = xpoint;
                }
                else
                {
                    x1 = xpoint;
                }

                if (Maths.Abs(fxpoint) < eps)
                {
                    break;
                }
                n++;
            }
            return(x2 - (x2 - x1) * f(x2) / (f(x2) - f(x1)));
        }
Beispiel #2
0
        /// <summary>
        /// Domain transform filter.
        /// </summary>
        /// <param name="I">Input signal</param>
        /// <param name="sigma_s">High sigma</param>
        /// <param name="sigma_r">Low sigma</param>
        /// <param name="iterations">Number of iterations</param>
        internal static void domainfilter(Complex32[] I, float sigma_s, float sigma_r, int iterations = 3)
        {
            // params
            int   h = I.GetLength(0);
            float sigma_H_i;
            int   i;

            // get differences
            Complex32[] dIcdy = Matrice.Diff(I, 1);

            // shift patterns
            Complex32[] dIdy = new Complex32[h];

            for (i = 1; i < h; i++)
            {
                dIdy[i] = Maths.Abs(dIcdy[i - 1]);
            }

            // sigma patterns and result image
            for (i = 0; i < h; i++)
            {
                dIdy[i] = 1 + sigma_s / sigma_r * dIdy[i];
            }

            // iterations
            for (i = 0; i < iterations; i++)
            {
                sigma_H_i = sigma_s * Maths.Sqrt(3) * Maths.Pow(2, (iterations - (i + 1))) / Maths.Sqrt(Maths.Pow(4, iterations) - 1);

                // 1D filter
                tdrf(I, dIdy, sigma_H_i);
            }

            return;
        }
Beispiel #3
0
        public static Generator Filter(this Generator gen, params FilterType[] types)
        {
            foreach (var type in types)
            {
                var tempGen = gen;
                switch (type)
                {
                case FilterType.Invert:
                    gen = new Function(
                        x => 1 - tempGen.Get(x),
                        xy => 1 - tempGen.Get(xy),
                        xyz => 1 - tempGen.Get(xyz));
                    break;

                case FilterType.Billow:
                    gen = new Function(
                        x => Maths.Abs((2 * tempGen.Get(x)) - 1),
                        xy => Maths.Abs((2 * tempGen.Get(xy)) - 1),
                        xyz => Maths.Abs((2 * tempGen.Get(xyz)) - 1));
                    break;

                case FilterType.Ridged:
                    gen = gen.Filter(FilterType.Billow, FilterType.Invert);
                    break;

                case FilterType.Sin:
                    gen = new Function(
                        x => (Maths.Sin(2 * math.PI * tempGen.Get(x)) / 2) + .5f,
                        xy => (Maths.Sin(2 * math.PI * tempGen.Get(xy)) / 2) + .5f,
                        xyz => (Maths.Sin(2 * math.PI * tempGen.Get(xyz)) / 2) + .5f);
                    break;

                case FilterType.Asin:
                    gen = new Function(
                        x => (Maths.Asin((2 * tempGen.Get(x)) - 1) / math.PI) + .5f,
                        xy => (Maths.Asin((2 * tempGen.Get(xy)) - 1) / math.PI) + .5f,
                        xyz => (Maths.Asin((2 * tempGen.Get(xyz)) - 1) / math.PI) + .5f);
                    break;

                case FilterType.Atan:
                    gen = new Function(
                        x => (2 * Maths.Atan((2 * tempGen.Get(x)) - 1) / math.PI) + .5f,
                        xy => (2 * Maths.Atan((2 * tempGen.Get(xy)) - 1) / math.PI) + .5f,
                        xyz => (2 * Maths.Atan((2 * tempGen.Get(xyz)) - 1) / math.PI) + .5f);
                    break;

                case FilterType.Tanh:
                    gen = new Function(
                        x => 2 * Maths.Tanh(2 * tempGen.Get(x) - 1) / 2 + .5f,
                        xy => 2 * Maths.Tanh(2 * tempGen.Get(xy) - 1) / 2 + .5f,
                        xyz => 2 * Maths.Tanh(2 * tempGen.Get(xyz) - 1) / 2 + .5f);
                    break;

                default:
                    throw new ArgumentException($"Invalid filter type: '{type.ToString()}'");
                }
            }

            return(gen);
        }
Beispiel #4
0
        /// <summary>
        /// Apply filter.
        /// </summary>
        /// <param name="data">Matrix</param>
        public void Apply(Complex32[,] data)
        {
            int width = data.GetLength(1);
            int height = data.GetLength(0);
            int i, j;

            if (this.type == ThresholdType.Abs)
            {
                for (i = 0; i < height; i++)
                {
                    for (j = 0; j < width; j++)
                    {
                        if (Maths.Abs(data[i, j]) < threshold)
                        {
                            data[i, j] = 0;
                        }
                    }
                }
            }
            else if (this.type == ThresholdType.Over)
            {
                for (i = 0; i < height; i++)
                {
                    for (j = 0; j < width; j++)
                    {
                        if (data[i, j].Real > threshold)
                        {
                            data[i, j] = 0;
                        }
                        if (data[i, j].Imag > threshold)
                        {
                            data[i, j] = 0;
                        }
                    }
                }
            }
            else
            {
                for (i = 0; i < height; i++)
                {
                    for (j = 0; j < width; j++)
                    {
                        if (data[i, j].Real < threshold)
                        {
                            data[i, j] = 0;
                        }
                        if (data[i, j].Imag < threshold)
                        {
                            data[i, j] = 0;
                        }
                    }
                }
            }
            return;
        }
Beispiel #5
0
        /// <summary>
        /// Domain transform filter.
        /// </summary>
        /// <param name="I">Input signal</param>
        /// <param name="sigma_s">High sigma</param>
        /// <param name="sigma_r">Low sigma</param>
        /// <param name="iterations">Number of iterations</param>
        internal static void domainfilter(Complex32[,] I, float sigma_s, float sigma_r, int iterations = 3)
        {
            // params
            int   h = I.GetLength(0);
            int   w = I.GetLength(1);
            float sigma_H_i;
            int   i, j;

            // get differences
            Complex32[,] dIcdx = Matrice.Diff(I, 1, Direction.Horizontal);
            Complex32[,] dIcdy = Matrice.Diff(I, 1, Direction.Vertical);

            // shift patterns
            Complex32[,] dIdx = new Complex32[h, w];
            Complex32[,] dIdy = new Complex32[h, w];

            for (i = 0; i < h; i++)
            {
                for (j = 1; j < w; j++)
                {
                    dIdx[i, j] = Maths.Abs(dIcdx[i, j - 1]);
                }
            }

            for (i = 1; i < h; i++)
            {
                for (j = 0; j < w; j++)
                {
                    dIdy[i, j] = Maths.Abs(dIcdy[i - 1, j]);
                }
            }

            // sigma patterns and result image
            for (i = 0; i < h; i++)
            {
                for (j = 0; j < w; j++)
                {
                    dIdx[i, j] = 1 + sigma_s / sigma_r * dIdx[i, j];
                    dIdy[i, j] = 1 + sigma_s / sigma_r * dIdy[i, j];
                }
            }

            // iterations
            for (i = 0; i < iterations; i++)
            {
                sigma_H_i = sigma_s * Maths.Sqrt(3) * Maths.Pow(2, (iterations - (i + 1))) / Maths.Sqrt(Maths.Pow(4, iterations) - 1);

                // 2D filter
                tdrf_h(I, dIdx, sigma_H_i);
                tdrf_v(I, dIdy, sigma_H_i);
            }

            return;
        }
Beispiel #6
0
        /// <summary>
        /// Implements a wavelet filter.
        /// </summary>
        /// <param name="data">Matrix</param>

        public void Apply(Complex32[,] data)
        {
            var B = WaveletDecomposition.Forward(data);
            int n, m;

            for (int i = 1; i < B.Length; i++)
            {
                var b = B[i];
                n = b.GetLength(0);
                m = b.GetLength(1);

                if (!Maths.IsEven(n))
                {
                    n--;                   // ?
                }
                if (!Maths.IsEven(m))
                {
                    m--;                   // ?
                }
                // visu_shrink
                var bb = Matrice.Reshape(b, b.Length).ToAbs();
                Array.Sort(bb);
                var median = Math.Sqrt(bb[bb.Length / 2]) * Math.Sqrt(Maths.Log2(n * m));

                for (int y = 0; y < n; y++)
                {
                    for (int x = 0; x < m; x++)
                    {
                        b[y, x] = Maths.Abs(b[y, x]) > median ? b[y, x] : 0;
                    }
                }

                B[i] = b;
            }

            var   output = WaveletDecomposition.Backward(B);
            float factor = 1 + Factor;

            n = data.GetLength(0);
            m = data.GetLength(1);

            for (int y = 0; y < n; y++)
            {
                for (int x = 0; x < m; x++)
                {
                    // pass filtering
                    data[y, x] = output[y, x] + factor * (data[y, x] - output[y, x]);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="f"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        private static Complex32 chord(IComplex f, Complex32 a, Complex32 b, float eps = 1e-8f)
        {
            int       n  = 0;
            Complex32 x0 = (b - a) / 2.0;
            Complex32 x;

            while (Maths.Abs(f(x0) / b) > eps && n < short.MaxValue)
            {
                x  = x0;
                x0 = x - (f(x) * (a - x)) / (f(a) - f(x));
                n++;
            }
            return(x0);
        }
Beispiel #8
0
        /// <summary>
        /// Apply filter.
        /// </summary>
        /// <param name="data">Array</param>
        public void Apply(Complex32[] data)
        {
            int length = data.Length;
            int i;

            if (this.type == ThresholdType.Abs)
            {
                for (i = 0; i < length; i++)
                {
                    if (Maths.Abs(data[i]) < threshold)
                    {
                        data[i] = 0;
                    }
                }
            }
            else if (this.type == ThresholdType.Over)
            {
                for (i = 0; i < length; i++)
                {
                    if (data[i].Real > threshold)
                    {
                        data[i].Real = 0;
                    }
                    if (data[i].Imag > threshold)
                    {
                        data[i].Imag = 0;
                    }
                }
            }
            else
            {
                for (i = 0; i < length; i++)
                {
                    if (data[i].Real < threshold)
                    {
                        data[i].Real = 0;
                    }
                    if (data[i].Imag < threshold)
                    {
                        data[i].Imag = 0;
                    }
                }
            }

            return;
        }
Beispiel #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="f"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        private static Complex32 secan(IComplex f, Complex32 a, Complex32 b, float eps = 1e-8f)
        {
            Complex32 x1 = a;
            Complex32 x2 = b;
            Complex32 fb = f(b);
            Complex32 mpoint;
            int       n = 0;

            while (Maths.Abs(f(x2)) > eps && n < short.MaxValue)
            {
                mpoint = x2 - (x2 - x1) * fb / (fb - f(x1));
                x1     = x2;
                x2     = mpoint;
                fb     = f(x2);
                n++;
            }
            return(x2);
        }
Beispiel #10
0
        internal static void AssertEqualOrNegatedWithinReason(Quaternion a, Quaternion b)
        {
            Boolean pass1 =
                Maths.Abs(a.I - b.I) <= MathsTests.TestTolerance &&
                Maths.Abs(a.J - b.J) <= MathsTests.TestTolerance &&
                Maths.Abs(a.K - b.K) <= MathsTests.TestTolerance &&
                Maths.Abs(a.U - b.U) <= MathsTests.TestTolerance;

            Quaternion c;

            Quaternion.Negate(ref b, out c);

            Boolean pass2 =
                Maths.Abs(a.I - c.I) <= MathsTests.TestTolerance &&
                Maths.Abs(a.J - c.J) <= MathsTests.TestTolerance &&
                Maths.Abs(a.K - c.K) <= MathsTests.TestTolerance &&
                Maths.Abs(a.U - c.U) <= MathsTests.TestTolerance;

            Assert.That(pass1 || pass2, Is.EqualTo(true));
        }
Beispiel #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="f"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="iterations"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        private static Complex32 romb(IComplex f, Complex32 a, Complex32 b, int iterations, float eps = 1e-8f)
        {
            int       n   = 2;
            Complex32 h   = b - a;
            Complex32 sum = 0.0;
            int       j   = 0;

            Complex32[,] R = new Complex32[iterations, iterations];
            R[1, 1]        = h * (f(a) + f(b)) / 2.0;
            h       = h / 2;
            R[2, 1] = R[1, 1] / 2 + h * f(a + h);
            R[2, 2] = (4 * R[2, 1] - R[1, 1]) / 3;
            for (j = 3; j <= iterations; j++)
            {
                n   = 2 * n;
                h   = h / 2;
                sum = 0.0;
                for (int k = 1; k <= n; k += 2)
                {
                    sum += f(a + k * h);
                }
                R[j, 1] = R[j - 1, 1] / 2 + h * sum;
                float factor = 4.0f;
                for (int k = 2; k <= j; k++)
                {
                    R[j, k] = (factor * R[j, k - 1] - R[j - 1, k - 1]) / (factor - 1);
                    factor  = factor * 4.0f;
                }
                if (Maths.Abs(R[j, j] - R[j, j - 1]) < eps * Maths.Abs(R[j, j]))
                {
                    sum = R[j, j];
                    return(sum);
                }
            }
            sum = R[n, n];
            return(sum);
        }
Beispiel #12
0
        /// <summary>Called when new data is received</summary>
        public override void Step()
        {
            // Only on new candles
            Position = FindLivePosition(Position);
            if (!Instrument.NewCandle)
            {
                return;
            }

            if (Debugger.IsAttached)
            {
                Debugging.Dump(Instrument, high_res: 20.0, emas: new[] { 100 });
                if (Instrument.Count == 230)
                {
                    Debug.WriteLine("Break");
                }
            }

            var sym = Instrument.Symbol;
            var mcs = Instrument.MedianCandleSize(-10, 0);
            var C0  = Instrument[0];
            var C1  = Instrument[-1];
            var C2  = Instrument[-2];

            // One at a time
            if (Position == null)
            {
                TradeType tt;
                string    msg;

                // Look for a reversal
                int           reversal_direction;
                QuoteCurrency target_entry;
                if (!Instrument.IsCandlePattern(0, out reversal_direction, out target_entry))
                {
                    return;
                }

                var preceeding_trend = Instrument.MeasureTrend(-10, 0);

                var tt_confirmation = C1.Bullish ? TradeType.Buy : TradeType.Sell;

                const double EmaSlopeToMCS = 20;
                var          ema           = Bot.Indicators.ExponentialMovingAverage(Bot.MarketSeries.Close, 100);
                var          ema_slope     = ema.Result.FirstDerivative(ema.Result.Count - 1) * EmaSlopeToMCS / mcs;

                // If the EMA slope is flat, look for ranging
                if (Math.Abs(ema_slope) < 1.0)
                {
                    // Side of the EMA. Must be significantly to one side of the EMA
                    var dist = C1.Close - ema.Result.LastValue;
                    if (Math.Abs(dist) < mcs)
                    {
                        return;
                    }

                    tt  = C1.Close < ema.Result.LastValue ? TradeType.Buy : TradeType.Sell;
                    msg = "{0} - ranging EMA. Slope = {1}, Distance = {2}".Fmt(tt, ema_slope, dist);
                }
                // Otherwise look for indecision near the EMA
                else
                {
                    var dist = C1.Close - ema.Result.LastValue;
                    if (Maths.Abs(dist) > mcs)
                    {
                        return;
                    }

                    tt  = ema_slope > 0.0 ? TradeType.Buy : TradeType.Sell;
                    msg = "{0} - trending EMA. Slope = {1}, Dist = {2}".Fmt(tt, ema_slope, dist);
                }

                // Check the candle confirms the direction
                if (tt != tt_confirmation)
                {
                    return;
                }

                var sign  = tt.Sign();
                var rtr   = new RangeF(1.0, 2.0);
                var trade = new Trade(Bot, Instrument, tt, Label, rtr_range: rtr);
                Bot.Print(msg);
                Position        = Bot.Broker.CreateOrder(trade);
                PositionManager = new PositionManager(Instrument, Position);
            }
            else
            {
                PositionManager.Step();
            }
        }
Beispiel #13
0
        public void GenerateRoom(Room parent, Room child)
        {
            IntVector2 direction            = child.node.position - parent.node.position;
            IntVector2 orthogonal_direction = direction.RotateHalfPi();

            Vector2    parent_center = parent.Center;
            Vector2    parent_border = parent.GetBorderCenter(direction);
            IntVector2 parent_orthogonal_dimension_minus_one_vector = parent.GetDimensionMinusOneVector(orthogonal_direction);
            int        parent_orthogonal_dimension = parent.GetDimension(orthogonal_direction);

            IntVector2 child_orthogonal_dimension_vector           = child.GetDimensionVector(orthogonal_direction);
            IntVector2 child_orthogonal_dimension_minus_one_vector = child.GetDimensionMinusOneVector(orthogonal_direction);
            int        child_orthogonal_dimension       = child.GetDimension(orthogonal_direction);
            IntVector2 child_dimension_minus_one_vector = child.GetDimensionMinusOneVector(direction);

            int wall_width          = 1;
            int useful_parent_width = parent_orthogonal_dimension - 2 * wall_width;
            int useful_child_width  = child_orthogonal_dimension - 2 * wall_width;

            Assert.That(
                useful_child_width >= options.min_hallway_width &&
                useful_parent_width >= options.min_hallway_width,
                "Cannot be less"
                );

            int min_orthogonal_offset = -useful_child_width + options.min_hallway_width;
            int max_orthogonal_offset = useful_parent_width - options.min_hallway_width;

            Queue <int> offsets_queue = Functions.ShuffledRangeQueue(
                min_orthogonal_offset, max_orthogonal_offset, rng);

            while (offsets_queue.Count != 0)
            {
                int current_orthogonal_offset = offsets_queue.Dequeue();

                int current_useful_parent_width = useful_parent_width;
                int current_useful_child_width  = useful_child_width;

                if (current_orthogonal_offset > 0)
                {
                    current_useful_parent_width -= current_orthogonal_offset;
                }
                else
                {
                    current_useful_child_width += current_orthogonal_offset;
                }

                int min_useful_width = Maths.Min(current_useful_parent_width, current_useful_child_width);

                int max_hallway_width = Maths.Min(options.max_hallway_width, min_useful_width);
                int min_hallway_width = options.min_hallway_width;

                int min_hallway_length = options.min_hallway_length;
                int max_hallway_length = options.max_hallway_length;

                int current_hallway_width  = rng.Next(min_hallway_width, max_hallway_width + 1);
                int current_hallway_length = rng.Next(min_hallway_length, max_hallway_length + 1);

                int min_hallway_offset = 0;
                int max_hallway_offset = min_useful_width - current_hallway_width;

                int current_hallway_offset = rng.Next(min_hallway_offset, max_hallway_offset + 1);

                Vector2 child_corner = parent_border
                                       + ((Vector2)parent_orthogonal_dimension_minus_one_vector) / 2
                                       + direction * (current_hallway_length + 1)
                                       + orthogonal_direction * current_orthogonal_offset;


                if (child_corner.IsWhole() == false)
                {
                    throw new System.Exception("Must be whole. Review the algo");
                }

                Vector2 child_center = child_corner
                                       - ((Vector2)child_orthogonal_dimension_minus_one_vector) / 2
                                       + ((Vector2)child_dimension_minus_one_vector) / 2;

                child.SetPositionFromCenter(child_center);

                if (!IntersectsRooms(child))
                {
                    // child.roomStuff = new RoomStuff
                    // {
                    //     hallway_length = current_hallway_length,
                    //     hallway_width = current_hallway_width,
                    //     wall_width = wall_width,
                    //     hallway_coord
                    // };

                    Vector2 hallway_start = parent_border
                                            + ((Vector2)parent_orthogonal_dimension_minus_one_vector) / 2
                                            - orthogonal_direction * wall_width
                                            - orthogonal_direction * current_hallway_offset;

                    if (current_orthogonal_offset < 0)
                    {
                        hallway_start += orthogonal_direction * current_orthogonal_offset;
                    }

                    IntVector2 hallway_start_int = (IntVector2)hallway_start;

                    IntVector2 hallway_dims = direction * Maths.Abs(current_hallway_length + 2)
                                              + orthogonal_direction * Maths.Abs(current_hallway_width + 2);

                    Vector2 hallway_center = hallway_start
                                             + (Vector2)direction * (((float)current_hallway_length + 1) / 2);

                    Room hallway = new Room(hallway_dims, null);
                    hallway.SetPositionFromCenter(hallway_center);

                    if (!IntersectsRooms(hallway))
                    {
                        WriteRoom(child);

                        WriteHallway(
                            current_hallway_length + 2,
                            current_hallway_width,
                            direction,
                            hallway_start_int);
                        rooms.Add(hallway);

                        offsets_queue.Clear();
                    }
                }
            }
        }
Beispiel #14
0
 /// <summary>
 /// Returns the value of the probability density function.
 /// </summary>
 /// <param name="x">Value</param>
 /// <returns>float precision floating point number</returns>
 public float Function(float x)
 {
     return(a / 2.0f * Maths.Exp(-a * Maths.Abs(x - b)));
 }
        void CollisionResponse(float deltaTime)
        {
            for (int i = 0; i < intersections.Length; i++)
            {
                Intersection           intersection    = intersections[i];
                PhysicsBodyComponent   p1              = intersection.Object1;
                PhysicsBodyComponent   p2              = intersection.Object2;
                AxisAlignedBoundingBox p1Collider      = p1.GetCollider();
                AxisAlignedBoundingBox p1DeltaCollider = p1.GetColliderAt(p1.Delta.FinalPosition);
                AxisAlignedBoundingBox p2Collider      = p2.GetCollider();
                AxisAlignedBoundingBox p2DeltaCollider = p2.GetColliderAt(p2.Delta.FinalPosition);

                if (intersection.Type == IntersectionType.Rigid)
                {
                    // Update the intersection data, so that previous updates for
                    // these objects are applied
                    intersection.UpdateFromDelta();

                    // If both entry times are invalid, the objects aren't intersecting anymore,
                    // so ignore the collision.
                    if (intersection.Object1EntryTime == 1 && intersection.Object2EntryTime == 1)
                    {
                        continue;
                    }

                    // Handle the collision based on static states
                    if (intersection.Object2.IsStatic)
                    {
                        // If we are past the first sweep pass for this object,
                        // and this intersection is no longer valid, then ignore it.
                        if (p1.Delta.DeltaPass > 0)
                        {
                            if (!p1DeltaCollider.Intersects(p2Collider))
                            {
                                continue;
                            }
                        }

                        // Gather intersection data
                        Vector3 surfaceNormal = intersection.Object2Normal;
                        float   collisionTime = intersection.Object1EntryTime;
                        float   remainingTime = 1f - collisionTime;
                        float   stepDist      = intersection.Resolver.StepDistance(p1DeltaCollider, p2Collider);

                        //if (surfaceNormal.Y == 0)
                        //    Diagnostics.DashCMD.WriteLine("{0} | {1}", stepDist.ToString(), Math.Min(p1.Delta.MaxStep, p1.MaxStep));
                        //Diagnostics.DashCMD.WriteLine(surfaceNormal);
                        // Try to step on object
                        if (p1.CanStep && p2.CanBeSteppedOn && surfaceNormal.Y == 0 &&
                            stepDist >= 0 && stepDist <= Math.Min(p1.Delta.MaxStep, p1.MaxStep))
                        {
                            // Step onto object
                            p1.Delta.FinalPosition.Y += stepDist + 0.001f;
                            p1.Delta.FinalVelocity.Y  = 0;
                            p1.Delta.IsGrounded       = p1.Delta.IsGrounded || true;
                            p1.Delta.Stepped          = true;
                        }
                        else // Normal collision resolve
                        {
                            // Calculate the compensation in position from the collision
                            Vector3 compensation = surfaceNormal * (Maths.Abs(p1.Delta.FinalVelocity * deltaTime)) * remainingTime;
                            p1.Delta.FinalPosition += compensation;

                            // If this normal moved the object anywhere upward,
                            // that object is now considered grounded
                            if (surfaceNormal.Y > 0)
                            {
                                p1.Delta.IsGrounded = p1.Delta.IsGrounded || true;
                            }

                            // Fix the velocity
                            if (p1.BounceOnWallCollision || p1.BounceOnVerticalCollision)
                            {
                                if ((surfaceNormal.X != 0 || surfaceNormal.Z != 0) && p1.BounceOnWallCollision)
                                {
                                    if (surfaceNormal.X != 0)
                                    {
                                        p1.Delta.FinalVelocity.X *= -(1f - p1.HorizontalBounceFalloff);
                                    }
                                    if (surfaceNormal.Z != 0)
                                    {
                                        p1.Delta.FinalVelocity.Z *= -(1f - p1.HorizontalBounceFalloff);
                                    }
                                }
                                else if (surfaceNormal.Y != 0 && p1.BounceOnVerticalCollision)
                                {
                                    p1.Delta.FinalVelocity.Y *= -(1f - p1.VerticalBounceFalloff);
                                    p1.Delta.FinalVelocity.X *= p1.InverseFriction;
                                    p1.Delta.FinalVelocity.Z *= p1.InverseFriction;
                                }
                                else
                                {
                                    intersection.Resolver.FixVelocity(ref p1.Delta.FinalVelocity, surfaceNormal);
                                }
                            }
                            else
                            {
                                intersection.Resolver.FixVelocity(ref p1.Delta.FinalVelocity, surfaceNormal);
                            }
                        }

                        // Another delta pass has occured
                        p1.Delta.DeltaPass++;

                        p1.OnCollide(p2);
                        p2.OnCollide(p1);
                    }
                    else if (intersection.Object1.IsStatic)
                    {
                        // If we are past the first sweep pass for this object,
                        // and this intersection is no longer valid, then ignore it.
                        if (p2.Delta.DeltaPass > 0)
                        {
                            if (!p2DeltaCollider.Intersects(p1Collider))
                            {
                                continue;
                            }
                        }

                        // Gather intersection data
                        Vector3 surfaceNormal = intersection.Object1Normal;
                        float   collisionTime = intersection.Object2EntryTime;
                        float   remainingTime = 1f - collisionTime;
                        float   stepDist      = intersection.Resolver.StepDistance(p2DeltaCollider, p1Collider);

                        // Try to step on object
                        if (p2.CanStep && p1.CanBeSteppedOn && surfaceNormal.Y == 0 &&
                            stepDist >= 0 && stepDist <= Math.Min(p2.Delta.MaxStep, p2.MaxStep))
                        {
                            // Step onto object
                            p2.Delta.FinalPosition.Y += stepDist + 0.001f;
                            p2.Delta.FinalVelocity.Y  = 0;
                            p2.Delta.IsGrounded       = p2.Delta.IsGrounded || true;
                            p2.Delta.Stepped          = true;
                        }
                        else // Normal collision resolve
                        {
                            // Calculate the compensation in position from the collision
                            Vector3 compensation = surfaceNormal * (Maths.Abs(p2.Delta.FinalVelocity * deltaTime)) * remainingTime;
                            p2.Delta.FinalPosition += compensation;

                            // If this normal moved the object anywhere upward,
                            // that object is now considered grounded
                            if (surfaceNormal.Y > 0)
                            {
                                p2.Delta.IsGrounded = p2.Delta.IsGrounded || true;
                            }

                            // Fix the velocity
                            if (p2.BounceOnWallCollision || p2.BounceOnVerticalCollision)
                            {
                                if ((surfaceNormal.X != 0 || surfaceNormal.Z != 0) && p2.BounceOnWallCollision)
                                {
                                    if (surfaceNormal.X != 0)
                                    {
                                        p2.Delta.FinalVelocity.X *= -(1f - p2.HorizontalBounceFalloff);
                                    }
                                    if (surfaceNormal.Z != 0)
                                    {
                                        p2.Delta.FinalVelocity.Z *= -(1f - p2.HorizontalBounceFalloff);
                                    }
                                }
                                else if (surfaceNormal.Y != 0 && p2.BounceOnVerticalCollision)
                                {
                                    p2.Delta.FinalVelocity.Y *= -(1f - p2.VerticalBounceFalloff);
                                    p1.Delta.FinalVelocity.X *= p1.InverseFriction;
                                    p1.Delta.FinalVelocity.Z *= p1.InverseFriction;
                                }
                                else
                                {
                                    intersection.Resolver.FixVelocity(ref p2.Delta.FinalVelocity, surfaceNormal);
                                }
                            }
                            else
                            {
                                intersection.Resolver.FixVelocity(ref p2.Delta.FinalVelocity, surfaceNormal);
                            }
                        }

                        // Another delta pass has occured
                        p2.Delta.DeltaPass++;

                        p1.OnCollide(p2);
                        p2.OnCollide(p1);
                    }
                }
                else
                {
                    // If we are past the first sweep pass for this object,
                    // and this intersection is no longer valid, then ignore it.
                    if ((!p1DeltaCollider.Intersects(p2Collider)) &&
                        (!p2DeltaCollider.Intersects(p1Collider)))
                    {
                        continue;
                    }


                    float   p1DeltaMiddleX = p1.Delta.FinalPosition.X + p1.Size.X / 2f;
                    float   p2DeltaMiddleX = p2.Delta.FinalPosition.X + p2.Size.X / 2f;
                    float   p1DeltaMiddleZ = p1.Delta.FinalPosition.Z + p1.Size.Z / 2f;
                    float   p2DeltaMiddleZ = p2.Delta.FinalPosition.Z + p2.Size.Z / 2f;
                    Vector3 p1Move         = new Vector3((p2DeltaMiddleX - p1DeltaMiddleX), 0, (p2DeltaMiddleZ - p1DeltaMiddleZ));
                    Vector3 p2Move         = new Vector3((p1DeltaMiddleX - p2DeltaMiddleX), 0, (p1DeltaMiddleZ - p2DeltaMiddleZ));

                    if (p1Move.X == p2Move.X)
                    {
                        p1Move.X += Maths.Random.Next((int)-p2.Size.X, (int)p2.Size.X) / deltaTime;
                    }

                    Vector2 masses = new Vector2((p2.Mass / p1.Mass), (p1.Mass / p2.Mass)) * 0.5f;

                    if (p1.CanBePushedBySoft)
                    {
                        p1.Delta.FinalVelocity -= p1Move * masses.X;
                        p1.Delta.FinalPosition  = p1.Transform.Position + p1.Delta.FinalVelocity * deltaTime;
                    }

                    if (p2.CanBePushedBySoft)
                    {
                        p2.Delta.FinalVelocity -= p2Move * masses.Y;
                        p2.Delta.FinalPosition  = p2.Transform.Position + p2.Delta.FinalVelocity * deltaTime;
                    }

                    p1.OnCollide(p2);
                    p2.OnCollide(p1);
                }
            }
        }