Raycast "flickering"

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

Raycast "flickering"

Post by Phippu »

Hi again!

I've played around with raycasting and basically it works fine. I tried to implement something like a laser ray that gets reflected. That works fine, but it seems that sometimes a raycast call doesn't hit an object, but in fact there is one! I've created a little demo so that you can see the problem directly (just replace the following code with the one from the wall demo):

Code: Select all

using System;
using System.Collections.Generic;
using BEPUphysics;
using BEPUphysics.Entities.Prefabs;
using BEPUphysicsDrawer.Lines;
using Microsoft.Xna.Framework;

namespace BEPUphysicsDemos.Demos
{
    /// <summary>
    /// Demo showing a wall of blocks stacked up.
    /// </summary>
    public class WallDemo : StandardDemo
    {
        private List<Line> lines = new List<Line>();

        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public WallDemo(DemosGame game)
            : base(game)
        {

            for (int i = 0; i < 15; i++)
            {
                float angle = MathHelper.TwoPi/15*i;
                Space.Add(new Box(new Vector3((float)Math.Cos(angle)*5,0.5f,(float)Math.Sin(angle)*5), 1, 1, 1));
            }

            for (int i = 0; i < 15; i++)
            {
                float angle = MathHelper.TwoPi / 15 * i + 0.25f;
                Space.Add(new Box(new Vector3((float)Math.Cos(angle) * 10, 0.5f, (float)Math.Sin(angle) * 10), 1, 1, 1));
            }


            for (int i = 0; i < 10; i++)
            {
                Line line = new Line(new Vector3(0, 0, 0), new Vector3(0, 0, 0), Color.Black, Color.White,
                                     Game.ConstraintDrawer);
                lines.Add(line);
            }

            Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50);
            Space.Add(ground);
            game.Camera.Position = new Vector3(0, 6, 15);
        }

        private float angle = 0;

        public override void Update(float dt)
        {
            base.Update(dt);

            angle += 0.001f;

            //"reset" lines
            for (int i = 0; i < lines.Count; i++)
            {
                lines[i].PositionA = Vector3.Zero;
                lines[i].PositionB = Vector3.Zero;
            }

            Vector3 position = new Vector3(0,0.5f,0);
            Vector3 direction = new Vector3((float)Math.Cos(angle),0,(float)Math.Sin(angle));
            RayCastResult rayCastResult;
            int iteration = 0;
            bool hadAHit = false;
            while (iteration<lines.Count-1 &&  Space.RayCast(new Ray(position,direction),out rayCastResult ))
            {
                hadAHit = true;

                lines[iteration].PositionA = position;
                lines[iteration].PositionB = rayCastResult.HitData.Location;

                position = rayCastResult.HitData.Location;
                direction = Vector3.Reflect(direction, rayCastResult.HitData.Normal);

                iteration++;
            }

            if (!hadAHit)
            {
                //just to make sure we see a line even if we hit no entity
                lines[lines.Count - 1].PositionA = position;
                lines[lines.Count - 1].PositionB = position + direction*50;
            }
        }

        /// <summary>
        /// Gets the name of the simulation.
        /// </summary>
        public override string Name
        {
            get { return "Wall"; }
        }
    }
}
As you can see in the demo the ray "flickers" and sometimes it doesn't reflect, sometimes it does.

How can I solve this problem? Thx a lot!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Raycast "flickering"

Post by Norbo »

The previous ray impact is right on the surface of the last hit object. The subsequent ray cast has a high chance of hitting that object again, but this time from the 'inside.' It flickers because the single precision floating point numbers sometimes result in the ray being inside, and sometimes outside.

Here's one way to fix it:

Code: Select all

        public override void Update(float dt)
        {
            base.Update(dt);

            angle += 0.001f;

            //"reset" lines
            for (int i = 0; i < lines.Count; i++)
            {
                lines[i].PositionA = Vector3.Zero;
                lines[i].PositionB = Vector3.Zero;
            }

            Vector3 position = new Vector3(0, 0.5f, 0);
            Vector3 direction = new Vector3((float)Math.Cos(angle), 0, (float)Math.Sin(angle));
            RayCastResult rayCastResult;
            int iteration = 0;
            BroadPhaseEntry lastHitObject = null;
            while (iteration < lines.Count - 1 && Space.RayCast(new Ray(position, direction), x => lastHitObject != x, out rayCastResult))
            {
                lines[iteration].PositionA = position;
                lines[iteration].PositionB = rayCastResult.HitData.Location;

                position = rayCastResult.HitData.Location;
                direction = Vector3.Reflect(direction, rayCastResult.HitData.Normal);
                lastHitObject = rayCastResult.HitObject;

                iteration++;
            }

            //just to make sure we see a line even if we hit no entity
            lines[lines.Count - 1].PositionA = position;
            lines[lines.Count - 1].PositionB = position + direction * 50;
        }
The relevant bit is that the lastHitObject is tracked and rejected by a ray cast filter.
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

Re: Raycast "flickering"

Post by Phippu »

Never thought that this is the problem, thank you so much!
Post Reply