public MorrowindEngine(MorrowindDataReader mwDataReader, UIManager uiManager) { Debug.Assert(instance == null); instance = this; dataReader = mwDataReader; textureManager = new TextureManager(dataReader); materialManager = new MaterialManager(textureManager); nifManager = new NIFManager(dataReader, materialManager); temporalLoadBalancer = new TemporalLoadBalancer(); cellManager = new CellManager(dataReader, textureManager, nifManager, temporalLoadBalancer); RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat; RenderSettings.ambientIntensity = TESUnity.instance.ambientIntensity; sunObj = GameObjectUtils.CreateDirectionalLight(Vector3.zero, Quaternion.Euler(new Vector3(50, 330, 0))); sunObj.GetComponent <Light>().shadows = TESUnity.instance.renderSunShadows ? LightShadows.Soft : LightShadows.None; sunObj.SetActive(false); waterObj = GameObject.Instantiate(TESUnity.instance.waterPrefab); waterObj.SetActive(false); if (!TESUnity.instance.waterBackSideTransparent) { var side = waterObj.transform.GetChild(0); var sideMaterial = side.GetComponent <Renderer>().sharedMaterial; sideMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); sideMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); sideMaterial.SetInt("_ZWrite", 1); sideMaterial.DisableKeyword("_ALPHATEST_ON"); sideMaterial.DisableKeyword("_ALPHABLEND_ON"); sideMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON"); sideMaterial.renderQueue = -1; } Cursor.SetCursor(textureManager.LoadTexture("tx_cursor", true), Vector2.zero, CursorMode.Auto); _uiManager = uiManager; _uiManager.Active = true; }
/// <summary> /// Creates terrain representing a LAND record. /// </summary> private IEnumerator InstantiateLANDCoroutine(LANDRecord LAND, GameObject parent) { Debug.Assert(LAND != null); // Don't create anything if the LAND doesn't have height data. if (LAND.VHGT == null) { yield break; } // Return before doing any work to provide an IEnumerator handle to the coroutine. yield return(null); const int LAND_SIDE_LENGTH_IN_SAMPLES = 65; var heights = new float[LAND_SIDE_LENGTH_IN_SAMPLES, LAND_SIDE_LENGTH_IN_SAMPLES]; // Read in the heights in Morrowind units. const int VHGTIncrementToMWUnits = 8; float rowOffset = LAND.VHGT.referenceHeight; for (int y = 0; y < LAND_SIDE_LENGTH_IN_SAMPLES; y++) { rowOffset += LAND.VHGT.heightOffsets[y * LAND_SIDE_LENGTH_IN_SAMPLES]; heights[y, 0] = VHGTIncrementToMWUnits * rowOffset; float colOffset = rowOffset; for (int x = 1; x < LAND_SIDE_LENGTH_IN_SAMPLES; x++) { colOffset += LAND.VHGT.heightOffsets[(y * LAND_SIDE_LENGTH_IN_SAMPLES) + x]; heights[y, x] = VHGTIncrementToMWUnits * colOffset; } } // Change the heights to percentages. float minHeight, maxHeight; ArrayUtils.GetExtrema(heights, out minHeight, out maxHeight); for (int y = 0; y < LAND_SIDE_LENGTH_IN_SAMPLES; y++) { for (int x = 0; x < LAND_SIDE_LENGTH_IN_SAMPLES; x++) { heights[y, x] = Utils.ChangeRange(heights[y, x], minHeight, maxHeight, 0, 1); } } // Texture the terrain. SplatPrototype[] splatPrototypes = null; float[,,] alphaMap = null; const int LAND_TEXTURE_INDICES_COUNT = 256; var textureIndices = (LAND.VTEX != null) ? LAND.VTEX.textureIndices : new ushort[LAND_TEXTURE_INDICES_COUNT]; // Create splat prototypes. var splatPrototypeList = new List <SplatPrototype>(); var texInd2splatInd = new Dictionary <ushort, int>(); for (int i = 0; i < textureIndices.Length; i++) { short textureIndex = (short)((short)textureIndices[i] - 1); if (!texInd2splatInd.ContainsKey((ushort)textureIndex)) { // Load terrain texture. string textureFilePath; if (textureIndex < 0) { textureFilePath = defaultLandTextureFilePath; } else { var LTEX = dataReader.FindLTEXRecord(textureIndex); textureFilePath = LTEX.DATA.value; } var texture = textureManager.LoadTexture(textureFilePath); // Yield after loading each texture to avoid doing too much work on one frame. yield return(null); // Create the splat prototype. var splat = new SplatPrototype(); splat.texture = texture; splat.smoothness = 0; splat.metallic = 0; splat.tileSize = new Vector2(6, 6); // Update collections. var splatIndex = splatPrototypeList.Count; splatPrototypeList.Add(splat); texInd2splatInd.Add((ushort)textureIndex, splatIndex); } } splatPrototypes = splatPrototypeList.ToArray(); // Create the alpha map. int VTEX_ROWS = 16; int VTEX_COLUMNS = VTEX_ROWS; alphaMap = new float[VTEX_ROWS, VTEX_COLUMNS, splatPrototypes.Length]; for (int y = 0; y < VTEX_ROWS; y++) { var yMajor = y / 4; var yMinor = y - (yMajor * 4); for (int x = 0; x < VTEX_COLUMNS; x++) { var xMajor = x / 4; var xMinor = x - (xMajor * 4); var texIndex = (short)((short)textureIndices[(yMajor * 64) + (xMajor * 16) + (yMinor * 4) + xMinor] - 1); if (texIndex >= 0) { var splatIndex = texInd2splatInd[(ushort)texIndex]; alphaMap[y, x, splatIndex] = 1; } else { alphaMap[y, x, 0] = 1; } } } // Yield before creating the terrain GameObject because it takes a while. yield return(null); // Create the terrain. var heightRange = maxHeight - minHeight; var terrainPosition = new Vector3(Convert.exteriorCellSideLengthInMeters * LAND.gridCoords.x, minHeight / Convert.meterInMWUnits, Convert.exteriorCellSideLengthInMeters * LAND.gridCoords.y); var heightSampleDistance = Convert.exteriorCellSideLengthInMeters / (LAND_SIDE_LENGTH_IN_SAMPLES - 1); var terrain = GameObjectUtils.CreateTerrain(heights, heightRange / Convert.meterInMWUnits, heightSampleDistance, splatPrototypes, alphaMap, terrainPosition); terrain.GetComponent <Terrain>().materialType = Terrain.MaterialType.BuiltInLegacyDiffuse; terrain.transform.parent = parent.transform; }