// Sets up rects for location area and border ready for circumnavigation protected bool SetLocationRects(DFPosition targetPixel, DFPosition targetMPworld) { GameObject terrainObject = GameManager.Instance.StreamingWorld.GetTerrainFromPixel(targetPixel); if (terrainObject) { DaggerfallTerrain dfTerrain = terrainObject.GetComponent <DaggerfallTerrain>(); if (dfTerrain && dfTerrain.MapData.hasLocation) { float locBorder = 1; DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(dfTerrain.MapData.mapRegionIndex, dfTerrain.MapData.mapLocationIndex); if (location.Loaded && location.MapTableData.LocationType == DFRegion.LocationTypes.TownCity) { locBorder = 1.5f; } Rect locationTileRect = dfTerrain.MapData.locationRect; locationTileRect.xMin += 1; locationTileRect.yMin += 1; locationBorderRect.Set(targetMPworld.X + (locationTileRect.x * TSize), targetMPworld.Y + (locationTileRect.y * TSize), locationTileRect.width * TSize, locationTileRect.height * TSize); locationTileRect.xMin += locBorder; locationTileRect.xMax -= locBorder; locationTileRect.yMin += locBorder; locationTileRect.yMax -= locBorder; locationRect.Set(targetMPworld.X + (locationTileRect.x * TSize), targetMPworld.Y + (locationTileRect.y * TSize), locationTileRect.width * TSize, locationTileRect.height * TSize); return(!location.HasCustomLocationPosition()); // Only aim for location center if it's centered in the map pixel } } locationBorderRect.Set(0, 0, 0, 0); locationRect.Set(0, 0, 0, 0); return(false); }
/// <summary> /// Remove cached tileData, if no TerrainTexturer has used it, to avoid memory buildup. /// </summary> /// <param name="sender"></param> /// <param name="terrainData"></param> public void UncacheTileData(DaggerfallTerrain sender, TerrainData terrainData) { var pos = PositionKey(sender.MapPixelX, sender.MapPixelY); if (tileDataCache.ContainsKey(pos)) { tileDataCache.Remove(pos); } }
public void CreateFirefly(Mod mod, DaggerfallTerrain dfTerrain, int x, int y, float scale, Terrain terrain, float distance) { float xVariation = Random.Range(-distance, distance); float zVariation = Random.Range(-distance, distance); //Vector3 pos = new Vector3(((x + xVariation) * scale), 0, ((y + zVariation) * scale)) + dfTerrain.transform.position; Vector3 pos = transform.position + new Vector3(xVariation * scale, 0, zVariation * scale); //pos.y = terrain.SampleHeight(new Vector3((x + xVariation) * scale, 0, (y + zVariation) * scale) + dfTerrain.transform.position) + dfTerrain.transform.position.y + Random.Range(1.5f, 3f); pos.y = terrain.SampleHeight(pos) + Random.Range(0.5f * scale, 1.5f * scale); GameObject firefly = mod.GetAsset <GameObject>("Firefly", true); firefly.transform.parent = transform; firefly.GetComponent <WORandomMover>().startPos = transform.InverseTransformPoint(pos); //firefly.transform.position = transform.InverseTransformPoint(pos); firefly.transform.position = pos; }
public BaseDataObject( DaggerfallTerrain DFTerrain, DaggerfallBillboardBatch DFBillboardBatch, Terrain Terrain, float Scale, float Steepness, int X, int Y, float MaxTerrainHeight) { dfTerrain = DFTerrain; dfBillboardBatch = DFBillboardBatch; terrain = Terrain; scale = Scale; steepness = Steepness; x = X; y = Y; maxTerrainHeight = MaxTerrainHeight; }
/// <summary> /// Check if player is really standing on an outdoor tile, not just positioned above one. /// For example when player is on their ship they are standing above water but should not be swimming. /// Same when player is levitating above water they should not hear splash sounds. /// </summary> /// <returns>True if player is physically in range of an outdoor tile.</returns> bool GetOnExteriorGroundMethod() { float rayDistance = (GameManager.Instance.TransportManager.IsOnFoot) ? walkingRayDistance : ridingRayDistance; // Must be outside and actually be standing on a terrain object not some other object (e.g. player ship) RaycastHit hit; if (GameManager.Instance.PlayerEnterExit.IsPlayerInside || !Physics.Raycast(transform.position, Vector3.down, out hit, rayDistance * 2)) { return(false); } else { DaggerfallTerrain terrain = hit.transform.GetComponent <DaggerfallTerrain>(); if (!terrain) { return(false); } } return(true); }
/// <summary> /// Check if player is really standing on an outdoor water tile, not just positioned above one. /// For example when player is on their ship they are standing above water but should not be swimming. /// Same when player is levitating above water they should not hear splash sounds. /// </summary> /// <returns>True if player is physically in range of an outdoor water tile.</returns> OnExteriorWaterMethod GetOnExteriorWaterMethod() { const float walkingRayDistance = 1.0f; const float ridingRayDistance = 2.0f; float rayDistance = (GameManager.Instance.TransportManager.IsOnFoot) ? walkingRayDistance : ridingRayDistance; // Must be outside and over a water tile if (GameManager.Instance.PlayerEnterExit.IsPlayerInside || GameManager.Instance.StreamingWorld.PlayerTileMapIndex != 0) { return(OnExteriorWaterMethod.None); } // Must actually be standing on a terrain object not some other object (e.g. player ship) RaycastHit hit; if (!Physics.Raycast(transform.position, Vector3.down, out hit, rayDistance)) { return(OnExteriorWaterMethod.None); } else { DaggerfallTerrain terrain = hit.transform.GetComponent <DaggerfallTerrain>(); if (!terrain) { return(OnExteriorWaterMethod.None); } } // Handle swimming/waterwalking if (GameManager.Instance.PlayerEntity.IsWaterWalking) { return(OnExteriorWaterMethod.WaterWalking); } else { return(OnExteriorWaterMethod.Swimming); } }
/// <summary> /// Apply wind strength on terrain promotion. /// This is called for every terrain. /// </summary> /// <param name="daggerTerrain"></param> /// <param name="terrainData">New terrain.</param> private void DaggerfallTerrain_OnPromoteTerrainData(DaggerfallTerrain daggerTerrain, TerrainData terrainData) { SetTerrainWindStrength(terrainData); }
void Update() { if (!DaggerfallUnity.Settings.Nystul_RealtimeReflections) { return; } GameObject goPlayerAdvanced = GameObject.Find("PlayerAdvanced"); PlayerGPS playerGPS = GameObject.Find("PlayerAdvanced").GetComponent <PlayerGPS>(); if (!playerGPS) { return; } if (GameManager.Instance.IsPlayerInside) { RaycastHit hit; float distanceToGround = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position, -Vector3.up, out hit, 100.0F)) { distanceToGround = hit.distance; } reflectionPlaneBottom.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceToGround, 0.0f); float distanceLevelBelow = getDistanceToLowerLevel(goPlayerAdvanced); //Debug.Log(string.Format("distance to lower level: {0}", distanceLevelBelow)); reflectionPlaneSeaLevel.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceLevelBelow, 0.0f); } else //if (!GameManager.Instance.IsPlayerInside) { Terrain terrainInstancePlayerTerrain = null; int referenceLocationX = playerGPS.CurrentMapPixel.X; int referenceLocationY = playerGPS.CurrentMapPixel.Y; ContentReader.MapSummary mapSummary; // if there is no location at current player position... if (!DaggerfallUnity.Instance.ContentReader.HasLocation(referenceLocationX, referenceLocationY, out mapSummary)) { // search for largest location in local 8-neighborhood and take this as reference location for location reflection plane int maxLocationArea = -1; for (int y = -1; y <= +1; y++) { for (int x = -1; x <= +1; x++) { if (DaggerfallUnity.Instance.ContentReader.HasLocation(playerGPS.CurrentMapPixel.X + x, playerGPS.CurrentMapPixel.Y + y, out mapSummary)) { DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex); byte locationRangeX = location.Exterior.ExteriorData.Width; byte locationRangeY = location.Exterior.ExteriorData.Height; int locationArea = locationRangeX * locationRangeY; if (locationArea > maxLocationArea) { referenceLocationX = playerGPS.CurrentMapPixel.X + x; referenceLocationY = playerGPS.CurrentMapPixel.Y + y; maxLocationArea = locationArea; } } } } } GameObject go = GameObject.Find("StreamingTarget"); if (go == null) { return; } foreach (Transform child in go.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } if ((dfTerrain.MapPixelX != referenceLocationX) || (dfTerrain.MapPixelY != referenceLocationY)) { continue; } Terrain terrainInstance = child.GetComponent <Terrain>(); terrainInstancePlayerTerrain = terrainInstance; if ((terrainInstance) && (terrainInstance.terrainData)) { float scale = terrainInstance.terrainData.heightmapScale.x; float xSamplePos = DaggerfallUnity.Instance.TerrainSampler.HeightmapDimension * 0.55f; float ySamplePos = DaggerfallUnity.Instance.TerrainSampler.HeightmapDimension * 0.55f; Vector3 pos = new Vector3(xSamplePos * scale, 0, ySamplePos * scale); float height = terrainInstance.SampleHeight(pos + terrainInstance.transform.position); float positionY = height + terrainInstance.transform.position.y; reflectionPlaneBottom.transform.position = new Vector3(goPlayerAdvanced.transform.position.x + terrainInstance.transform.position.x, positionY, goPlayerAdvanced.transform.position.z + terrainInstance.transform.position.z); } } if (!terrainInstancePlayerTerrain) { return; } //Debug.Log(string.Format("playerGPS: {0}, plane: {1}", goPlayerAdvanced.transform.position.y, reflectionPlaneBottom.transform.position.y)); if (playerGPS.transform.position.y < reflectionPlaneBottom.transform.position.y) { RaycastHit hit; float distanceToGround = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position, -Vector3.up, out hit, 100.0F)) { distanceToGround = hit.distance; } //Debug.Log(string.Format("distance to ground: {0}", distanceToGround)); reflectionPlaneBottom.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceToGround, 0.0f); } StreamingWorld streamingWorld = GameObject.Find("StreamingWorld").GetComponent <StreamingWorld>(); Vector3 vecWaterHeight = new Vector3(0.0f, (DaggerfallUnity.Instance.TerrainSampler.OceanElevation) * streamingWorld.TerrainScale, 0.0f); // water height level on y-axis (+1.0f some coastlines are incorrect otherwise) Vector3 vecWaterHeightTransformed = terrainInstancePlayerTerrain.transform.TransformPoint(vecWaterHeight); // transform to world coordinates //Debug.Log(string.Format("x,y,z: {0}, {1}, {2}", vecWaterHeight.x, vecWaterHeight.y, vecWaterHeight.z)); //Debug.Log(string.Format("transformed x,y,z: {0}, {1}, {2}", vecWaterHeightTransformed.x, vecWaterHeightTransformed.y, vecWaterHeightTransformed.z)); reflectionPlaneSeaLevel.transform.position = new Vector3(goPlayerAdvanced.transform.position.x, vecWaterHeightTransformed.y, goPlayerAdvanced.transform.position.z); } if (GameManager.Instance.IsPlayerInside && !playerInside) { playerInside = true; // player now inside mirrorRefl.CurrentBackgroundSettings = MirrorReflection.EnvironmentSetting.IndoorSetting; mirrorReflSeaLevel.CurrentBackgroundSettings = MirrorReflection.EnvironmentSetting.IndoorSetting; if (useDeferredReflections) { componentDefferedPlanarReflections.enabled = true; } } else if (!GameManager.Instance.IsPlayerInside && playerInside) { playerInside = false; // player now outside mirrorRefl.CurrentBackgroundSettings = MirrorReflection.EnvironmentSetting.OutdoorSetting; mirrorReflSeaLevel.CurrentBackgroundSettings = MirrorReflection.EnvironmentSetting.OutdoorSetting; if (useDeferredReflections) { componentDefferedPlanarReflections.enabled = false; } } }
void InjectMaterialPropertiesOutdoor() { if (GameManager.Instance.IsPlayerInside || (!componentUpdateReflectionTextures.IsEnabledOutdoorGroundReflections && !componentUpdateReflectionTextures.IsEnabledOutdoorSeaReflections)) { return; } GameObject go = GameObject.Find("StreamingTarget"); if (!go) { return; } foreach (Transform child in go.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } PlayerGPS playerGPS = GameObject.Find("PlayerAdvanced").GetComponent <PlayerGPS>(); if (!playerGPS) { continue; } //if ((dfTerrain.MapPixelX != playerGPS.CurrentMapPixel.X) || (dfTerrain.MapPixelY != playerGPS.CurrentMapPixel.Y)) // continue; Terrain terrain = child.GetComponent <Terrain>(); if (terrain) { if ((terrain.materialTemplate)) //&&(terrain.materialTemplate.shader.name != "Daggerfall/TilemapWithReflections")) // uncommenting this makes initial location (after startup, not fast travelling) not receive correct shader - don't know why - so workaround is to force injecting materialshader even for unset material (not sure why it works, but it does) { if ((SystemInfo.supports2DArrayTextures) && DaggerfallUnity.Settings.EnableTextureArrays) { if (terrain.materialTemplate.HasProperty("_TileTexArr") && terrain.materialTemplate.HasProperty("_TileNormalMapTexArr") && terrain.materialTemplate.HasProperty("_TileMetallicGlossMapTexArr") && terrain.materialTemplate.HasProperty("_TilemapTex") && terrain.materialTemplate.HasProperty("_TilemapDim")) { Texture tileTextureArray = terrain.materialTemplate.GetTexture("_TileTexArr"); Texture tileNormalMapTextureArray = terrain.materialTemplate.GetTexture("_TileNormalMapTexArr"); Texture tileMetallicGlossMapTextureArray = terrain.materialTemplate.GetTexture("_TileMetallicGlossMapTexArr"); Texture tileMapTexture = terrain.materialTemplate.GetTexture("_TilemapTex"); int tileMapDim = terrain.materialTemplate.GetInt("_TilemapDim"); Material newMat = new Material(componentUpdateReflectionTextures.ShaderTilemapTextureArrayWithReflections); newMat.SetTexture("_TileTexArr", tileTextureArray); newMat.SetTexture("_TileNormalMapTexArr", tileNormalMapTextureArray); if (terrain.materialTemplate.IsKeywordEnabled("_NORMALMAP")) { newMat.EnableKeyword("_NORMALMAP"); } else { newMat.DisableKeyword("_NORMALMAP"); } newMat.SetTexture("_TileMetallicGlossMapTexArr", tileMetallicGlossMapTextureArray); newMat.SetTexture("_TilemapTex", tileMapTexture); newMat.SetInt("_TilemapDim", tileMapDim); newMat.SetTexture("_ReflectionGroundTex", texReflectionGround); newMat.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneLowerLevel.transform.position.y); newMat.SetTexture("_ReflectionSeaTex", texReflectionLowerLevel); newMat.SetFloat("_SeaLevelHeight", gameObjectReflectionPlaneSeaLevel.transform.position.y); terrain.materialTemplate = newMat; } } else { if (terrain.materialTemplate.HasProperty("_TileAtlasTex") && terrain.materialTemplate.HasProperty("_TilemapTex") && terrain.materialTemplate.HasProperty("_TilemapDim")) { Texture tileSetTexture = terrain.materialTemplate.GetTexture("_TileAtlasTex"); //Texture2D tileAtlas = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(402).albedoMap; //System.IO.File.WriteAllBytes("./Assets/Daggerfall/RealtimeReflections/Resources/tileatlas_402.png", tileAtlas.EncodeToPNG()); Texture tileMapTexture = terrain.materialTemplate.GetTexture("_TilemapTex"); int tileMapDim = terrain.materialTemplate.GetInt("_TilemapDim"); Material newMat = new Material(componentUpdateReflectionTextures.ShaderTilemapWithReflections); newMat.SetTexture("_TileAtlasTex", tileSetTexture); newMat.SetTexture("_TilemapTex", tileMapTexture); newMat.SetInt("_TilemapDim", tileMapDim); newMat.SetTexture("_ReflectionGroundTex", texReflectionGround); newMat.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneLowerLevel.transform.position.y); newMat.SetTexture("_ReflectionSeaTex", texReflectionLowerLevel); newMat.SetFloat("_SeaLevelHeight", gameObjectReflectionPlaneSeaLevel.transform.position.y); WeatherManager weatherManager = GameObject.Find("WeatherManager").GetComponent <WeatherManager>(); if (!weatherManager.IsRaining) { //Texture2D tileAtlasReflectiveTexture = Resources.Load("tileatlas_reflective") as Texture2D; Texture2D tileAtlasReflectiveTexture = componentUpdateReflectionTextures.TextureTileatlasReflective; newMat.SetTexture("_TileAtlasReflectiveTex", tileAtlasReflectiveTexture); } else { //Texture2D tileAtlasReflectiveTexture = Resources.Load("tileatlas_reflective_raining") as Texture2D; Texture2D tileAtlasReflectiveTexture = componentUpdateReflectionTextures.TextureTileatlasReflectiveRaining; newMat.SetTexture("_TileAtlasReflectiveTex", tileAtlasReflectiveTexture); } terrain.materialTemplate = newMat; } } } } } }
// Add Grass private void AddGrass(DaggerfallTerrain daggerTerrain, TerrainData terrainData) { // Used to check performance // Stopwatch stopwatch = new Stopwatch(); // stopwatch.Start(); details = new int[256, 256]; //Get the current season currentSeason = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue; //Proceed if it's NOT winter, and if the worldClimate contains grass, which is everything above 225, with the exception of 229 if (currentSeason != DaggerfallDateTime.Seasons.Winter && (daggerTerrain.MapData.worldClimate > 225 && daggerTerrain.MapData.worldClimate != 229)) { //Switch the grass texture based on the climate if (daggerTerrain.MapData.worldClimate == 226 || daggerTerrain.MapData.worldClimate == 227 || daggerTerrain.MapData.worldClimate == 228 || daggerTerrain.MapData.worldClimate == 230) detailPrototype[0].prototypeTexture = brownGrass; else detailPrototype[0].prototypeTexture = greenGrass; tilemap = daggerTerrain.TileMap; terrainData.detailPrototypes = detailPrototype; terrainData.wavingGrassTint = Color.gray; terrainData.SetDetailResolution(256, 8); int colorValue; //Check all the tiles, Daggerfall uses the red color value to draw tiles for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { colorValue = tilemap[(i * 128) + j].r; //For easier checking switch (colorValue) { //Four corner tiles case 8: case 9: case 10: case 11: details[i * 2, j * 2] = Random.Range(thickLower, thickHigher); details[i * 2, (j * 2) + 1] = Random.Range(thickLower, thickHigher); details[(i * 2) + 1, j * 2] = Random.Range(thickLower, thickHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thickLower, thickHigher); break; //Upper left corner case 40: case 224: case 164: case 176: case 181: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //Lower left corner case 41: case 221: case 165: case 177: case 182: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //Lower right corner case 42: case 222: case 166: case 178: case 183: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Upper right corner case 43: case 223: case 167: case 179: case 180: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Left side case 44: case 66: case 84: case 160: case 168: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //lower side case 45: case 67: case 85: case 161: case 169: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //right side case 46: case 64: case 86: case 162: case 170: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //upper side case 47: case 65: case 87: case 163: case 171: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //All expect lower right case 48: case 62: case 88: case 156: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //All expect upper right case 49: case 63: case 89: case 157: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //All expect upper left case 50: case 60: case 90: case 158: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //All expect lower left case 51: case 61: case 91: case 159: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Left to right case 204: case 206: case 214: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Right to left case 205: case 207: case 213: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; } } } } terrainData.SetDetailLayer(0, 0, 0, details); // stopwatch.Stop(); // // Write result // UnityEngine.Debug.Log("Time elapsed: " + // stopwatch.Elapsed); }
void InjectMaterialPropertiesOutdoor() { GameObject go = GameObject.Find("StreamingTarget"); if (!go) { return; } foreach (Transform child in go.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } PlayerGPS playerGPS = GameObject.Find("PlayerAdvanced").GetComponent <PlayerGPS>(); if (!playerGPS) { continue; } //if ((dfTerrain.MapPixelX != playerGPS.CurrentMapPixel.X) || (dfTerrain.MapPixelY != playerGPS.CurrentMapPixel.Y)) // continue; Terrain terrain = child.GetComponent <Terrain>(); if (terrain) { if ((terrain.materialTemplate)) //&&(terrain.materialTemplate.shader.name != "Daggerfall/TilemapWithReflections")) // uncommenting this makes initial location (after startup, not fast travelling) not receive correct shader - don't know why - so workaround is to force injecting materialshader even for unset material (not sure why it works, but it does) { Texture tileSetTexture = terrain.materialTemplate.GetTexture("_TileAtlasTex"); //Texture2D tileAtlas = dfUnity.MaterialReader.TextureReader.GetTerrainTilesetTexture(402).albedoMap; //System.IO.File.WriteAllBytes("./Assets/ReflectionsMod/Resources/tileatlas_402.png", tileAtlas.EncodeToPNG()); Texture tileMapTexture = terrain.materialTemplate.GetTexture("_TilemapTex"); int tileMapDim = terrain.materialTemplate.GetInt("_TilemapDim"); Material newMat = new Material(Shader.Find("Daggerfall/TilemapWithReflections")); newMat.SetTexture("_TileAtlasTex", tileSetTexture); newMat.SetTexture("_TilemapTex", tileMapTexture); newMat.SetInt("_TilemapDim", tileMapDim); newMat.SetTexture("_ReflectionGroundTex", texReflectionGround); newMat.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneLowerLevel.transform.position.y); newMat.SetTexture("_ReflectionSeaTex", texReflectionLowerLevel); newMat.SetFloat("_SeaLevelHeight", gameObjectReflectionPlaneSeaLevel.transform.position.y); WeatherManager weatherManager = GameObject.Find("WeatherManager").GetComponent <WeatherManager>(); if (!weatherManager.IsRaining) { Texture2D tileAtlasReflectiveTexture = Resources.Load("tileatlas_reflective") as Texture2D; newMat.SetTexture("_TileAtlasReflectiveTex", tileAtlasReflectiveTexture); } else { Texture2D tileAtlasReflectiveTexture = Resources.Load("tileatlas_reflective_raining") as Texture2D; newMat.SetTexture("_TileAtlasReflectiveTex", tileAtlasReflectiveTexture); } terrain.materialTemplate = newMat; } } } }
void Update() { GameObject goPlayerAdvanced = GameObject.Find("PlayerAdvanced"); PlayerGPS playerGPS = GameObject.Find("PlayerAdvanced").GetComponent <PlayerGPS>(); if (!playerGPS) { return; } //if (GameManager.Instance.IsPlayerInside) if (GameManager.Instance.IsPlayerInsideBuilding) { RaycastHit hit; float distanceToGround = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position, -Vector3.up, out hit, 100.0F)) { distanceToGround = hit.distance; } // additional checks in distance of player/character controller in all directions - important so that reflections don't disappear too early, e.g attics near ladder float radius = GameManager.Instance.PlayerController.radius; float distanceToGroundNorth = 0, distanceToGroundSouth = 0, distanceToGroundWest = 0, distanceToGroundEast = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position + new Vector3(0.0f, 0.0f, -radius), -Vector3.up, out hit, 100.0F)) { distanceToGroundNorth = hit.distance; } if (Physics.Raycast(goPlayerAdvanced.transform.position + new Vector3(0.0f, 0.0f, radius), -Vector3.up, out hit, 100.0F)) { distanceToGroundSouth = hit.distance; } if (Physics.Raycast(goPlayerAdvanced.transform.position + new Vector3(-radius, 0.0f, 0.0f), -Vector3.up, out hit, 100.0F)) { distanceToGroundWest = hit.distance; } if (Physics.Raycast(goPlayerAdvanced.transform.position + new Vector3(radius, 0.0f, 0.0f), -Vector3.up, out hit, 100.0F)) { distanceToGroundEast = hit.distance; } distanceToGround = Mathf.Min(distanceToGround, Mathf.Min(distanceToGroundNorth, Mathf.Min(distanceToGroundSouth, Mathf.Min(distanceToGroundWest, distanceToGroundEast)))); reflectionPlaneGround.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceToGround, 0.0f); //new Vector3(0.0f, GameManager.Instance.PlayerController.height * 0.5f, 0.0f); float distanceLevelBelow = getDistanceToLowerLevel(goPlayerAdvanced); //Debug.Log(string.Format("distance to lower level: {0}", distanceLevelBelow)); reflectionPlaneLowerLevel.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceLevelBelow, 0.0f); } else if (GameManager.Instance.IsPlayerInsideDungeon || GameManager.Instance.IsPlayerInsideCastle) { RaycastHit hit; float distanceToGround = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position, -Vector3.up, out hit, 100.0F)) { distanceToGround = hit.distance; } reflectionPlaneGround.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceToGround, 0.0f); //new Vector3(0.0f, GameManager.Instance.PlayerController.height * 0.5f, 0.0f); //Debug.Log(string.Format("distance to lower level: {0}", distanceLevelBelow)); Vector3 pos = goPlayerAdvanced.transform.position; reflectionPlaneLowerLevel.transform.position = new Vector3(pos.x, GameManager.Instance.PlayerEnterExit.blockWaterLevel * -1 * MeshReader.GlobalScale, pos.z); //// prevent underwater reflections below water level //if (reflectionPlaneGround.transform.position.y < reflectionPlaneLowerLevel.transform.position.y) //{ // reflectionPlaneGround.transform.position = reflectionPlaneLowerLevel.transform.position; //} } else //if (!GameManager.Instance.IsPlayerInside) { Terrain terrainInstancePlayerTerrain = null; int referenceLocationX = playerGPS.CurrentMapPixel.X; int referenceLocationY = playerGPS.CurrentMapPixel.Y; ContentReader.MapSummary mapSummary; // if there is no location at current player position... if (!DaggerfallUnity.Instance.ContentReader.HasLocation(referenceLocationX, referenceLocationY, out mapSummary)) { // search for largest location in local 8-neighborhood and take this as reference location for location reflection plane int maxLocationArea = -1; for (int y = -1; y <= +1; y++) { for (int x = -1; x <= +1; x++) { if (DaggerfallUnity.Instance.ContentReader.HasLocation(playerGPS.CurrentMapPixel.X + x, playerGPS.CurrentMapPixel.Y + y, out mapSummary)) { DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex); byte locationRangeX = location.Exterior.ExteriorData.Width; byte locationRangeY = location.Exterior.ExteriorData.Height; int locationArea = locationRangeX * locationRangeY; if (locationArea > maxLocationArea) { referenceLocationX = playerGPS.CurrentMapPixel.X + x; referenceLocationY = playerGPS.CurrentMapPixel.Y + y; maxLocationArea = locationArea; } } } } } GameObject go = GameObject.Find("StreamingTarget"); if (go == null) { return; } foreach (Transform child in go.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } if ((dfTerrain.MapPixelX != referenceLocationX) || (dfTerrain.MapPixelY != referenceLocationY)) { continue; } Terrain terrainInstance = child.GetComponent <Terrain>(); terrainInstancePlayerTerrain = terrainInstance; if ((terrainInstance) && (terrainInstance.terrainData)) { float scale = terrainInstance.terrainData.heightmapScale.x; float xSamplePos = DaggerfallUnity.Instance.TerrainSampler.HeightmapDimension * 0.55f; float ySamplePos = DaggerfallUnity.Instance.TerrainSampler.HeightmapDimension * 0.55f; Vector3 pos = new Vector3(xSamplePos * scale, 0, ySamplePos * scale); float height = terrainInstance.SampleHeight(pos + terrainInstance.transform.position); float positionY = height + terrainInstance.transform.position.y; reflectionPlaneGround.transform.position = new Vector3(goPlayerAdvanced.transform.position.x + terrainInstance.transform.position.x, positionY, goPlayerAdvanced.transform.position.z + terrainInstance.transform.position.z); } } if (!terrainInstancePlayerTerrain) { return; } //Debug.Log(string.Format("playerGPS: {0}, plane: {1}", goPlayerAdvanced.transform.position.y, reflectionPlaneGround.transform.position.y)); if (playerGPS.transform.position.y < reflectionPlaneGround.transform.position.y) { RaycastHit hit; float distanceToGround = 0; if (Physics.Raycast(goPlayerAdvanced.transform.position, -Vector3.up, out hit, 100.0F)) { distanceToGround = hit.distance; } //Debug.Log(string.Format("distance to ground: {0}", distanceToGround)); reflectionPlaneGround.transform.position = goPlayerAdvanced.transform.position - new Vector3(0.0f, distanceToGround, 0.0f); } StreamingWorld streamingWorld = GameObject.Find("StreamingWorld").GetComponent <StreamingWorld>(); Vector3 vecWaterHeight = new Vector3(0.0f, (DaggerfallUnity.Instance.TerrainSampler.OceanElevation + 0.0f) * streamingWorld.TerrainScale, 0.0f); // water height level on y-axis (+1.0f some coastlines are incorrect otherwise) Vector3 vecWaterHeightTransformed = terrainInstancePlayerTerrain.transform.TransformPoint(vecWaterHeight); // transform to world coordinates //Debug.Log(string.Format("x,y,z: {0}, {1}, {2}", vecWaterHeight.x, vecWaterHeight.y, vecWaterHeight.z)); //Debug.Log(string.Format("transformed x,y,z: {0}, {1}, {2}", vecWaterHeightTransformed.x, vecWaterHeightTransformed.y, vecWaterHeightTransformed.z)); reflectionPlaneLowerLevel.transform.position = new Vector3(goPlayerAdvanced.transform.position.x, vecWaterHeightTransformed.y, goPlayerAdvanced.transform.position.z); } if (GameManager.Instance.IsPlayerInsideBuilding && playerEnvironment != PlayerEnvironment.Building) { UpdateBackgroundSettingsIndoor(); } else if ((GameManager.Instance.IsPlayerInsideCastle || GameManager.Instance.IsPlayerInsideDungeon) && playerEnvironment != PlayerEnvironment.DungeonOrCastle) { UpdateBackgroundSettingsIndoor(); } else if (!GameManager.Instance.IsPlayerInside && playerEnvironment != PlayerEnvironment.Outdoors) { UpdateBackgroundSettingsOutdoor(); } }
void AddLocation(DaggerfallTerrain daggerTerrain, TerrainData terrainData) { //Destroy old locations by going through all the child objects, but //don't delete the billboard batch (The surrounding vegettion) foreach (Transform child in daggerTerrain.gameObject.transform) { if (!child.GetComponent <DaggerfallBillboardBatch>()) { Destroy(child.gameObject); } } foreach (LocationInstance loc in locationInstance) { if (daggerTerrain.MapPixelX != loc.worldX || daggerTerrain.MapPixelY != loc.worldY) { continue; } if (loc.terrainX <= 0 || loc.terrainY <= 0 || (loc.terrainX > 128 || loc.terrainY > 128)) { Debug.LogWarning("Invalid Location at " + daggerTerrain.MapPixelX + " : " + daggerTerrain.MapPixelY + " : The location pixelX + or/and pixelY must be higher than 0 and lower than 128"); continue; } //Now that we ensured that it is a valid location, then load the locationpreset LocationPrefab locationPrefab = LocationHelper.LoadLocationPrefab(Application.dataPath + LocationHelper.locationPrefabFolder + loc.prefab + ".txt"); if (locationPrefab == null) { Debug.LogWarning("Can't find location Preset: " + loc.prefab); continue; } if ((loc.terrainX + locationPrefab.height > 128 || loc.terrainY + locationPrefab.width > 128)) { Debug.LogWarning("Invalid Location at " + daggerTerrain.MapPixelX + " : " + daggerTerrain.MapPixelY + " : The locationpreset exist outside the terrain"); continue; } if ((loc.terrainX + locationPrefab.height > 127 || loc.terrainY + locationPrefab.width > 127)) { Debug.LogWarning("Invalid Location at " + daggerTerrain.MapPixelX + " : " + daggerTerrain.MapPixelY + " : The locationpreset must be 1 pixel away (both X and Y) from the terrainBorder"); continue; } //Smooth the terrain if (loc.type == 0) { daggerTerrain.MapData.hasLocation = true; //daggerTerrain.MapData.locationName = loc.name; daggerTerrain.MapData.locationRect = new Rect(loc.terrainX, loc.terrainY, locationPrefab.width, locationPrefab.height); int count = 0; float tmpAverageHeight = 0; for (int x = loc.terrainX; x <= loc.terrainX + locationPrefab.width; x++) { for (int y = loc.terrainY; y <= loc.terrainY + locationPrefab.height; y++) { tmpAverageHeight += daggerTerrain.MapData.heightmapSamples[y, x]; count++; } } daggerTerrain.MapData.averageHeight = tmpAverageHeight /= count; //TerrainHelper.BlendLocationTerrain(ref daggerTerrain.MapData); //orginal alternative for (int x = 1; x <= 127; x++) { for (int y = 1; y <= 127; y++) { daggerTerrain.MapData.heightmapSamples[y, x] = Mathf.Lerp(daggerTerrain.MapData.heightmapSamples[y, x], daggerTerrain.MapData.averageHeight, 1 / (GetDistanceFromRect(daggerTerrain.MapData.locationRect, new Vector2(x, y)) + 1)); } } terrainData.SetHeights(0, 0, daggerTerrain.MapData.heightmapSamples); } foreach (LocationPrefab.LocationObject obj in locationPrefab.obj) { if (!LocationHelper.ValidateValue(obj.type, obj.name)) { continue; } GameObject go = LocationHelper.LoadObject(obj.type, obj.name, daggerTerrain.gameObject.transform, new Vector3((loc.terrainX * TERRAIN_SIZE_MULTI) + obj.pos.x, (daggerTerrain.MapData.averageHeight * TERRAIN_HEIGHT_MAX) + obj.pos.y, (loc.terrainY * TERRAIN_SIZE_MULTI) + obj.pos.z), obj.rot, new Vector3(obj.scale.x, obj.scale.y, obj.scale.z), loc.locationID, obj.objectID ); if (go.GetComponent <DaggerfallBillboard>()) { float tempY = go.transform.position.y; go.GetComponent <DaggerfallBillboard>().AlignToBase(); go.transform.position = new Vector3(go.transform.position.x, tempY + ((go.transform.position.y - tempY) * go.transform.localScale.y), go.transform.position.z); } if (!go.GetComponent <DaggerfallLoot>()) { go.isStatic = true; } } continue; } }
public void OnWillRenderObject() { if (reflectionTexturesScript.isOutdoorEnvironment()) { if (!gameObjectStreamingTarget) { return; } foreach (Transform child in gameObjectStreamingTarget.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } Terrain terrain = child.GetComponent <Terrain>(); if (terrain) { if (terrain.materialTemplate) { if (terrain.materialTemplate.shader.name == "Daggerfall/TilemapWithReflections") { terrain.materialTemplate.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneGroundLevel.transform.position.y); terrain.materialTemplate.SetFloat("_SeaLevelHeight", gameObjectReflectionPlaneSeaLevel.transform.position.y); } } } } } if (reflectionTexturesScript.isIndoorEnvironment()) { Renderer[] renderers = null; // TODO: find a way to eliminate GameObject.Find() here and determine if inside building or dungeon GameObject gameObjectInterior = GameObject.Find("Interior"); GameObject gameObjectDungeon = GameObject.Find("Dungeon"); if (gameObjectInterior != null) { renderers = gameObjectInterior.GetComponentsInChildren <Renderer>(); } else if (gameObjectDungeon != null) { renderers = gameObjectDungeon.GetComponentsInChildren <Renderer>(); } if (renderers != null) { foreach (Renderer r in renderers) { foreach (Material m in r.sharedMaterials) { if (m.shader.name == "Daggerfall/FloorMaterialWithReflections") { m.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneGroundLevel.transform.position.y); m.SetFloat("_LowerLevelHeight", gameObjectReflectionPlaneLowerLevel.transform.position.y); } } } } } }
/// <summary> /// Add Grass and other details on terrain. /// </summary> private void AddTerrainDetails(DaggerfallTerrain daggerTerrain, TerrainData terrainData) { #if TEST_PERFORMANCE var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); #endif UnityEngine.Random.InitState(TerrainHelper.MakeTerrainKey(daggerTerrain.MapPixelX, daggerTerrain.MapPixelY)); // Terrain settings terrainData.SetDetailResolution(256, 8); terrainData.wavingGrassTint = Color.gray; Terrain terrain = daggerTerrain.gameObject.GetComponent <Terrain>(); terrain.detailObjectDistance = options.DetailObjectDistance; terrain.detailObjectDensity = options.DetailObjectDensity; // Get the current season and climate var currentSeason = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue; ClimateBases climate = GetClimate(daggerTerrain.MapData.worldClimate); // Update detail layers Color32[] tilemap = daggerTerrain.TileMap; densityManager.InitDetailsLayers(); switch (climate) { case ClimateBases.Temperate: case ClimateBases.Mountain: case ClimateBases.Swamp: if (currentSeason != DaggerfallDateTime.Seasons.Winter) { detailPrototypesManager.UpdateClimateSummer(climate); densityManager.SetDensitySummer(terrain, tilemap, climate); } else { detailPrototypesManager.UpdateClimateWinter(climate); densityManager.SetDensityWinter(terrain, tilemap, climate); } break; case ClimateBases.Desert: detailPrototypesManager.UpdateClimateDesert(); densityManager.SetDensityDesert(tilemap); break; } // Assign detail prototypes to the terrain terrainData.detailPrototypes = detailPrototypesManager.DetailPrototypes; // Assign detail layers to the terrain terrainData.SetDetailLayer(0, 0, detailPrototypesManager.Grass, densityManager.Grass); if ((options.GrassStyle & GrassStyle.Mixed) == GrassStyle.Mixed && climate != ClimateBases.Desert) { terrainData.SetDetailLayer(0, 0, detailPrototypesManager.GrassDetails, densityManager.GrassDetails); terrainData.SetDetailLayer(0, 0, detailPrototypesManager.GrassAccents, densityManager.GrassAccents); } if (options.WaterPlants) { terrainData.SetDetailLayer(0, 0, detailPrototypesManager.WaterPlants, densityManager.WaterPlants); } if (options.TerrainStones) { terrainData.SetDetailLayer(0, 0, detailPrototypesManager.Rocks, densityManager.Rocks); } #if TEST_PERFORMANCE stopwatch.Stop(); Debug.LogFormat("RealGrass - Time elapsed: {0} ms.", stopwatch.Elapsed.Milliseconds); #endif }
public void OnWillRenderObject() { if (!GameManager.Instance.IsPlayerInside) { if (!gameObjectStreamingTarget) { return; } foreach (Transform child in gameObjectStreamingTarget.transform) { DaggerfallTerrain dfTerrain = child.GetComponent <DaggerfallTerrain>(); if (!dfTerrain) { continue; } Terrain terrain = child.GetComponent <Terrain>(); if (terrain) { if (terrain.materialTemplate) { if (terrain.materialTemplate.shader.name == "Daggerfall/TilemapWithReflections") { terrain.materialTemplate.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneGroundLevel.transform.position.y); terrain.materialTemplate.SetFloat("_SeaLevelHeight", gameObjectReflectionPlaneSeaLevel.transform.position.y); } } } } } else if (GameManager.Instance.IsPlayerInside) { Renderer[] renderers = null; // renderers must be aquired here and not in Update() because it seems that this function's execution can happen in parallel to Update() - so a concurrent conflict can occur (and does) if (gameObjectInterior != null) { renderers = gameObjectInterior.GetComponentsInChildren <Renderer>(); } else if (gameObjectDungeon != null) { renderers = gameObjectDungeon.GetComponentsInChildren <Renderer>(); } //Debug.Log(String.Format("renderers: {0}", renderers.Length)); if (renderers != null) { foreach (Renderer r in renderers) { Material[] mats = r.sharedMaterials; foreach (Material m in mats) { if (m.shader.name == "Daggerfall/FloorMaterialWithReflections") { m.SetFloat("_GroundLevelHeight", gameObjectReflectionPlaneGroundLevel.transform.position.y); m.SetFloat("_LowerLevelHeight", gameObjectReflectionPlaneLowerLevel.transform.position.y); } } r.sharedMaterials = mats; } } } }
private void DaggerfallTerrain_OnPromoteTerrainData(DaggerfallTerrain sender, TerrainData terrainData) { AddTerrainDetails(sender, terrainData); }
//overloaded variant void InjectMaterialProperties(DaggerfallTerrain sender) { InjectMaterialProperties(-1, -1); }
// Add Grass private void AddGrass(DaggerfallTerrain daggerTerrain, TerrainData terrainData) { // Used to check performance // Stopwatch stopwatch = new Stopwatch(); // stopwatch.Start(); details = new int[256, 256]; //Get the current season currentSeason = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue; //Proceed if it's NOT winter, and if the worldClimate contains grass, which is everything above 225, with the exception of 229 if (currentSeason != DaggerfallDateTime.Seasons.Winter && (daggerTerrain.MapData.worldClimate > 225 && daggerTerrain.MapData.worldClimate != 229)) { //Switch the grass texture based on the climate if (daggerTerrain.MapData.worldClimate == 226 || daggerTerrain.MapData.worldClimate == 227 || daggerTerrain.MapData.worldClimate == 228 || daggerTerrain.MapData.worldClimate == 230) { detailPrototype[0].prototypeTexture = brownGrass; } else { detailPrototype[0].prototypeTexture = greenGrass; } tilemap = daggerTerrain.TileMap; terrainData.detailPrototypes = detailPrototype; terrainData.wavingGrassTint = Color.gray; terrainData.SetDetailResolution(256, 8); int colorValue; //Check all the tiles, Daggerfall uses the red color value to draw tiles for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { colorValue = tilemap[(i * 128) + j].r; //For easier checking switch (colorValue) { //Four corner tiles case 8: case 9: case 10: case 11: details[i * 2, j * 2] = Random.Range(thickLower, thickHigher); details[i * 2, (j * 2) + 1] = Random.Range(thickLower, thickHigher); details[(i * 2) + 1, j * 2] = Random.Range(thickLower, thickHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thickLower, thickHigher); break; //Upper left corner case 40: case 224: case 164: case 176: case 181: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //Lower left corner case 41: case 221: case 165: case 177: case 182: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //Lower right corner case 42: case 222: case 166: case 178: case 183: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Upper right corner case 43: case 223: case 167: case 179: case 180: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Left side case 44: case 66: case 84: case 160: case 168: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //lower side case 45: case 67: case 85: case 161: case 169: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); break; //right side case 46: case 64: case 86: case 162: case 170: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //upper side case 47: case 65: case 87: case 163: case 171: details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //All expect lower right case 48: case 62: case 88: case 156: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //All expect upper right case 49: case 63: case 89: case 157: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); break; //All expect upper left case 50: case 60: case 90: case 158: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //All expect lower left case 51: case 61: case 91: case 159: details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Left to right case 204: case 206: case 214: details[i * 2, j * 2] = Random.Range(thinLower, thinHigher); details[(i * 2) + 1, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; //Right to left case 205: case 207: case 213: details[(i * 2) + 1, j * 2] = Random.Range(thinLower, thinHigher); details[i * 2, (j * 2) + 1] = Random.Range(thinLower, thinHigher); break; } } } } terrainData.SetDetailLayer(0, 0, 0, details); // stopwatch.Stop(); // // Write result // UnityEngine.Debug.Log("Time elapsed: " + // stopwatch.Elapsed); }