Ejemplo n.º 1
0
        void OnDestroy()
        {
            ImprovedWorldTerrain.Unload();

            worldHeights              = null;
            worldTerrainGameObject    = null;
            terrainMaterial           = null;
            terrainInfoTileMap        = null;
            textureTerrainInfoTileMap = null;

            textureAtlasDesertSummer   = null;
            textureAtlasWoodlandSummer = null;
            textureAtlasMountainSummer = null;
            textureAtlasSwampSummer    = null;

            textureAtlasDesertWinter   = null;
            textureAtlasWoodlandWinter = null;
            textureAtlasMountainWinter = null;
            textureAtlasSwampWinter    = null;

            textureAtlasDesertRain   = null;
            textureAtlasWoodlandRain = null;
            textureAtlasMountainRain = null;
            textureAtlasSwampRain    = null;

            Resources.UnloadUnusedAssets();

            System.GC.Collect();
        }
        public override void GenerateSamples(ref MapPixelData mapPixel)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            // Create samples arrays
            mapPixel.tilemapSamples   = new TilemapSample[MapsFile.WorldMapTileDim, MapsFile.WorldMapTileDim];
            mapPixel.heightmapSamples = new float[HeightmapDimension, HeightmapDimension];

            // Divisor ensures continuous 0-1 range of tile samples
            float div = (float)(HeightmapDimension - 1) / 3f;

            // Read neighbouring height samples for this map pixel
            int mx = mapPixel.mapPixelX;
            int my = mapPixel.mapPixelY;

            byte[,] shm = dfUnity.ContentReader.WoodsFileReader.GetHeightMapValuesRange(mx - 2, my - 2, 4);
            byte[,] lhm = dfUnity.ContentReader.WoodsFileReader.GetLargeHeightMapValuesRange(mx - 1, my, 3);

            float[,] multiplierValue = new float[4, 4];
            for (int y = 0; y < 4; y++)
            {
                for (int x = 0; x < 4; x++)
                {
                    int mapPixelX = Math.Max(0, Math.Min(mx + x - 2, WoodsFile.mapWidthValue));
                    int mapPixelY = Math.Max(0, Math.Min(my + y - 2, WoodsFile.mapHeightValue));

                    multiplierValue[x, y] = ImprovedWorldTerrain.computeHeightMultiplier(mapPixelX, mapPixelY);
                }
            }

            // Extract height samples for all chunks
            float averageHeight = 0;
            float maxHeight = float.MinValue;
            float baseHeight, noiseHeight;
            float x1, x2, x3, x4;
            int   dim = HeightmapDimension;

            //mapPixel.heightmapSamples = new float[dim, dim];
            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    float rx           = (float)x / div;
                    float ry           = (float)y / div;
                    int   ix           = Mathf.FloorToInt(rx);
                    int   iy           = Mathf.FloorToInt(ry);
                    float sfracx       = (float)x / (float)(dim - 1);
                    float sfracy       = (float)y / (float)(dim - 1);
                    float fracx        = (float)(x - ix * div) / div;
                    float fracy        = (float)(y - iy * div) / div;
                    float scaledHeight = 0;

                    // Bicubic sample small height map for base terrain elevation
                    x1            = TerrainHelper.CubicInterpolator(shm[0, 3] * multiplierValue[0, 3], shm[1, 3] * multiplierValue[1, 3], shm[2, 3] * multiplierValue[2, 3], shm[3, 3] * multiplierValue[3, 3], sfracx);
                    x2            = TerrainHelper.CubicInterpolator(shm[0, 2] * multiplierValue[0, 2], shm[1, 2] * multiplierValue[1, 2], shm[2, 2] * multiplierValue[2, 2], shm[3, 2] * multiplierValue[3, 2], sfracx);
                    x3            = TerrainHelper.CubicInterpolator(shm[0, 1] * multiplierValue[0, 1], shm[1, 1] * multiplierValue[1, 1], shm[2, 1] * multiplierValue[2, 1], shm[3, 1] * multiplierValue[3, 1], sfracx);
                    x4            = TerrainHelper.CubicInterpolator(shm[0, 0] * multiplierValue[0, 0], shm[1, 0] * multiplierValue[1, 0], shm[2, 0] * multiplierValue[2, 0], shm[3, 0] * multiplierValue[3, 0], sfracx);
                    baseHeight    = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, sfracy);
                    scaledHeight += baseHeight * baseHeightScale;

                    // Bicubic sample large height map for noise mask over terrain features
                    x1            = TerrainHelper.CubicInterpolator(lhm[ix, iy + 0], lhm[ix + 1, iy + 0], lhm[ix + 2, iy + 0], lhm[ix + 3, iy + 0], fracx);
                    x2            = TerrainHelper.CubicInterpolator(lhm[ix, iy + 1], lhm[ix + 1, iy + 1], lhm[ix + 2, iy + 1], lhm[ix + 3, iy + 1], fracx);
                    x3            = TerrainHelper.CubicInterpolator(lhm[ix, iy + 2], lhm[ix + 1, iy + 2], lhm[ix + 2, iy + 2], lhm[ix + 3, iy + 2], fracx);
                    x4            = TerrainHelper.CubicInterpolator(lhm[ix, iy + 3], lhm[ix + 1, iy + 3], lhm[ix + 2, iy + 3], lhm[ix + 3, iy + 3], fracx);
                    noiseHeight   = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, fracy);
                    scaledHeight += noiseHeight * noiseMapScale;

                    // Additional noise mask for small terrain features at ground level
                    int   noisex   = mapPixel.mapPixelX * (HeightmapDimension - 1) + x;
                    int   noisey   = (MapsFile.MaxMapPixelY - mapPixel.mapPixelY) * (HeightmapDimension - 1) + y;
                    float lowFreq  = TerrainHelper.GetNoise(noisex, noisey, 0.3f, 0.5f, 0.5f, 1);
                    float highFreq = TerrainHelper.GetNoise(noisex, noisey, 0.9f, 0.5f, 0.5f, 1);
                    scaledHeight += (lowFreq * highFreq) * extraNoiseScale;

                    // Clamp lower values to ocean elevation
                    if (scaledHeight < scaledOceanElevation)
                    {
                        scaledHeight = scaledOceanElevation;
                    }

                    // Accumulate average height
                    averageHeight += scaledHeight;

                    // Get max height
                    if (scaledHeight > maxHeight)
                    {
                        maxHeight = scaledHeight;
                    }

                    // Set sample
                    float height = Mathf.Clamp01(scaledHeight / MaxTerrainHeight);
                    mapPixel.heightmapSamples[y, x] = height;
                }
            }

            // Average and max heights are passed back for locations
            mapPixel.averageHeight = (averageHeight /= (float)(dim * dim)) / MaxTerrainHeight;
            mapPixel.maxHeight     = maxHeight / MaxTerrainHeight;
        }
Ejemplo n.º 3
0
        private GameObject generateWorldTerrain()
        {
            // Create Unity Terrain game object
            GameObject terrainGameObject = Terrain.CreateTerrainGameObject(null);

            terrainGameObject.name = string.Format("WorldTerrain");

            terrainGameObject.gameObject.transform.localPosition = Vector3.zero;

            // assign terrainGameObject to layer "WorldTerrain" if available (used for rendering with secondary camera to prevent floating-point precision problems with huge clipping ranges)
            int layerExtendedTerrain = LayerMask.NameToLayer("WorldTerrain");

            if (layerExtendedTerrain != -1)
            {
                terrainGameObject.layer = layerExtendedTerrain;
            }

            int worldMapResolution = Math.Max(worldMapWidth, worldMapHeight);

            if (worldHeights == null)
            {
                worldHeights = new float[worldMapResolution, worldMapResolution];
            }

            for (int y = 0; y < worldMapHeight; y++)
            {
                for (int x = 0; x < worldMapWidth; x++)
                {
                    // get height data for this map pixel from world map and scale it to approximately match StreamingWorld's terrain heights
                    float sampleHeight = Convert.ToSingle(dfUnity.ContentReader.WoodsFileReader.GetHeightMapValue(x, y));

                    sampleHeight *= (ImprovedWorldTerrain.computeHeightMultiplier(x, y) * ImprovedTerrainSampler.baseHeightScale + ImprovedTerrainSampler.noiseMapScale);

                    // make ocean elevation the lower limit
                    if (sampleHeight < ImprovedTerrainSampler.scaledOceanElevation)
                    {
                        sampleHeight = ImprovedTerrainSampler.scaledOceanElevation;
                    }

                    // normalize with TerrainHelper.maxTerrainHeight
                    worldHeights[worldMapHeight - 1 - y, x] = Mathf.Clamp01(sampleHeight / ImprovedTerrainSampler.maxTerrainHeight);
                }
            }

            // Basemap not used and is just pushed far away
            const float basemapDistance = 1000000f;

            // Ensure TerrainData is created
            Terrain terrain = terrainGameObject.GetComponent <Terrain>();

            if (terrain.terrainData == null)
            {
                // Setup terrain data
                TerrainData terrainData = new TerrainData();
                terrainData.name = "TerrainData";

                // this is not really an assignment! you tell unity terrain what resolution you want for your heightmap and it will allocate resources and take the next power of 2 increased by 1 as heightmapResolution...
                terrainData.heightmapResolution = worldMapResolution;

                float heightmapResolution = terrainData.heightmapResolution;
                // Calculate width and length of terrain in world units
                float terrainSize = ((MapsFile.WorldMapTerrainDim * MeshReader.GlobalScale) * (heightmapResolution - 1.0f));


                terrainData.size = new Vector3(terrainSize, ImprovedTerrainSampler.maxTerrainHeight, terrainSize);

                //terrainData.size = new Vector3(terrainSize, TerrainHelper.maxTerrainHeight * TerrainScale * worldMapResolution, terrainSize);
                terrainData.SetDetailResolution(worldMapResolution, 16);
                terrainData.alphamapResolution = worldMapResolution;
                terrainData.baseMapResolution  = worldMapResolution;

                // Apply terrain data
                terrain.terrainData     = terrainData;
                terrain.basemapDistance = basemapDistance;
            }

            terrain.heightmapPixelError = 0; // 0 ... prevent unity terrain lod approach, set to higher values to enable it
            //terrain.castShadows = true;

            // Promote heights
            Vector3 size = terrain.terrainData.size;

            terrain.terrainData.size = new Vector3(size.x, ImprovedTerrainSampler.maxTerrainHeight * streamingWorld.TerrainScale, size.z);
            terrain.terrainData.SetHeights(0, 0, worldHeights);


            // update world terrain position - do this before terrainGameObject.transform invocation, so that object2world matrix is updated with correct values
            Vector3 offset = new Vector3(0.0f, 0.0f, 0.0f);

            updatePositionWorldTerrain(ref terrainGameObject, offset);

            textureAtlasDesertSummer            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(2).albedoMap;
            textureAtlasDesertSummer.filterMode = FilterMode.Point;

            textureAtlasWoodlandSummer            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(302).albedoMap;
            textureAtlasWoodlandSummer.filterMode = FilterMode.Point;

            textureAtlasMountainSummer            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(102).albedoMap;
            textureAtlasMountainSummer.filterMode = FilterMode.Point;

            textureAtlasSwampSummer            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(402).albedoMap;
            textureAtlasSwampSummer.filterMode = FilterMode.Point;

            textureAtlasDesertWinter            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(3).albedoMap;
            textureAtlasDesertWinter.filterMode = FilterMode.Point;

            textureAtlasWoodlandWinter            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(303).albedoMap;
            textureAtlasWoodlandWinter.filterMode = FilterMode.Point;

            textureAtlasMountainWinter            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(103).albedoMap;
            textureAtlasMountainWinter.filterMode = FilterMode.Point;

            textureAtlasSwampWinter            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(403).albedoMap;
            textureAtlasSwampWinter.filterMode = FilterMode.Point;

            textureAtlasDesertRain            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(4).albedoMap;
            textureAtlasDesertRain.filterMode = FilterMode.Point;

            textureAtlasWoodlandRain            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(304).albedoMap;
            textureAtlasWoodlandRain.filterMode = FilterMode.Point;

            textureAtlasMountainRain            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(104).albedoMap;
            textureAtlasMountainRain.filterMode = FilterMode.Point;

            textureAtlasSwampRain            = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(404).albedoMap;
            textureAtlasSwampRain.filterMode = FilterMode.Point;

            terrainMaterial      = new Material(Shader.Find("Daggerfall/IncreasedTerrainTilemap"));
            terrainMaterial.name = string.Format("world terrain material");

            // Assign textures and parameters
            terrainMaterial.SetTexture("_TileAtlasTexDesert", textureAtlasDesertSummer);
            terrainMaterial.SetTexture("_TileAtlasTexWoodland", textureAtlasWoodlandSummer);
            terrainMaterial.SetTexture("_TileAtlasTexMountain", textureAtlasMountainSummer);
            terrainMaterial.SetTexture("_TileAtlasTexSwamp", textureAtlasSwampSummer);
            //terrainMaterial.SetTexture("_TilemapTex", textureTerrainInfoTileMap);

            terrainMaterial.SetInt("_TextureSetSeasonCode", 0);

            updateSeasonalTextures(); // change seasonal textures if necessary

            terrainMaterial.SetInt("_PlayerPosX", this.playerGPS.CurrentMapPixel.X);
            terrainMaterial.SetInt("_PlayerPosY", this.playerGPS.CurrentMapPixel.Y);

            terrainMaterial.SetInt("_TerrainDistance", streamingWorld.TerrainDistance - 1);                                                                  // -1... allow the outer ring of of detailed terrain to intersect with far terrain (to prevent some holes)

            Vector3 vecWaterHeight            = new Vector3(0.0f, (ImprovedTerrainSampler.scaledOceanElevation + 1.0f) * streamingWorld.TerrainScale, 0.0f); // water height level on y-axis (+1.0f some coastlines are incorrect otherwise)
            Vector3 vecWaterHeightTransformed = terrainGameObject.transform.TransformPoint(vecWaterHeight);                                                  // transform to world coordinates

            terrainMaterial.SetFloat("_WaterHeightTransformed", vecWaterHeightTransformed.y);

            terrainMaterial.SetTexture("_SkyTex", renderTextureSky);

            setMaterialFogParameters();

            terrainMaterial.SetInt("_FogFromSkyTex", 0);

            //terrainMaterial.SetFloat("_BlendFactor", blendFactor);
            terrainMaterial.SetFloat("_BlendStart", blendStart);
            terrainMaterial.SetFloat("_BlendEnd", blendEnd);

            #if REFLECTIONSMOD_CODE_AVAILABLE
            if (isActiveReflectionsMod)
            {
                RenderTexture reflectionSeaTexture = GameObject.Find("ReflectionsMod").GetComponent <ReflectionsMod.UpdateReflectionTextures>().getSeaReflectionRenderTexture();
                if (reflectionSeaTexture != null)
                {
                    terrainMaterial.EnableKeyword("ENABLE_WATER_REFLECTIONS");
                    terrainMaterial.SetTexture("_SeaReflectionTex", reflectionSeaTexture);
                    terrainMaterial.SetInt("_UseSeaReflectionTex", 1);
                }
                else
                {
                    terrainMaterial.SetInt("_UseSeaReflectionTex", 0);
                }
            }
            #else
            terrainMaterial.SetInt("_UseSeaReflectionTex", 0);
            #endif

            // Promote material
            terrain.materialTemplate = terrainMaterial;
            terrain.materialType     = Terrain.MaterialType.Custom;

            terrainGameObject.SetActive(true);

            return(terrainGameObject);
        }
Ejemplo n.º 4
0
 void InitImprovedWorldTerrain()
 {
     // preprocess heights
     ImprovedWorldTerrain.InitImprovedWorldTerrain(DaggerfallUnity.Instance.ContentReader);
 }