public void SetDefaultCell(LTEX tex) { ResetColorsAndNormals(); texBanks.Clear(); TextureBank tb = new TextureBank(); tb.SetSingleTexture(tex); texBanks.Add(tb); }
public void SetSingleTexture(LTEX tex1) { //There this will create a default bank which can be used for default land which has one texture t1 = tex1; DataStream WeightData = wBuffer.Lock(0, 0, LockFlags.None); WeightVertex defaultw; defaultw.w1 = 255; defaultw.w2 = 0; defaultw.w3 = 0; defaultw.w4 = 0; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { WeightData.Write(defaultw); } } wBuffer.Unlock(); }
private void workerLoadPlugins(object sender, System.ComponentModel.DoWorkEventArgs e) { map = (LAND[,])Array.CreateInstance(typeof(LAND), new int[] { 501, 501 }, new int[] { -250, -250 }); DefaultTex = new LTEX(); DefaultTex.FilePath = "_land_default.tga"; DefaultTex.index = 0; try { DefaultTex.LoadTexture(); } catch (Exception ex) { throw new ApplicationException("Failed to load default ground texture (" + ex.Message + ")", ex); } CellCount = 0; int progress = 0; List<string> errors = new List<string>(); foreach (string file in files) { if (DEBUG) allWarnings.Add("Loading plugin: " + file); BinaryReader br = new BinaryReader(File.OpenRead(file), System.Text.Encoding.Default); List<LTEX> Textures = new List<LTEX>(); //Add the default texture first, because all vtex id's are +1 compared to the ltex ids Textures.Add(DefaultTex); string s = ""; while (br.BaseStream.Position < br.BaseStream.Length) { s = ReadString(br); if (s == "LAND") { int size = br.ReadInt32(); int read = 0; br.BaseStream.Position += 8; LAND land = new LAND(); land.Textures = Textures; int lx = -999; int ly = -999; while (read < size) { s = ReadString(br); int size2 = br.ReadInt32(); read += size2 + 8; switch (s) { case "INTV": lx = br.ReadInt32(); ly = br.ReadInt32(); land.xpos = lx; land.ypos = ly; break; case "VHGT": int offset = (int)br.ReadSingle(); for (int y = 0; y < 65; y++) { offset += br.ReadSByte(); land.Heights[0, y] = offset; int pos = offset; for (int x = 1; x < 65; x++) { pos += br.ReadSByte(); land.Heights[x, y] = pos; if (pos > VeryHigh) VeryHigh = pos; if (pos < VeryLow) VeryLow = pos; } } br.BaseStream.Seek(3, SeekOrigin.Current); break; case "VNML": for (int y = 0; y < 65; y++) { for (int x = 0; x < 65; x++) { sbyte vx, vy, vz; vx = br.ReadSByte(); vy = br.ReadSByte(); vz = br.ReadSByte(); land.Normals[x, y] = new Normal(vx, vy, vz); } } break; case "VCLR": for (int y = 0; y < 65; y++) { for (int x = 0; x < 65; x++) { land.Color[x, y] = new RGB(br.ReadByte(), br.ReadByte(), br.ReadByte()); } } break; case "VTEX": for (int y1 = 0; y1 < 4; y1++) { for (int x1 = 0; x1 < 4; x1++) { for (int y2 = 0; y2 < 4; y2++) { for (int x2 = 0; x2 < 4; x2++) { land.Tex[x1 * 4 + x2, y1 * 4 + y2] = br.ReadInt16(); } } } } break; default: br.BaseStream.Position += size2; break; } } if (lx != -999 && ly != -999) { //Keep track of map extents if (lx > MapMaxX) { MapMaxX = lx; } if (ly > MapMaxY) { MapMaxY = ly; } if (lx < MapMinX) { MapMinX = lx; } if (ly < MapMinY) { MapMinY = ly; } int max = Math.Max(MapMaxX - MapMinX, MapMaxY - MapMinY); if (max > MapSize) MapSize = max; if (map[lx, ly] == null) CellCount++; map[lx, ly] = land; } } else if (s == "LTEX") { //TODO: Fix! //Presumably, not all LTEX's have the subrecords in an identical order LTEX tex = new LTEX(); int size = br.ReadInt32(); long pos = br.BaseStream.Position + 8; br.BaseStream.Position += 16; ReadCString(br); br.BaseStream.Position += 8; tex.index = br.ReadInt32() + 1; br.BaseStream.Position += 8; tex.FilePath = ReadCString(br).ToLower(Statics.Culture); try { tex.LoadTexture(); } catch (Exception ex) { errors.Add("Texture '" + tex.FilePath + "' in plugin '" + file + "' failed to load (" + ex.Message + ")"); tex.tex = DefaultTex.tex; } Textures.Add(tex); br.BaseStream.Position = pos + size; } else { int size = br.ReadInt32(); br.BaseStream.Position += size + 8; } } br.Close(); Textures.Sort(new LTEXSorter()); backgroundWorker.ReportProgress(++progress); } }
public void SetCell(LAND cell) { //Write the new colors and normals into the color buffer DataStream ColorNormalData = colorBuffer.Lock(0, 0, LockFlags.None); NormalColorVertex ncv; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { ncv.r = cell.Color[x, y].r; ncv.g = cell.Color[x, y].g; ncv.b = cell.Color[x, y].b; ncv.a = 255; ncv.nx = cell.Normals[x, y].X; ncv.ny = cell.Normals[x, y].Y; ncv.nz = cell.Normals[x, y].Z; ColorNormalData.Write(ncv); } } colorBuffer.Unlock(); //Dispose of any current texture banks texBanks.Clear(); //Group the unique textures in this cell in fours //Find all te uniqe textures in this cell System.Collections.Generic.Dictionary <string, LTEX> tex_dict = new System.Collections.Generic.Dictionary <string, LTEX>(); for (int x = 0; x <= 64; ++x) { for (int y = 0; y <= 64; ++y) { int cell_x = cell.xpos; int cell_y = cell.ypos; int tex_x = (int)Math.Floor(((float)y - 1.0f) / 4.0f); //-2.0f int tex_y = (int)Math.Floor(((float)x - 3.0f) / 4.0f); //-2.0f DistantLandForm.ModCell(ref cell_x, ref tex_x); DistantLandForm.ModCell(ref cell_y, ref tex_y); LTEX tmp = DistantLandForm.GetTex(cell_x, cell_y, tex_x, tex_y); string idx = tmp.FilePath; tex_dict[idx] = tmp; } } //Create one bank for each group of 4 textures int index = 0; TextureBank tb = new TextureBank(); foreach (LTEX tex in tex_dict.Values) { switch (index) { case 0: tb.t1 = tex; ++index; break; case 1: tb.t2 = tex; ++index; break; case 2: tb.t3 = tex; ++index; break; case 3: tb.t4 = tex; texBanks.Add(tb); tb = new TextureBank(); index = 0; break; } } if (index != 0) { texBanks.Add(tb); } if (texBanks.Count > 1) { int blah = 4; int blu = 7; int blablu = blah + blu; } //Calculate weights for all banks foreach (TextureBank bank in texBanks) { bank.CalcWeights(cell); } }
public void CalcWeights(LAND cell) { WeightVertex[] WeightData = new WeightVertex[65 * 65]; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { //Figure out which index to use int i = x * 65 + y; //Figure out which texture is used here int cell_x = cell.xpos; int cell_y = cell.ypos; int tex_x = (int)Math.Floor(((float)y - 1.0f) / 4.0f); //-2.0f int tex_y = (int)Math.Floor(((float)x - 3.0f) / 4.0f); //-2.0f DistantLandForm.ModCell(ref cell_x, ref tex_x); DistantLandForm.ModCell(ref cell_y, ref tex_y); LTEX tmp = DistantLandForm.GetTex(cell_x, cell_y, tex_x, tex_y); string tex_index = tmp.FilePath; //Write values if (t1 != null && t1.FilePath == tex_index) { WeightData[i].w1 = 255; continue; } else { WeightData[i].w1 = 0; } if (t2 != null && t2.FilePath == tex_index) { WeightData[i].w2 = 255; continue; } else { WeightData[i].w2 = 0; } if (t3 != null && t3.FilePath == tex_index) { WeightData[i].w3 = 255; continue; } else { WeightData[i].w3 = 0; } if (t4 != null && t4.FilePath == tex_index) { WeightData[i].w4 = 255; continue; } else { WeightData[i].w4 = 0; } } } //Blur the weights as we transfer them so the transitions aren't quite so blocky and horrible. ////Normal Gaussian //float bf1 = 0.00081723f; //float bf2 = 0.02804153f; //float bf3 = 0.23392642f; //float bf4 = 0.47442968f; //Reduced center influence float bf1 = 0.1f; float bf2 = 0.15f; float bf3 = 0.2f; float bf4 = 0.1f; //Horizontal Pass WeightVertex[] FirstPassWD = new WeightVertex[65 * 65]; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { //Figure out which index to use int i = y * 65 + x; if (x == 0 || x == 64 || y == 0 || y == 64) { //We're at the edge, so just copy the value (don't want to interfere with the way the edges of cells look FirstPassWD[i] = WeightData[i]; continue; } //We're not at the edge, so add some influence from the surrounding weights //Additional incides WeightVertex wv0, wv1, wv2, wv3, wv4, wv5, wv6; wv0 = SampleWeightData(ref WeightData, x - 3, y); wv1 = SampleWeightData(ref WeightData, x - 2, y); wv2 = SampleWeightData(ref WeightData, x - 1, y); wv3 = SampleWeightData(ref WeightData, x, y); wv4 = SampleWeightData(ref WeightData, x + 1, y); wv5 = SampleWeightData(ref WeightData, x + 2, y); wv6 = SampleWeightData(ref WeightData, x + 3, y); float value; value = 0.0f; value += (float)wv0.w1 * bf1; value += (float)wv1.w1 * bf2; value += (float)wv2.w1 * bf3; value += (float)wv3.w1 * bf4; value += (float)wv4.w1 * bf3; value += (float)wv5.w1 * bf2; value += (float)wv6.w1 * bf1; FirstPassWD[i].w1 = (byte)value; value = 0.0f; value += (float)wv0.w2 * bf1; value += (float)wv1.w2 * bf2; value += (float)wv2.w2 * bf3; value += (float)wv3.w2 * bf4; value += (float)wv4.w2 * bf3; value += (float)wv5.w2 * bf2; value += (float)wv6.w2 * bf1; FirstPassWD[i].w2 = (byte)value; value = 0.0f; value += (float)wv0.w3 * bf1; value += (float)wv1.w3 * bf2; value += (float)wv2.w3 * bf3; value += (float)wv3.w3 * bf4; value += (float)wv4.w3 * bf3; value += (float)wv5.w3 * bf2; value += (float)wv6.w3 * bf1; FirstPassWD[i].w3 = (byte)value; value = 0.0f; value += (float)wv0.w4 * bf1; value += (float)wv1.w4 * bf2; value += (float)wv2.w4 * bf3; value += (float)wv3.w4 * bf4; value += (float)wv4.w4 * bf3; value += (float)wv5.w4 * bf2; value += (float)wv6.w4 * bf1; FirstPassWD[i].w4 = (byte)value; } } //Vertical pass - writes to final vertex buffer DataStream FinalWeightData = wBuffer.Lock(0, 0, LockFlags.None); //Blur the weights as we transfer them so the transitions aren't quite so blocky and horrible. for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { if (x == 0 || x == 64 || y == 0 || y == 64) { //We're at the edge, so just copy the value (don't want to interfere with the way the edges of cells look FinalWeightData.Write(WeightData[65 * y + x]); continue; } //We're not at the edge, so add some influence from the surrounding weights //Additional incides WeightVertex wv0, wv1, wv2, wv3, wv4, wv5, wv6, wvfinal; wv0 = SampleWeightData(ref FirstPassWD, x, y - 3); wv1 = SampleWeightData(ref FirstPassWD, x, y - 2); wv2 = SampleWeightData(ref FirstPassWD, x, y - 1); wv3 = SampleWeightData(ref FirstPassWD, x, y); wv4 = SampleWeightData(ref FirstPassWD, x, y + 1); wv5 = SampleWeightData(ref FirstPassWD, x, y + 2); wv6 = SampleWeightData(ref FirstPassWD, x, y + 3); float value; value = 0.0f; value += (float)wv0.w1 * bf1; value += (float)wv1.w1 * bf2; value += (float)wv2.w1 * bf3; value += (float)wv3.w1 * bf4; value += (float)wv4.w1 * bf3; value += (float)wv5.w1 * bf2; value += (float)wv6.w1 * bf1; wvfinal.w1 = (byte)value; value = 0.0f; value += (float)wv0.w2 * bf1; value += (float)wv1.w2 * bf2; value += (float)wv2.w2 * bf3; value += (float)wv3.w2 * bf4; value += (float)wv4.w2 * bf3; value += (float)wv5.w2 * bf2; value += (float)wv6.w2 * bf1; wvfinal.w2 = (byte)value; value = 0.0f; value += (float)wv0.w3 * bf1; value += (float)wv1.w3 * bf2; value += (float)wv2.w3 * bf3; value += (float)wv3.w3 * bf4; value += (float)wv4.w3 * bf3; value += (float)wv5.w3 * bf2; value += (float)wv6.w3 * bf1; wvfinal.w3 = (byte)value; value = 0.0f; value += (float)wv0.w4 * bf1; value += (float)wv1.w4 * bf2; value += (float)wv2.w4 * bf3; value += (float)wv3.w4 * bf4; value += (float)wv4.w4 * bf3; value += (float)wv5.w4 * bf2; value += (float)wv6.w4 * bf1; wvfinal.w4 = (byte)value; FinalWeightData.Write(wvfinal); } } wBuffer.Unlock(); }
public void SetSingleTexture( LTEX tex1 ) { //There this will create a default bank which can be used for default land which has one texture t1 = tex1; WeightVertex[] WeightData = (WeightVertex[])wBuffer.Lock(0, LockFlags.None); for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { //Figure out which index to use int i = y * 65 + x; //Write values WeightData[i].w1 = 255; WeightData[i].w2 = 0; WeightData[i].w3 = 0; WeightData[i].w4 = 0; } } wBuffer.Unlock(); }
public void SetSingleTexture( LTEX tex1 ) { //There this will create a default bank which can be used for default land which has one texture t1 = tex1; DataStream WeightData = wBuffer.Lock(0, 0, LockFlags.None); WeightVertex defaultw; defaultw.w1 = 255; defaultw.w2 = 0; defaultw.w3 = 0; defaultw.w4 = 0; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { WeightData.Write(defaultw); } } wBuffer.Unlock(); }
public void CalcWeights(LAND cell) { WeightVertex[] WeightData = new WeightVertex[65 * 65]; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { // Figure out which index to use int i = y * 65 + x; // Figure out which texture is used here, match Morrowind rounding int cell_x = cell.xpos; int cell_y = cell.ypos; int tex_x = (int)Math.Floor(((float)x - 2.0f) / 4.0f); int tex_y = (int)Math.Ceiling(((float)y - 2.0f) / 4.0f); DistantLandForm.ModCell(ref cell_x, ref tex_x); DistantLandForm.ModCell(ref cell_y, ref tex_y); LTEX tmp = DistantLandForm.GetTex(cell_x, cell_y, tex_x, tex_y); string tex_index = tmp.FilePath; // Write values if (t1 != null && t1.FilePath == tex_index) { WeightData[i].w1 = 255; continue; } else { WeightData[i].w1 = 0; } if (t2 != null && t2.FilePath == tex_index) { WeightData[i].w2 = 255; continue; } else { WeightData[i].w2 = 0; } if (t3 != null && t3.FilePath == tex_index) { WeightData[i].w3 = 255; continue; } else { WeightData[i].w3 = 0; } if (t4 != null && t4.FilePath == tex_index) { WeightData[i].w4 = 255; continue; } else { WeightData[i].w4 = 0; } } } // Blur the weights as we transfer them so the transitions aren't quite so blocky and horrible. // Blur kernel float[] blur = new float[] { 0.04f, 0.16f, 0.6f, 0.16f, 0.04f }; // Horizontal Pass WeightVertex[] FirstPassWD = new WeightVertex[65 * 65]; for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { // Figure out which index to use int i = y * 65 + x; if (x == 0 || x == 64 || y == 0 || y == 64) { // We're at the edge, so just copy the value (don't want to interfere with the way the edges of cells look FirstPassWD[i] = WeightData[i]; continue; } // We're not at the edge, so add some influence from the surrounding weights // Additional incides WeightVertex wv0, wv1, wv2, wv3, wv4; float value; wv0 = SampleWeightData(ref WeightData, x - 2, y); wv1 = SampleWeightData(ref WeightData, x - 1, y); wv2 = SampleWeightData(ref WeightData, x, y); wv3 = SampleWeightData(ref WeightData, x + 1, y); wv4 = SampleWeightData(ref WeightData, x + 2, y); value = (float)wv0.w1 * blur[0] + (float)wv1.w1 * blur[1] + (float)wv2.w1 * blur[2] + (float)wv3.w1 * blur[3] + (float)wv4.w1 * blur[4]; FirstPassWD[i].w1 = (byte)value; value = (float)wv0.w2 * blur[0] + (float)wv1.w2 * blur[1] + (float)wv2.w2 * blur[2] + (float)wv3.w2 * blur[3] + (float)wv4.w2 * blur[4]; FirstPassWD[i].w2 = (byte)value; value = (float)wv0.w3 * blur[0] + (float)wv1.w3 * blur[1] + (float)wv2.w3 * blur[2] + (float)wv3.w3 * blur[3] + (float)wv4.w3 * blur[4]; FirstPassWD[i].w3 = (byte)value; value = (float)wv0.w4 * blur[0] + (float)wv1.w4 * blur[1] + (float)wv2.w4 * blur[2] + (float)wv3.w4 * blur[3] + (float)wv4.w4 * blur[4]; FirstPassWD[i].w4 = (byte)value; } } // Vertical pass - writes to final vertex buffer DataStream FinalWeightData = wBuffer.Lock(0, 0, LockFlags.None); // Blur the weights as we transfer them so the transitions aren't quite so blocky and horrible. for (int y = 0; y <= 64; y++) { for (int x = 0; x <= 64; x++) { if (x == 0 || x == 64 || y == 0 || y == 64) { // We're at the edge, so just copy the value (don't want to interfere with the way the edges of cells look FinalWeightData.Write(WeightData[65 * y + x]); continue; } // We're not at the edge, so add some influence from the surrounding weights // Additional incides WeightVertex wv0, wv1, wv2, wv3, wv4, wvfinal; float value; wv0 = SampleWeightData(ref FirstPassWD, x, y - 2); wv1 = SampleWeightData(ref FirstPassWD, x, y - 1); wv2 = SampleWeightData(ref FirstPassWD, x, y); wv3 = SampleWeightData(ref FirstPassWD, x, y + 1); wv4 = SampleWeightData(ref FirstPassWD, x, y + 2); value = (float)wv0.w1 * blur[0] + (float)wv1.w1 * blur[1] + (float)wv2.w1 * blur[2] + (float)wv3.w1 * blur[3] + (float)wv4.w1 * blur[4]; wvfinal.w1 = (byte)value; value = (float)wv0.w2 * blur[0] + (float)wv1.w2 * blur[1] + (float)wv2.w2 * blur[2] + (float)wv3.w2 * blur[3] + (float)wv4.w2 * blur[4]; wvfinal.w2 = (byte)value; value = (float)wv0.w3 * blur[0] + (float)wv1.w3 * blur[1] + (float)wv2.w3 * blur[2] + (float)wv3.w3 * blur[3] + (float)wv4.w3 * blur[4]; wvfinal.w3 = (byte)value; value = (float)wv0.w4 * blur[0] + (float)wv1.w4 * blur[1] + (float)wv2.w4 * blur[2] + (float)wv3.w4 * blur[3] + (float)wv4.w4 * blur[4]; wvfinal.w4 = (byte)value; FinalWeightData.Write(wvfinal); } } wBuffer.Unlock(); }