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; } } } } } }
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); }