public void Cast(CollisionWorld cw)
        {
            var cb = new ClosestConvexResultCallback(Vector3.Zero, Vector3.Zero);
            for (int i = 0; i < NUMRAYS_IN_BAR; i++)
            {
                cb.ClosestHitFraction = 1.0f;
                cb.ConvexFromWorld = source[i];
                cb.ConvexToWorld = dest[i];

                Quaternion qFrom = Quaternion.RotationAxis(new Vector3(1.0f, 0.0f, 0.0f), 0.0f);
                Quaternion qTo = Quaternion.RotationAxis(new Vector3(1.0f, 0.0f, 0.0f), 0.7f);
                Matrix from = Matrix.RotationQuaternion(qFrom) * Matrix.Translation(source[i]);
                Matrix to = Matrix.RotationQuaternion(qTo) * Matrix.Translation(dest[i]);
                cw.ConvexSweepTest(boxShape, from, to, cb);
                if (cb.HasHit)
                {
                    hit_surface[i] = cb.HitPointWorld;
                    hit_com[i] = Vector3.Lerp(source[i], dest[i], cb.ClosestHitFraction);
                    hit_fraction[i] = cb.ClosestHitFraction;
                    normal[i] = cb.HitNormalWorld;
                    normal[i].Normalize();
                }
                else
                {
                    hit_com[i] = dest[i];
                    hit_surface[i] = dest[i];
                    hit_fraction[i] = 1.0f;
                    normal[i] = new Vector3(1.0f, 0.0f, 0.0f);
                }
            }

            frame_counter++;
            if (frame_counter > 50)
            {
                min_ms = ms < min_ms ? ms : min_ms;
                max_ms = ms > max_ms ? ms : max_ms;
                sum_ms += ms;
                sum_ms_samples++;
                float mean_ms = (float)sum_ms / (float)sum_ms_samples;
                Console.WriteLine("{0} rays in {1} ms {2} {3} {4}", NUMRAYS_IN_BAR * frame_counter, ms, min_ms, max_ms, mean_ms);
                ms = 0;
                frame_counter = 0;
            }
        }