public TerrainRenderer(int id, IEnumerable <FileInfo> files, ZoneType type, ClientDataWrapper wrapper) : base(id, files, type, wrapper) { // Init Terrain Height Calculator TerrainHeightCache = TerrainHeightCalculator; AddNifCache(TerrainNifs); AddNifInstancesYZSwapped(TerrainFixtures); // Store Terrain var terrain = TerrainHeightMap; var vertices = new List <Vector3>(); var indices = new List <TriangleIndex>(); for (int x = 0; x < terrain.Length; x++) { var yLength = terrain[x].Length; for (int y = 0; y < yLength; y++) { var height = terrain[x][y]; vertices.Add(new Vector3(x, height, y)); } } var width = terrain.Length; for (int x = 0; x < terrain.Length - 1; x++) { var yLength = terrain[x].Length; for (int y = 0; y < yLength - 1; y++) { var tri1 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)((x + 1) * width + y), C = (uint)(x * width + y), }; var tri2 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)(x * width + y), C = (uint)(x * width + (y + 1)), }; indices.Add(tri1); indices.Add(tri2); } } // Build Terrain object as a Primitive Nif var Terrain = new TriangleCollection { Vertices = vertices.ToArray(), Indices = indices.ToArray(), }; // Add Terrain like a Nif var insertid = 0; if (NifCache.Count > 0) { insertid = NifCache.Max(kv => kv.Key) + 1; } NifCache.Add(insertid, new ClientMesh("terrain", Terrain, Terrain, Terrain)); InstancesMatrix = InstancesMatrix.Concat(new [] { new KeyValuePair <int, Matrix>(insertid, Matrix.Identity) }).ToArray(); }
/// <summary> /// Get World Matrix For NifGeometry /// </summary> /// <param name="nifGeom"></param> /// <param name="UnitFactor"></param> /// <param name="heightCalculator"></param> /// <returns></returns> protected static Matrix ComputeWorldMatrix(NifGeometry nifGeom, float UnitFactor, TerrainHeightCalculator heightCalculator) { if (nifGeom == null) throw new ArgumentNullException("nifGeom"); // Find Ground float nifHeight = nifGeom.Z * UnitFactor; if (nifGeom.OnGround) { nifHeight = heightCalculator[nifGeom.X, nifGeom.Y] * UnitFactor; } // Get Translation (XY Inverted), Scale, Rotation Matrix translation; ZoneDrawingExtensions.CreateTranslation(nifGeom.X * UnitFactor, nifHeight, nifGeom.Y * UnitFactor, out translation); Matrix scale; ZoneDrawingExtensions.CreateScale(nifGeom.Scale * UnitFactor, out scale); Matrix rotation; ZoneDrawingExtensions.CreateRotation(new Vector3(nifGeom.RotationX, nifGeom.RotationY, nifGeom.RotationZ), nifGeom.Angle , out rotation); Matrix result = Matrix.Identity; // Flip if needed if (nifGeom.Flip) { Matrix flip; ZoneDrawingExtensions.CreateScale(-1f, 1f, 1f, out flip); result = flip; } Matrix intermediateResult; // Combine Scale, Rotation, Invertion Rotation, Translation ZoneDrawingExtensions.Mult(ref result, ref scale, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref rotation, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref RotationMatrix, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref translation, out intermediateResult); result = intermediateResult; // Combine Matrix with Parent Matrix if (nifGeom.RelativeTo != null) { Matrix relativeMatrix = ComputeWorldMatrix(nifGeom.RelativeTo, UnitFactor, heightCalculator); ZoneDrawingExtensions.Mult(ref result, ref relativeMatrix, out intermediateResult); result = intermediateResult; } return result; }
/// <summary> /// Get World Matrix For NifGeometry /// </summary> /// <param name="nifGeom"></param> /// <param name="UnitFactor"></param> /// <param name="heightCalculator"></param> /// <returns></returns> protected static Matrix ComputeWorldMatrix(NifGeometry nifGeom, float UnitFactor, TerrainHeightCalculator heightCalculator) { if (nifGeom == null) { throw new ArgumentNullException("nifGeom"); } // Find Ground float nifHeight = nifGeom.Z * UnitFactor; if (nifGeom.OnGround) { nifHeight = heightCalculator[nifGeom.X, nifGeom.Y] * UnitFactor; } // Get Translation (XY Inverted), Scale, Rotation Matrix translation; ZoneDrawingExtensions.CreateTranslation(nifGeom.X * UnitFactor, nifHeight, nifGeom.Y * UnitFactor, out translation); Matrix scale; ZoneDrawingExtensions.CreateScale(nifGeom.Scale * UnitFactor, out scale); Matrix rotation; ZoneDrawingExtensions.CreateRotation(new Vector3(nifGeom.RotationX, nifGeom.RotationY, nifGeom.RotationZ), nifGeom.Angle, out rotation); Matrix result = Matrix.Identity; // Flip if needed if (nifGeom.Flip) { Matrix flip; ZoneDrawingExtensions.CreateScale(-1f, 1f, 1f, out flip); result = flip; } Matrix intermediateResult; // Combine Scale, Rotation, Invertion Rotation, Translation ZoneDrawingExtensions.Mult(ref result, ref scale, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref rotation, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref RotationMatrix, out intermediateResult); result = intermediateResult; ZoneDrawingExtensions.Mult(ref result, ref translation, out intermediateResult); result = intermediateResult; // Combine Matrix with Parent Matrix if (nifGeom.RelativeTo != null) { Matrix relativeMatrix = ComputeWorldMatrix(nifGeom.RelativeTo, UnitFactor, heightCalculator); ZoneDrawingExtensions.Mult(ref result, ref relativeMatrix, out intermediateResult); result = intermediateResult; } return(result); }