mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-23 07:22:52 +08:00
Added heightmap rendering and waterheight.dat file reading/rendering code
This commit is contained in:
parent
25df592731
commit
0f6474242d
550
CodeWalker.Core/GameFiles/FileTypes/WatermapFile.cs
Normal file
550
CodeWalker.Core/GameFiles/FileTypes/WatermapFile.cs
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||||
|
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using SharpDX;
|
||||||
|
|
||||||
|
namespace CodeWalker.GameFiles
|
||||||
|
{
|
||||||
|
[TC(typeof(EXP))]
|
||||||
|
public class WatermapFile : GameFile, PackedFile
|
||||||
|
{
|
||||||
|
public byte[] RawFileData { get; set; }
|
||||||
|
|
||||||
|
public uint Magic { get; set; } = 0x574D4150; //'WMAP'
|
||||||
|
public uint Version { get; set; } = 100;
|
||||||
|
public uint DataLength { get; set; } //59360 - data length
|
||||||
|
public float CornerX { get; set; } //-4050.0f - topleft X
|
||||||
|
public float CornerY { get; set; } //8400.0f - topleft Y
|
||||||
|
public float TileX { get; set; } //50.0f - tile size X
|
||||||
|
public float TileY { get; set; } //50.0f - tile size Y (step negative?)
|
||||||
|
public ushort Width { get; set; } //183 - image Width
|
||||||
|
public ushort Height { get; set; } //249 - image Height
|
||||||
|
public uint WatermapIndsCount { get; set; } //10668
|
||||||
|
public uint WatermapRefsCount { get; set; } //11796
|
||||||
|
public ushort RiverVecsCount { get; set; } //99
|
||||||
|
public ushort RiverCount { get; set; } //13
|
||||||
|
public ushort LakeVecsCount { get; set; } //28
|
||||||
|
public ushort LakeCount { get; set; } //15
|
||||||
|
public ushort PoolCount { get; set; } //314
|
||||||
|
public ushort ColoursOffset { get; set; } //13316
|
||||||
|
public byte[] Unks1 { get; set; }//2,2,16,48,16,48,32,0 ..?
|
||||||
|
|
||||||
|
public CompHeader[] CompHeaders { get; set; }
|
||||||
|
public short[] CompWatermapInds { get; set; }//indices into CompWatermapRefs
|
||||||
|
public WaterItemRef[] CompWatermapRefs { get; set; }//contains multibit, type, index1, [index2](optional)
|
||||||
|
public byte[] Zeros1 { get; set; }//x12
|
||||||
|
public Vector4[] RiverVecs { get; set; }
|
||||||
|
public WaterFlow[] Rivers { get; set; }
|
||||||
|
public Vector4[] LakeVecs { get; set; }
|
||||||
|
public WaterFlow[] Lakes { get; set; }
|
||||||
|
public WaterPool[] Pools { get; set; }
|
||||||
|
public Color[] Colours { get; set; }//x342
|
||||||
|
public uint ColourCount { get; set; }//342 (RiverCount + LakeCount + PoolCount)
|
||||||
|
|
||||||
|
|
||||||
|
public short[] GridWatermapInds { get; set; } //expanded from CompWatermapInds.
|
||||||
|
public WaterItemRef[][] GridWatermapRefs { get; set; } //expanded from CompWatermapHeaders. ends up max 7 items
|
||||||
|
|
||||||
|
|
||||||
|
public WatermapFile() : base(null, GameFileType.Watermap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public WatermapFile(RpfFileEntry entry) : base(entry, GameFileType.Watermap)
|
||||||
|
{
|
||||||
|
RpfFileEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(byte[] data, RpfFileEntry entry)
|
||||||
|
{
|
||||||
|
RawFileData = data;
|
||||||
|
if (entry != null)
|
||||||
|
{
|
||||||
|
RpfFileEntry = entry;
|
||||||
|
Name = entry.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (MemoryStream ms = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
DataReader r = new DataReader(ms, Endianess.BigEndian);
|
||||||
|
|
||||||
|
Read(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Save()
|
||||||
|
{
|
||||||
|
MemoryStream s = new MemoryStream();
|
||||||
|
DataWriter w = new DataWriter(s, Endianess.BigEndian);
|
||||||
|
|
||||||
|
Write(w);
|
||||||
|
|
||||||
|
var buf = new byte[s.Length];
|
||||||
|
s.Position = 0;
|
||||||
|
s.Read(buf, 0, buf.Length);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Read(DataReader r)
|
||||||
|
{
|
||||||
|
Magic = r.ReadUInt32();//'WMAP'
|
||||||
|
Version = r.ReadUInt32();//100 - version?
|
||||||
|
DataLength = r.ReadUInt32();//59360 - data length (excluding last flags array!)
|
||||||
|
CornerX = r.ReadSingle();//-4050.0f - min XY?
|
||||||
|
CornerY = r.ReadSingle();//8400.0f - max XY?
|
||||||
|
TileX = r.ReadSingle();//50.0f - tile size X
|
||||||
|
TileY = r.ReadSingle();//50.0f - tile size Y
|
||||||
|
Width = r.ReadUInt16();//183 - image Width
|
||||||
|
Height = r.ReadUInt16();//249 - image Height
|
||||||
|
WatermapIndsCount = r.ReadUInt32();//10668
|
||||||
|
WatermapRefsCount = r.ReadUInt32();//11796
|
||||||
|
RiverVecsCount = r.ReadUInt16();//99
|
||||||
|
RiverCount = r.ReadUInt16();//13
|
||||||
|
LakeVecsCount = r.ReadUInt16();//28
|
||||||
|
LakeCount = r.ReadUInt16();//15
|
||||||
|
PoolCount = r.ReadUInt16();//314
|
||||||
|
ColoursOffset = r.ReadUInt16();//13316
|
||||||
|
Unks1 = r.ReadBytes(8);//2,2,16,48,16,48,32,0 flags..?
|
||||||
|
|
||||||
|
|
||||||
|
var shortslen = (int)((WatermapIndsCount + WatermapRefsCount) * 2) + (Height * 4);//offset from here to Zeros1
|
||||||
|
var padcount = (16 - (shortslen % 16)) % 16;//12 .. is this right? all are zeroes.
|
||||||
|
var strucslen = ((RiverVecsCount + LakeVecsCount) * 16) + ((RiverCount + LakeCount) * 48) + (PoolCount * 32);
|
||||||
|
var datalen = shortslen + padcount + strucslen; //DataLength calculation
|
||||||
|
var extoffs = padcount + strucslen - 60 - 60;//ExtraFlagsOffset calculation
|
||||||
|
|
||||||
|
|
||||||
|
CompHeaders = new CompHeader[Height];//249 - image height
|
||||||
|
for (int i = 0; i < Height; i++) CompHeaders[i].Read(r);
|
||||||
|
|
||||||
|
CompWatermapInds = new short[WatermapIndsCount];//10668
|
||||||
|
for (int i = 0; i < WatermapIndsCount; i++) CompWatermapInds[i] = r.ReadInt16();
|
||||||
|
|
||||||
|
CompWatermapRefs = new WaterItemRef[WatermapRefsCount];//11796
|
||||||
|
for (int i = 0; i < WatermapRefsCount; i++) CompWatermapRefs[i] = new WaterItemRef(r.ReadUInt16());
|
||||||
|
|
||||||
|
Zeros1 = r.ReadBytes(padcount);//align to 16 bytes (position:45984)
|
||||||
|
|
||||||
|
RiverVecs = new Vector4[RiverVecsCount];//99
|
||||||
|
for (int i = 0; i < RiverVecsCount; i++) RiverVecs[i] = r.ReadVector4();
|
||||||
|
|
||||||
|
Rivers = new WaterFlow[RiverCount];//13
|
||||||
|
for (int i = 0; i < RiverCount; i++) Rivers[i] = new WaterFlow(WaterItemType.River, r, RiverVecs);
|
||||||
|
|
||||||
|
LakeVecs = new Vector4[LakeVecsCount];//28
|
||||||
|
for (int i = 0; i < LakeVecsCount; i++) LakeVecs[i] = r.ReadVector4();
|
||||||
|
|
||||||
|
Lakes = new WaterFlow[LakeCount];//15
|
||||||
|
for (int i = 0; i < LakeCount; i++) Lakes[i] = new WaterFlow(WaterItemType.Lake, r, LakeVecs);
|
||||||
|
|
||||||
|
Pools = new WaterPool[PoolCount];//314
|
||||||
|
for (int i = 0; i < PoolCount; i++) Pools[i] = new WaterPool(r);
|
||||||
|
|
||||||
|
ColourCount = (uint)(RiverCount + LakeCount + PoolCount); //342
|
||||||
|
Colours = new Color[ColourCount]; //342
|
||||||
|
for (int i = 0; i < 342; i++) Colours[i] = Color.FromAbgr(r.ReadUInt32());
|
||||||
|
|
||||||
|
|
||||||
|
var flagoff = 0; //assign extra colours out of the main array
|
||||||
|
for (int i = 0; i < Rivers.Length; i++)
|
||||||
|
{
|
||||||
|
var river = Rivers[i];
|
||||||
|
river.Colour = Colours[flagoff++];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Lakes.Length; i++)
|
||||||
|
{
|
||||||
|
var lake = Lakes[i];
|
||||||
|
lake.Colour = Colours[flagoff++];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Pools.Length; i++)
|
||||||
|
{
|
||||||
|
var pool = Pools[i];
|
||||||
|
pool.Colour = Colours[flagoff++];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < CompWatermapRefs.Length; i++) //assign items to CompWatermapRefs
|
||||||
|
{
|
||||||
|
var ir = CompWatermapRefs[i];
|
||||||
|
switch (ir.Type)
|
||||||
|
{
|
||||||
|
case WaterItemType.River: CompWatermapRefs[i].Item = Rivers[ir.ItemIndex]; break;
|
||||||
|
case WaterItemType.Lake: CompWatermapRefs[i].Item = Lakes[ir.ItemIndex]; break;
|
||||||
|
case WaterItemType.Pool: CompWatermapRefs[i].Item = Pools[ir.ItemIndex]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//decompress main data into grid form
|
||||||
|
GridWatermapInds = new short[Width * Height];
|
||||||
|
GridWatermapRefs = new WaterItemRef[Width * Height][];
|
||||||
|
var reflist = new List<WaterItemRef>();
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
var ch = CompHeaders[y];
|
||||||
|
for (int i = 0; i < ch.Count; i++)
|
||||||
|
{
|
||||||
|
var x = ch.Start + i;
|
||||||
|
var n = CompWatermapInds[ch.Offset + i];
|
||||||
|
var o = y * Width + x;
|
||||||
|
|
||||||
|
reflist.Clear();
|
||||||
|
WaterItemRef[] refarr = null;
|
||||||
|
if (n >= 0)
|
||||||
|
{
|
||||||
|
var h = CompWatermapRefs[n];
|
||||||
|
reflist.Add(h);
|
||||||
|
var cn = n;
|
||||||
|
while (h.EndOfList == false)
|
||||||
|
{
|
||||||
|
cn++;
|
||||||
|
h = CompWatermapRefs[cn];
|
||||||
|
reflist.Add(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
refarr = reflist.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
GridWatermapInds[o] = n;
|
||||||
|
GridWatermapRefs[o] = refarr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var pgm = GetPGM();
|
||||||
|
|
||||||
|
|
||||||
|
var rem = r.Length - r.Position;//60788
|
||||||
|
if (rem != 0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var sb = new StringBuilder();
|
||||||
|
//for (int y = Height - 1; y >= 0; y--)
|
||||||
|
//{
|
||||||
|
// for (int x = 0; x < Width; x++)
|
||||||
|
// {
|
||||||
|
// var v = GridWatermapVals[y * Width + x];
|
||||||
|
// sb.Append(Convert.ToString(v, 16).ToUpperInvariant().PadLeft(4, '0'));
|
||||||
|
// sb.Append(" ");
|
||||||
|
// }
|
||||||
|
// sb.AppendLine();
|
||||||
|
//}
|
||||||
|
//var hstr = sb.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
private void Write(DataWriter w)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
w.Write(Magic);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteXml(StringBuilder sb, int indent)
|
||||||
|
{
|
||||||
|
//HmapXml.ValueTag(sb, indent, "Width", Width.ToString());
|
||||||
|
//HmapXml.ValueTag(sb, indent, "Height", Height.ToString());
|
||||||
|
//HmapXml.SelfClosingTag(sb, indent, "BBMin " + FloatUtil.GetVector3XmlString(BBMin));
|
||||||
|
//HmapXml.SelfClosingTag(sb, indent, "BBMax " + FloatUtil.GetVector3XmlString(BBMax));
|
||||||
|
//HmapXml.WriteRawArray(sb, InvertImage(MaxHeights, Width, Height), indent, "MaxHeights", "", HmapXml.FormatHexByte, Width);
|
||||||
|
//HmapXml.WriteRawArray(sb, InvertImage(MinHeights, Width, Height), indent, "MinHeights", "", HmapXml.FormatHexByte, Width);
|
||||||
|
}
|
||||||
|
public void ReadXml(XmlNode node)
|
||||||
|
{
|
||||||
|
//Width = (ushort)Xml.GetChildUIntAttribute(node, "Width");
|
||||||
|
//Height = (ushort)Xml.GetChildUIntAttribute(node, "Height");
|
||||||
|
//BBMin = Xml.GetChildVector3Attributes(node, "BBMin");
|
||||||
|
//BBMax = Xml.GetChildVector3Attributes(node, "BBMax");
|
||||||
|
//MaxHeights = InvertImage(Xml.GetChildRawByteArray(node, "MaxHeights"), Width, Height);
|
||||||
|
//MinHeights = InvertImage(Xml.GetChildRawByteArray(node, "MinHeights"), Width, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public struct CompHeader
|
||||||
|
{
|
||||||
|
public byte Start { get; set; }
|
||||||
|
public byte Count { get; set; }
|
||||||
|
public ushort Offset { get; set; }
|
||||||
|
|
||||||
|
public void Read(DataReader r)
|
||||||
|
{
|
||||||
|
Start = r.ReadByte();
|
||||||
|
Count = r.ReadByte();
|
||||||
|
Offset = r.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("{0}, {1}, {2}",
|
||||||
|
Start, Count, Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public struct WaterItemRef
|
||||||
|
{
|
||||||
|
public ushort RawValue { get; set; }
|
||||||
|
|
||||||
|
public bool EndOfList { get { return ((RawValue >> 15) & 0x1) == 1; } } //highest bit indicates if it's at the end of the list
|
||||||
|
public WaterItemType Type { get { return (WaterItemType)((RawValue >> 13) & 0x3); } } //next 2 bits are the item type
|
||||||
|
public ushort ItemIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case WaterItemType.River:
|
||||||
|
case WaterItemType.Lake:
|
||||||
|
return (ushort)((RawValue >> 7) & 0x3F);
|
||||||
|
case WaterItemType.Pool:
|
||||||
|
default:
|
||||||
|
return (ushort)(RawValue & 0x7FF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ushort VectorIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case WaterItemType.River:
|
||||||
|
case WaterItemType.Lake:
|
||||||
|
return (ushort)(RawValue & 0x7F);
|
||||||
|
case WaterItemType.Pool:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WaterItem Item { get; set; } //lookup reference
|
||||||
|
public Vector4 Vector
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Item?.Vectors == null) return Vector4.Zero;
|
||||||
|
if (VectorIndex >= Item.Vectors.Length) return Vector4.Zero;
|
||||||
|
return Item.Vectors[VectorIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WaterItemRef(ushort rawval) { RawValue = rawval; Item = null; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (Item != null) return Item.ToString() + ": " + Vector.ToString();
|
||||||
|
return Type.ToString() + ": " + ItemIndex.ToString() + ": " + VectorIndex.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum WaterItemType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
River = 1,
|
||||||
|
Lake = 2,
|
||||||
|
Pool = 3,
|
||||||
|
}
|
||||||
|
public abstract class WaterItem
|
||||||
|
{
|
||||||
|
//length:32
|
||||||
|
public Vector3 Position { get; set; }
|
||||||
|
public uint Unk04 { get; set; }//0
|
||||||
|
public Vector3 Size { get; set; }
|
||||||
|
public uint Unk09 { get; set; }//0
|
||||||
|
|
||||||
|
public WaterItemType Type { get; private set; }
|
||||||
|
|
||||||
|
public Vector4[] Vectors { get; set; }//built from packed data
|
||||||
|
public Color Colour { get; set; } //from the end of the file
|
||||||
|
|
||||||
|
public WaterItem(WaterItemType type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Read(DataReader r)
|
||||||
|
{
|
||||||
|
Position = r.ReadVector3();
|
||||||
|
Unk04 = r.ReadUInt32();
|
||||||
|
Size = r.ReadVector3();
|
||||||
|
Unk09 = r.ReadUInt32();
|
||||||
|
|
||||||
|
if (Unk04 != 0)
|
||||||
|
{ }
|
||||||
|
if (Unk09 != 0)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("{0} - Size: {1}, Pos: {2}", Type, Size, Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class WaterFlow : WaterItem
|
||||||
|
{
|
||||||
|
//length:48 (including base)
|
||||||
|
public byte VectorCount { get; set; }
|
||||||
|
public byte Unk11 { get; set; }//0
|
||||||
|
public ushort VectorOffset { get; set; }
|
||||||
|
public uint Unk13 { get; set; }//0
|
||||||
|
public uint Unk14 { get; set; }//0
|
||||||
|
public uint Unk15 { get; set; }//0
|
||||||
|
|
||||||
|
public WaterFlow(WaterItemType type) : base(type) { }
|
||||||
|
public WaterFlow(WaterItemType type, DataReader r, Vector4[] vecs) : base(type)
|
||||||
|
{
|
||||||
|
Read(r);
|
||||||
|
|
||||||
|
if (VectorCount > 0)
|
||||||
|
{
|
||||||
|
Vectors = new Vector4[VectorCount];
|
||||||
|
for (int i = 0; i < VectorCount; i++)
|
||||||
|
{
|
||||||
|
Vectors[i] = vecs[VectorOffset + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Read(DataReader r)
|
||||||
|
{
|
||||||
|
base.Read(r);
|
||||||
|
VectorCount = r.ReadByte();
|
||||||
|
Unk11 = r.ReadByte();
|
||||||
|
VectorOffset = r.ReadUInt16();
|
||||||
|
Unk13 = r.ReadUInt32();
|
||||||
|
Unk14 = r.ReadUInt32();
|
||||||
|
Unk15 = r.ReadUInt32();
|
||||||
|
|
||||||
|
//if (Unk11 != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unk13 != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unk14 != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unk15 != 0)
|
||||||
|
//{ }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return base.ToString() + " : " + VectorCount.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class WaterPool : WaterItem
|
||||||
|
{
|
||||||
|
//length:32 (from base)
|
||||||
|
|
||||||
|
public WaterPool() : base(WaterItemType.Pool) { }
|
||||||
|
public WaterPool(DataReader r) : base(WaterItemType.Pool) { Read(r); }
|
||||||
|
|
||||||
|
public override void Read(DataReader r)
|
||||||
|
{
|
||||||
|
base.Read(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return base.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string GetPGM()
|
||||||
|
{
|
||||||
|
if (GridWatermapInds == null) return string.Empty;
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("P2\n{0} {1}\n65535\n", Width, Height);
|
||||||
|
//sb.AppendFormat("P2\n{0} {1}\n255\n", Width, Height);
|
||||||
|
|
||||||
|
for (int y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Width; x++)
|
||||||
|
{
|
||||||
|
var h = GridWatermapInds[y * Width + x];
|
||||||
|
sb.Append(h.ToString());
|
||||||
|
sb.Append(" ");
|
||||||
|
}
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class WatermapXml : MetaXmlBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public static string GetXml(WatermapFile wmf)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendLine(XmlHeader);
|
||||||
|
|
||||||
|
if ((wmf != null))
|
||||||
|
{
|
||||||
|
var name = "Watermap";
|
||||||
|
|
||||||
|
OpenTag(sb, 0, name);
|
||||||
|
|
||||||
|
wmf.WriteXml(sb, 1);
|
||||||
|
|
||||||
|
CloseTag(sb, 0, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class XmlWatermap
|
||||||
|
{
|
||||||
|
|
||||||
|
public static WatermapFile GetWatermap(string xml)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xml);
|
||||||
|
return GetWatermap(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WatermapFile GetWatermap(XmlDocument doc)
|
||||||
|
{
|
||||||
|
WatermapFile wmf = new WatermapFile();
|
||||||
|
wmf.ReadXml(doc.DocumentElement);
|
||||||
|
return wmf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -81,6 +81,7 @@ namespace CodeWalker.GameFiles
|
|||||||
Yld = 25,
|
Yld = 25,
|
||||||
Yfd = 26,
|
Yfd = 26,
|
||||||
Heightmap = 27,
|
Heightmap = 27,
|
||||||
|
Watermap = 28,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,6 +200,7 @@ namespace CodeWalker.GameFiles
|
|||||||
//TestPlacements();
|
//TestPlacements();
|
||||||
//TestDrawables();
|
//TestDrawables();
|
||||||
//TestHeightmaps();
|
//TestHeightmaps();
|
||||||
|
//TestWatermaps();
|
||||||
//GetShadersXml();
|
//GetShadersXml();
|
||||||
//GetArchetypeTimesList();
|
//GetArchetypeTimesList();
|
||||||
//string typestr = PsoTypes.GetTypesString();
|
//string typestr = PsoTypes.GetTypesString();
|
||||||
@ -3953,6 +3954,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
bool savetest = false;
|
bool savetest = false;
|
||||||
var errorfiles = new List<RpfEntry>();
|
var errorfiles = new List<RpfEntry>();
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
int[] flagcheck = new int[16];
|
||||||
foreach (RpfFile file in AllRpfs)
|
foreach (RpfFile file in AllRpfs)
|
||||||
{
|
{
|
||||||
foreach (RpfEntry entry in file.AllEntries)
|
foreach (RpfEntry entry in file.AllEntries)
|
||||||
@ -3993,6 +3996,25 @@ namespace CodeWalker.GameFiles
|
|||||||
{ continue; }
|
{ continue; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
var groups = yft?.Fragment?.PhysicsLODGroup?.PhysicsLOD1?.Groups?.data_items;
|
||||||
|
if (groups != null)
|
||||||
|
{
|
||||||
|
foreach (var g in groups)
|
||||||
|
{
|
||||||
|
ushort f = (ushort)(g.UnkByte52 + (g.UnkByte53 << 8));
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (flagcheck[i]>=3) continue;
|
||||||
|
var t = 1 << i;
|
||||||
|
if ((f & t) > 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine(entry.Path + ": " + g.Name.ToString() + ", UnkByte52:" + g.UnkByte52.ToString() + ", UnkByte53:" + g.UnkByte53.ToString() + " zflag:" + (i+1).ToString());
|
||||||
|
flagcheck[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//catch (Exception ex)
|
//catch (Exception ex)
|
||||||
@ -4001,6 +4023,8 @@ namespace CodeWalker.GameFiles
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var teststr = sb.ToString();
|
||||||
|
|
||||||
if (errorfiles.Count > 0)
|
if (errorfiles.Count > 0)
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
@ -4538,6 +4562,41 @@ namespace CodeWalker.GameFiles
|
|||||||
if (errorfiles.Count > 0)
|
if (errorfiles.Count > 0)
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
public void TestWatermaps()
|
||||||
|
{
|
||||||
|
var errorfiles = new List<RpfEntry>();
|
||||||
|
foreach (RpfFile file in AllRpfs)
|
||||||
|
{
|
||||||
|
foreach (RpfEntry entry in file.AllEntries)
|
||||||
|
{
|
||||||
|
if (entry.NameLower.EndsWith(".dat") && entry.NameLower.StartsWith("waterheight"))
|
||||||
|
{
|
||||||
|
UpdateStatus(string.Format(entry.Path));
|
||||||
|
WatermapFile wmf = null;
|
||||||
|
wmf = RpfMan.GetFile<WatermapFile>(entry);
|
||||||
|
//var d1 = wmf.RawFileData;
|
||||||
|
//var d2 = wmf.Save();
|
||||||
|
//var xml = WatermapXml.GetXml(wmf);
|
||||||
|
//var wmf2 = XmlWatermap.GetWatermap(xml);
|
||||||
|
//var d2 = wmf2.Save();
|
||||||
|
|
||||||
|
//if (d1.Length == d2.Length)
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < d1.Length; i++)
|
||||||
|
// {
|
||||||
|
// if (d1[i] != d2[i])
|
||||||
|
// { }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{ }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorfiles.Count > 0)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
public void GetShadersXml()
|
public void GetShadersXml()
|
||||||
{
|
{
|
||||||
bool doydr = true;
|
bool doydr = true;
|
||||||
|
170
CodeWalker.Core/World/Heightmaps.cs
Normal file
170
CodeWalker.Core/World/Heightmaps.cs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
using CodeWalker.GameFiles;
|
||||||
|
using SharpDX;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CodeWalker.World
|
||||||
|
{
|
||||||
|
public class Heightmaps : BasePathData
|
||||||
|
{
|
||||||
|
public volatile bool Inited = false;
|
||||||
|
public GameFileCache GameFileCache;
|
||||||
|
|
||||||
|
public List<HeightmapFile> HeightmapFiles = new List<HeightmapFile>();
|
||||||
|
|
||||||
|
|
||||||
|
public Vector4[] GetNodePositions()
|
||||||
|
{
|
||||||
|
return NodePositions;
|
||||||
|
}
|
||||||
|
public EditorVertex[] GetPathVertices()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public EditorVertex[] GetTriangleVertices()
|
||||||
|
{
|
||||||
|
return TriangleVerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4[] NodePositions;
|
||||||
|
public EditorVertex[] TriangleVerts;
|
||||||
|
|
||||||
|
|
||||||
|
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||||
|
{
|
||||||
|
Inited = false;
|
||||||
|
|
||||||
|
GameFileCache = gameFileCache;
|
||||||
|
|
||||||
|
|
||||||
|
HeightmapFiles.Clear();
|
||||||
|
|
||||||
|
|
||||||
|
if (gameFileCache.EnableDlc)
|
||||||
|
{
|
||||||
|
LoadHeightmap("update\\update.rpf\\common\\data\\levels\\gta5\\heightmap.dat");
|
||||||
|
LoadHeightmap("update\\update.rpf\\common\\data\\levels\\gta5\\heightmapheistisland.dat");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadHeightmap("common.rpf\\data\\levels\\gta5\\heightmap.dat");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BuildVertices();
|
||||||
|
|
||||||
|
Inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadHeightmap(string filename)
|
||||||
|
{
|
||||||
|
var hmf = GameFileCache.RpfMan.GetFile<HeightmapFile>(filename);
|
||||||
|
HeightmapFiles.Add(hmf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void BuildVertices()
|
||||||
|
{
|
||||||
|
|
||||||
|
var vlist = new List<EditorVertex>();
|
||||||
|
var nlist = new List<Vector4>();
|
||||||
|
|
||||||
|
foreach (var hmf in HeightmapFiles)
|
||||||
|
{
|
||||||
|
BuildHeightmapVertices(hmf, vlist, nlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vlist.Count > 0)
|
||||||
|
{
|
||||||
|
TriangleVerts = vlist.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TriangleVerts = null;
|
||||||
|
}
|
||||||
|
if (nlist.Count > 0)
|
||||||
|
{
|
||||||
|
NodePositions = nlist.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NodePositions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private void BuildHeightmapVertices(HeightmapFile hmf, List<EditorVertex> vl, List<Vector4> nl)
|
||||||
|
{
|
||||||
|
var v1 = new EditorVertex();
|
||||||
|
var v2 = new EditorVertex();
|
||||||
|
var v3 = new EditorVertex();
|
||||||
|
var v4 = new EditorVertex();
|
||||||
|
|
||||||
|
uint cgrn = (uint)new Color(0, 128, 0, 60).ToRgba();
|
||||||
|
uint cyel = (uint)new Color(128, 128, 0, 200).ToRgba();
|
||||||
|
|
||||||
|
var w = hmf.Width;
|
||||||
|
var h = hmf.Height;
|
||||||
|
var hmin = hmf.MinHeights;
|
||||||
|
var hmax = hmf.MaxHeights;
|
||||||
|
var min = hmf.BBMin;
|
||||||
|
var max = hmf.BBMax;
|
||||||
|
var siz = max - min;
|
||||||
|
var step = siz / new Vector3(w - 1, h - 1, 255);
|
||||||
|
|
||||||
|
v1.Colour = v2.Colour = v3.Colour = v4.Colour = cyel;
|
||||||
|
for (int yi = 1; yi < h; yi++)
|
||||||
|
{
|
||||||
|
var yo = yi - 1;
|
||||||
|
for (int xi = 1; xi < w; xi++)
|
||||||
|
{
|
||||||
|
var xo = xi - 1;
|
||||||
|
var o1 = yo * w + xo;
|
||||||
|
var o2 = yo * w + xi;
|
||||||
|
var o3 = yi * w + xo;
|
||||||
|
var o4 = yi * w + xi;
|
||||||
|
v1.Position = min + step * new Vector3(xo, yo, hmin[o1]);
|
||||||
|
v2.Position = min + step * new Vector3(xi, yo, hmin[o2]);
|
||||||
|
v3.Position = min + step * new Vector3(xo, yi, hmin[o3]);
|
||||||
|
v4.Position = min + step * new Vector3(xi, yi, hmin[o4]);
|
||||||
|
vl.Add(v1); vl.Add(v2); vl.Add(v3);
|
||||||
|
vl.Add(v3); vl.Add(v2); vl.Add(v4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v1.Colour = v2.Colour = v3.Colour = v4.Colour = cgrn;
|
||||||
|
for (int yi = 1; yi < h; yi++)
|
||||||
|
{
|
||||||
|
var yo = yi - 1;
|
||||||
|
for (int xi = 1; xi < w; xi++)
|
||||||
|
{
|
||||||
|
var xo = xi - 1;
|
||||||
|
var o1 = yo * w + xo;
|
||||||
|
var o2 = yo * w + xi;
|
||||||
|
var o3 = yi * w + xo;
|
||||||
|
var o4 = yi * w + xi;
|
||||||
|
v1.Position = min + step * new Vector3(xo, yo, hmax[o1]);
|
||||||
|
v2.Position = min + step * new Vector3(xi, yo, hmax[o2]);
|
||||||
|
v3.Position = min + step * new Vector3(xo, yi, hmax[o3]);
|
||||||
|
v4.Position = min + step * new Vector3(xi, yi, hmax[o4]);
|
||||||
|
vl.Add(v1); vl.Add(v2); vl.Add(v3);
|
||||||
|
vl.Add(v3); vl.Add(v2); vl.Add(v4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < w; x++)
|
||||||
|
{
|
||||||
|
var o = y * w + x;
|
||||||
|
nl.Add(new Vector4(min + step * new Vector3(x, y, hmin[o]), 10));
|
||||||
|
nl.Add(new Vector4(min + step * new Vector3(x, y, hmax[o]), 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
290
CodeWalker.Core/World/Watermaps.cs
Normal file
290
CodeWalker.Core/World/Watermaps.cs
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
using CodeWalker.GameFiles;
|
||||||
|
using SharpDX;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CodeWalker.World
|
||||||
|
{
|
||||||
|
public class Watermaps : BasePathData
|
||||||
|
{
|
||||||
|
public volatile bool Inited = false;
|
||||||
|
public GameFileCache GameFileCache;
|
||||||
|
|
||||||
|
public List<WatermapFile> WatermapFiles = new List<WatermapFile>();
|
||||||
|
|
||||||
|
|
||||||
|
public Vector4[] GetNodePositions()
|
||||||
|
{
|
||||||
|
return NodePositions;
|
||||||
|
}
|
||||||
|
public EditorVertex[] GetPathVertices()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public EditorVertex[] GetTriangleVertices()
|
||||||
|
{
|
||||||
|
return TriangleVerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4[] NodePositions;
|
||||||
|
public EditorVertex[] TriangleVerts;
|
||||||
|
|
||||||
|
|
||||||
|
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
|
||||||
|
{
|
||||||
|
Inited = false;
|
||||||
|
|
||||||
|
GameFileCache = gameFileCache;
|
||||||
|
|
||||||
|
|
||||||
|
WatermapFiles.Clear();
|
||||||
|
|
||||||
|
|
||||||
|
LoadWatermap("common.rpf\\data\\levels\\gta5\\waterheight.dat");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BuildVertices();
|
||||||
|
|
||||||
|
Inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadWatermap(string filename)
|
||||||
|
{
|
||||||
|
var wmf = GameFileCache.RpfMan.GetFile<WatermapFile>(filename);
|
||||||
|
WatermapFiles.Add(wmf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void BuildVertices()
|
||||||
|
{
|
||||||
|
|
||||||
|
var vlist = new List<EditorVertex>();
|
||||||
|
var nlist = new List<Vector4>();
|
||||||
|
|
||||||
|
foreach (var wmf in WatermapFiles)
|
||||||
|
{
|
||||||
|
BuildWatermapVertices(wmf, vlist, nlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vlist.Count > 0)
|
||||||
|
{
|
||||||
|
TriangleVerts = vlist.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TriangleVerts = null;
|
||||||
|
}
|
||||||
|
if (nlist.Count > 0)
|
||||||
|
{
|
||||||
|
NodePositions = nlist.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NodePositions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private void BuildWatermapVertices(WatermapFile wmf, List<EditorVertex> vl, List<Vector4> nl)
|
||||||
|
{
|
||||||
|
var v1 = new EditorVertex();
|
||||||
|
var v2 = new EditorVertex();
|
||||||
|
var v3 = new EditorVertex();
|
||||||
|
var v4 = new EditorVertex();
|
||||||
|
|
||||||
|
uint cblu = (uint)new Color(0, 0, 128, 60).ToRgba();
|
||||||
|
|
||||||
|
|
||||||
|
float getHeight(int o)
|
||||||
|
{
|
||||||
|
var harr = wmf.GridWatermapRefs[o];
|
||||||
|
if (harr == null) return 0;
|
||||||
|
if (harr.Length == 0) return 0;
|
||||||
|
var h0 = harr[0];
|
||||||
|
var i0 = h0.Item;
|
||||||
|
if (h0.Type == WatermapFile.WaterItemType.River)
|
||||||
|
{
|
||||||
|
return h0.Vector.Z;
|
||||||
|
}
|
||||||
|
if (h0.Type == WatermapFile.WaterItemType.Lake)
|
||||||
|
{
|
||||||
|
if (i0 != null) return i0.Position.Z;
|
||||||
|
}
|
||||||
|
if (h0.Type == WatermapFile.WaterItemType.Pool)
|
||||||
|
{
|
||||||
|
if (i0 != null) return i0.Position.Z;
|
||||||
|
}
|
||||||
|
return h0.Vector.Z;
|
||||||
|
}
|
||||||
|
uint getColour(int o)
|
||||||
|
{
|
||||||
|
var harr = wmf.GridWatermapRefs[o];
|
||||||
|
if (harr == null) return cblu;
|
||||||
|
if (harr.Length == 0) return cblu;
|
||||||
|
var i0 = harr[0].Item;
|
||||||
|
if (i0 == null) return cblu;
|
||||||
|
var c = i0.Colour;
|
||||||
|
c.A = 128;
|
||||||
|
return (uint)c.ToRgba();
|
||||||
|
}
|
||||||
|
var w = wmf.Width;
|
||||||
|
var h = wmf.Height;
|
||||||
|
var min = new Vector3(wmf.CornerX, wmf.CornerY, 0.0f);
|
||||||
|
var step = new Vector3(wmf.TileX, -wmf.TileY, 1.0f);
|
||||||
|
//var siz = new Vector3(w, h, 1) * step;
|
||||||
|
for (int yi = 1; yi < h; yi++)
|
||||||
|
{
|
||||||
|
var yo = yi - 1;
|
||||||
|
for (int xi = 1; xi < w; xi++)
|
||||||
|
{
|
||||||
|
var xo = xi - 1;
|
||||||
|
var o1 = yi * w + xo;
|
||||||
|
var o2 = yi * w + xi;
|
||||||
|
var o3 = yo * w + xo;
|
||||||
|
var o4 = yo * w + xi;
|
||||||
|
v1.Position = min + step * new Vector3(xo, yi, getHeight(o1));
|
||||||
|
v2.Position = min + step * new Vector3(xi, yi, getHeight(o2));
|
||||||
|
v3.Position = min + step * new Vector3(xo, yo, getHeight(o3));
|
||||||
|
v4.Position = min + step * new Vector3(xi, yo, getHeight(o4));
|
||||||
|
v1.Colour = getColour(o1);
|
||||||
|
v2.Colour = getColour(o2);
|
||||||
|
v3.Colour = getColour(o3);
|
||||||
|
v4.Colour = getColour(o4);
|
||||||
|
//vl.Add(v1); vl.Add(v2); vl.Add(v3);
|
||||||
|
//vl.Add(v3); vl.Add(v2); vl.Add(v4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//for (int y = 0; y < h; y++)
|
||||||
|
//{
|
||||||
|
// for (int x = 0; x < w; x++)
|
||||||
|
// {
|
||||||
|
// var o = y * w + x;
|
||||||
|
// nl.Add(new Vector4(min + step * new Vector3(x, y, getHeight(o)), 10));
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
void addQuad(Quad q)
|
||||||
|
{
|
||||||
|
v1.Position = q.P1;
|
||||||
|
v2.Position = q.P2;
|
||||||
|
v3.Position = q.P3;
|
||||||
|
v4.Position = q.P4;
|
||||||
|
vl.Add(v1); vl.Add(v2); vl.Add(v3);
|
||||||
|
vl.Add(v3); vl.Add(v2); vl.Add(v4);
|
||||||
|
}
|
||||||
|
void addRivEnd(Vector3 p, Vector3 s, Vector3 d, float r)
|
||||||
|
{
|
||||||
|
v1.Position = p;
|
||||||
|
v2.Position = p + s * r;
|
||||||
|
v3.Position = p + d * r;
|
||||||
|
v4.Position = p - s * r;
|
||||||
|
vl.Add(v1); vl.Add(v2); vl.Add(v3);
|
||||||
|
vl.Add(v1); vl.Add(v3); vl.Add(v4);
|
||||||
|
}
|
||||||
|
var rivers = wmf.Rivers;
|
||||||
|
if (rivers != null)
|
||||||
|
{
|
||||||
|
foreach (var river in rivers)
|
||||||
|
{
|
||||||
|
if ((river.Vectors == null) || (river.VectorCount <= 1))
|
||||||
|
{ continue; }
|
||||||
|
|
||||||
|
var rwid = 20.0f;
|
||||||
|
var rc = river.Colour;
|
||||||
|
rc.A = 128;
|
||||||
|
v1.Colour = v2.Colour = v3.Colour = v4.Colour = (uint)rc.ToRgba();
|
||||||
|
var quads = new Quad[river.Vectors.Length - 1];
|
||||||
|
var li = river.Vectors.Length - 1;
|
||||||
|
for (int i = 1; i < river.Vectors.Length; i++)
|
||||||
|
{
|
||||||
|
var o = i - 1;
|
||||||
|
var vo = river.Vectors[o];
|
||||||
|
var vi = river.Vectors[i];
|
||||||
|
var dif = vi.XYZ() - vo.XYZ();
|
||||||
|
var dir = Vector3.Normalize(dif);
|
||||||
|
var sid = Vector3.Normalize(Vector3.Cross(dir, Vector3.UnitZ));
|
||||||
|
if (Math.Abs(dir.Z) > 0.95f)
|
||||||
|
{
|
||||||
|
dir = Vector3.UnitY;
|
||||||
|
sid = Vector3.UnitX;
|
||||||
|
}
|
||||||
|
quads[o].P1 = vo.XYZ() - sid*rwid;
|
||||||
|
quads[o].P2 = vo.XYZ() + sid*rwid;
|
||||||
|
quads[o].P3 = vi.XYZ() - sid*rwid;
|
||||||
|
quads[o].P4 = vi.XYZ() + sid*rwid;
|
||||||
|
if (i == 1) addRivEnd(vo.XYZ(), -sid, -dir, rwid);
|
||||||
|
if (i == li) addRivEnd(vi.XYZ(), sid, dir, rwid);
|
||||||
|
}
|
||||||
|
for (int i = 1; i < quads.Length; i++)
|
||||||
|
{
|
||||||
|
var o = i - 1;
|
||||||
|
quads[o].P3 = quads[i].P1 = (quads[o].P3 + quads[i].P1) * 0.5f;
|
||||||
|
quads[o].P4 = quads[i].P2 = (quads[o].P4 + quads[i].P2) * 0.5f;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < quads.Length; i++)
|
||||||
|
{
|
||||||
|
addQuad(quads[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var lakes = wmf.Lakes;
|
||||||
|
if (lakes != null)
|
||||||
|
{
|
||||||
|
foreach (var lake in lakes)
|
||||||
|
{
|
||||||
|
if ((lake.Vectors == null) || (lake.VectorCount == 0))
|
||||||
|
{ continue; }
|
||||||
|
|
||||||
|
var lp = lake.Position;
|
||||||
|
var lc = lake.Colour;
|
||||||
|
lc.A = 128;
|
||||||
|
v1.Colour = v2.Colour = v3.Colour = v4.Colour = (uint)lc.ToRgba();
|
||||||
|
for (int i = 0; i < lake.Vectors.Length; i++)
|
||||||
|
{
|
||||||
|
var vi = lake.Vectors[i];
|
||||||
|
var vp = new Vector3(vi.X, vi.Y, lp.Z);
|
||||||
|
var q = new Quad();
|
||||||
|
q.P1 = vp + new Vector3(vi.Z, -vi.W, 0);
|
||||||
|
q.P2 = vp + new Vector3(vi.Z, vi.W, 0);
|
||||||
|
q.P3 = vp + new Vector3(-vi.Z, -vi.W, 0);
|
||||||
|
q.P4 = vp + new Vector3(-vi.Z, vi.W, 0);
|
||||||
|
addQuad(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pools = wmf.Pools;
|
||||||
|
if (pools != null)
|
||||||
|
{
|
||||||
|
foreach (var pool in pools)
|
||||||
|
{
|
||||||
|
var pp = pool.Position;
|
||||||
|
var ps = pool.Size;
|
||||||
|
var pc = pool.Colour;
|
||||||
|
pc.A = 128;
|
||||||
|
v1.Colour = v2.Colour = v3.Colour = v4.Colour = (uint)pc.ToRgba();
|
||||||
|
var q = new Quad();
|
||||||
|
q.P1 = pp + new Vector3(ps.X, -ps.Y, 0);
|
||||||
|
q.P2 = pp + new Vector3(ps.X, ps.Y, 0);
|
||||||
|
q.P3 = pp + new Vector3(-ps.X, -ps.Y, 0);
|
||||||
|
q.P4 = pp + new Vector3(-ps.X, ps.Y, 0);
|
||||||
|
addQuad(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Quad
|
||||||
|
{
|
||||||
|
public Vector3 P1;
|
||||||
|
public Vector3 P2;
|
||||||
|
public Vector3 P3;
|
||||||
|
public Vector3 P4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,8 +32,10 @@ namespace CodeWalker
|
|||||||
MloInstance = 13,
|
MloInstance = 13,
|
||||||
Scenario = 14,
|
Scenario = 14,
|
||||||
PopZone = 15,
|
PopZone = 15,
|
||||||
Audio = 16,
|
Heightmap = 16,
|
||||||
Occlusion = 17,
|
Watermap = 17,
|
||||||
|
Audio = 18,
|
||||||
|
Occlusion = 19,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ namespace CodeWalker
|
|||||||
Trains trains = new Trains();
|
Trains trains = new Trains();
|
||||||
Scenarios scenarios = new Scenarios();
|
Scenarios scenarios = new Scenarios();
|
||||||
PopZones popzones = new PopZones();
|
PopZones popzones = new PopZones();
|
||||||
|
Heightmaps heightmaps = new Heightmaps();
|
||||||
|
Watermaps watermaps = new Watermaps();
|
||||||
AudioZones audiozones = new AudioZones();
|
AudioZones audiozones = new AudioZones();
|
||||||
|
|
||||||
public Space Space { get { return space; } }
|
public Space Space { get { return space; } }
|
||||||
@ -138,6 +140,8 @@ namespace CodeWalker
|
|||||||
List<YmtFile> renderscenariolist = new List<YmtFile>();
|
List<YmtFile> renderscenariolist = new List<YmtFile>();
|
||||||
|
|
||||||
bool renderpopzones = false;
|
bool renderpopzones = false;
|
||||||
|
bool renderheightmaps = false;
|
||||||
|
bool renderwatermaps = false;
|
||||||
|
|
||||||
bool renderaudiozones = false;
|
bool renderaudiozones = false;
|
||||||
bool renderaudioouterbounds = true;
|
bool renderaudioouterbounds = true;
|
||||||
@ -729,6 +733,14 @@ namespace CodeWalker
|
|||||||
{
|
{
|
||||||
RenderWorldPopZones();
|
RenderWorldPopZones();
|
||||||
}
|
}
|
||||||
|
if (renderheightmaps || (SelectionMode == MapSelectionMode.Heightmap))
|
||||||
|
{
|
||||||
|
RenderWorldHeightmaps();
|
||||||
|
}
|
||||||
|
if (renderwatermaps || (SelectionMode == MapSelectionMode.Watermap))
|
||||||
|
{
|
||||||
|
RenderWorldWatermaps();
|
||||||
|
}
|
||||||
if (renderaudiozones || (SelectionMode == MapSelectionMode.Audio))
|
if (renderaudiozones || (SelectionMode == MapSelectionMode.Audio))
|
||||||
{
|
{
|
||||||
RenderWorldAudioZones();
|
RenderWorldAudioZones();
|
||||||
@ -889,6 +901,36 @@ namespace CodeWalker
|
|||||||
Renderer.RenderPopZones(popzones);
|
Renderer.RenderPopZones(popzones);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RenderWorldHeightmaps()
|
||||||
|
{
|
||||||
|
if (!heightmaps.Inited) return;
|
||||||
|
|
||||||
|
//renderheightmaplist.Clear();
|
||||||
|
//renderheightmaplist.AddRange(heightmaps.Heightmaps);
|
||||||
|
|
||||||
|
if (ProjectForm != null)
|
||||||
|
{
|
||||||
|
//ProjectForm.GetVisibleHeightmaps(camera, renderheightmaplist);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer.RenderBasePath(heightmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderWorldWatermaps()
|
||||||
|
{
|
||||||
|
if (!watermaps.Inited) return;
|
||||||
|
|
||||||
|
//renderwatermaplist.Clear();
|
||||||
|
//renderwatermaplist.AddRange(watermaps.Watermaps);
|
||||||
|
|
||||||
|
if (ProjectForm != null)
|
||||||
|
{
|
||||||
|
//ProjectForm.GetVisibleWatermaps(camera, renderwatermaplist);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer.RenderBasePath(watermaps);
|
||||||
|
}
|
||||||
|
|
||||||
private void RenderWorldAudioZones()
|
private void RenderWorldAudioZones()
|
||||||
{
|
{
|
||||||
if (!audiozones.Inited) return;
|
if (!audiozones.Inited) return;
|
||||||
@ -4010,6 +4052,12 @@ namespace CodeWalker
|
|||||||
UpdateStatus("Loading popzones...");
|
UpdateStatus("Loading popzones...");
|
||||||
popzones.Init(gameFileCache, UpdateStatus);
|
popzones.Init(gameFileCache, UpdateStatus);
|
||||||
|
|
||||||
|
UpdateStatus("Loading heightmaps...");
|
||||||
|
heightmaps.Init(gameFileCache, UpdateStatus);
|
||||||
|
|
||||||
|
UpdateStatus("Loading watermaps...");
|
||||||
|
watermaps.Init(gameFileCache, UpdateStatus);
|
||||||
|
|
||||||
UpdateStatus("Loading audio zones...");
|
UpdateStatus("Loading audio zones...");
|
||||||
audiozones.Init(gameFileCache, UpdateStatus);
|
audiozones.Init(gameFileCache, UpdateStatus);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user