Example #1
0
        public void PerFrameProcessing(Vector3 cameraLocation)
        {
            // free the passes from last frame if there are any
            if (framePageDecalInfos != null)
            {
                FreePasses(framePageDecalInfos);
                framePageDecalInfos = null;
            }


            // compute the camera page
            PageCoord lastCameraPage = cameraPage;

            cameraPage = new PageCoord(cameraLocation, TerrainManager.Instance.PageSize);

            // update the decals
            Update(cameraLocation.x, cameraLocation.z);

            // build the per-page data structures
            framePageDecalInfos = BuildPageInfos();

            // if there are any visible decals, then build the material passes for all affected pages
            if (framePageDecalInfos != null)
            {
                BuildPasses(framePageDecalInfos);
            }
        }
        private void ComputeTouchedPages()
        {
            Debug.Assert(closed);

            // compute the min and max page coord of the pages that this boundary may intersect with
            boundsMinPage = new PageCoord(bounds.Minimum, pageSize);
            boundsMaxPage = new PageCoord(bounds.Maximum, pageSize);

            touchedPages.Clear();

            // iterate over the pages and see which intersect with the boundary, and add
            // those to the list
            for (int x = boundsMinPage.X; x <= boundsMaxPage.X; x++)
            {
                for (int z = boundsMinPage.Z; z <= boundsMaxPage.Z; z++)
                {
                    PageCoord pc = new PageCoord(x, z);
                    if (IntersectSquare(pc.WorldLocation(pageSize), pageSize))
                    {
                        touchedPages.Add(pc);
                    }
                }
            }

            Console.WriteLine("boundary {0} touches pages:", name);
            foreach (PageCoord tp in touchedPages)
            {
                Console.WriteLine("  {0}", tp.ToString());
            }
        }
Example #3
0
        private byte[] newMask(PageCoord pc)
        {
            // allocate the new mask
            byte[] mask = new byte[pageSize * pageSize];

            // add it to the dictionary
            pages.Add(pc, mask);

            // update bounds
            if (pc.X < minPageX)
            {
                minPageX = pc.X;
            }
            if (pc.X > maxPageX)
            {
                maxPageX = pc.X;
            }
            if (pc.Z < minPageZ)
            {
                minPageZ = pc.Z;
            }
            if (pc.Z > maxPageZ)
            {
                maxPageZ = pc.Z;
            }
            return(mask);
        }
        private void SetPageHilights(bool value)
        {
            PageCoord minVis = TerrainManager.Instance.MinVisiblePage;
            PageCoord maxVis = TerrainManager.Instance.MaxVisiblePage;

            foreach (PageCoord tp in touchedPages)
            {
                if (tp.X >= minVis.X && tp.X <= maxVis.X && tp.Z >= minVis.Z && tp.Z <= maxVis.Z)
                {
                    // tp page is visible
                    visible = true;

                    PageCoord pageOff = tp - minVis;
                    Page      page    = TerrainManager.Instance.LookupPage(pageOff.X, pageOff.Z);
                    if (value)
                    {
                        page.TerrainPage.HilightMask = PageMaskTexture(tp);
                        page.TerrainPage.HilightType = TerrainPage.PageHilightType.Colorized;
                    }
                    else
                    {
                        page.TerrainPage.HilightType = TerrainPage.PageHilightType.None;

                        // if there is an existing hilight mask, make sure we free it properly
                        Texture t = page.TerrainPage.HilightMask;
                        if (t != null)
                        {
                            page.TerrainPage.HilightMask = null;
                            t.Dispose();
                        }
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Find the tile for a given location
        /// </summary>
        /// <param name="location"></param>
        /// <returns>Returns the tile.  Will raise an array bounds exception if the location is not in this page</returns>
        public Tile LookupTile(Vector3 location)
        {
            PageCoord locPageCoord  = new PageCoord(location, size / numTiles);
            PageCoord tilePageCoord = new PageCoord(Location, size / numTiles);
            PageCoord tileOffset    = locPageCoord - tilePageCoord;

            return(tiles[tileOffset.X, tileOffset.Z]);
        }
        private Texture PageMaskTexture(PageCoord pc)
        {
            Image i = BuildPageMask(pc.WorldLocation(pageSize));

            String  texName = String.Format("{0}-{1}", name, pc.ToString());
            Texture t       = TextureManager.Instance.LoadImage(texName, i);

            return(t);
        }
Example #7
0
        // Get the mask for the given PageCoord.  Returns null if no mask is available
        public byte[] GetMask(PageCoord pc)
        {
            byte[] rawMask;
            if (!pages.TryGetValue(pc, out rawMask))
            {
                rawMask = null;
            }

            return(rawMask);
        }
Example #8
0
        protected Technique FindPageTechnique(PageCoord coord)
        {
            Page      page = TerrainManager.Instance.LookupPage(coord);
            Technique t    = null;

            if (page != null)
            {
                Material mat = page.TerrainPage.Material;
                t = mat.GetBestTechnique();
            }

            return(t);
        }
Example #9
0
        public bool Intersects(PageCoord pc)
        {
            bool ret = false;

            // do bounds intersection first
            if ((pc.X >= minPageX) && (pc.X <= maxPageX) && (pc.Z >= minPageZ) && (pc.Z <= maxPageZ))
            {
                byte[] mask;
                // if bounds intersection succeeds, then look up in the dictionary
                ret = pages.TryGetValue(pc, out mask);
            }

            return(ret);
        }
        public PlantRenderable(IndexData ind, VertexData vert, AxisAlignedBox bbox, PageCoord pc, SceneNode parent, Vector3 blockLoc)
        {
            indexData       = ind;
            vertexData      = vert;
            material        = MaterialManager.Instance.GetByName("Multiverse/DetailVeg");
            box             = bbox;
            pageCoord       = pc;
            parentSceneNode = parent;
            sceneNode       = parentSceneNode.CreateChildSceneNode(string.Format("DetailVeg-{0}", pageCoord));
            sceneNode.AttachObject(this);
            sceneNode.Position = new Vector3(blockLoc.x, 0, blockLoc.z);

            this.ShowBoundingBox = false;

            CastShadows = true;
        }
Example #11
0
        private void SetRoadMask(TerrainPage terrainPage)
        {
            // generate a texture from the mask
            PageCoord pc = new PageCoord(terrainPage.Location, TerrainManager.Instance.PageSize);

            byte[] byteMask = mask.GetMask(pc);
            if (byteMask != null)
            {
                Image   maskImage = Image.FromDynamicImage(byteMask, mask.PageSize, mask.PageSize, PixelFormat.A8);
                String  texName   = String.Format("RoadMask-{0}", pc.ToString());
                Texture texImage  = TextureManager.Instance.LoadImage(texName, maskImage);

                terrainPage.HilightMask = texImage;
                terrainPage.HilightType = TerrainPage.PageHilightType.EdgeSharpBlend;
            }
        }
Example #12
0
        /// <summary>
        /// Page Constructor
        /// </summary>
        /// <param name="relativeLocation">The location of the page in world space, relative to the page containing the camera</param>
        /// <param name="indexX">index into the TerrainManager's page array</param>
        ///	<param name="indexZ">index into the TerrainManager's page array</param>
        public Page(Vector3 relativeLocation, int indexX, int indexZ)
        {
            size = TerrainManager.Instance.PageSize;
            this.relativeLocation = relativeLocation;
            this.indexX           = indexX;
            this.indexZ           = indexZ;

            // Figure out which page the camera is in
            PageCoord cameraPageCoord = new PageCoord(TerrainManager.Instance.VisPageRadius, TerrainManager.Instance.VisPageRadius);

            // compute the distance (in pages) from this page to the camera page
            pagesFromCamera = cameraPageCoord.Distance(new PageCoord(indexX, indexZ));

            // create a scene node for this page
            String nodeName = String.Format("Page[{0},{1}]", indexX, indexZ);

            sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName);

            sceneNode.Position = relativeLocation;

            // ask the world manager how many tiles we need in this page based on the distance from the camera
            numTiles = TerrainManager.Instance.TilesPerPage(pagesFromCamera);

            // compute size of a tile in sample space
            tileSize = size / numTiles;

            // allocate the array of tiles
            tiles = new Tile[numTiles, numTiles];

            // this is the size of the tile in "world space"
            float tileWorldSize = tileSize * TerrainManager.oneMeter;

            // create the tiles for this page
            for (int tilex = 0; tilex < numTiles; tilex++)
            {
                float tileWorldX = tilex * tileWorldSize + relativeLocation.x;

                for (int tilez = 0; tilez < numTiles; tilez++)
                {
                    float tileWorldZ = tilez * tileWorldSize + relativeLocation.z;

                    Tile t = new Tile(new Vector3(tileWorldX, 0, tileWorldZ), tileSize, this, tilex, tilez);
                    tiles[tilex, tilez] = t;
                }
            }
        }
        public TerrainPage(Vector3 location, Page page)
        {
            this.location = location;
            pageCoord     = new PageCoord(location, TerrainManager.Instance.PageSize);

            terrainMaterial = TerrainManager.Instance.TerrainMaterialConfig.NewTerrainMaterial(pageCoord.X, pageCoord.Z);

            currentPage = page;
            Debug.Assert(location == currentPage.Location, "creating TerrainPage with page at different location");
            numTiles  = currentPage.NumTiles;
            patchSize = TerrainManager.Instance.PageSize / numTiles;

            // set up the page height maps for this page of terrain
            subPageSize = TerrainManager.Instance.SubPageSize;
            int subPagesPerPage = TerrainManager.Instance.PageSize / subPageSize;

            pageHeightMap = new PageHeightMap(subPagesPerPage, TerrainManager.Instance.PageSize,
                                              TerrainManager.Instance.MaxMetersPerSample, TerrainManager.Instance.MinMetersPerSample);

            pageHeightMap.Location = location;

            // create and position a scene node for this terrain page
            string nodeName = String.Format("TerrainPage[{0},{1}]", (int)(location.x / TerrainManager.oneMeter),
                                            (int)(location.z / TerrainManager.oneMeter));

            // DEBUG - Console.WriteLine("Creating {0}", name);
            sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName);

            sceneNode.Position = location;

            sceneNode.AttachObject(this);

            // create the render operation
            renderOp = new RenderOperation();
            renderOp.operationType = OperationType.TriangleList;
            renderOp.useIndices    = true;

            CreatePatches();

            SetCastShadows();

            UpdateBounds();

            TerrainManager.Instance.ShadowConfig.ShadowTechniqueChange += ShadowTechniqueChangeHandler;
        }
        public bool IntersectPage(PageCoord pc)
        {
            // check if page intersects bounds first
            if (pc.X < boundsMinPage.X || pc.X > boundsMaxPage.X || pc.Z < boundsMinPage.Z || pc.Z > boundsMaxPage.Z)
            {
                return(false);
            }

            foreach (PageCoord tp in touchedPages)
            {
                if (tp == pc)
                {
                    return(true);
                }
            }

            return(false);
        }
Example #15
0
        //
        // Iterate page masks, only returning those in the given page range
        //
        public void IterateMasks(ReturnMask retDelegate, PageCoord minPage, PageCoord maxPage)
        {
            // get out quick if our bounds don't overlap the requested page range
            if ((minPageX > maxPage.X) || (maxPageX < minPage.X) || (minPageZ > maxPage.Z) || (maxPageZ < minPage.Z))
            {
                return;
            }
            foreach (KeyValuePair <PageCoord, byte[]> kvp in pages)
            {
                PageCoord pc = kvp.Key;

                // only call delegate if current page overlaps with requested page range
                if ((pc.X >= minPage.X) && (pc.X <= maxPage.X) && (pc.Z >= minPage.Z) && (pc.Z <= maxPage.Z))
                {
                    retDelegate(pc, kvp.Value);
                }
            }
        }
        internal VegetationTile(SceneNode parentSceneNode,
                                List <VegetationSemantic> vegetationBoundaries, int x, int z,
                                PageCoord newPage, int blockSize,
                                float roadClearRadius,
                                MVImageSet imageSet,
                                Random rand)
        {
            this.roadClearRadius = roadClearRadius;

            plantTypes = new List <PlantType>();

            PageCoord tmpPage = new PageCoord(x + newPage.X - 1, z + newPage.Z - 1);

            pc = tmpPage;

            Vector3 blockLoc = tmpPage.WorldLocation(blockSize);
            Vector2 blockMin = new Vector2(blockLoc.x, blockLoc.z);
            Vector2 blockMax = new Vector2(blockMin.x + blockSize * TerrainManager.oneMeter,
                                           blockMin.y + blockSize * TerrainManager.oneMeter);

            List <Vector2> roadSegments = TerrainManager.Instance.Roads.IntersectBlock(blockMin, blockMax);

            foreach (VegetationSemantic vegetationBoundary in vegetationBoundaries)
            {
                Boundary boundary = vegetationBoundary.BoundaryObject;
                if (boundary.IntersectSquare(new Vector3(blockMin.x, 0f, blockMin.y), blockSize))
                {
                    foreach (PlantType boundaryPlantType in vegetationBoundary.PlantTypes)
                    {
                        PlantType plantType = boundaryPlantType.Clone();
                        plantType.MaybeUseImageSet(imageSet);
                        plantTypes.Add(plantType);
                        totalInstances += plantType.AddPlantInstances(boundary, blockMin, blockSize, rand);
                    }
                }
            }
            if (totalInstances > 0)
            {
                BuildIndexBuffer();
                AxisAlignedBox bounds;
                VertexData     vertexData = BuildVertexData(blockLoc, blockSize, roadSegments, out bounds);
                plantRenderable = new PlantRenderable(indexData, vertexData, bounds, tmpPage, parentSceneNode, blockLoc);
            }
        }
        private void NewCameraPage(PageCoord newPage)
        {
            if (enabled && TerrainManager.Instance.CameraSet)
            {
                // free the old vegetation tiles

                VegetationTile[,] newVegetationTiles = new VegetationTile[3, 3];
                if (vegetationTiles != null)
                {
                    foreach (VegetationTile tile in vegetationTiles)
                    {
                        PageCoord pc = tile.pc;
                        int       x  = pc.X - (newPage.X - 1);
                        int       z  = pc.Z - (newPage.Z - 1);
                        if ((x >= 0) && (x < 3) && (z >= 0) && (z < 3))
                        {
                            newVegetationTiles[x, z] = tile;
                        }
                        else
                        {
                            FreeVegetationTile(tile);
                        }
                    }
                }

                vegetationTiles = newVegetationTiles;

                for (int x = 0; x < 3; x++)
                {
                    for (int z = 0; z < 3; z++)
                    {
                        if (vegetationTiles[x, z] == null)
                        {
                            vegetationTiles[x, z] = new VegetationTile(parentSceneNode, vegetationBoundaries, x, z,
                                                                       newPage, blockSize,
                                                                       roadClearRadius, detailVegImageSet, rand);
                        }
                    }
                }

                cameraPage = newPage;
            }
        }
        private void UpdateVisibility()
        {
            PageCoord minVis = TerrainManager.Instance.MinVisiblePage;
            PageCoord maxVis = TerrainManager.Instance.MaxVisiblePage;

            visible = false;
            if (maxVis.X < boundsMinPage.X || minVis.X > boundsMaxPage.X || maxVis.Z < boundsMinPage.Z || minVis.Z > boundsMaxPage.Z)
            {
                // this boundary doesn't overlap with the visible area around the camera.
                return;
            }

            foreach (PageCoord tp in touchedPages)
            {
                if (tp.X >= minVis.X && tp.X <= maxVis.X && tp.Z >= minVis.Z && tp.Z <= maxVis.Z)
                {
                    // tp page is visible
                    visible = true;
                }
            }
        }
Example #19
0
        public void SetPoint(int x, int z, byte value)
        {
            // compute pagecoord of the page containing this point
            PageCoord pc = new PageCoord(new Vector3(x * TerrainManager.oneMeter, 0, z * TerrainManager.oneMeter), pageSize);

            // PageCoord pc = new PageCoord(x / pageSize, z / pageSize);
            byte[] rawMask;

            // lookup the mask.  If it is not found, then make a new empty mask and add it to the dictionary
            if (!pages.TryGetValue(pc, out rawMask))
            {
                rawMask = newMask(pc);
            }

            // compute x and z coords of base of page
            int pagex = pc.X * pageSize;
            int pagez = pc.Z * pageSize;

            // compute x and z offsets within page
            int xoff = x - pagex;
            int zoff = z - pagez;

            rawMask[(zoff * pageSize) + xoff] = value;
        }
        /// <summary>
        /// Compute the "distance" between two pages.  Returns the axis aligned
        /// distance along X or Z (whichever is greater).
        /// </summary>
        /// <param name="c2">coordinate to compare to this</param>
        /// <returns></returns>
        public int Distance(PageCoord c2)
        {
            int xDiff = c2.X - X;
            int zDiff = c2.Z - Z;

            if (xDiff < 0)
            {
                xDiff = -xDiff;
            }

            if (zDiff < 0)
            {
                zDiff = -zDiff;
            }

            if (xDiff > zDiff)
            {
                return(xDiff);
            }
            else
            {
                return(zDiff);
            }
        }
        private void ShiftPageHeightMaps(PageCoord pc)
        {
            ValidatePageArray();

            int dx = pc.X;
            int dz = pc.Z;

            // make sure we are actually moving
            Debug.Assert((dx != 0) || (dz != 0));

            int copyStartX = 0;
            int copyEndX = pageArraySize;
            int copyIncrX = 1;
            int copyStartZ = 0;
            int copyEndZ = pageArraySize;
            int copyIncrZ = 1;

            // keep track of the bounds of the area we keep after shifting
            int clearStartX = 0;
            int clearEndX = 0;
            int keepStartZ = 0;
            int keepEndZ = pageArraySize;

            int maxMove = pageArraySize - 1;

            // set to true if we are moving the camera far enough that all of the current heightmaps
            // move out of view
            bool bigMove = false;

            if ((dx > maxMove) || (dx < -maxMove) || (dz > maxMove) || (dz < -maxMove))
            {
                bigMove = true;
            }

            if (!bigMove)
            {
                // compute move params for the X axis
                if (dx > 0)
                {
                    copyStartX = pageArraySize - dx - 1;
                    copyEndX = -1;
                    copyIncrX = -1;

                    clearStartX = 0;
                    clearEndX = dx;
                }
                else if (dx < 0)
                {
                    copyStartX = -dx;
                    copyEndX = pageArraySize;
                    copyIncrX = 1;

                    clearStartX = pageArraySize + dx;
                    clearEndX = pageArraySize;
                }

                // compute move params for the Z axis
                if (dz > 0)
                {
                    copyStartZ = pageArraySize - dz - 1;
                    copyEndZ = -1;
                    copyIncrZ = -1;
                    keepStartZ = dz;
                    keepEndZ = pageArraySize;
                }
                else if (dz < 0)
                {
                    copyStartZ = -dz;
                    copyEndZ = pageArraySize;
                    copyIncrZ = 1;
                    keepStartZ = 0;
                    keepEndZ = pageArraySize + dz;
                }

                long startTick = Root.Instance.Timer.Milliseconds;

                // copy all height maps that we are keeping
                for (int z = copyStartZ; z != copyEndZ; z += copyIncrZ)
                {
                    for (int x = copyStartX; x != copyEndX; x += copyIncrX)
                    {
                        // move the heightmap to its new page, and set its page property
                        // dispose of the old terrain page
                        int destX = x + dx;
                        int destZ = z + dz;

                        if (pages[destX, destZ].TerrainPage != null)
                        {
                            pages[destX, destZ].TerrainPage.Dispose();
                        }

                        // move the terrainPage, and set its CurrentPage to the new page
                        pages[destX, destZ].TerrainPage = pages[x, z].TerrainPage;
                        pages[destX, destZ].TerrainPage.CurrentPage = pages[destX, destZ];

                        // clear out the old reference to the TerrainPage we just moved
                        pages[x, z].TerrainPage = null;
                    }
                }

                long middleTick = Root.Instance.Timer.Milliseconds;

                // Perform processing on all pages that are newly revealed after the shift
                // Set locations on the pageHeightMaps so that they get rebuilt at their new
                //  locations.
                // Clear and reinitialize the terrain patches of all these pages
                int newPages = 0;
                for (int z = 0; z < pageArraySize; z++)
                {
                    if ((z < keepStartZ) || (z >= keepEndZ))
                    {
                        // this row does not overlap the keep area, so reainitialize all pages
                        for (int x = 0; x < pageArraySize; x++)
                        {
                            // dispose of the old terrainPage
                            if (pages[x, z].TerrainPage != null)
                            {

                                FreeTerrainPage(pages[x, z]);
                            }
                            pages[x, z].TerrainPage = NewTerrainPage(pages[x, z]);
                            newPages++;
                        }
                    }
                    else  // this row overlaps the keep area
                    {
                        for (int x = clearStartX; x < clearEndX; x++)
                        {
                            // dispose of the old terrainPage
                            if (pages[x, z].TerrainPage != null)
                            {
                                FreeTerrainPage(pages[x, z]);
                            }
                            pages[x, z].TerrainPage = NewTerrainPage(pages[x, z]);
                            newPages++;
                        }
                    }
                }

                long finalTick = Root.Instance.Timer.Milliseconds;

                LogManager.Instance.Write("ShiftPageHeightMaps: Shift: {0}", middleTick - startTick);
                LogManager.Instance.Write("ShiftPageHeightMaps: Clear/Create: {0}", finalTick - middleTick);
                LogManager.Instance.Write("ShiftPageHeightMaps: dx = {0}, dz = {1}, newPages = {2}", dx, dz, newPages);

            }
            else // bigmove
            {
                long startTick = Root.Instance.Timer.Milliseconds;

                InitTerrainPages();

                long finalTick = Root.Instance.Timer.Milliseconds;
                LogManager.Instance.Write("ShiftPageHeightMaps: BigMove: {0}", finalTick - startTick);
            }

            ValidatePageArray();
        }
        private void ComputeTouchedPages()
        {
            Debug.Assert(closed);

            // compute the min and max page coord of the pages that this boundary may intersect with
            boundsMinPage = new PageCoord(bounds.Minimum, pageSize);
            boundsMaxPage = new PageCoord(bounds.Maximum, pageSize);

            touchedPages.Clear();

            // iterate over the pages and see which intersect with the boundary, and add
            // those to the list
            for (int x = boundsMinPage.X; x <= boundsMaxPage.X; x++)
            {
                for (int z = boundsMinPage.Z; z <= boundsMaxPage.Z; z++)
                {
                    PageCoord pc = new PageCoord(x, z);
                    if (IntersectSquare(pc.WorldLocation(pageSize), pageSize))
                    {
                        touchedPages.Add(pc);
                    }
                }
            }

            Console.WriteLine("boundary {0} touches pages:", name);
            foreach (PageCoord tp in touchedPages)
            {
                Console.WriteLine("  {0}", tp.ToString());
            }
        }
 public TouchedPage(PageCoord coord, Texture mask)
 {
     this.coord = coord;
     this.mask = mask;
 }
Example #24
0
        private void SetRoadMask(TerrainPage terrainPage)
        {
            // generate a texture from the mask
            PageCoord pc = new PageCoord(terrainPage.Location, TerrainManager.Instance.PageSize);

            byte[] byteMask = mask.GetMask(pc);
            if (byteMask != null)
            {

                Image maskImage = Image.FromDynamicImage(byteMask, mask.PageSize, mask.PageSize, PixelFormat.A8);
                String texName = String.Format("RoadMask-{0}", pc.ToString());
                Texture texImage = TextureManager.Instance.LoadImage(texName, maskImage);

                terrainPage.HilightMask = texImage;
                terrainPage.HilightType = TerrainPage.PageHilightType.EdgeSharpBlend;
            }
        }
        public bool Update(float cameraX, float cameraZ)
        {
            float time     = TerrainManager.Instance.Time;
            bool  deleteMe = false;

            if (firstUpdate)
            {
                timeAlive   = 0;
                firstUpdate = false;
                dirty       = true;
            }

            if (deleteRadius != 0)
            {
                // compute distance from camera
                float dx   = posX - cameraX;
                float dz   = posZ - cameraZ;
                float dxsq = dx * dx;
                float dzsq = dz * dz;

                if ((dxsq + dzsq) > (deleteRadius * deleteRadius))
                {
                    // if distance from the camera is greater than deleteRadius, then delete this element
                    deleteMe = true;
                }
            }

            float deltaT = time - lastUpdateTime;

            timeAlive += deltaT;

            if ((lifetime != 0) && (timeAlive > lifetime))
            {
                // time has run out, so delete this element
                deleteMe = true;
            }

            lastUpdateTime = time;

            if (dirty)
            {
                float halfx = sizeX / 2f;
                float halfz = sizeZ / 2f;

                // compute area possibly touched by the decal
                if (rot != 0)
                {
                    float theta = MathUtil.DegreesToRadians(rot);
                    float cos   = MathLib.MathUtil.Cos(theta);
                    float sin   = MathLib.MathUtil.Sin(theta);

                    float x1 = halfx * cos - halfz * sin;
                    float z1 = halfx * sin + halfz * cos;

                    float x2 = -halfx * cos - halfz * sin;
                    float z2 = -halfx * sin + halfz * cos;

                    float x3 = halfx * cos + halfz * sin;
                    float z3 = halfx * sin - halfz * cos;

                    float x4 = -halfx * cos + halfz * sin;
                    float z4 = -halfx * sin - halfz * cos;

                    maxX = Math.Max(Math.Max(x1, x2), Math.Max(x3, x4));
                    maxZ = Math.Max(Math.Max(z1, z2), Math.Max(z3, z4));
                }
                else
                {
                    maxX = halfx;
                    maxZ = halfz;
                }

                float worldX1 = posX - maxX;
                float worldX2 = posX + maxX;
                float worldZ1 = posZ - maxZ;
                float worldZ2 = posZ + maxZ;

                minPC = new PageCoord(new Vector3(worldX1, 0, worldZ1), TerrainManager.Instance.PageSize);
                maxPC = new PageCoord(new Vector3(worldX2, 0, worldZ2), TerrainManager.Instance.PageSize);
            }

            return(deleteMe);
        }
 public PageDecalInfo(PageCoord coord)
 {
     this.coord = coord;
     decals = new List<DecalElement>();
     passes = new List<Pass>();
 }
 /// <summary>
 ///		Used when a PageCoord is added to another PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static PageCoord Add(PageCoord left, PageCoord right)
 {
     return(left + right);
 }
        // Get the mask for the given PageCoord.  Returns null if no mask is available
        public byte[] GetMask(PageCoord pc)
        {
            byte[] rawMask;
            if (!pages.TryGetValue(pc, out rawMask))
            {
                rawMask = null;
            }

            return rawMask;
        }
        public void SetPoint(int x, int z, byte value)
        {
            // compute pagecoord of the page containing this point
            PageCoord pc = new PageCoord(new Vector3(x * TerrainManager.oneMeter, 0, z * TerrainManager.oneMeter), pageSize);
            // PageCoord pc = new PageCoord(x / pageSize, z / pageSize);
            byte[] rawMask;

            // lookup the mask.  If it is not found, then make a new empty mask and add it to the dictionary
            if (!pages.TryGetValue(pc, out rawMask))
            {
                rawMask = newMask(pc);
            }

            // compute x and z coords of base of page
            int pagex = pc.X * pageSize;
            int pagez = pc.Z * pageSize;

            // compute x and z offsets within page
            int xoff = x - pagex;
            int zoff = z - pagez;

            rawMask[(zoff * pageSize) + xoff] = value;
        }
        public bool WithinVisibleArea(Vector3 location)
        {
            PageCoord locPage = new PageCoord(location, pageSize);
            PageCoord pageOffset = locPage - cameraPage + new PageCoord(visPageRadius, visPageRadius);

            if ( pageOffset.X < 0 || pageOffset.X >= pageArraySize || pageOffset.Z < 0 || pageOffset.Z >= pageArraySize )
            {
                return false;
            }

            return true;
        }
 public TouchedPage(PageCoord coord, Texture mask)
 {
     this.coord = coord;
     this.mask  = mask;
 }
Example #32
0
        /// <summary>
        /// Find the tile for a given location
        /// </summary>
        /// <param name="location"></param>
        /// <returns>Returns the tile.  Will raise an array bounds exception if the location is not in this page</returns>
        public Tile LookupTile(Vector3 location)
        {
            PageCoord locPageCoord = new PageCoord(location, size / numTiles);
            PageCoord tilePageCoord = new PageCoord(Location, size / numTiles);
            PageCoord tileOffset = locPageCoord - tilePageCoord;

            return tiles[tileOffset.X, tileOffset.Z];
        }
Example #33
0
        /// <summary>
        /// Page Constructor
        /// </summary>
        /// <param name="relativeLocation">The location of the page in world space, relative to the page containing the camera</param>
        /// <param name="indexX">index into the TerrainManager's page array</param>
        ///	<param name="indexZ">index into the TerrainManager's page array</param>
        public Page(Vector3 relativeLocation, int indexX, int indexZ)
        {
            size = TerrainManager.Instance.PageSize;
            this.relativeLocation = relativeLocation;
            this.indexX = indexX;
            this.indexZ = indexZ;

            // Figure out which page the camera is in
            PageCoord cameraPageCoord = new PageCoord(TerrainManager.Instance.VisPageRadius, TerrainManager.Instance.VisPageRadius);

            // compute the distance (in pages) from this page to the camera page
            pagesFromCamera = cameraPageCoord.Distance(new PageCoord(indexX, indexZ));

            // create a scene node for this page
            String nodeName = String.Format("Page[{0},{1}]", indexX, indexZ);
            sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName);

            sceneNode.Position = relativeLocation;

            // ask the world manager how many tiles we need in this page based on the distance from the camera
            numTiles = TerrainManager.Instance.TilesPerPage(pagesFromCamera);

            // compute size of a tile in sample space
            tileSize = size / numTiles;

            // allocate the array of tiles
            tiles = new Tile[numTiles,numTiles];

            // this is the size of the tile in "world space"
            float tileWorldSize = tileSize * TerrainManager.oneMeter;

            // create the tiles for this page
            for ( int tilex = 0; tilex < numTiles; tilex++ )
            {
                float tileWorldX = tilex * tileWorldSize + relativeLocation.x;

                for ( int tilez = 0; tilez < numTiles; tilez++ )
                {
                    float tileWorldZ = tilez * tileWorldSize + relativeLocation.z;

                    Tile t = new Tile(new Vector3(tileWorldX, 0, tileWorldZ), tileSize, this, tilex, tilez);
                    tiles[tilex, tilez] = t;
                }
            }
        }
        public float GetAreaHeight(Vector3[] points)
        {
            if (!cameraSet)
            {
                return float.MinValue;
            }

            // compute axis aligned bounding box of points
            float fx1 = points[0].x;
            float fx2 = points[0].x;
            float fz1 = points[0].z;
            float fz2 = points[0].z;

            for (int i = 1; i < points.Length; i++)
            {
                if (points[i].x < fx1)
                {
                    fx1 = points[i].x;
                }
                else if (points[i].x > fx2)
                {
                    fx2 = points[i].x;
                }

                if (points[i].z < fz1)
                {
                    fz1 = points[i].z;
                }
                else if (points[i].z > fz2)
                {
                    fz2 = points[i].z;
                }
            }

            PageCoord minPage = new PageCoord(new Vector3(fx1, 0, fz1), pageSize);
            PageCoord maxPage = new PageCoord(new Vector3(fx2, 0, fz2), pageSize);

            PageCoord minPageOffset = minPage - cameraPage + new PageCoord(visPageRadius, visPageRadius);
            PageCoord maxPageOffset = maxPage - cameraPage + new PageCoord(visPageRadius, visPageRadius);

            // if we are outside the visible area around the camera, get out now
            if ((minPageOffset.X < 0) || (minPageOffset.Z < 0) || (maxPageOffset.X > pages.GetUpperBound(0)) || (maxPageOffset.Z > pages.GetUpperBound(1)))
            {
                return float.MinValue;
            }

            float height = float.MinValue;

            for (int pageX = minPageOffset.X; pageX <= maxPageOffset.X; pageX++)
            {
                for (int pageZ = minPageOffset.Z; pageZ <= maxPageOffset.Z; pageZ++)
                {
                    Page p = LookupPage(pageX, pageZ);

                    float pageHeight = p.TerrainPage.PageHeightMap.GetAreaHeight(fx1, fx2, fz1, fz2);

                    if (pageHeight > height)
                    {
                        height = pageHeight;
                    }
                }
            }
            return height;
        }
        private byte[] newMask(PageCoord pc)
        {
            // allocate the new mask
            byte[] mask = new byte[pageSize * pageSize];

            // add it to the dictionary
            pages.Add(pc, mask);

            // update bounds
            if (pc.X < minPageX)
            {
                minPageX = pc.X;
            }
            if (pc.X > maxPageX)
            {
                maxPageX = pc.X;
            }
            if (pc.Z < minPageZ)
            {
                minPageZ = pc.Z;
            }
            if (pc.Z > maxPageZ)
            {
                maxPageZ = pc.Z;
            }
            return mask;
        }
        protected Technique FindPageTechnique(PageCoord coord)
        {
            Page page = TerrainManager.Instance.LookupPage(coord);
            Technique t = null;
            if (page != null)
            {
                Material mat = page.TerrainPage.Material;
                t = mat.GetBestTechnique();
            }

            return t;
        }
        public Page LookupPage(PageCoord locPage)
        {
            Debug.Assert(cameraSet, "Camera not set in LookupPage");
            PageCoord pageOffset = locPage - cameraPage + new PageCoord(visPageRadius, visPageRadius);

            if ( pageOffset.X < 0 || pageOffset.X >= pageArraySize || pageOffset.Z < 0 || pageOffset.Z >= pageArraySize )
            {
                return null;
            }

            return pages[pageOffset.X, pageOffset.Z];
        }
 /// <summary>
 ///		Used to subtract a PageCoord from another PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static PageCoord Subtract(PageCoord left, PageCoord right)
 {
     return(left - right);
 }
        /// <summary>
        /// Compute the "distance" between two pages.  Returns the axis aligned
        /// distance along X or Z (whichever is greater).
        /// </summary>
        /// <param name="c2">coordinate to compare to this</param>
        /// <returns></returns>
        public int Distance(PageCoord c2)
        {
            int xDiff = c2.X - X;
            int zDiff = c2.Z - Z;

            if ( xDiff < 0 )
            {
                xDiff = -xDiff;
            }

            if ( zDiff < 0 )
            {
                zDiff = -zDiff;
            }

            if ( xDiff > zDiff )
            {
                return xDiff;
            }
            else
            {
                return zDiff;
            }
        }
Example #40
0
 public PageDecalInfo(PageCoord coord)
 {
     this.coord = coord;
     decals     = new List <DecalElement>();
     passes     = new List <Pass>();
 }
 /// <summary>
 ///		Used to negate the elements of a PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <returns></returns>
 public static PageCoord Negate(PageCoord left)
 {
     return(-left);
 }
 /// <summary>
 /// Find the page for a given location
 /// </summary>
 /// <param name="location"></param>
 /// <returns>Returns the page, or null if that page is not currently loaded</returns>
 public Page LookupPage(Vector3 location)
 {
     PageCoord locPage = new PageCoord(location, pageSize);
     return LookupPage(locPage);
 }
        public TerrainPage(Vector3 location, Page page)
        {
            this.location = location;
            pageCoord = new PageCoord(location, TerrainManager.Instance.PageSize);

            terrainMaterial = TerrainManager.Instance.TerrainMaterialConfig.NewTerrainMaterial(pageCoord.X, pageCoord.Z);

            currentPage = page;
            Debug.Assert(location == currentPage.Location, "creating TerrainPage with page at different location");
            numTiles = currentPage.NumTiles;
            patchSize = TerrainManager.Instance.PageSize / numTiles;

            // set up the page height maps for this page of terrain
            subPageSize = TerrainManager.Instance.SubPageSize;
            int subPagesPerPage = TerrainManager.Instance.PageSize / subPageSize;

            pageHeightMap = new PageHeightMap(subPagesPerPage, TerrainManager.Instance.PageSize,
                TerrainManager.Instance.MaxMetersPerSample, TerrainManager.Instance.MinMetersPerSample);

            pageHeightMap.Location = location;

            // create and position a scene node for this terrain page
            string nodeName = String.Format("TerrainPage[{0},{1}]", (int)(location.x / TerrainManager.oneMeter),
                (int)(location.z / TerrainManager.oneMeter));

            // DEBUG - Console.WriteLine("Creating {0}", name);
            sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName);

            sceneNode.Position = location;

            sceneNode.AttachObject(this);

            // create the render operation
            renderOp = new RenderOperation();
            renderOp.operationType = OperationType.TriangleList;
            renderOp.useIndices = true;

            CreatePatches();

            SetCastShadows();

            UpdateBounds();

            TerrainManager.Instance.ShadowConfig.ShadowTechniqueChange += ShadowTechniqueChangeHandler;
        }
 /// <summary>
 ///		Used to negate the elements of a PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <returns></returns>
 public static PageCoord Negate(PageCoord left)
 {
     return -left;
 }
 /// <summary>
 ///		Used to subtract a PageCoord from another PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static PageCoord Subtract(PageCoord left, PageCoord right)
 {
     return left - right;
 }
        public bool Intersects(PageCoord pc)
        {
            bool ret = false;
            // do bounds intersection first
            if ((pc.X >= minPageX) && (pc.X <= maxPageX) && (pc.Z >= minPageZ) && (pc.Z <= maxPageZ))
            {
                byte[] mask;
                // if bounds intersection succeeds, then look up in the dictionary
                ret = pages.TryGetValue(pc, out mask);
            }

            return ret;
        }
        private Texture PageMaskTexture(PageCoord pc)
        {
            Image i = BuildPageMask(pc.WorldLocation(pageSize));

            String texName = String.Format("{0}-{1}", name, pc.ToString());
            Texture t = TextureManager.Instance.LoadImage(texName, i);

            return t;
        }
        //
        // Iterate page masks, only returning those in the given page range
        //
        public void IterateMasks(ReturnMask retDelegate, PageCoord minPage, PageCoord maxPage)
        {
            // get out quick if our bounds don't overlap the requested page range
            if ((minPageX > maxPage.X) || (maxPageX < minPage.X) || (minPageZ > maxPage.Z) || (maxPageZ < minPage.Z))
            {
                return;
            }
            foreach (KeyValuePair<PageCoord, byte[]> kvp in pages)
            {
                PageCoord pc = kvp.Key;

                // only call delegate if current page overlaps with requested page range
                if ((pc.X >= minPage.X) && (pc.X <= maxPage.X) && (pc.Z >= minPage.Z) && (pc.Z <= maxPage.Z))
                {
                    retDelegate(pc, kvp.Value);
                }
            }
        }
        public bool IntersectPage(PageCoord pc)
        {
            // check if page intersects bounds first
            if (pc.X < boundsMinPage.X || pc.X > boundsMaxPage.X || pc.Z < boundsMinPage.Z || pc.Z > boundsMaxPage.Z)
            {
                return false;
            }

            foreach (PageCoord tp in touchedPages)
            {
                if (tp == pc)
                {
                    return true;
                }
            }

            return false;
        }
 /// <summary>
 /// return the location of the page origin of the page containing the given location
 /// </summary>
 /// <param name="location"></param>
 /// <returns></returns>
 private Vector3 PageOrigin(Vector3 location)
 {
     PageCoord locPage = new PageCoord(location, pageSize);
     return locPage.WorldLocation(pageSize);
 }
        public void PerFrameProcessing(Vector3 cameraLocation)
        {
            // free the passes from last frame if there are any
            if (framePageDecalInfos != null)
            {
                FreePasses(framePageDecalInfos);
                framePageDecalInfos = null;
            }

            // compute the camera page
            PageCoord lastCameraPage = cameraPage;
            cameraPage = new PageCoord(cameraLocation, TerrainManager.Instance.PageSize);

            // update the decals
            Update(cameraLocation.x, cameraLocation.z);

            // build the per-page data structures
            framePageDecalInfos = BuildPageInfos();

            // if there are any visible decals, then build the material passes for all affected pages
            if (framePageDecalInfos != null)
            {
                BuildPasses(framePageDecalInfos);
            }
        }
 /// <summary>
 ///		Used when a PageCoord is added to another PageCoord.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public static PageCoord Add(PageCoord left, PageCoord right)
 {
     return left + right;
 }