Represents part of the world geometry that is a result of a SceneQuery.
Since world geometry is normally vast and sprawling, we need a way of retrieving parts of it based on a query. That is what this struct is for; note there are potentially as many data structures for world geometry as there are SceneManagers, however this structure includes a few common abstractions as well as a more general format.

The type of world fragment that is returned from a query depends on the SceneManager, and the fragment types are supported on the query.

Example #1
0
        bool Axiom.Core.IRaySceneQueryListener.OnQueryResult(SceneQuery.WorldFragment fragment, float distance)
        {
            // create an entry and add it to the cached result list
            RaySceneQueryResultEntry entry = new RaySceneQueryResultEntry();

            entry.Distance      = distance;
            entry.SceneObject   = null;
            entry.worldFragment = fragment;
            lastResults.Add(entry);

            // continue gathering results
            return(true);
        }
 public BspBrush(PlaneList planes, SceneQuery.WorldFragment fragment)
 {
     this.planes = planes;
     this.fragment = fragment;
 }
 public BspBrush()
 {
     planes = new PlaneList();
     fragment = new SceneQuery.WorldFragment();
 }
        /// <summary>
        ///		<see cref="IntersectionSceneQuery"/>
        /// </summary>
        public override void Execute( IIntersectionSceneQueryListener listener )
        {
            // Do movables to movables as before

            base.Execute( listener );

            SceneQuery.WorldFragment frag = new SceneQuery.WorldFragment();

            // Do entities to world

            SceneManager sceneMgr = (SceneManager)( this.creator );

            for(int i = 0; i < sceneMgr.Entities.Count; i++)

            {

                Entity entityA = sceneMgr.Entities[i];

                // Apply mask

                if ( ( entityA.QueryFlags & queryMask) == 0 )

                {

                    AxisAlignedBox box = entityA.GetWorldBoundingBox( );

                    ArrayList opList = new ArrayList();

            /*

                    for ( int j = 0; j < mOptions->world_height; j++ )

                    {

                        for ( int i = 0; i < mOptions->world_width; i++ )

                        {

            //					if ( sceneMgr->mPages[ i ][ j ]->isLoaded( ) == true )

            //					{

            //						sceneMgr->mPages[ i ][ j ]->getIPLRenderOpsInBox( box, opList );

            //					}

                        }

                    }

            */

                    for ( int j = 0; j < opList.Count; ++j )

                    {

                        frag.FragmentType = WorldFragmentType.RenderOperation;

                        frag.RenderOp = (RenderOperation) opList[i];

                        listener.OnQueryResult( entityA, frag );

                    }

                }

            }
        }
 public SceneQueryMovableObjectWorldFragmentPair(MovableObject obj, SceneQuery.WorldFragment fragment)
 {
     this.obj = obj;
     this.fragment = fragment;
 }
        /// <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;
                    }
                }
            }
        }
        /// <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;

                            }

                        }

                    }

                }

            }
        }
Example #8
0
        bool Axiom.Core.IIntersectionSceneQueryListener.OnQueryResult(MovableObject obj, SceneQuery.WorldFragment fragment)
        {
            // create an entry and add it to the cached result list
            lastResults.Objects2World.Add(new SceneQueryMovableObjectWorldFragmentPair(obj, fragment));

            // continue gathering results
            return(true);
        }