예제 #1
0
 /// <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));
 }
예제 #2
0
 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);
 }
예제 #3
0
 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);
                    }
                }
            }
        }
예제 #10
0
 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);
 }
예제 #12
0
 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;
 }
예제 #13
0
 /// <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;
        }