Exemplo n.º 1
0
        public Page(long TableX, long TableZ)
        {
            isLoaded = false;
            isPreLoaded = false;

            tableX = TableX;
            tableZ = TableZ;

            numTiles = (long) ((float) Options.Instance.PageSize / Options.Instance.TileSize);
            pageNode = null;

            long size = Options.Instance.PageSize - 1;
            // Boundaries of this page
            // the middle page is at world coordinates 0,0
            float factorX = size * Options.Instance.Scale.x;
            float factorZ = size * Options.Instance.Scale.z;
            iniX =  (tableX + tableX - Options.Instance.World_Width) / 2.0f * factorX ;
            iniZ =  (tableZ + tableZ - Options.Instance.World_Height) / 2.0f * factorZ ;
            float EndX = iniX + factorX;
            float EndZ = iniZ + factorZ;
            float MaxHeight = Data2DManager.Instance.GetMaxHeight(tableX, tableZ);
            float chgfactor = Options.Instance.Change_Factor;
            boundsExt = new AxisAlignedBox();
            boundsExt.SetExtents( new Vector3(( float )( iniX ),
                                    0,
                                ( float )( iniZ )),
                                new Vector3(( float )( EndX ),
                                MaxHeight,
                                ( float )( EndZ ) ));
            //Change Zone of this page
            boundsInt = new AxisAlignedBox();
            boundsInt.SetExtents( new Vector3(( float )( iniX + chgfactor ),
                                    0,
                                ( float )( iniZ + chgfactor )),
                                new Vector3(( float )( EndX - chgfactor ),
                                    MaxHeight,
                                    ( float )( EndZ - chgfactor )	));

            neighbors = new Page[4];
            for ( long i = 0; i < 4; i++ )
            {
                neighbors[ i ] = null;
            }
        }
        /// <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;
        }
        /// <summary>
        ///		Sets the corners of the rectangle, in relative coordinates.
        /// </summary>
        /// <param name="left">Left position in screen relative coordinates, -1 = left edge, 1.0 = right edge.</param>
        /// <param name="top">Top position in screen relative coordinates, 1 = top edge, -1 = bottom edge.</param>
        /// <param name="right">Position in screen relative coordinates.</param>
        /// <param name="bottom">Position in screen relative coordinates.</param>
        public void SetCorners(float left, float top, float right, float bottom)
        {
            float[] data = new float[] {
                left, top, -1,
                left, bottom, -1,
                right, top, -1,
                right, bottom, -1
            };

            HardwareVertexBuffer buffer =
                vertexData.vertexBufferBinding.GetBuffer(POSITION);

            buffer.WriteData(0, buffer.Size, data, true);

            box = new AxisAlignedBox();
            box.SetExtents(new Vector3(left, top, 0), new Vector3(right, bottom, 0));
        }
        /// <summary>
        ///		Utility method for extruding a bounding box.
        /// </summary>
        /// <param name="box">Original bounding box, will be updated in-place.</param>
        /// <param name="lightPosition">4D light position in object space, when w=0.0f this
        /// represents a directional light</param>
        /// <param name="extrudeDistance">The distance to extrude.</param>
        protected virtual void ExtrudeBounds(AxisAlignedBox box, Vector4 lightPosition, float extrudeDistance)
        {
            Vector3 extrusionDir = Vector3.Zero;

            if (lightPosition.w == 0) {
                extrusionDir.x = -lightPosition.x;
                extrusionDir.y = -lightPosition.y;
                extrusionDir.z = -lightPosition.z;
                extrusionDir.Normalize();
                extrusionDir *= extrudeDistance;
                box.SetExtents(box.Minimum + extrusionDir, box.Maximum + extrusionDir);
            }
            else {
                Vector3[] corners = box.Corners;
                Vector3 vmin = new Vector3();
                Vector3 vmax = new Vector3();

                for(int i = 0; i < 8; i++) {
                    extrusionDir.x = corners[i].x - lightPosition.x;
                    extrusionDir.y = corners[i].y - lightPosition.y;
                    extrusionDir.z = corners[i].z - lightPosition.z;
                    extrusionDir.Normalize();
                    extrusionDir *= extrudeDistance;
                    Vector3 res = corners[i] + extrusionDir;

                    if(i == 0) {
                        vmin = res;
                        vmax = res;
                    }
                    else {
                        vmin.Floor(res);
                        vmax.Ceil(res);
                    }
                }

                box.SetExtents(vmin, vmax);
            }
        }