/// <summary> /// Gets the vegetation voxel based on position, biome and a random value /// </summary> /// <returns>The vegetation.</returns> /// <param name="biome">Biome.</param> /// <param name="random">Random.</param> public VoxelDefinition GetVegetation (BiomeDefinition biome, float random) { float acumProb = 0; int index = 0; for (int t = 0; t < biome.vegetation.Length; t++) { acumProb += biome.vegetation [t].probability; if (random < acumProb) { index = t; break; } } return biome.vegetation [index].vegetation; }
void ToggleBiomes(bool visible) { for (int k = 0; k < world.biomes.Length; k++) { BiomeDefinition biome = world.biomes [k]; if (biome == null) { continue; } biome.showInBiomeMap = visible; } }
void CalcBiome() { BiomeDefinition biome = env.GetBiome(inputAltitude, inputMoisture); if (biome == null) { biomeTestResult = "No matching biome."; } else { biomeTestResult = "Matching biome: " + biome.name + "."; } }
void InitBiomes() { biomeLookUp = new BiomeDefinition[441]; // 21 * 21 if (world == null) { return; } if (world.biomes == null) { return; } for (int b = 0; b < world.biomes.Length; b++) { BiomeDefinition biome = world.biomes [b]; if (biome == null || biome.zones == null) { continue; } for (int z = 0; z < biome.zones.Length; z++) { BiomeZone zone = biome.zones [z]; for (int elevation = 0; elevation <= 20; elevation++) { float e = elevation / 20f; for (int moisture = 0; moisture <= 20; moisture++) { float m = moisture / 20f; if (e >= zone.elevationMin && e <= zone.elevationMax && m >= zone.moistureMin && m <= zone.moistureMax) { biomeLookUp [elevation * 21 + moisture] = biome; } } } } if (biome.ores == null) { biome.ores = new BiomeOre[0]; } } SetBiomeDefaultColors(false); }
void DrawLegend(Color color, string text, BiomeDefinition biome) { Rect space = EditorGUILayout.BeginHorizontal(); space.position += new Vector2(5, 0); space.width = 16; space.height = 16; Color prevColor = GUI.color; GUI.color = color; EditorGUI.DrawPreviewTexture(space, Texture2D.whiteTexture); space.position += new Vector2(20, 0); space.width = 20; if (biome != null) { GUI.color = biome.showInBiomeMap ? prevColor : new Color(prevColor.r, prevColor.g, prevColor.b, 0.4f); } else { GUI.color = prevColor; } space.width = 20; if (biome != null) { biome.showInBiomeMap = EditorGUI.Toggle(space, biome.showInBiomeMap); space.width = 35; space.position += new Vector2(20, 0); if (GUI.Button(space, "->")) { Selection.activeObject = biome; } space.position += new Vector2(35, 0); } space.width = 120; EditorGUI.LabelField(space, text); GUI.color = prevColor; EditorGUILayout.BeginVertical(); GUILayout.Space(20); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); }
/// <summary> /// Assigns a color to each biome. /// </summary> public void SetBiomeDefaultColors(bool force) { if (world != null) { if (world.biomes != null) { for (int b = 0; b < world.biomes.Length; b++) { BiomeDefinition biome = world.biomes [b]; if (biome == null || biome.zones == null) { continue; } if (force || biome.biomeMapColor.a == 0) { long color = distinctColors [b % distinctColors.Length]; Color32 biomeColor = new Color32((byte)(color >> 16), (byte)((color >> 8) & 255), (byte)(color & 255), 255); biome.biomeMapColor = biomeColor; } } } } }
/// <summary> /// Paints the terrain inside the chunk defined by its central "position" /// </summary> /// <returns><c>true</c>, if terrain was painted, <c>false</c> otherwise.</returns> /// <param name="position">Central position of the chunk.</param> public override bool PaintChunk(VoxelChunk chunk) { Vector3 position = chunk.position; if (position.y + 8 < minHeight) { chunk.isAboveSurface = false; return(false); } int bedrockRow = -1; if ((object)bedrockVoxel != null && position.y < minHeight + 8) { bedrockRow = (int)(minHeight - (position.y - 8) + 1) * ONE_Y_ROW; } position.x -= 8; position.y -= 8; position.z -= 8; Vector3 pos; int waterLevel = env.waterLevel > 0 ? env.waterLevel : -1; Voxel[] voxels = chunk.voxels; bool hasContent = false; bool isAboveSurface = false; generation++; env.GetHeightMapInfoFast(position.x, position.z, heightChunkData); // iterate 256 slice of chunk (z/x plane = 16*16 positions) for (int arrayIndex = 0; arrayIndex < 256; arrayIndex++) { float groundLevel = heightChunkData [arrayIndex].groundLevel; float surfaceLevel = waterLevel > groundLevel ? waterLevel : groundLevel; if (surfaceLevel < position.y) { // position is above terrain or water isAboveSurface = true; continue; } BiomeDefinition biome = heightChunkData [arrayIndex].biome; if ((object)biome == null) { biome = world.defaultBiome; if ((object)biome == null) { continue; } } int y = (int)(surfaceLevel - position.y); if (y > 15) { y = 15; } pos.y = position.y + y; pos.x = position.x + (arrayIndex & 0xF); pos.z = position.z + (arrayIndex >> 4); // Place voxels int voxelIndex = y * ONE_Y_ROW + arrayIndex; if (pos.y > groundLevel) { // water above terrain if (pos.y == surfaceLevel) { isAboveSurface = true; } while (pos.y > groundLevel && voxelIndex >= 0) { voxels [voxelIndex].Set(waterVoxel); voxelIndex -= ONE_Y_ROW; pos.y--; } } else if (pos.y == groundLevel) { isAboveSurface = true; if (voxels [voxelIndex].hasContent == 0) { if (paintShore && pos.y == waterLevel) { // this is on the shore, place a shoreVoxel voxels [voxelIndex].Set(shoreVoxel); } else { // we're at the surface of the biome => draw the voxel top of the biome and also check for random vegetation and trees voxels [voxelIndex].Set(biome.voxelTop); #if UNITY_EDITOR if (!env.draftModeActive) { #endif // Check tree probability if (pos.y > waterLevel) { float rn = WorldRand.GetValue(pos); if (env.enableTrees && biome.treeDensity > 0 && rn < biome.treeDensity && biome.trees.Length > 0) { // request one tree at this position env.RequestTreeCreation(chunk, pos, env.GetTree(biome.trees, rn / biome.treeDensity)); } else if (env.enableVegetation && biome.vegetationDensity > 0 && rn < biome.vegetationDensity && biome.vegetation.Length > 0) { if (voxelIndex >= 15 * ONE_Y_ROW) { // request one vegetation voxel one position above which means the chunk above this one env.RequestVegetationCreation(chunk.top, voxelIndex - ONE_Y_ROW * 15, env.GetVegetation(biome, rn / biome.vegetationDensity)); } else { // directly place a vegetation voxel above this voxel voxels [voxelIndex + ONE_Y_ROW].Set(env.GetVegetation(biome, rn / biome.vegetationDensity)); env.vegetationCreated++; } } } #if UNITY_EDITOR } #endif } } voxelIndex -= ONE_Y_ROW; } // Continue filling down biome.biomeGeneration = generation; while (voxelIndex > bedrockRow) { if (voxels [voxelIndex].hasContent == 0) { voxels [voxelIndex].SetFastOpaque(biome.voxelDirt); } voxelIndex -= ONE_Y_ROW; } if (bedrockRow >= 0) { voxels [voxelIndex].SetFastOpaque(bedrockVoxel); } hasContent = true; } // Spawn random ore if (addOre) { // Check if there's any ore in this chunk (randomly) float noiseValue = WorldRand.GetValue(chunk.position); for (int b = 0; b < world.biomes.Length; b++) { BiomeDefinition biome = world.biomes [b]; if (biome.biomeGeneration != generation) { continue; } for (int o = 0; o < biome.ores.Length; o++) { if (biome.ores [o].ore == null) { continue; } if (biome.ores [o].probabilityMin <= noiseValue && biome.ores [o].probabilityMax >= noiseValue) { // ore picked; determine the number of veins in this chunk int veinsCount = biome.ores [o].veinsCountMin + (int)(WorldRand.GetValue() * (biome.ores [o].veinsCountMax - biome.ores [o].veinsCountMin + 1f)); for (int vein = 0; vein < veinsCount; vein++) { Vector3 veinPos = chunk.position; veinPos.x += vein; // Determine random vein position in the chunk Vector3 v = WorldRand.GetVector3(veinPos, 16); int px = (int)v.x; int py = (int)v.y; int pz = (int)v.z; veinPos = env.GetVoxelPosition(veinPos, px, py, pz); int oreIndex = py * ONE_Y_ROW + pz * ONE_Z_ROW + px; int veinSize = biome.ores [o].veinMinSize + (oreIndex % (biome.ores [o].veinMaxSize - biome.ores [o].veinMinSize + 1)); // span ore vein SpawnOre(chunk, biome.ores [o].ore, veinPos, px, py, pz, veinSize, biome.ores [o].depthMin, biome.ores [o].depthMax); } break; } } } } // Finish, return chunk.isAboveSurface = isAboveSurface; return(hasContent); }
void RefreshBiomeTexture() { if (biomeTex == null || biomeTex.width != mapResolution) { biomeTex = new Texture2D(mapResolution, mapResolution, TextureFormat.ARGB32, false); } int width = biomeTex.width; int height = biomeTex.height; Color[] colors = new Color[width * height]; if (env == null || tg == null) { colors.Fill <Color> (new Color(0, 0.5f, 0, 0.5f)); } else { env.SetBiomeDefaultColors(false); colors.Fill <Color> (Misc.colorTransparent); // reset biome stats for (int k = 0; k < world.biomes.Length; k++) { if (world.biomes [k] != null) { world.biomes [k].biomeMapOccurrences = 0; } } // draw biome colors for (int j = 0; j < height; j++) { float z = (maxZ - minZ) * (float)j / height + minZ; int jj = j * width; for (int k = 0; k < width; k++) { float x = (maxX - minX) * (float)k / width + minX; HeightMapInfo info = env.GetTerrainInfo(x, z); if (info.groundLevel <= tg.waterLevel) { colors [jj + k] = waterColor; } else { BiomeDefinition biome = info.biome; if (biome == null) { continue; } biome.biomeMapOccurrences++; if (biome.showInBiomeMap) { colors [jj + k] = biome.biomeMapColor; } } } } int gridCount = (int)((maxZ - minZ) / gridStep); Color gridColor = new Color(64, 64, 64, 0.2f); // draw horizontal grid lines for (int j = 0; j <= gridCount; j++) { int y = (int)((height - 1f) * j / gridCount); for (int k = 0; k < width; k++) { colors [y * width + k] = gridColor; } } gridCount = (int)((maxX - minX) / gridStep); // draw vertical grid lines for (int j = 0; j <= gridCount; j++) { int x = (int)((width - 1f) * j / gridCount); for (int k = 0; k < height; k++) { colors [k * width + x] = gridColor; } } } biomeTex.SetPixels(colors); biomeTex.Apply(); }
void OnGUI() { if (env == null) { env = VoxelPlayEnvironment.instance; if (env == null) { world = null; } EditorGUILayout.HelpBox("Biome Explorer cannot find a Voxel Play Environment instance in the current scene.", MessageType.Error); GUIUtility.ExitGUI(); } else { world = env.world; } if (world == null) { EditorGUILayout.HelpBox("Assign a World Definition to the Voxel Play Environment instance.", MessageType.Warning); GUIUtility.ExitGUI(); } if (terrainTex == null || moistureTex == null) { RefreshTextures(); GUIUtility.ExitGUI(); } GUIStyle labelStyle = new GUIStyle(GUI.skin.label); if (titleLabelStyle == null) { titleLabelStyle = new GUIStyle(EditorStyles.label); } titleLabelStyle.normal.textColor = titleColor; titleLabelStyle.fontStyle = FontStyle.Bold; EditorGUILayout.BeginHorizontal(); EditorGUILayout.HelpBox("Preview terrain generation and biome distribution based on current settings.", MessageType.Info); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Min X", GUILayout.Width(100)); proposedMinX = EditorGUILayout.FloatField(proposedMinX, GUILayout.MaxWidth(120)); EditorGUILayout.LabelField("Max X", GUILayout.Width(100)); proposedMaxX = EditorGUILayout.FloatField(proposedMaxX, GUILayout.MaxWidth(120)); if (GUILayout.Button("<<", GUILayout.Width(40))) { float shift = (maxX - minX) * 0.5f; proposedMinX -= shift; proposedMaxX -= shift; requestRefresh = true; } if (GUILayout.Button("<", GUILayout.Width(40))) { float shift = (maxX - minX) * 0.1f; proposedMinX -= shift; proposedMaxX -= shift; requestRefresh = true; } if (GUILayout.Button(">", GUILayout.Width(40))) { float shift = (maxX - minX) * 0.1f; proposedMinX += shift; proposedMaxX += shift; requestRefresh = true; } if (GUILayout.Button(">>", GUILayout.Width(40))) { float shift = (maxX - minX) * 0.5f; proposedMinX += shift; proposedMaxX += shift; requestRefresh = true; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Min Z", GUILayout.Width(100)); proposedMinZ = EditorGUILayout.FloatField(proposedMinZ, GUILayout.MaxWidth(120)); EditorGUILayout.LabelField("Max Z", GUILayout.Width(100)); proposedMaxZ = EditorGUILayout.FloatField(proposedMaxZ, GUILayout.MaxWidth(120)); if (GUILayout.Button("<<", GUILayout.Width(40))) { float shift = (maxZ - minZ) * 0.5f; proposedMinZ -= shift; proposedMaxZ -= shift; proposedSliceZ = (proposedMinZ + proposedMaxZ) * 0.5f; requestRefresh = true; } if (GUILayout.Button("<", GUILayout.Width(40))) { float shift = (maxZ - minZ) * 0.1f; proposedMinZ -= shift; proposedMaxZ -= shift; proposedSliceZ = (proposedMinZ + proposedMaxZ) * 0.5f; requestRefresh = true; } if (GUILayout.Button(">", GUILayout.Width(40))) { float shift = (maxZ - minZ) * 0.1f; proposedMinZ += shift; proposedMaxZ += shift; proposedSliceZ = (proposedMinZ + proposedMaxZ) * 0.5f; requestRefresh = true; } if (GUILayout.Button(">>", GUILayout.Width(40))) { float shift = (maxZ - minZ) * 0.5f; proposedMinZ += shift; proposedMaxZ += shift; proposedSliceZ = (proposedMinZ + proposedMaxZ) * 0.5f; requestRefresh = true; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Slice Z", GUILayout.Width(100)); proposedSliceZ = EditorGUILayout.FloatField(proposedSliceZ, GUILayout.MaxWidth(120)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(new GUIContent("Refresh Window", "Refresh textures to reflect new filters."), GUILayout.Width(140))) { requestRefresh = true; } if (GUILayout.Button(new GUIContent("-> World Definition", "Show World Definition in the inspector."), GUILayout.Width(140))) { Selection.activeObject = world; } if (GUILayout.Button(new GUIContent("-> Terrain Generator", "Show Terrain Generator in the inspector."), GUILayout.Width(140))) { Selection.activeObject = tg; } if (GUILayout.Button(new GUIContent("-> Environment", "Show Voxel Play Environment in the inspector."), GUILayout.Width(140))) { Selection.activeGameObject = env.gameObject; } if (GUILayout.Button(new GUIContent("Reload Config", "Resets heightmaps and biome cache and initializes terrain generator."), GUILayout.Width(140))) { env.NotifyTerrainGeneratorConfigurationChanged(); requestRefresh = true; GUIUtility.ExitGUI(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); Rect space; if (previewTextureMat == null) { previewTextureMat = Resources.Load <Material> ("VoxelPlay/PreviewTexture"); } // Draw heightmap distribution if (terrainTex != null) { EditorGUILayout.LabelField(new GUIContent("Height Map Preview"), titleLabelStyle); space = EditorGUILayout.BeginVertical(); space.width -= 20; GUILayout.Space(terrainTex.height); EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(15); space.position += new Vector2(15, 0); EditorGUI.DrawPreviewTexture(space, terrainTex, previewTextureMat); GUILayout.Space(5); EditorGUILayout.EndHorizontal(); // Draw 0-1 range space.position -= new Vector2(15, 0); EditorGUI.LabelField(space, "1"); space.position += new Vector2(0, space.height - 10f); EditorGUI.LabelField(space, "0"); // Draw x-axis labels EditorGUILayout.BeginHorizontal(); GUILayout.Space(15); EditorGUILayout.LabelField("Min X = " + minX); labelStyle.alignment = TextAnchor.MiddleCenter; EditorGUILayout.LabelField("Slize Z = " + sliceZ + " / Min Y = " + calcMinAltitude.ToString("F3") + " / Max Y = " + calcMaxAltitude.ToString("F3"), labelStyle); labelStyle.alignment = TextAnchor.MiddleRight; EditorGUILayout.LabelField("Max X = " + maxX, labelStyle); EditorGUILayout.EndHorizontal(); } EditorGUILayout.Separator(); EditorGUILayout.Separator(); // Draw moisture distribution if (terrainTex != null) { EditorGUILayout.LabelField(new GUIContent("Moisture Preview"), titleLabelStyle); space = EditorGUILayout.BeginVertical(); space.width -= 20; GUILayout.Space(moistureTex.height); EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(15); space.position += new Vector2(15, 0); EditorGUI.DrawPreviewTexture(space, moistureTex, previewTextureMat); GUILayout.Space(5); EditorGUILayout.EndHorizontal(); // Draw 0-1 range space.position -= new Vector2(15, 0); EditorGUI.LabelField(space, "1"); space.position += new Vector2(0, space.height - 10f); EditorGUI.LabelField(space, "0"); // Draw x-axis labels EditorGUILayout.BeginHorizontal(); GUILayout.Space(15); EditorGUILayout.LabelField("Min X = " + minX); labelStyle.alignment = TextAnchor.MiddleCenter; EditorGUILayout.LabelField("Slize Z = " + sliceZ + " / Min Y = " + calcMinMoisture.ToString("F3") + " / Max Y = " + calcMaxMoisture.ToString("F3"), labelStyle); labelStyle.alignment = TextAnchor.MiddleRight; EditorGUILayout.LabelField("Max X = " + maxX, labelStyle); EditorGUILayout.EndHorizontal(); } EditorGUILayout.Separator(); EditorGUILayout.Separator(); if (world.biomes != null && biomeTex != null) { // Draw heightmap texture EditorGUILayout.LabelField(new GUIContent("Biome Map Preview"), titleLabelStyle); EditorGUILayout.BeginHorizontal(); // Biome legend EditorGUILayout.BeginVertical(GUILayout.MaxWidth(180)); EditorGUILayout.Separator(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Hide All", GUILayout.Width(80))) { ToggleBiomes(false); requestRefresh = true; } if (GUILayout.Button("Show All", GUILayout.Width(80))) { ToggleBiomes(true); requestRefresh = true; } if (GUILayout.Button("Default Colors", GUILayout.Width(120))) { env.SetBiomeDefaultColors(true); requestRefresh = true; } EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); for (int k = 0; k < world.biomes.Length; k++) { BiomeDefinition biome = world.biomes [k]; if (biome == null) { continue; } float perc = 100f * (float)biome.biomeMapOccurrences / (biomeTex.width * biomeTex.height); DrawLegend(biome.biomeMapColor, biome.name + " (" + perc.ToString("F2") + "%)", biome); } DrawLegend(waterColor, "Water", null); if (EditorGUI.EndChangeCheck()) { requestRefresh = true; } EditorGUILayout.Separator(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Grid Size", GUILayout.Width(100)); gridStep = EditorGUILayout.IntField(gridStep, GUILayout.Width(60)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Texture Size", GUILayout.Width(100)); mapResolution = EditorGUILayout.IntField(mapResolution, GUILayout.Width(60)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); EditorGUILayout.Separator(); // Tester EditorGUILayout.LabelField(new GUIContent("Biome Tester"), titleLabelStyle); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Altitude?", GUILayout.Width(100)); inputAltitude = EditorGUILayout.Slider(inputAltitude, 0, 1, GUILayout.Width(130)); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Moisture?", GUILayout.Width(100)); inputMoisture = EditorGUILayout.Slider(inputMoisture, 0, 1, GUILayout.Width(130)); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { CalcBiome(); } EditorGUILayout.LabelField(biomeTestResult); EditorGUILayout.EndVertical(); // Biome map space = EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUI.DrawPreviewTexture(space, biomeTex, previewTextureMat, ScaleMode.ScaleToFit); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); } if (requestRefresh) { RefreshTextures(); } }
void LoadWorldTextures() { requireTextureArrayUpdate = false; // Init texture array if (worldTextures == null) { worldTextures = new List <WorldTexture> (); } else { worldTextures.Clear(); } if (worldTexturesDict == null) { worldTexturesDict = new Dictionary <Texture2D, int> (); } else { worldTexturesDict.Clear(); } // Clear definitions if (voxelDefinitions != null) { // Voxel Definitions no longer are added to the dictionary, clear the index field. for (int k = 0; k < voxelDefinitionsCount; k++) { if (voxelDefinitions [k] != null) { voxelDefinitions [k].Reset(); } } } else { voxelDefinitions = new VoxelDefinition[128]; } voxelDefinitionsCount = 0; if (voxelDefinitionsDict == null) { voxelDefinitionsDict = new Dictionary <string, VoxelDefinition> (); } else { voxelDefinitionsDict.Clear(); } if (sessionUserVoxels == null) { sessionUserVoxels = new List <VoxelDefinition> (); } // The null voxel definition VoxelDefinition nullVoxelDefinition = ScriptableObject.CreateInstance <VoxelDefinition> (); nullVoxelDefinition.hidden = true; nullVoxelDefinition.canBeCollected = false; nullVoxelDefinition.name = "Null"; AddVoxelTextures(nullVoxelDefinition); // Check default voxel if (defaultVoxel == null) { defaultVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/DefaultVoxel"); } AddVoxelTextures(defaultVoxel); // Add all biome textures if (world.biomes != null) { for (int k = 0; k < world.biomes.Length; k++) { BiomeDefinition biome = world.biomes [k]; if (biome == null) { continue; } AddVoxelTextures(biome.voxelTop); if (biome.voxelTop.biomeDirtCounterpart == null) { biome.voxelTop.biomeDirtCounterpart = biome.voxelDirt; } AddVoxelTextures(biome.voxelDirt); if (biome.vegetation != null) { for (int v = 0; v < biome.vegetation.Length; v++) { AddVoxelTextures(biome.vegetation [v].vegetation); } } if (biome.trees != null) { for (int t = 0; t < biome.trees.Length; t++) { ModelDefinition tree = biome.trees [t].tree; if (tree == null) { continue; } for (int b = 0; b < tree.bits.Length; b++) { AddVoxelTextures(tree.bits [b].voxelDefinition); } } } if (biome.ores != null) { for (int v = 0; v < biome.ores.Length; v++) { // ensure proper size if (biome.ores [v].veinMinSize == biome.ores [v].veinMaxSize && biome.ores [v].veinMaxSize == 0) { biome.ores [v].veinMinSize = 2; biome.ores [v].veinMaxSize = 6; biome.ores [v].veinsCountMin = 1; biome.ores [v].veinsCountMax = 2; } AddVoxelTextures(biome.ores [v].ore); } } } } // Special voxels if (world.cloudVoxel == null) { world.cloudVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/VoxelCloud"); } AddVoxelTextures(world.cloudVoxel); // Add additional world voxels if (world.moreVoxels != null) { for (int k = 0; k < world.moreVoxels.Length; k++) { AddVoxelTextures(world.moreVoxels [k]); } } // Add all items' textures are available if (world.items != null) { int itemCount = world.items.Length; for (int k = 0; k < itemCount; k++) { ItemDefinition item = world.items [k]; if (item.category == ItemCategory.Voxel) { AddVoxelTextures(item.voxelType); } } } // Add any other voxel found inside Defaults VoxelDefinition[] vdd = Resources.LoadAll <VoxelDefinition> ("VoxelPlay/Defaults"); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } // Add any other voxel found inside World directory vdd = Resources.LoadAll <VoxelDefinition> ("Worlds/" + world.name); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } // Add any other voxel found inside a resource directory with same name of world (if not placed into Worlds directory) vdd = Resources.LoadAll <VoxelDefinition> (world.name); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } // Add user provided voxels during playtime int count = sessionUserVoxels.Count; for (int k = 0; k < count; k++) { AddVoxelTextures(sessionUserVoxels [k]); } // Unload textures (doesn't work at runtime on PC! this commented section should be removed) // #if !UNITY_EDITOR // for (int k = 0; k < voxelDefinitionsCount; k++) { // VoxelDefinition vd = voxelDefinitions [k]; // if (vd.index == 0) // continue; // if (vd.textureTop != null) // Resources.UnloadAsset (vd.textureTop); // if (vd.textureTopEmission != null) // Resources.UnloadAsset (vd.textureTopEmission); // if (vd.textureTopNRM != null) // Resources.UnloadAsset (vd.textureTopNRM); // if (vd.textureTopDISP != null) // Resources.UnloadAsset (vd.textureTopDISP); // if (vd.textureLeft != null) // Resources.UnloadAsset (vd.textureLeft); // if (vd.textureLeftEmission != null) // Resources.UnloadAsset (vd.textureLeftEmission); // if (vd.textureLeftNRM != null) // Resources.UnloadAsset (vd.textureLeftNRM); // if (vd.textureLeftDISP != null) // Resources.UnloadAsset (vd.textureLeftDISP); // if (vd.textureRight != null) // Resources.UnloadAsset (vd.textureRight); // if (vd.textureRightEmission != null) // Resources.UnloadAsset (vd.textureRightEmission); // if (vd.textureRightNRM != null) // Resources.UnloadAsset (vd.textureRightNRM); // if (vd.textureRightDISP != null) // Resources.UnloadAsset (vd.textureRightDISP); // if (vd.textureBottom != null) // Resources.UnloadAsset (vd.textureBottom); // if (vd.textureBottomEmission != null) // Resources.UnloadAsset (vd.textureBottomEmission); // if (vd.textureBottomNRM != null) // Resources.UnloadAsset (vd.textureBottomNRM); // if (vd.textureBottomDISP != null) // Resources.UnloadAsset (vd.textureBottomDISP); // if (vd.textureSide != null) // Resources.UnloadAsset (vd.textureSide); // if (vd.textureSideEmission != null) // Resources.UnloadAsset (vd.textureSideEmission); // if (vd.textureSideNRM != null) // Resources.UnloadAsset (vd.textureSideNRM); // if (vd.textureSideDISP != null) // Resources.UnloadAsset (vd.textureSideDISP); // if (vd.textureForward != null) // Resources.UnloadAsset (vd.textureForward); // if (vd.textureForwardEmission != null) // Resources.UnloadAsset (vd.textureForwardEmission); // if (vd.textureForwardNRM != null) // Resources.UnloadAsset (vd.textureForwardNRM); // if (vd.textureForwardDISP != null) // Resources.UnloadAsset (vd.textureForwardDISP); // } // #endif // Create array texture int textureCount = worldTextures.Count; if (textureCount > 0) { Texture2DArray pointFilterTextureArray = new Texture2DArray(textureSize, textureSize, textureCount, TextureFormat.ARGB32, hqFiltering); if (enableReliefMapping || !enableSmoothLighting) { pointFilterTextureArray.wrapMode = TextureWrapMode.Repeat; } else { pointFilterTextureArray.wrapMode = TextureWrapMode.Clamp; } pointFilterTextureArray.filterMode = hqFiltering ? FilterMode.Bilinear : FilterMode.Point; pointFilterTextureArray.mipMapBias = -mipMapBias; for (int k = 0; k < textureCount; k++) { if (worldTextures [k].colorsAndEmission != null) { pointFilterTextureArray.SetPixels32(worldTextures [k].colorsAndEmission, k); } else if (worldTextures [k].normalsAndElevation != null) { pointFilterTextureArray.SetPixels32(worldTextures [k].normalsAndElevation, k); } } worldTextures.Clear(); pointFilterTextureArray.Apply(hqFiltering, true); // Assign textures to materials for (int k = 0; k < materials.Length; k++) { if (materials[k] != null && materials[k].HasProperty("_MainTex")) { materials[k].SetTexture("_MainTex", pointFilterTextureArray); } } if (modelHighlightMat == null) { modelHighlightMat = Instantiate <Material> (Resources.Load <Material> ("VoxelPlay/Materials/VP Highlight Model")) as Material; } modelHighlightMat.SetTexture("_MainTex", pointFilterTextureArray); } }
void LoadWorldTextures() { requireTextureArrayUpdate = false; // Init texture array if (worldTextures == null) { worldTextures = new List <WorldTexture> (); } else { worldTextures.Clear(); } if (worldTexturesDict == null) { worldTexturesDict = new Dictionary <Texture2D, int> (); } else { worldTexturesDict.Clear(); } // Clear definitions if (voxelDefinitions != null) { // Voxel Definitions no longer are added to the dictionary, clear the index field. for (int k = 0; k < voxelDefinitionsCount; k++) { if (voxelDefinitions [k] != null) { voxelDefinitions [k].Reset(); } } } else { voxelDefinitions = new VoxelDefinition [128]; } voxelDefinitionsCount = 0; if (voxelDefinitionsDict == null) { voxelDefinitionsDict = new Dictionary <string, VoxelDefinition> (); } else { voxelDefinitionsDict.Clear(); } if (sessionUserVoxels == null) { sessionUserVoxels = new List <VoxelDefinition> (); } // The null voxel definition VoxelDefinition nullVoxelDefinition = ScriptableObject.CreateInstance <VoxelDefinition> (); nullVoxelDefinition.name = "Null"; nullVoxelDefinition.hidden = true; nullVoxelDefinition.canBeCollected = false; nullVoxelDefinition.ignoresRayCast = true; nullVoxelDefinition.renderType = RenderType.Empty; AddVoxelTextures(nullVoxelDefinition); // Check default voxel if (defaultVoxel == null) { defaultVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/DefaultVoxel"); } AddVoxelTextures(defaultVoxel); // Add all biome textures if (world.biomes != null) { for (int k = 0; k < world.biomes.Length; k++) { BiomeDefinition biome = world.biomes [k]; if (biome == null) { continue; } if (biome.voxelTop != null) { AddVoxelTextures(biome.voxelTop); if (biome.voxelTop.biomeDirtCounterpart == null) { biome.voxelTop.biomeDirtCounterpart = biome.voxelDirt; } } AddVoxelTextures(biome.voxelDirt); if (biome.vegetation != null) { for (int v = 0; v < biome.vegetation.Length; v++) { AddVoxelTextures(biome.vegetation [v].vegetation); } } if (biome.trees != null) { for (int t = 0; t < biome.trees.Length; t++) { ModelDefinition tree = biome.trees [t].tree; if (tree == null) { continue; } for (int b = 0; b < tree.bits.Length; b++) { AddVoxelTextures(tree.bits [b].voxelDefinition); } } } if (biome.ores != null) { for (int v = 0; v < biome.ores.Length; v++) { // ensure proper size if (biome.ores [v].veinMinSize == biome.ores [v].veinMaxSize && biome.ores [v].veinMaxSize == 0) { biome.ores [v].veinMinSize = 2; biome.ores [v].veinMaxSize = 6; biome.ores [v].veinsCountMin = 1; biome.ores [v].veinsCountMax = 2; } AddVoxelTextures(biome.ores [v].ore); } } } } // Special voxels if (enableClouds) { if (world.cloudVoxel == null) { world.cloudVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/VoxelCloud"); } AddVoxelTextures(world.cloudVoxel); } // Add additional world voxels if (world.moreVoxels != null) { for (int k = 0; k < world.moreVoxels.Length; k++) { AddVoxelTextures(world.moreVoxels [k]); } } // Add all items' textures are available if (world.items != null) { int itemCount = world.items.Length; for (int k = 0; k < itemCount; k++) { ItemDefinition item = world.items [k]; if (item != null && item.category == ItemCategory.Voxel) { AddVoxelTextures(item.voxelType); } } } // Add any other voxel found inside Defaults VoxelDefinition [] vdd = Resources.LoadAll <VoxelDefinition> ("VoxelPlay/Defaults"); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } // Add any other voxel found inside World directory if (!string.IsNullOrEmpty(world.name)) { vdd = Resources.LoadAll <VoxelDefinition> ("Worlds/" + world.name); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } // Add any other voxel found inside a resource directory with same name of world (if not placed into Worlds directory) vdd = Resources.LoadAll <VoxelDefinition> (world.name); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } } // Add any other voxel found inside a resource directory under the world definition asset if (!string.IsNullOrEmpty(world.resourceLocation)) { vdd = Resources.LoadAll <VoxelDefinition> (world.resourceLocation); for (int k = 0; k < vdd.Length; k++) { AddVoxelTextures(vdd [k]); } } // Add connected textures ConnectedTexture [] ctt = Resources.LoadAll <ConnectedTexture> (""); for (int k = 0; k < ctt.Length; k++) { ConnectedTexture ct = ctt [k]; VoxelDefinition vd = ctt [k].voxelDefinition; if (vd == null || vd.index == 0) { continue; } for (int j = 0; j < ct.config.Length; j++) { ct.config [j].textureIndex = AddTexture(ct.config [j].texture, null, null, null); } ct.Init(); } // Add user provided voxels during playtime int count = sessionUserVoxels.Count; for (int k = 0; k < count; k++) { AddVoxelTextures(sessionUserVoxels [k]); } sessionUserVoxelsLastIndex = voxelDefinitionsCount - 1; // Add transparent voxel definitions for the see-through effect if (seeThrough) { int lastOne = voxelDefinitionsCount; // this loop will add voxels so end at the last regular voxel definition (don't process see-through versions) for (int k = 0; k < lastOne; k++) { VoxelDefinition vd = voxelDefinitions [k]; if (vd.renderType == RenderType.CutoutCross) { vd.seeThroughMode = SeeThroughMode.FullyInvisible; } else { if (vd.seeThroughMode == SeeThroughMode.Transparency) { if (vd.renderType.supportsAlphaSeeThrough()) { vd.seeThroughVoxelTempTransp = CreateSeeThroughVoxelDefinition(vd); } else { vd.seeThroughMode = SeeThroughMode.FullyInvisible; } } } } } // Create array texture int textureCount = worldTextures.Count; if (textureCount > 0) { Texture2DArray pointFilterTextureArray = new Texture2DArray(textureSize, textureSize, textureCount, TextureFormat.ARGB32, hqFiltering); if (enableReliefMapping || !enableSmoothLighting) { pointFilterTextureArray.wrapMode = TextureWrapMode.Repeat; } else { pointFilterTextureArray.wrapMode = TextureWrapMode.Clamp; } pointFilterTextureArray.filterMode = hqFiltering ? FilterMode.Bilinear : FilterMode.Point; pointFilterTextureArray.mipMapBias = -mipMapBias; for (int k = 0; k < textureCount; k++) { if (worldTextures [k].colorsAndEmission != null) { pointFilterTextureArray.SetPixels32(worldTextures [k].colorsAndEmission, k); } else if (worldTextures [k].normalsAndElevation != null) { pointFilterTextureArray.SetPixels32(worldTextures [k].normalsAndElevation, k); } } worldTextures.Clear(); pointFilterTextureArray.Apply(hqFiltering, true); // Assign textures to materials if (renderingMaterials != null) { for (int k = 0; k < renderingMaterials.Length; k++) { if (renderingMaterials [k].usesTextureArray) { Material mat = renderingMaterials [k].material; if (mat != null && mat.HasProperty("_MainTex")) { mat.SetTexture("_MainTex", pointFilterTextureArray); } } } } matDynamicOpaque.SetTexture("_MainTex", pointFilterTextureArray); matDynamicCutout.SetTexture("_MainTex", pointFilterTextureArray); if (modelHighlightMat == null) { modelHighlightMat = Instantiate <Material> (Resources.Load <Material> ("VoxelPlay/Materials/VP Highlight Model")) as Material; } modelHighlightMat.SetTexture("_MainTex", pointFilterTextureArray); } }