Ejemplo n.º 1
0
		public override void Execute( IRaySceneQueryListener listener )
		{
			Vector3 dir = ray.Direction;
			Vector3 origin = ray.Origin;
			// Straight up / down?
			if ( dir == Vector3.UnitY || dir == Vector3.NegativeUnitY )
			{
				float height = ( (TerrainSceneManager)creator ).GetHeightAt( origin, -1 );
				if ( height != -1 && ( height <= origin.y && dir.y < 0 ) || ( height >= origin.y && dir.y > 0 ) )
				{
					this.WorldFragment.SingleIntersection.x = origin.x;
					this.WorldFragment.SingleIntersection.z = origin.z;
					this.WorldFragment.SingleIntersection.y = height;
					if ( !listener.OnQueryResult( this.WorldFragment, ( this.WorldFragment.SingleIntersection - origin ).Length ) )
						return;
				}
			}
			else
			{
				TerrainSceneManager tsm = (TerrainSceneManager)creator;
				this.WorldFragment.SingleIntersection = tsm.IntersectSegment( origin, origin + ( dir * 100000 ) );
				if ( !listener.OnQueryResult( this.WorldFragment, ( this.WorldFragment.SingleIntersection - origin ).Length ) )
					return;
			}
		}
Ejemplo n.º 2
0
        public override void Execute(IRaySceneQueryListener listener)
        {
            Vector3 dir    = ray.Direction;
            Vector3 origin = ray.Origin;

            // Straight up / down?
            if (dir == Vector3.UnitY || dir == Vector3.NegativeUnitY)
            {
                float height = ((TerrainSceneManager)creator).GetHeightAt(origin, -1);
                if (height != -1 && (height <= origin.y && dir.y < 0) || (height >= origin.y && dir.y > 0))
                {
                    this.WorldFragment.SingleIntersection.x = origin.x;
                    this.WorldFragment.SingleIntersection.z = origin.z;
                    this.WorldFragment.SingleIntersection.y = height;
                    if (!listener.OnQueryResult(this.WorldFragment, (this.WorldFragment.SingleIntersection - origin).Length))
                    {
                        return;
                    }
                }
            }
            else
            {
                var tsm = (TerrainSceneManager)creator;
                this.WorldFragment.SingleIntersection = tsm.IntersectSegment(origin, origin + (dir * 100000));
                if (!listener.OnQueryResult(this.WorldFragment, (this.WorldFragment.SingleIntersection - origin).Length))
                {
                    return;
                }
            }
        }
Ejemplo n.º 3
0
        public override void Execute(IRaySceneQueryListener listener)
        {
            var list = new List <PCZSceneNode>();

            //find the nodes that intersect the AAB
            ((PCZSceneManager)creator).FindNodesIn(ray, ref list, this.startZone, (PCZSceneNode)this.excludeNode);

            //grab all moveables from the node that intersect...

            foreach (PCZSceneNode node in list)
            {
                foreach (MovableObject m in node.Objects)
                {
                    if ((m.QueryFlags & queryMask) != 0 && (m.TypeFlags & this.queryTypeMask) != 0 && m.IsAttached)
                    {
                        IntersectResult result = ray.Intersects(m.GetWorldBoundingBox());
                        if (result.Hit)
                        {
                            listener.OnQueryResult(m, result.Distance);
                            // deal with attached objects, since they are not directly attached to nodes
                            if (m.MovableType == "Entity")
                            {
                                //Check: not sure here...
                                var e = (Entity)m;
                                foreach (MovableObject c in e.SubEntities)
                                {
                                    if ((c.QueryFlags & queryMask) > 0)
                                    {
                                        result = ray.Intersects(c.GetWorldBoundingBox());
                                        if (result.Hit)
                                        {
                                            listener.OnQueryResult(c, result.Distance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // reset startzone and exclude node
            this.startZone   = null;
            this.excludeNode = null;
        }
Ejemplo n.º 4
0
		public override void Execute( IRaySceneQueryListener listener )
		{
			MovableObjectFactoryMap factories = Root.Instance.MovableObjectFactories;
			foreach ( KeyValuePair<string, MovableObjectFactory> map in factories )
			{
				MovableObjectCollection movableObjects = this.creator.GetMovableObjectCollection( map.Value.Type );
				foreach ( MovableObject movableObject in movableObjects.Values )
				{
					// skip group if query type doesn't match
					if ( ( this.QueryTypeMask & movableObject.TypeFlags ) == 0 )
					{
						break;
					}

					// skip if unattached or filtered out by query flags
					if ( !movableObject.IsAttached || ( movableObject.QueryFlags & this.queryMask ) == 0 )
					{
						continue;
					}

					// test the intersection against the world bounding box of the entity
					IntersectResult results = Utility.Intersects( this.ray, movableObject.GetWorldBoundingBox() );

					// if the results came back positive, fire the event handler
					if ( results.Hit == true )
					{
						listener.OnQueryResult( movableObject, results.Distance );
					}
				}
			}
		}
Ejemplo n.º 5
0
		public override void Execute( IRaySceneQueryListener listener )
		{
			var list = new List<PCZSceneNode>();
			//find the nodes that intersect the AAB
			( (PCZSceneManager)creator ).FindNodesIn( ray, ref list, this.startZone, (PCZSceneNode)this.excludeNode );

			//grab all moveables from the node that intersect...

			foreach ( PCZSceneNode node in list )
			{
				foreach ( MovableObject m in node.Objects )
				{
					if ( ( m.QueryFlags & queryMask ) != 0 && ( m.TypeFlags & this.queryTypeMask ) != 0 && m.IsAttached )
					{
						IntersectResult result = ray.Intersects( m.GetWorldBoundingBox() );
						if ( result.Hit )
						{
							listener.OnQueryResult( m, result.Distance );
							// deal with attached objects, since they are not directly attached to nodes
							if ( m.MovableType == "Entity" )
							{
								//Check: not sure here...
								var e = (Entity)m;
								foreach ( MovableObject c in e.SubEntities )
								{
									if ( ( c.QueryFlags & queryMask ) > 0 )
									{
										result = ray.Intersects( c.GetWorldBoundingBox() );
										if ( result.Hit )
										{
											listener.OnQueryResult( c, result.Distance );
										}
									}
								}
							}
						}
					}
				}
			}
			// reset startzone and exclude node
			this.startZone = null;
			this.excludeNode = null;
		}
        /// <summary>
        ///		<see cref="RaySceneQuery"/>
        /// </summary>
        public void Execute(IRaySceneQueryListener listener, Camera camera)
        {
            clearFragmentList();

            // if the world is not initialized, then just quit out now with no hits
            if (!TerrainManager.Instance.Initialized)
            {
                return;
            }

            ulong mask = QueryMask;
            SceneQuery.WorldFragment frag;

            bool terrainQuery = (mask & (ulong)RaySceneQueryType.AllTerrain) != 0 || (mask & (ulong)RaySceneQueryType.FirstTerrain) != 0;

            // if the query is a terrain query that is exactly vertical, then force it into the "Height" fastpath
            if (((mask & (ulong)RaySceneQueryType.Height) != 0) || (terrainQuery && (this.Ray.Direction.x == 0.0f) && (this.Ray.Direction.z == 0.0f)))
            {
                // we don't want to bother checking for entities because a
                // UNIT_Y ray is assumed to be a height test, not a ray test
                frag = new SceneQuery.WorldFragment();
                fragmentList.Add(frag);

                frag.FragmentType = WorldFragmentType.SingleIntersection;
                Vector3 origin = this.Ray.Origin;
                origin.y = 0; // ensure that it's within bounds
                frag.SingleIntersection = getHeightAt(origin);
                listener.OnQueryResult(frag, Math.Abs(frag.SingleIntersection.y - this.Ray.Origin.y));
            }
            else
            {
                // Check for all entity contacts
                if ((mask & (ulong)RaySceneQueryType.Entities) != 0)
                {
                    base.Execute(listener);
                }

                // Check for contact with the closest entity triangle
                // or all entity triangles.  Ignores entities that
                // don't have a TriangleIntersector associated with
                // their meshes.
                bool firstTriangleQuery = (mask & (ulong)(RaySceneQueryType.FirstEntityTriangle)) != 0;
                bool allTrianglesQuery = (mask & (ulong)(RaySceneQueryType.AllEntityTriangles)) != 0;
                if (firstTriangleQuery | allTrianglesQuery)
                {
                    rayOrigin = this.ray.Origin;
                    // Start by getting the entities whose bounding
                    // boxes intersect the ray.  If there are none,
                    // we're done.
                    List<MovableObject> candidates = new List<MovableObject>();
                    foreach (Dictionary<string, MovableObject> objectMap in creator.MovableObjectMaps)
                    {
                        foreach (MovableObject obj in objectMap.Values)
                        {
                            // skip if unattached or filtered out by query flags
                            if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                                continue;

                            // test the intersection against the world bounding box of the entity
                            IntersectResult results = MathUtil.Intersects(ray, obj.GetWorldBoundingBox());
                            if (results.Hit)
                                candidates.Add(obj);
                        }
                    }

                    // Get the camera.Near value
                    Camera cam = camera;
                    float nearDistance = cam.Near;
                    float closestDistance = float.MaxValue;
                    Vector3 closestIntersection = Vector3.Zero;
                    Entity closestEntity = null;
                    List<EntityAndIntersection> allEntities = new List<EntityAndIntersection>();
                    foreach (MovableObject obj in candidates)
                    {
                        // skip if unattached or filtered out by query flags
                        if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                            continue;

                        Entity entity = obj as Entity;
                        if (entity == null)
                            continue;

                        // skip if its mesh doesn't have triangles
                        if (entity.Mesh == null || entity.Mesh.TriangleIntersector == null)
                            continue;

                        // transform the ray to the space of the mesh
                        Matrix4 inverseTransform = entity.ParentNodeFullTransform.Inverse();
                        Matrix4 inverseWithoutTranslation = inverseTransform;
                        inverseWithoutTranslation.Translation = Vector3.Zero;
                        Vector3 transformedOrigin = inverseTransform * ray.Origin;
                        Ray transformedRay = new Ray(transformedOrigin,
                                                     (inverseWithoutTranslation * ray.Direction).ToNormalized());

                        // test the intersection against the world bounding box of the entity
                        Vector3 untransformedIntersection;
                        if (entity.Mesh.TriangleIntersector.ClosestRayIntersection(transformedRay, Vector3.Zero,
                                                                                   nearDistance, out untransformedIntersection))
                        {
                            Vector3 intersection = entity.ParentNodeFullTransform * untransformedIntersection;
                            if (allTrianglesQuery)
                                allEntities.Add(new EntityAndIntersection(entity, intersection));
                            float distance = (ray.Origin - intersection).Length;
                            if (firstTriangleQuery && distance < closestDistance)
                            {
                                closestDistance = distance;
                                closestEntity = entity;
                                closestIntersection = intersection;
                            }
                        }
                    }
                    if (firstTriangleQuery && closestEntity != null)
                    {
                        frag = new SceneQuery.WorldFragment();
                        fragmentList.Add(frag);
                        frag.FragmentType = WorldFragmentType.SingleIntersection;
                        frag.SingleIntersection = closestIntersection;
                        listener.OnQueryResult(frag, closestDistance);
                    }
                    else if (allTrianglesQuery && allEntities.Count > 0)
                    {
                        allEntities.Sort(distanceToCameraCompare);
                        foreach (EntityAndIntersection ei in allEntities)
                            listener.OnQueryResult(ei.entity, (rayOrigin - ei.intersection).Length);
                    }
                }

                if (terrainQuery)
                {
                    Vector3 ray = Ray.Origin;
                    Vector3 land = getHeightAt(ray);
                    float dist = 0, resFactor = TerrainManager.oneMeter;

                    // find the larger of x and z directions of the ray direction
                    float maxXZ = Math.Max(Math.Abs(Ray.Direction.x), Math.Abs(Ray.Direction.z));

                    // Only bother if the non-default mask has been set
                    if ((mask & (ulong)RaySceneQueryType.OnexRes) != 0)
                    {
                        if ((mask & (ulong)RaySceneQueryType.TwoxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 2;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.FourxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 4;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.EightxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 8;
                        }
                    }

                    // this scales the res factor so that we move along the ray by a distance that results
                    // in shift of one meter along either the X or Z axis (whichever is longer)
                    resFactor = resFactor / maxXZ;

                    SubPageHeightMap sp;
                    // bool east = false; (unused)
                    // bool south = false; (unused)

                    // if ( Ray.Origin.x > 0 )
                    // {
                    //	east = true;
                    // }
                    // if ( Ray.Origin.z > 0 )
                    // {
                    //	south = true;
                    // }

                    ray = Ray.Origin;
                    sp = TerrainManager.Instance.LookupSubPage(ray);

                    while (sp != null)
                    {
                        SubPageHeightMap newsp;
                        AxisAlignedBox tileBounds = sp.BoundingBox;

                        IntersectResult intersect = MathUtil.Intersects(Ray, tileBounds);

                        if (intersect.Hit)
                        {
                            // step through this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            {
                                land = getHeightAt(ray);
                                if (ray.y < land.y)
                                {
                                    frag = new SceneQuery.WorldFragment();
                                    fragmentList.Add(frag);

                                    frag.FragmentType = WorldFragmentType.SingleIntersection;
                                    frag.SingleIntersection = land;
                                    listener.OnQueryResult(frag, dist);

                                    if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                    {
                                        return;
                                    }
                                }

                                ray += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                            // if we fall off the end of the above loop without getting a hit, then the hit should be
                            // right at the far edge of the tile, so handle that case.
                            land = getHeightAt(ray);
                            if (ray.y < land.y)
                            {
                                frag = new SceneQuery.WorldFragment();
                                fragmentList.Add(frag);

                                frag.FragmentType = WorldFragmentType.SingleIntersection;
                                frag.SingleIntersection = land;
                                listener.OnQueryResult(frag, dist);

                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile ray collision");

                                if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile reached without expected intersection");
                            }
                        }
                        else
                        {
                            // step over this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            { // XXX - this is not the most efficient method...
                                ray += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                        }

                        sp = newsp;
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        ///		<see cref="RaySceneQuery"/>
        /// </summary>
        public void Execute(IRaySceneQueryListener listener, Camera camera)
        {
            clearFragmentList();

            // if the world is not initialized, then just quit out now with no hits
            if (!TerrainManager.Instance.Initialized)
            {
                return;
            }

            ulong mask = QueryMask;

            SceneQuery.WorldFragment frag;

            bool terrainQuery = (mask & (ulong)RaySceneQueryType.AllTerrain) != 0 || (mask & (ulong)RaySceneQueryType.FirstTerrain) != 0;

            // if the query is a terrain query that is exactly vertical, then force it into the "Height" fastpath
            if (((mask & (ulong)RaySceneQueryType.Height) != 0) || (terrainQuery && (this.Ray.Direction.x == 0.0f) && (this.Ray.Direction.z == 0.0f)))
            {
                // we don't want to bother checking for entities because a
                // UNIT_Y ray is assumed to be a height test, not a ray test
                frag = new SceneQuery.WorldFragment();
                fragmentList.Add(frag);

                frag.FragmentType = WorldFragmentType.SingleIntersection;
                Vector3 origin = this.Ray.Origin;
                origin.y = 0; // ensure that it's within bounds
                frag.SingleIntersection = getHeightAt(origin);
                listener.OnQueryResult(frag, Math.Abs(frag.SingleIntersection.y - this.Ray.Origin.y));
            }
            else
            {
                // Check for all entity contacts
                if ((mask & (ulong)RaySceneQueryType.Entities) != 0)
                {
                    base.Execute(listener);
                }

                // Check for contact with the closest entity triangle
                // or all entity triangles.  Ignores entities that
                // don't have a TriangleIntersector associated with
                // their meshes.
                bool firstTriangleQuery = (mask & (ulong)(RaySceneQueryType.FirstEntityTriangle)) != 0;
                bool allTrianglesQuery  = (mask & (ulong)(RaySceneQueryType.AllEntityTriangles)) != 0;
                if (firstTriangleQuery | allTrianglesQuery)
                {
                    rayOrigin = this.ray.Origin;
                    // Start by getting the entities whose bounding
                    // boxes intersect the ray.  If there are none,
                    // we're done.
                    List <MovableObject> candidates = new List <MovableObject>();
                    foreach (Dictionary <string, MovableObject> objectMap in creator.MovableObjectMaps)
                    {
                        foreach (MovableObject obj in objectMap.Values)
                        {
                            // skip if unattached or filtered out by query flags
                            if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                            {
                                continue;
                            }

                            // test the intersection against the world bounding box of the entity
                            IntersectResult results = MathUtil.Intersects(ray, obj.GetWorldBoundingBox());
                            if (results.Hit)
                            {
                                candidates.Add(obj);
                            }
                        }
                    }

                    // Get the camera.Near value
                    Camera  cam                 = camera;
                    float   nearDistance        = cam.Near;
                    float   closestDistance     = float.MaxValue;
                    Vector3 closestIntersection = Vector3.Zero;
                    Entity  closestEntity       = null;
                    List <EntityAndIntersection> allEntities = new List <EntityAndIntersection>();
                    foreach (MovableObject obj in candidates)
                    {
                        // skip if unattached or filtered out by query flags
                        if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                        {
                            continue;
                        }

                        Entity entity = obj as Entity;
                        if (entity == null)
                        {
                            continue;
                        }

                        // skip if its mesh doesn't have triangles
                        if (entity.Mesh == null || entity.Mesh.TriangleIntersector == null)
                        {
                            continue;
                        }

                        // transform the ray to the space of the mesh
                        Matrix4 inverseTransform          = entity.ParentNodeFullTransform.Inverse();
                        Matrix4 inverseWithoutTranslation = inverseTransform;
                        inverseWithoutTranslation.Translation = Vector3.Zero;
                        Vector3 transformedOrigin = inverseTransform * ray.Origin;
                        Ray     transformedRay    = new Ray(transformedOrigin,
                                                            (inverseWithoutTranslation * ray.Direction).ToNormalized());

                        // test the intersection against the world bounding box of the entity
                        Vector3 untransformedIntersection;
                        if (entity.Mesh.TriangleIntersector.ClosestRayIntersection(transformedRay, Vector3.Zero,
                                                                                   nearDistance, out untransformedIntersection))
                        {
                            Vector3 intersection = entity.ParentNodeFullTransform * untransformedIntersection;
                            if (allTrianglesQuery)
                            {
                                allEntities.Add(new EntityAndIntersection(entity, intersection));
                            }
                            float distance = (ray.Origin - intersection).Length;
                            if (firstTriangleQuery && distance < closestDistance)
                            {
                                closestDistance     = distance;
                                closestEntity       = entity;
                                closestIntersection = intersection;
                            }
                        }
                    }
                    if (firstTriangleQuery && closestEntity != null)
                    {
                        frag = new SceneQuery.WorldFragment();
                        fragmentList.Add(frag);
                        frag.FragmentType       = WorldFragmentType.SingleIntersection;
                        frag.SingleIntersection = closestIntersection;
                        listener.OnQueryResult(frag, closestDistance);
                    }
                    else if (allTrianglesQuery && allEntities.Count > 0)
                    {
                        allEntities.Sort(distanceToCameraCompare);
                        foreach (EntityAndIntersection ei in allEntities)
                        {
                            listener.OnQueryResult(ei.entity, (rayOrigin - ei.intersection).Length);
                        }
                    }
                }

                if (terrainQuery)
                {
                    Vector3 ray = Ray.Origin;
                    Vector3 land = getHeightAt(ray);
                    float   dist = 0, resFactor = TerrainManager.oneMeter;

                    // find the larger of x and z directions of the ray direction
                    float maxXZ = Math.Max(Math.Abs(Ray.Direction.x), Math.Abs(Ray.Direction.z));

                    // Only bother if the non-default mask has been set
                    if ((mask & (ulong)RaySceneQueryType.OnexRes) != 0)
                    {
                        if ((mask & (ulong)RaySceneQueryType.TwoxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 2;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.FourxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 4;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.EightxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 8;
                        }
                    }

                    // this scales the res factor so that we move along the ray by a distance that results
                    // in shift of one meter along either the X or Z axis (whichever is longer)
                    resFactor = resFactor / maxXZ;

                    SubPageHeightMap sp;
                    // bool east = false; (unused)
                    // bool south = false; (unused)

                    // if ( Ray.Origin.x > 0 )
                    // {
                    //	east = true;
                    // }
                    // if ( Ray.Origin.z > 0 )
                    // {
                    //	south = true;
                    // }

                    ray = Ray.Origin;
                    sp  = TerrainManager.Instance.LookupSubPage(ray);

                    while (sp != null)
                    {
                        SubPageHeightMap newsp;
                        AxisAlignedBox   tileBounds = sp.BoundingBox;

                        IntersectResult intersect = MathUtil.Intersects(Ray, tileBounds);

                        if (intersect.Hit)
                        {
                            // step through this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            {
                                land = getHeightAt(ray);
                                if (ray.y < land.y)
                                {
                                    frag = new SceneQuery.WorldFragment();
                                    fragmentList.Add(frag);

                                    frag.FragmentType       = WorldFragmentType.SingleIntersection;
                                    frag.SingleIntersection = land;
                                    listener.OnQueryResult(frag, dist);

                                    if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                    {
                                        return;
                                    }
                                }

                                ray  += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                            // if we fall off the end of the above loop without getting a hit, then the hit should be
                            // right at the far edge of the tile, so handle that case.
                            land = getHeightAt(ray);
                            if (ray.y < land.y)
                            {
                                frag = new SceneQuery.WorldFragment();
                                fragmentList.Add(frag);

                                frag.FragmentType       = WorldFragmentType.SingleIntersection;
                                frag.SingleIntersection = land;
                                listener.OnQueryResult(frag, dist);

                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile ray collision");

                                if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile reached without expected intersection");
                            }
                        }
                        else
                        {
                            // step over this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            { // XXX - this is not the most efficient method...
                                ray  += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                        }

                        sp = newsp;
                    }
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>

        ///		<see cref="RaySceneQuery"/>

        /// </summary>

        public override void Execute(IRaySceneQueryListener listener)

        {
            clearFragmentList( );



            ulong mask = QueryMask;

            SceneQuery.WorldFragment frag;



            if ((mask & (ulong)RaySceneQueryType.Height) != 0)

            {
                // we don't want to bother checking for entities because a

                // UNIT_Y ray is assumed to be a height test, not a ray test

                frag = new SceneQuery.WorldFragment( );

                fragmentList.Add(frag);



                frag.FragmentType = WorldFragmentType.SingleIntersection;

                Vector3 origin = this.Ray.Origin;

                origin.y = 0;                 // ensure that it's within bounds

                frag.SingleIntersection = getHeightAt(origin);

                listener.OnQueryResult(frag, Math.Abs(frag.SingleIntersection.y - this.Ray.Origin.y));
            }

            else

            {
                // Check for entity contacts

                if ((mask & (ulong)RaySceneQueryType.Entities) != 0)

                {
                    base.Execute(listener);
                }



                if ((mask & (ulong)RaySceneQueryType.AllTerrain) != 0 || (mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)

                {
                    Vector3 ray = Ray.Origin;

                    Vector3 land = getHeightAt(ray);

                    float dist = 0, resFactor = 1;



                    // Only bother if the non-default mask has been set

                    if ((mask & (ulong)RaySceneQueryType.OnexRes) != 0)

                    {
                        if ((mask & (ulong)RaySceneQueryType.TwoxRes) != 0)

                        {
                            resFactor = 0.5F;
                        }

                        else if ((mask & (ulong)RaySceneQueryType.FourxRes) != 0)

                        {
                            resFactor = 0.25F;
                        }

                        else if ((mask & (ulong)RaySceneQueryType.EightxRes) != 0)

                        {
                            resFactor = 0.125F;
                        }
                    }



                    while (land.y != -1)

                    {
                        ray += Ray.Direction * resFactor;

                        dist += 1 * resFactor;



                        land = getHeightAt(ray);

                        if (ray.y < land.y)

                        {
                            frag = new SceneQuery.WorldFragment( );

                            fragmentList.Add(frag);



                            frag.FragmentType = WorldFragmentType.SingleIntersection;

                            frag.SingleIntersection = land;

                            listener.OnQueryResult(frag, dist);



                            if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)

                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
        public override void Execute(IRaySceneQueryListener listener)
        {
            // Note that becuase we have no scene partitioning, we actually
            // perform a complete scene search even if restricted results are
            // requested; smarter scene manager queries can utilise the paritioning
            // of the scene in order to reduce the number of intersection tests
            // required to fulfil the query

            // TODO: BillboardSets? Will need per-billboard collision most likely
            // Entities only for now
            foreach (Dictionary<string, MovableObject> objectMap in creator.MovableObjectMaps) {
                foreach (MovableObject obj in objectMap.Values) {
                    // skip if unattached or filtered out by query flags
                    if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0) {
                        continue;
                    }

                    // test the intersection against the world bounding box of the entity
                    IntersectResult results = MathUtil.Intersects(ray, obj.GetWorldBoundingBox());

                    // if the results came back positive, fire the event handler
                    if (results.Hit == true) {
                        listener.OnQueryResult(obj, results.Distance);
                    }
                }
            }
        }
        /// <summary>
        ///		<see cref="RaySceneQuery"/>
        /// </summary>
        public override void Execute( IRaySceneQueryListener listener )
        {
            clearFragmentList( );

            ulong mask = QueryMask;

            SceneQuery.WorldFragment frag;

            if ( (mask & (ulong)RaySceneQueryType.Height) != 0)

            {

                // we don't want to bother checking for entities because a

                // UNIT_Y ray is assumed to be a height test, not a ray test

                frag = new SceneQuery.WorldFragment( );

                fragmentList.Add( frag );

                frag.FragmentType = WorldFragmentType.SingleIntersection;

                Vector3 origin = this.Ray.Origin;

                origin.y = 0; // ensure that it's within bounds

                frag.SingleIntersection = getHeightAt( origin );

                listener.OnQueryResult( frag, Math.Abs(frag.SingleIntersection.y - this.Ray.Origin.y) );

            }

            else

            {

                // Check for entity contacts

                if ( (mask & (ulong)RaySceneQueryType.Entities) != 0 )

                {

                    base.Execute( listener );

                }

                if ( (mask & (ulong)RaySceneQueryType.AllTerrain) != 0 || (mask & (ulong)RaySceneQueryType.FirstTerrain) !=0 )

                {

                    Vector3 ray = Ray.Origin;

                    Vector3 land = getHeightAt( ray );

                    float dist = 0, resFactor = 1;

                    // Only bother if the non-default mask has been set

                    if ( ( mask & (ulong)RaySceneQueryType.OnexRes ) != 0 )

                    {

                        if ( (mask & (ulong)RaySceneQueryType.TwoxRes) != 0 )

                        {

                            resFactor = 0.5F;

                        }

                        else if ( (mask & (ulong)RaySceneQueryType.FourxRes) !=0 )

                        {

                            resFactor = 0.25F;

                        }

                        else if ( (mask & (ulong)RaySceneQueryType.EightxRes) != 0 )

                        {

                            resFactor = 0.125F;

                        }

                    }

                    while ( land.y != -1 )

                    {

                        ray += Ray.Direction * resFactor;

                        dist += 1 * resFactor;

                        land = getHeightAt( ray );

                        if ( ray.y < land.y )

                        {

                            frag = new SceneQuery.WorldFragment( );

                            fragmentList.Add( frag );

                            frag.FragmentType = WorldFragmentType.SingleIntersection;

                            frag.SingleIntersection = land;

                            listener.OnQueryResult( frag, dist );

                            if ( (mask & (ulong)RaySceneQueryType.FirstTerrain )!= 0)

                            {

                                return;

                            }

                        }

                    }

                }

            }
        }