/// <summary> /// Tests for intersection between this sphere and another sphere. /// </summary> /// <param name="sphere">Other sphere.</param> /// <returns>True if the spheres intersect, false otherwise.</returns> public bool Intersects(Sphere sphere) { return ((sphere.center - center).Length <= (sphere.radius + radius)); }
public override bool IsObjectVisible(Sphere bound, out FrustumPlane culledBy) { if (cullingFrustum != null) return cullingFrustum.IsObjectVisible(bound, out culledBy); else return base.IsObjectVisible(bound, out culledBy); }
public override bool ProjectSphere(Sphere sphere, out float left, out float top, out float right, out float bottom) { if (cullingFrustum != null) return cullingFrustum.ProjectSphere(sphere, out left, out top, out right, out bottom); else return base.ProjectSphere(sphere, out left, out top, out right, out bottom); }
// TODO: Scene queries. /// <summary> /// Creates an AxisAlignedBoxSceneQuery for this scene manager. /// </summary> /// <remarks> /// This method creates a new instance of a query object for this scene manager, /// for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery /// for full details. /// <p/> /// The instance returned from this method must be destroyed by calling /// SceneManager.DestroyQuery when it is no longer required. /// </remarks> /// <param name="box">Details of the box which describes the region for this query.</param> /*public virtual AxisAlignedBoxSceneQuery CreateAABBQuery(AxisAlignedBox box) { return CreateAABBQuery(box, 0xFFFFFFFF); } /// <summary> /// Creates an AxisAlignedBoxSceneQuery for this scene manager. /// </summary> /// <remarks> /// This method creates a new instance of a query object for this scene manager, /// for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery /// for full details. /// <p/> /// The instance returned from this method must be destroyed by calling /// SceneManager.DestroyQuery when it is no longer required. /// </remarks> /// <param name="box">Details of the box which describes the region for this query.</param> /// <param name="mask">The query mask to apply to this query; can be used to filter out certain objects; see SceneQuery for details.</param> public virtual AxisAlignedBoxSceneQuery CreateAABBQuery(AxisAlignedBox box, ulong mask) { // TODO: return null; }*/ /// <summary> /// Creates a SphereSceneQuery for this scene manager. /// </summary> /// <remarks> /// This method creates a new instance of a query object for this scene manager, /// for a spherical region. See SceneQuery and SphereSceneQuery /// for full details. /// </remarks> /// <param name="sphere">Details of the sphere which describes the region for this query.</param> /// <param name="mask">The query mask to apply to this query; can be used to filter out certain objects; see SceneQuery for details.</param> public override SphereRegionSceneQuery CreateSphereRegionQuery(Sphere sphere, ulong mask) { BspSphereRegionSceneQuery q = new BspSphereRegionSceneQuery(this); q.Sphere = sphere; q.QueryMask = mask; return q; }
public void Merge(AxisAlignedBox boxBounds, Sphere sphereBounds, Camera cam) { aabb.Merge(boxBounds); float camDistToCenter = (cam.DerivedPosition - sphereBounds.Center).Length; minDistance = Math.Min(minDistance, Math.Max(0f, camDistToCenter - sphereBounds.Radius)); maxDistance = Math.Max(maxDistance, camDistToCenter + sphereBounds.Radius); }
/// <summary> /// Tests whether this box intersects a sphere. /// </summary> /// <param name="sphere"></param> /// <returns>True if the sphere intersects, false otherwise.</returns> public bool Intersects(Sphere sphere) { return MathUtil.Intersects(sphere, this); }
public Intersection Intersect(Sphere sphere, AxisAlignedBox box) { intersect++; float Radius = sphere.Radius; Vector3 Center = sphere.Center; Vector3[] Corners = box.Corners; float s = 0; float d = 0; int i; bool Partial; Radius *= Radius; Vector3 MinDistance = (Corners[0] - Center); Vector3 MaxDistance = (Corners[4] - Center); if((MinDistance.LengthSquared < Radius) && (MaxDistance.LengthSquared < Radius)) { return Intersection.Inside; } //find the square of the distance //from the sphere to the box for(i=0;i<3;i++) { if ( Center[i] < Corners[0][i] ) { s = Center[i] - Corners[0][i]; d += s * s; } else if ( Center[i] > Corners[4][i] ) { s = Center[i] - Corners[4][i]; d += s * s; } } Partial = (d <= Radius); if(!Partial) { return Intersection.Outside; } else { return Intersection.Intersect; } }
/// <summary> /// Creates a <see cref="SphereRegionSceneQuery"/> for this scene manager. /// </summary> /// <remarks> /// This method creates a new instance of a query object for this scene manager, /// for querying for objects within a spherical region. /// </remarks> /// <param name="sphere">Sphere to use for the region query.</param> /// <param name="mask">Custom user defined flags to use for the query.</param> /// <returns>A specialized implementation of SphereRegionSceneQuery for this scene manager.</returns> public virtual SphereRegionSceneQuery CreateSphereRegionQuery(Sphere sphere, ulong mask) { DefaultSphereRegionSceneQuery query = new DefaultSphereRegionSceneQuery(this); query.Sphere = sphere; query.QueryMask = mask; return query; }
public override void Execute(ISceneQueryListener listener) { // TODO: BillboardSets? Will need per-billboard collision most likely // Entities only for now Sphere testSphere = new Sphere(); 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; } testSphere.Center = obj.ParentNode.DerivedPosition; testSphere.Radius = obj.BoundingRadius; // if the results came back positive, fire the event handler if (sphere.Intersects(testSphere)) { listener.OnQueryResult(obj); } } } }
public bool RemoveNewHeight(Sphere oldHeight) { //std::vector<Sphere>::iterator cur, end = mNewHeight.end(); //for( cur = mNewHeight.begin(); cur < end; cur++ ) for (int index= 0; index < newHeight.Count; index ++) { if( ((Sphere)newHeight[index]).Intersects( oldHeight ) == true ) { // Since we don´t allow to heights to intersect we can delete this one newHeight.RemoveAt(index); return true; } } return false; }
/// <summary> /// Creates a <see cref="SphereRegionSceneQuery"/> for this scene manager. /// </summary> /// <remarks> /// This method creates a new instance of a query object for this scene manager, /// for querying for objects within a spherical region. /// </remarks> /// <param name="sphere">Sphere to use for the region query.</param> /// <returns>A specialized implementation of SphereRegionSceneQuery for this scene manager.</returns> public SphereRegionSceneQuery CreateSphereRegionQuery(Sphere sphere) { return CreateSphereRegionQuery(sphere, 0xffffffff); }
public bool AddNewHeight(Sphere NewHeight) { //std::vector<Sphere>::iterator cur, end = mNewHeight.end(); //for( cur = mNewHeight.begin(); cur < end; cur++ ) for (int index= 0; index < newHeight.Count; index ++) { if( ((Sphere)newHeight[index]).Intersects( NewHeight ) == true ) { // We don´t allow to heights to intersect return false; } } newHeight.Add(NewHeight); return true; }
/// <summary> /// Tests whether this ray intersects the given sphere. /// </summary> /// <param name="sphere"></param> /// <returns> /// Struct containing info on whether there was a hit, and the distance from the /// origin of this ray where the intersect happened. /// </returns> public IntersectResult Intersects(Sphere sphere) { return MathUtil.Intersects(this, sphere); }
/// <summary> /// Renders a set of solid objects for the shadow receiver pass. /// Will only render /// </summary> /// <param name="list">List of solid objects.</param> protected virtual void RenderShadowReceiverObjects(SortedList list, bool doLightIteration, List<Light> manualLightList) { // compute sphere of area around camera that can receive shadows. Sphere shadowSphere = new Sphere(autoParamDataSource.CameraPosition, ShadowConfig.ShadowFarDistance); List<IRenderable> shadowList = new List<IRenderable>(); // ----- SOLIDS LOOP ----- // renderSolidObjectsMeter.Enter(); for (int i = 0; i < list.Count; i++) { RenderableList renderables = (RenderableList)list.GetByIndex(i); // bypass if this group is empty if (renderables.Count == 0) { continue; } Pass pass = (Pass)list.GetKey(i); // Give SM a chance to eliminate this pass if (!ValidatePassForRendering(pass)) continue; shadowList.Clear(); // special case for a single renderable using the material, so that we can // avoid calling SetPass() when there is only one renderable and it doesn't // need to be drawn. for (int r = 0; r < renderables.Count; r++) { bool drawObject = true; IRenderable renderable = (IRenderable)renderables[r]; MovableObject movableObject = renderable as MovableObject; if (movableObject != null) { // it is a movableObject, so we can if (!movableObject.GetWorldBoundingBox().Intersects(shadowSphere)) { // objects bounding box doesn't intercect the shadow sphere, so we don't // need to render it in this pass. drawObject = false; } } if (drawObject) { shadowList.Add(renderable); } } // if nobody is within shadow range, then we don't need to render, and skip the SetPass() if (shadowList.Count == 0) { continue; } // For solids, we try to do each pass in turn Pass usedPass = SetPass(pass); // render each object associated with this rendering pass foreach (IRenderable renderable in shadowList) { // Give SM a chance to eliminate if (!ValidateRenderableForRendering(usedPass, renderable)) continue; // Render a single object, this will set up auto params if required if (MeterManager.Collecting) MeterManager.AddInfoEvent("RenderSingle shadow receiver material {0}, doLight {1}, lightCnt {2}", renderable.Material.Name, doLightIteration, (manualLightList != null ? manualLightList.Count : 0)); try { RenderSingleObject(renderable, usedPass, doLightIteration, manualLightList); } catch (Exception e) { LogManager.Instance.WriteException("Invalid call to Axiom.Core.SceneManager.RenderSingleObject: {0}\n{1}", e.Message, e.StackTrace); if (renderable.Material != null) LogManager.Instance.Write("Failed renderable material: {0}", renderable.Material.Name); } } } // renderSolidObjectsMeter.Exit(); }
public bool AddNewHeight( Sphere newSphere ) { long x, z; // Calculate where is going to be placed the new height this.GetPageIndices( newSphere.Center, out x, out z); // TODO: DeScale and add the sphere to all the necessary pages //place it there return data2D[ x ][ z ].AddNewHeight(newSphere); }
/// <summary> /// Internal method for locating a list of lights which could be affecting the frustum. /// </summary> /// <remarks> /// Custom scene managers are encouraged to override this method to make use of their /// scene partitioning scheme to more efficiently locate lights, and to eliminate lights /// which may be occluded by word geometry. /// </remarks> /// <param name="camera">Camera to find lights within it's view.</param> protected virtual void FindLightsAffectingFrustum(Camera camera) { // Basic iteration for this scene manager lightsAffectingFrustum.Clear(); // sphere to use for testing Sphere sphere = new Sphere(); ICollection<MovableObject> lightList = GetMovableObjectCollection("Light"); foreach (Light light in lightList) { if (light.IsVisible) { if(light.Type == LightType.Directional) { // Always visible lightsAffectingFrustum.Add(light); } else { // treating spotlight as point for simplicity // Just see if the lights attenuation range is within the frustum sphere.Center = light.DerivedPosition; sphere.Radius = light.AttenuationRange; if (camera.IsObjectVisible(sphere)) { lightsAffectingFrustum.Add(light); } } } } }
public bool RemoveNewHeight( Sphere oldSphere ) { long x, z; // Calculate where is going to be placed the new height GetPageIndices( oldSphere.Center, out x, out z); // TODO: DeScale and add the sphere to all the necessary pages //remove it return data2D[ x ][ z ].RemoveNewHeight(oldSphere); }
/// <summary> /// Internal method for locating a list of shadow casters which /// could be affecting the frustum for a given light. /// </summary> /// <remarks> /// Custom scene managers are encouraged to override this method to add optimizations, /// and to add their own custom shadow casters (perhaps for world geometry) /// </remarks> /// <param name="light"></param> /// <param name="camera"></param> protected virtual IList FindShadowCastersForLight(Light light, Camera camera) { shadowCasterList.Clear(); if (light.Type == LightType.Directional) { // Basic AABB query encompassing the frustum and the extrusion of it AxisAlignedBox aabb = new AxisAlignedBox(); Vector3[] corners = camera.WorldSpaceCorners; Vector3 min, max; Vector3 extrude = light.DerivedDirection * -shadowDirLightExtrudeDist; // do first corner min = max = corners[0]; min.Floor(corners[0] + extrude); max.Ceil(corners[0] + extrude); for (int c = 1; c < 8; ++c) { min.Floor(corners[c]); max.Ceil(corners[c]); min.Floor(corners[c] + extrude); max.Ceil(corners[c] + extrude); } aabb.SetExtents(min, max); if (shadowCasterAABBQuery == null) shadowCasterAABBQuery = CreateAABBRegionQuery(aabb); else shadowCasterAABBQuery.Box = aabb; // Execute, use callback shadowCasterQueryListener.Prepare(false, light.GetFrustumClipVolumes(camera), light, camera, shadowCasterList, shadowFarDistanceSquared); shadowCasterAABBQuery.Execute(shadowCasterQueryListener); } else { Sphere s = new Sphere(light.DerivedPosition, light.AttenuationRange); // eliminate early if camera cannot see light sphere if (camera.IsObjectVisible(s)) { // create or init a sphere region query if(shadowCasterSphereQuery == null) { shadowCasterSphereQuery = CreateSphereRegionQuery(s); } else { shadowCasterSphereQuery.Sphere = s; } // check if the light is within view of the camera bool lightInFrustum = camera.IsObjectVisible(light.DerivedPosition); List<PlaneBoundedVolume> volumeList = null; // Only worth building an external volume list if // light is outside the frustum if(!lightInFrustum) { volumeList = light.GetFrustumClipVolumes(camera); } // prepare the query and execute using the callback shadowCasterQueryListener.Prepare( lightInFrustum, volumeList, light, camera, shadowCasterList, shadowFarDistanceSquared); shadowCasterSphereQuery.Execute(shadowCasterQueryListener); } } return shadowCasterList; }
public void FindNodes(Sphere sphere, List<SceneNode> sceneNodeList, SceneNode exclude, bool full, Octree octant) { //TODO: Implement }
/// <summary> /// Internal method for rendering all the objects for a given light into the stencil buffer. /// </summary> /// <param name="light">The light source.</param> /// <param name="camera">The camera being viewed from.</param> protected virtual void RenderShadowVolumesToStencil(Light light, Camera camera) { // get the shadow caster list IList casters = FindShadowCastersForLight(light, camera); if (casters.Count == 0) // No casters, just do nothing return; // Set up scissor test (point & spot lights only) bool scissored = false; if (light.Type != LightType.Directional && targetRenderSystem.Caps.CheckCap(Capabilities.ScissorTest)) { // Project the sphere onto the camera float left, right, top, bottom; Sphere sphere = new Sphere(light.DerivedPosition, light.AttenuationRange); if (camera.ProjectSphere(sphere, out left, out top, out right, out bottom)) { scissored = true; // Turn normalised device coordinates into pixels int iLeft, iTop, iWidth, iHeight; currentViewport.GetActualDimensions(out iLeft, out iTop, out iWidth, out iHeight); int szLeft, szRight, szTop, szBottom; szLeft = (int)(iLeft + ((left + 1) * 0.5f * iWidth)); szRight = (int)(iLeft + ((right + 1) * 0.5f * iWidth)); szTop = (int)(iTop + ((-top + 1) * 0.5f * iHeight)); szBottom = (int)(iTop + ((-bottom + 1) * 0.5f * iHeight)); targetRenderSystem.SetScissorTest(true, szLeft, szTop, szRight, szBottom); } } targetRenderSystem.UnbindGpuProgram(GpuProgramType.Fragment); // Can we do a 2-sided stencil? bool stencil2sided = false; if (targetRenderSystem.Caps.CheckCap(Capabilities.TwoSidedStencil) && targetRenderSystem.Caps.CheckCap(Capabilities.StencilWrap)) { // enable stencil2sided = true; } // Do we have access to vertex programs? bool extrudeInSoftware = true; bool finiteExtrude = !shadowUseInfiniteFarPlane || !targetRenderSystem.Caps.CheckCap(Capabilities.InfiniteFarPlane); if (targetRenderSystem.Caps.CheckCap(Capabilities.VertexPrograms)) { extrudeInSoftware = false; EnableHardwareShadowExtrusion(light, finiteExtrude); } else { targetRenderSystem.UnbindGpuProgram(GpuProgramType.Vertex); } // Add light to internal list for use in render call List<Light> tmpLightList = new List<Light>(); tmpLightList.Add(light); // Turn off color writing and depth writing targetRenderSystem.SetColorBufferWriteEnabled(false, false, false, false); targetRenderSystem.DepthWrite = false; targetRenderSystem.StencilCheckEnabled = true; targetRenderSystem.DepthFunction = CompareFunction.Less; // Calculate extrusion distance float extrudeDistance = 0; if (light.Type == LightType.Directional) { extrudeDistance = shadowDirLightExtrudeDist; } // get the near clip volume PlaneBoundedVolume nearClipVol = light.GetNearClipVolume(camera); // Determine whether zfail is required // We need to use zfail for ALL objects if we find a single object which // requires it bool zfailAlgo = false; CheckShadowCasters(casters, nearClipVol, light, extrudeInSoftware, finiteExtrude, zfailAlgo, camera, extrudeDistance, stencil2sided, tmpLightList); // revert colour write state targetRenderSystem.SetColorBufferWriteEnabled(true, true, true, true); // revert depth state targetRenderSystem.SetDepthBufferParams(); targetRenderSystem.StencilCheckEnabled = false; targetRenderSystem.UnbindGpuProgram(GpuProgramType.Vertex); if (scissored) { // disable scissor test targetRenderSystem.SetScissorTest(false); } }
/// <summary> /// Intersection test with <see cref="Sphere"/>. /// </summary> /// <param name="sphere">Sphere to test.</param> /// <returns>True if the sphere intersects this volume, and false otherwise.</returns> public bool Intersects(Sphere sphere) { for (int i = 0; i < planes.Count; i++) { Plane plane = planes[i]; // Test which side of the plane the sphere is float d = plane.GetDistance(sphere.Center); // Negate d if planes point inwards if(outside == PlaneSide.Negative) { d = -d; } if((d - sphere.Radius) > 0) { return false; } } // assume intersecting return true; }
/// <summary> /// Walks the BSP tree looking for the node which the camera is in, and tags any geometry /// which is in a visible leaf for later processing. /// </summary> protected BspNode WalkTree(Camera camera, bool onlyShadowCasters) { // Locate the leaf node where the camera is located BspNode cameraNode = level.FindLeaf(camera.DerivedPosition); matFaceGroupMap.Clear(); faceGroupChecked = new bool[level.FaceGroups.Length]; TextureLight[] lights = new TextureLight[lightList.Count]; BspNode[] lightNodes = new BspNode[lightList.Count]; Sphere[] lightSpheres = new Sphere[lightList.Count]; // The base SceneManager uses this for shadows. // The BspSceneManager uses this for texture lighting as well. if (shadowTechnique == ShadowTechnique.None) { lightsAffectingFrustum.Clear(); lightAddedToFrustum = new bool[lightList.Count]; } for (int lp=0; lp < lightList.Count; lp++) { TextureLight light = (TextureLight) lightList[lp]; lights[lp] = light; lightNodes[lp] = (BspNode) level.objectToNodeMap.FindFirst(light); if (light.Type != LightType.Directional) { // treating spotlight as point for simplicity lightSpheres[lp] = new Sphere(light.DerivedPosition, light.AttenuationRange); } } // Scan through all the other leaf nodes looking for visibles int i = level.NumNodes - level.LeafStart; int p = level.LeafStart; BspNode node; while(i-- > 0) { node = level.Nodes[p]; if(level.IsLeafVisible(cameraNode, node)) { // Visible according to PVS, check bounding box against frustum FrustumPlane plane; if(camera.IsObjectVisible(node.BoundingBox, out plane)) { if (!onlyShadowCasters) { for (int lp=0; lp < lights.Length; lp++) { if (lightAddedToFrustum[lp] || !lights[lp].IsVisible) continue; if (level.IsLeafVisible(lightNodes[lp], node) && (lights[lp].Type == LightType.Directional || lightSpheres[lp].Intersects(node.BoundingBox))) { // This is set so that the lights are rendered with ascending // Priority order. lights[lp].TempSquaredDist = lights[lp].Priority; lightsAffectingFrustum.Add(lights[lp]); lightAddedToFrustum[lp] = true; } } } ProcessVisibleLeaf(node, camera, onlyShadowCasters); if(showNodeAABs) AddBoundingBox(node.BoundingBox, true); } } p++; } return cameraNode; }