summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xNW4RTools/BrresReader.cs33
-rwxr-xr-xNW4RTools/BrresWriter.cs548
-rw-r--r--NW4RTools/ColladaExporter.cs22
-rw-r--r--NW4RTools/Models/Animation/CharacterAnim.cs6
-rwxr-xr-xNW4RTools/Models/ByteCode.cs2
-rw-r--r--NW4RTools/ObjExporter.cs19
-rwxr-xr-xNW4RTools/ObjImporter.cs53
-rw-r--r--NW4RTools/Texture.cs6
-rwxr-xr-xTestApp/Main.cs312
9 files changed, 679 insertions, 322 deletions
diff --git a/NW4RTools/BrresReader.cs b/NW4RTools/BrresReader.cs
index 9616b5b..fbf2e2a 100755
--- a/NW4RTools/BrresReader.cs
+++ b/NW4RTools/BrresReader.cs
@@ -354,7 +354,7 @@ namespace NW4RTools {
UInt16 kfCount = ins.ReadUInt16();
ins.Skip(2);
- OffsetMap[kfPos] = String.Format("Element Keyframe Data for {0:X} [{1} frames]", savePos, kfCount);
+ OffsetMap[kfPos] = String.Format("Element Keyframe Data for {0:X} [{1} frames] format: {2}", savePos, kfCount, format);
float invKeyFrameRange = ins.ReadFloat();
elem.Keyframes = new Keyframe[kfCount];
@@ -390,8 +390,8 @@ namespace NW4RTools {
ins.Seek(savePos + 4);
} else if (
- format == CharacterAnim.RotateFormatType.DataUnk4 ||
- format == CharacterAnim.RotateFormatType.DataUnk5) {
+ format == CharacterAnim.RotateFormatType.DataFrm8 ||
+ format == CharacterAnim.RotateFormatType.DataFrm16) {
// SOMETHING ELSE
int savePos = ins.Position;
ins.Seek(startPos + ins.ReadInt32());
@@ -401,14 +401,14 @@ namespace NW4RTools {
elem.Multiplier = ins.ReadFloat();
elem.BaseValue = ins.ReadFloat();
- elem.Values = new int[CHR_ANIM_HACK.FrameCount];
+ elem.Values = new int[CHR_ANIM_HACK.FrameCount + 1];
- for (int i = 0; i < CHR_ANIM_HACK.FrameCount; i++) {
+ for (int i = 0; i < (CHR_ANIM_HACK.FrameCount + 1); i++) {
switch (format) {
- case CharacterAnim.RotateFormatType.DataUnk4:
+ case CharacterAnim.RotateFormatType.DataFrm8:
elem.Values[i] = ins.ReadByte();
break;
- case CharacterAnim.RotateFormatType.DataUnk5:
+ case CharacterAnim.RotateFormatType.DataFrm16:
elem.Values[i] = ins.ReadUInt16();
break;
}
@@ -417,18 +417,17 @@ namespace NW4RTools {
ins.Seek(savePos + 4);
} else if (
- format == CharacterAnim.RotateFormatType.DataUnk6) {
+ format == CharacterAnim.RotateFormatType.DataFrm32) {
// WHAT THE FUCK
int savePos = ins.Position;
ins.Seek(startPos + ins.ReadInt32());
int kfPos = ins.Position;
- OffsetMap[kfPos] = String.Format("Element Type 6 Frame Data for {0:X}", savePos);
+ OffsetMap[kfPos] = String.Format("Element Constant Frame Data for {0:X}", savePos);
- elem.BaseValue = ins.ReadFloat();
- elem.FloatValues = new float[CHR_ANIM_HACK.FrameCount];
+ elem.FloatValues = new float[CHR_ANIM_HACK.FrameCount + 1];
- for (int i = 0; i < CHR_ANIM_HACK.FrameCount; i++) {
+ for (int i = 0; i < (CHR_ANIM_HACK.FrameCount + 1); i++) {
elem.FloatValues[i] = ins.ReadFloat();
}
@@ -516,7 +515,7 @@ namespace NW4RTools {
if (elem.IsConstant) {
elem.ConstValue = ins.ReadColor();
- } else {
+ } else {
int savePos = ins.Position;
ins.Seek(savePos + ins.ReadInt32());
@@ -608,8 +607,8 @@ namespace NW4RTools {
var elem = new TextureSRTAnim.Element();
int savePos = ins.Position;
- ins.Seek(startPos + ins.ReadInt32());
-
+ ins.Seek(startPos + ins.ReadInt32());
+
elem.Exists = true;
OffsetMap.Add(ins.Position, String.Format("Element"));
@@ -876,8 +875,8 @@ namespace NW4RTools {
var insn4 = new ByteCode.DrawShapeInstruction();
insn4.MaterialID = ins.ReadUInt16();
insn4.ShapeID = ins.ReadUInt16();
- insn4.NodeID = ins.ReadUInt16();
- insn4.Unk = ins.ReadByte();
+ insn4.NodeID = ins.ReadUInt16();
+ insn4.Unk = ins.ReadByte();
bc.Instructions.Add(insn4);
break;
diff --git a/NW4RTools/BrresWriter.cs b/NW4RTools/BrresWriter.cs
index 033007e..0b81a65 100755
--- a/NW4RTools/BrresWriter.cs
+++ b/NW4RTools/BrresWriter.cs
@@ -80,12 +80,12 @@ namespace NW4RTools {
public int PairingLookupByTexture;
public int BlockSize;
// Duplicate shader structs are removed from the model, so they require special tracking
- public List<Shader> UniqueShaders;
- public Dictionary<Material, int> MaterialSizes;
-
- public ModelCalcInfo() {
- UniqueShaders = new List<Shader>();
- MaterialSizes = new Dictionary<Material,int>();
+ public List<Shader> UniqueShaders;
+ public Dictionary<Material, int> MaterialSizes;
+
+ public ModelCalcInfo() {
+ UniqueShaders = new List<Shader>();
+ MaterialSizes = new Dictionary<Material,int>();
}
}
private Dictionary<Model, ModelCalcInfo> ModelCalcInfos;
@@ -133,11 +133,11 @@ namespace NW4RTools {
#region Texture SRT Animation Data Storage
private class TexSRTAnmNodeInfo {
public int[] TextureOffsets;
- public int[] IndirectTextureOffsets;
-
- public TexSRTAnmNodeInfo() {
- TextureOffsets = new int[8];
- IndirectTextureOffsets = new int[3];
+ public int[] IndirectTextureOffsets;
+
+ public TexSRTAnmNodeInfo() {
+ TextureOffsets = new int[8];
+ IndirectTextureOffsets = new int[3];
}
}
@@ -478,8 +478,8 @@ namespace NW4RTools {
MaterialDLOffsets[kv.Value] = CurrentPos;
CurrentPos += 0x20 + 0x80 + 0x40 + 0xA0;
- // Sized!
- int size = CurrentPos - MaterialOffsets[kv.Value];
+ // Sized!
+ int size = CurrentPos - MaterialOffsets[kv.Value];
ModelCalcInfos[m].MaterialSizes[kv.Value] = size;
}
}
@@ -830,14 +830,14 @@ namespace NW4RTools {
case CharacterAnim.RotateFormatType.Data96:
CurrentPos += 8 + (kf.Keyframes.Length * 12);
break;
- case CharacterAnim.RotateFormatType.DataUnk4:
+ case CharacterAnim.RotateFormatType.DataFrm8:
CurrentPos += 8 + (kf.Values.Length);
break;
- case CharacterAnim.RotateFormatType.DataUnk5:
+ case CharacterAnim.RotateFormatType.DataFrm16:
CurrentPos += 8 + (kf.Values.Length * 2);
break;
- case CharacterAnim.RotateFormatType.DataUnk6:
- CurrentPos += 4 + (kf.FloatValues.Length * 4);
+ case CharacterAnim.RotateFormatType.DataFrm32:
+ CurrentPos += (kf.FloatValues.Length * 4);
break;
default:
throw new NotImplementedException();
@@ -942,8 +942,8 @@ namespace NW4RTools {
CurrentPos += GetSizeForResDict(anim.Nodes.Count);
var anminfo = new TexSRTAnmInfo();
- TexSRTAnmInfos.Add(anim, anminfo);
-
+ TexSRTAnmInfos.Add(anim, anminfo);
+
// Now size each node
foreach (var nodepair in anim.Nodes) {
AddString(nodepair.Key);
@@ -954,29 +954,29 @@ namespace NW4RTools {
LogPosition("TextureSRT Anim Node: " + nodepair.Key);
CurrentPos += 12;
- var nodeinfo = new TexSRTAnmNodeInfo();
- anminfo.NodeInfo.Add(node, nodeinfo);
-
- // Figure out what anims we're using
- for (int i = 0; i < 8; i++)
- if (node.Textures[i].Exists)
- CurrentPos += 4;
- for (int i = 0; i < 3; i++)
- if (node.IndirectTextures[i].Exists)
- CurrentPos += 4;
-
- for (int i = 0; i < 8; i++) {
- if (node.Textures[i].Exists) {
- nodeinfo.TextureOffsets[i] = CurrentPos;
- CalculateAnmTexSrtElement(anminfo.KFInfo, node.Textures[i]);
- }
- }
-
- for (int i = 0; i < 3; i++) {
- if (node.IndirectTextures[i].Exists) {
- nodeinfo.IndirectTextureOffsets[i] = CurrentPos;
- CalculateAnmTexSrtElement(anminfo.KFInfo, node.IndirectTextures[i]);
- }
+ var nodeinfo = new TexSRTAnmNodeInfo();
+ anminfo.NodeInfo.Add(node, nodeinfo);
+
+ // Figure out what anims we're using
+ for (int i = 0; i < 8; i++)
+ if (node.Textures[i].Exists)
+ CurrentPos += 4;
+ for (int i = 0; i < 3; i++)
+ if (node.IndirectTextures[i].Exists)
+ CurrentPos += 4;
+
+ for (int i = 0; i < 8; i++) {
+ if (node.Textures[i].Exists) {
+ nodeinfo.TextureOffsets[i] = CurrentPos;
+ CalculateAnmTexSrtElement(anminfo.KFInfo, node.Textures[i]);
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ if (node.IndirectTextures[i].Exists) {
+ nodeinfo.IndirectTextureOffsets[i] = CurrentPos;
+ CalculateAnmTexSrtElement(anminfo.KFInfo, node.IndirectTextures[i]);
+ }
}
}
@@ -984,51 +984,51 @@ namespace NW4RTools {
anminfo.BlockSize = CurrentPos - TexSRTAnmOffsets[anim];
}
- }
-
- private void CalculateAnmTexSrtElement(KeyframeWriterInfo kfinfo, TextureSRTAnim.Element elem) {
- CurrentPos += 4;
-
- if (!(elem.ScaleS.IsConstWith(1) && elem.ScaleT.IsConstWith(1))) {
- // Scale is not all 1
- kfinfo.Add(elem.ScaleS);
- CurrentPos += 4;
-
- if (elem.ScaleT != elem.ScaleS) {
- // Not uniform
- kfinfo.Add(elem.ScaleT);
- CurrentPos += 4;
- }
- }
-
- if (!elem.Rotate.IsConstWith(0)) {
- // Rotate is not zero
- kfinfo.Add(elem.Rotate);
- CurrentPos += 4;
- }
-
- if (!(elem.TransS.IsConstWith(0) && elem.TransT.IsConstWith(0))) {
- // Translate is not all zero
- kfinfo.Add(elem.TransS);
- kfinfo.Add(elem.TransT);
- CurrentPos += 8;
- }
}
- #endregion
-
- #region Keyframe Animation Calculation
- private void CalculateKeyframeData(KeyframeWriterInfo kfinfo) {
- foreach (var pair in kfinfo.KeyframeAnims) {
- var anim = pair.two;
-
- kfinfo.KeyframeAnimOffsets[pair] = CurrentPos;
-
- CurrentPos += 8 + (anim.Keyframes.Length * 12);
- }
- }
- #endregion
-
-
+
+ private void CalculateAnmTexSrtElement(KeyframeWriterInfo kfinfo, TextureSRTAnim.Element elem) {
+ CurrentPos += 4;
+
+ if (!(elem.ScaleS.IsConstWith(1) && elem.ScaleT.IsConstWith(1))) {
+ // Scale is not all 1
+ kfinfo.Add(elem.ScaleS);
+ CurrentPos += 4;
+
+ if (elem.ScaleT != elem.ScaleS) {
+ // Not uniform
+ kfinfo.Add(elem.ScaleT);
+ CurrentPos += 4;
+ }
+ }
+
+ if (!elem.Rotate.IsConstWith(0)) {
+ // Rotate is not zero
+ kfinfo.Add(elem.Rotate);
+ CurrentPos += 4;
+ }
+
+ if (!(elem.TransS.IsConstWith(0) && elem.TransT.IsConstWith(0))) {
+ // Translate is not all zero
+ kfinfo.Add(elem.TransS);
+ kfinfo.Add(elem.TransT);
+ CurrentPos += 8;
+ }
+ }
+ #endregion
+
+ #region Keyframe Animation Calculation
+ private void CalculateKeyframeData(KeyframeWriterInfo kfinfo) {
+ foreach (var pair in kfinfo.KeyframeAnims) {
+ var anim = pair.two;
+
+ kfinfo.KeyframeAnimOffsets[pair] = CurrentPos;
+
+ CurrentPos += 8 + (anim.Keyframes.Length * 12);
+ }
+ }
+ #endregion
+
+
private void AlignCalcPos(int alignTo) {
if ((CurrentPos & (alignTo - 1)) == 0)
return;
@@ -1277,7 +1277,7 @@ namespace NW4RTools {
var op4 = insn as ByteCode.DrawShapeInstruction;
Output.WriteUInt16(op4.MaterialID);
Output.WriteUInt16(op4.ShapeID);
- Output.WriteUInt16(op4.NodeID);
+ Output.WriteUInt16(op4.NodeID);
Output.WriteByte(op4.Unk);
break;
@@ -1346,7 +1346,7 @@ namespace NW4RTools {
Material mat = kv.Value;
int startPos = Output.Position;
- // size, model offset, name offset, index
+ // size, model offset, name offset, index
var modelInfo = ModelCalcInfos[m];
Output.WriteUInt32((UInt32)modelInfo.MaterialSizes[mat]);
Output.WriteInt32(ModelOffsets[m] - startPos);
@@ -1907,6 +1907,19 @@ namespace NW4RTools {
Output.WriteFloat(invKeyFrameRange);
}
+ if (format == CharacterAnim.RotateFormatType.DataFrm8 ||
+ format == CharacterAnim.RotateFormatType.DataFrm16) {
+ // Header for CV 8 and 16
+ Output.WriteFloat(kf.Multiplier);
+ Output.WriteFloat(kf.BaseValue);
+ Misc.Assert(kf.Values.Length == (anm.FrameCount + 1));
+ }
+
+ if (format == CharacterAnim.RotateFormatType.DataFrm32) {
+ // Assert this
+ Misc.Assert(kf.FloatValues.Length == (anm.FrameCount + 1));
+ }
+
switch (format) {
case CharacterAnim.RotateFormatType.Data32:
for (int i = 0; i < kf.Keyframes.Length; i++) {
@@ -1930,8 +1943,23 @@ namespace NW4RTools {
Output.WriteFloat(kf.Keyframes[i].Slope);
}
break;
+ case CharacterAnim.RotateFormatType.DataFrm8:
+ for (int i = 0; i < (anm.FrameCount + 1); i++) {
+ Output.WriteByte((byte)kf.Values[i]);
+ }
+ break;
+ case CharacterAnim.RotateFormatType.DataFrm16:
+ for (int i = 0; i < (anm.FrameCount + 1); i++) {
+ Output.WriteUInt16((ushort)kf.Values[i]);
+ }
+ break;
+ case CharacterAnim.RotateFormatType.DataFrm32:
+ for (int i = 0; i < (anm.FrameCount + 1); i++) {
+ Output.WriteFloat(kf.FloatValues[i]);
+ }
+ break;
default:
- throw new NotImplementedException();
+ throw new NotImplementedException(String.Format("Unknown format: {0}", format));
}
Output.AlignTo(4);
@@ -1999,7 +2027,7 @@ namespace NW4RTools {
Output.WriteUInt32(flags);
for (int i = 0; i < node.Elements.Length; i++) {
- if (node.Elements[i].Exists) {
+ if (node.Elements[i].Exists) {
Output.WriteUInt32(node.Elements[i].Mask);
if (node.Elements[i].IsConstant) {
Output.WriteColor(node.Elements[i].ConstValue);
@@ -2041,176 +2069,176 @@ namespace NW4RTools {
i++;
}
}
- #endregion
-
- #region Texture SRT Animation Writing
- private void WriteAnmTexSrt() {
- foreach (var kv in File.GetGroup<TextureSRTAnim>("AnmTexSrt(NW4R)")) {
- using (var c = Debug.Push("TextureSRT Animation: {0}", kv.Key)) {
- Output.AlignTo(0x20);
-
- int startPos = Output.Position;
- TextureSRTAnim anm = kv.Value;
- var info = TexSRTAnmInfos[anm];
-
- Misc.Assert(startPos == TexSRTAnmOffsets[anm]);
-
- // Base struct: magic 'SRT0', block size, version[currently 5], resfile offset
- Output.WriteUInt32(0x53525430);
- Output.WriteUInt32((UInt32)info.BlockSize);
- Output.WriteUInt32(5);
- Output.WriteInt32(-startPos);
-
- // Data offset, name offset, other crap
- Output.WriteInt32(0x2C);
- Output.WriteUInt32(0);
- Output.WriteInt32(StringPositions[kv.Key] - startPos);
- Output.WriteUInt32(0);
-
- Output.WriteUInt16((UInt16)anm.FrameCount);
- Output.WriteUInt16((UInt16)anm.Nodes.Count);
-
- Output.WriteUInt32((UInt32)anm.MatrixMode);
- Output.WriteUInt32(anm.Loop ? 1U : 0U);
-
- WriteResDict<TextureSRTAnim.Node>(anm.Nodes, info.NodeOffsets);
-
- WriteAnmTexSrtNodes(anm);
- WriteKeyframeData(info.KFInfo);
- }
- }
- }
-
- private void WriteAnmTexSrtNodes(TextureSRTAnim anm) {
- var info = TexSRTAnmInfos[anm];
-
- foreach (var kv in anm.Nodes) {
- using (var c = Debug.Push("Element: {0}", kv.Key)) {
- int startPos = Output.Position;
- TextureSRTAnim.Node node = kv.Value;
- TexSRTAnmNodeInfo nodeinfo = info.NodeInfo[node];
-
- Misc.Assert(startPos == info.NodeOffsets[node]);
-
- Output.WriteInt32(StringPositions[kv.Key] - startPos);
-
- UInt32 flags = 0, indFlags = 0;
-
- for (int i = 0; i < 8; i++)
- if (node.Textures[i].Exists)
- flags |= (UInt32)(1 << i);
- for (int i = 0; i < 3; i++)
- if (node.IndirectTextures[i].Exists)
- indFlags |= (UInt32)(1 << i);
-
- Output.WriteUInt32(flags);
- Output.WriteUInt32(indFlags);
-
- var elemsToAddLater = new List<TextureSRTAnim.Element>();
-
- for (int i = 0; i < 8; i++)
- if (node.Textures[i].Exists) {
- Output.WriteInt32(nodeinfo.TextureOffsets[i] - startPos);
- elemsToAddLater.Add(node.Textures[i]);
- }
-
- for (int i = 0; i < 3; i++)
- if (node.IndirectTextures[i].Exists) {
- Output.WriteInt32(nodeinfo.IndirectTextureOffsets[i] - startPos);
- elemsToAddLater.Add(node.IndirectTextures[i]);
- }
-
- foreach (var elem in elemsToAddLater)
- WriteAnmTexSrtElement(elem, info.KFInfo);
- }
- }
- }
-
- private void WriteAnmTexSrtElement(TextureSRTAnim.Element elem, KeyframeWriterInfo kfinfo) {
- UInt32 flags = 1;
-
- int flagPos = Output.Position;
- Output.WriteUInt32(0); // placeholder!
-
- if (elem.ScaleS.IsConstWith(1) && elem.ScaleT.IsConstWith(1)) {
- flags |= 2 | 0x10 | 0x20 | 0x40;
- } else {
- WriteKeyframeAnim(elem.ScaleS, kfinfo);
- if (elem.ScaleS.IsConstant)
- flags |= 0x20;
-
- if (elem.ScaleS == elem.ScaleT) {
- flags |= 0x10;
- if (elem.ScaleS.IsConstant)
- flags |= 0x40;
- } else {
- WriteKeyframeAnim(elem.ScaleT, kfinfo);
- if (elem.ScaleT.IsConstant)
- flags |= 0x40;
- }
- }
-
- if (elem.Rotate.IsConstWith(0)) {
- flags |= 4 | 0x80;
- } else {
- WriteKeyframeAnim(elem.Rotate, kfinfo);
- if (elem.Rotate.IsConstant)
- flags |= 0x80;
- }
-
- if (elem.TransS.IsConstWith(0) && elem.TransT.IsConstWith(0)) {
- flags |= 8 | 0x100 | 0x200;
- } else {
- WriteKeyframeAnim(elem.TransS, kfinfo);
- WriteKeyframeAnim(elem.TransT, kfinfo);
-
- if (elem.TransS.IsConstant)
- flags |= 0x100;
- if (elem.TransT.IsConstant)
- flags |= 0x200;
- }
-
- // Replace the flags
- int savePos = Output.Position;
- Output.Seek(flagPos);
- Output.WriteUInt32(flags);
- Output.Seek(savePos);
- }
- #endregion
-
- #region Keyframe Data Writing
- private void WriteKeyframeAnim(KeyframeAnim anim, KeyframeWriterInfo kfinfo) {
- if (anim.IsConstant)
- Output.WriteFloat(anim.ConstValue);
- else
- Output.WriteInt32(kfinfo.GetPosition(anim) - Output.Position);
- }
-
- private void WriteKeyframeData(KeyframeWriterInfo kfinfo) {
- foreach (var pair in kfinfo.KeyframeAnims) {
- var anim = pair.two;
- var kf = pair.two;
- var expectedOffset = kfinfo.KeyframeAnimOffsets[pair];
-
- Misc.Assert(expectedOffset == Output.Position);
-
- Output.WriteUInt16((UInt16)kf.Keyframes.Length);
- Output.AddPadding(2);
-
- float delta = kf.Keyframes[kf.Keyframes.Length - 1].Frame - kf.Keyframes[0].Frame;
- float invKeyFrameRange = (1.0f / delta);
- Output.WriteFloat(invKeyFrameRange);
-
- for (int i = 0; i < kf.Keyframes.Length; i++) {
- Output.WriteFloat(kf.Keyframes[i].Frame);
- Output.WriteFloat(kf.Keyframes[i].Value);
- Output.WriteFloat(kf.Keyframes[i].Slope);
- }
- }
- }
- #endregion
-
- #region ResDicts
+ #endregion
+
+ #region Texture SRT Animation Writing
+ private void WriteAnmTexSrt() {
+ foreach (var kv in File.GetGroup<TextureSRTAnim>("AnmTexSrt(NW4R)")) {
+ using (var c = Debug.Push("TextureSRT Animation: {0}", kv.Key)) {
+ Output.AlignTo(0x20);
+
+ int startPos = Output.Position;
+ TextureSRTAnim anm = kv.Value;
+ var info = TexSRTAnmInfos[anm];
+
+ Misc.Assert(startPos == TexSRTAnmOffsets[anm]);
+
+ // Base struct: magic 'SRT0', block size, version[currently 5], resfile offset
+ Output.WriteUInt32(0x53525430);
+ Output.WriteUInt32((UInt32)info.BlockSize);
+ Output.WriteUInt32(5);
+ Output.WriteInt32(-startPos);
+
+ // Data offset, name offset, other crap
+ Output.WriteInt32(0x2C);
+ Output.WriteUInt32(0);
+ Output.WriteInt32(StringPositions[kv.Key] - startPos);
+ Output.WriteUInt32(0);
+
+ Output.WriteUInt16((UInt16)anm.FrameCount);
+ Output.WriteUInt16((UInt16)anm.Nodes.Count);
+
+ Output.WriteUInt32((UInt32)anm.MatrixMode);
+ Output.WriteUInt32(anm.Loop ? 1U : 0U);
+
+ WriteResDict<TextureSRTAnim.Node>(anm.Nodes, info.NodeOffsets);
+
+ WriteAnmTexSrtNodes(anm);
+ WriteKeyframeData(info.KFInfo);
+ }
+ }
+ }
+
+ private void WriteAnmTexSrtNodes(TextureSRTAnim anm) {
+ var info = TexSRTAnmInfos[anm];
+
+ foreach (var kv in anm.Nodes) {
+ using (var c = Debug.Push("Element: {0}", kv.Key)) {
+ int startPos = Output.Position;
+ TextureSRTAnim.Node node = kv.Value;
+ TexSRTAnmNodeInfo nodeinfo = info.NodeInfo[node];
+
+ Misc.Assert(startPos == info.NodeOffsets[node]);
+
+ Output.WriteInt32(StringPositions[kv.Key] - startPos);
+
+ UInt32 flags = 0, indFlags = 0;
+
+ for (int i = 0; i < 8; i++)
+ if (node.Textures[i].Exists)
+ flags |= (UInt32)(1 << i);
+ for (int i = 0; i < 3; i++)
+ if (node.IndirectTextures[i].Exists)
+ indFlags |= (UInt32)(1 << i);
+
+ Output.WriteUInt32(flags);
+ Output.WriteUInt32(indFlags);
+
+ var elemsToAddLater = new List<TextureSRTAnim.Element>();
+
+ for (int i = 0; i < 8; i++)
+ if (node.Textures[i].Exists) {
+ Output.WriteInt32(nodeinfo.TextureOffsets[i] - startPos);
+ elemsToAddLater.Add(node.Textures[i]);
+ }
+
+ for (int i = 0; i < 3; i++)
+ if (node.IndirectTextures[i].Exists) {
+ Output.WriteInt32(nodeinfo.IndirectTextureOffsets[i] - startPos);
+ elemsToAddLater.Add(node.IndirectTextures[i]);
+ }
+
+ foreach (var elem in elemsToAddLater)
+ WriteAnmTexSrtElement(elem, info.KFInfo);
+ }
+ }
+ }
+
+ private void WriteAnmTexSrtElement(TextureSRTAnim.Element elem, KeyframeWriterInfo kfinfo) {
+ UInt32 flags = 1;
+
+ int flagPos = Output.Position;
+ Output.WriteUInt32(0); // placeholder!
+
+ if (elem.ScaleS.IsConstWith(1) && elem.ScaleT.IsConstWith(1)) {
+ flags |= 2 | 0x10 | 0x20 | 0x40;
+ } else {
+ WriteKeyframeAnim(elem.ScaleS, kfinfo);
+ if (elem.ScaleS.IsConstant)
+ flags |= 0x20;
+
+ if (elem.ScaleS == elem.ScaleT) {
+ flags |= 0x10;
+ if (elem.ScaleS.IsConstant)
+ flags |= 0x40;
+ } else {
+ WriteKeyframeAnim(elem.ScaleT, kfinfo);
+ if (elem.ScaleT.IsConstant)
+ flags |= 0x40;
+ }
+ }
+
+ if (elem.Rotate.IsConstWith(0)) {
+ flags |= 4 | 0x80;
+ } else {
+ WriteKeyframeAnim(elem.Rotate, kfinfo);
+ if (elem.Rotate.IsConstant)
+ flags |= 0x80;
+ }
+
+ if (elem.TransS.IsConstWith(0) && elem.TransT.IsConstWith(0)) {
+ flags |= 8 | 0x100 | 0x200;
+ } else {
+ WriteKeyframeAnim(elem.TransS, kfinfo);
+ WriteKeyframeAnim(elem.TransT, kfinfo);
+
+ if (elem.TransS.IsConstant)
+ flags |= 0x100;
+ if (elem.TransT.IsConstant)
+ flags |= 0x200;
+ }
+
+ // Replace the flags
+ int savePos = Output.Position;
+ Output.Seek(flagPos);
+ Output.WriteUInt32(flags);
+ Output.Seek(savePos);
+ }
+ #endregion
+
+ #region Keyframe Data Writing
+ private void WriteKeyframeAnim(KeyframeAnim anim, KeyframeWriterInfo kfinfo) {
+ if (anim.IsConstant)
+ Output.WriteFloat(anim.ConstValue);
+ else
+ Output.WriteInt32(kfinfo.GetPosition(anim) - Output.Position);
+ }
+
+ private void WriteKeyframeData(KeyframeWriterInfo kfinfo) {
+ foreach (var pair in kfinfo.KeyframeAnims) {
+ var anim = pair.two;
+ var kf = pair.two;
+ var expectedOffset = kfinfo.KeyframeAnimOffsets[pair];
+
+ Misc.Assert(expectedOffset == Output.Position);
+
+ Output.WriteUInt16((UInt16)kf.Keyframes.Length);
+ Output.AddPadding(2);
+
+ float delta = kf.Keyframes[kf.Keyframes.Length - 1].Frame - kf.Keyframes[0].Frame;
+ float invKeyFrameRange = (1.0f / delta);
+ Output.WriteFloat(invKeyFrameRange);
+
+ for (int i = 0; i < kf.Keyframes.Length; i++) {
+ Output.WriteFloat(kf.Keyframes[i].Frame);
+ Output.WriteFloat(kf.Keyframes[i].Value);
+ Output.WriteFloat(kf.Keyframes[i].Slope);
+ }
+ }
+ }
+ #endregion
+
+ #region ResDicts
private struct RawDictEntry {
public ushort Ref;
public ushort Unk;
diff --git a/NW4RTools/ColladaExporter.cs b/NW4RTools/ColladaExporter.cs
index 645b8dc..8ee111e 100644
--- a/NW4RTools/ColladaExporter.cs
+++ b/NW4RTools/ColladaExporter.cs
@@ -643,6 +643,7 @@ namespace NW4RTools {
List<string> triStrips = new List<string>();
List<string> lineStrips = new List<string>();
+ File.WriteAllBytes("DL.bin", shape.DisplayList2);
// Now go through the display list
while (true) {
@@ -651,7 +652,26 @@ namespace NW4RTools {
byte cmd = dl.ReadByte();
if (cmd == 0)
- break;
+ continue;
+
+ // These can contain other stuff. Who knew.
+
+ if ((cmd & 0x80) == 0) {
+ GXCommand castCmd = (GXCommand)cmd;
+
+ switch (castCmd) {
+ case GXCommand.LoadPosMtxFromArray:
+ case GXCommand.LoadNrmMtxFromArray:
+ case GXCommand.LoadTexCoordMtxFromArray:
+ case GXCommand.LoadLightFromArray:
+ dl.Skip(4);
+ break;
+ default:
+ Console.WriteLine("UNIMPLEMENTED GX COMMAND: {0}", castCmd);
+ break;
+ }
+ continue; // don't process it as a primitive
+ }
PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7);
int vtxCount = dl.ReadUInt16();
diff --git a/NW4RTools/Models/Animation/CharacterAnim.cs b/NW4RTools/Models/Animation/CharacterAnim.cs
index 72efd56..2fab9f9 100644
--- a/NW4RTools/Models/Animation/CharacterAnim.cs
+++ b/NW4RTools/Models/Animation/CharacterAnim.cs
@@ -58,9 +58,9 @@ namespace NW4RTools.Models.Animation {
Data32 = 1,
Data48 = 2,
Data96 = 3,
- DataUnk4 = 4,
- DataUnk5 = 5,
- DataUnk6 = 6,
+ DataFrm8 = 4,
+ DataFrm16 = 5,
+ DataFrm32 = 6,
Zero = 7,
}
diff --git a/NW4RTools/Models/ByteCode.cs b/NW4RTools/Models/ByteCode.cs
index 62968e9..ed16d10 100755
--- a/NW4RTools/Models/ByteCode.cs
+++ b/NW4RTools/Models/ByteCode.cs
@@ -50,7 +50,7 @@ namespace NW4RTools.Models {
public UInt16 MaterialID;
public UInt16 ShapeID;
- public UInt16 NodeID;
+ public UInt16 NodeID;
public byte Unk;
}
diff --git a/NW4RTools/ObjExporter.cs b/NW4RTools/ObjExporter.cs
index 7b1afef..8cb9088 100644
--- a/NW4RTools/ObjExporter.cs
+++ b/NW4RTools/ObjExporter.cs
@@ -138,6 +138,25 @@ namespace NW4RTools {
if (cmd == 0)
break;
+ // These can contain other stuff. Who knew.
+
+ if ((cmd & 0x80) == 0) {
+ GXCommand castCmd = (GXCommand)cmd;
+
+ switch (castCmd) {
+ case GXCommand.LoadPosMtxFromArray:
+ case GXCommand.LoadNrmMtxFromArray:
+ case GXCommand.LoadTexCoordMtxFromArray:
+ case GXCommand.LoadLightFromArray:
+ dl.Skip(4);
+ break;
+ default:
+ Console.WriteLine("UNIMPLEMENTED GX COMMAND: {0}", castCmd);
+ break;
+ }
+ continue; // don't process it as a primitive
+ }
+
PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7);
int vtxCount = dl.ReadUInt16();
Output.WriteLine("# Primitive: {0} ({1} vertices)", prim, vtxCount);
diff --git a/NW4RTools/ObjImporter.cs b/NW4RTools/ObjImporter.cs
index 384fb66..cdc9fcd 100755
--- a/NW4RTools/ObjImporter.cs
+++ b/NW4RTools/ObjImporter.cs
@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
+using System.Globalization;
using NW4RTools.Models;
namespace NW4RTools {
@@ -271,7 +272,7 @@ namespace NW4RTools {
var output = new float[count];
for (int i = 0; i < count; i++) {
- output[i] = float.Parse(src[i + index]);
+ output[i] = float.Parse(src[i + index], CultureInfo.InvariantCulture);
}
return output;
@@ -293,13 +294,13 @@ namespace NW4RTools {
if (line.Length == 0 || line[0] == '#')
continue;
- var parsed = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
-
- switch (parsed[0]) {
- case "newmtl":
- // Create a new material and initialise everything
- // Default settings taken from Test_Lift material
- currentMaterial = new Material();
+ var parsed = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ switch (parsed[0]) {
+ case "newmtl":
+ // Create a new material and initialise everything
+ // Default settings taken from Test_Lift material
+ currentMaterial = new Material();
currentMaterial.ChanCtrls[0] = new ChanCtrl();
currentMaterial.ChanCtrls[0].Flags = 0x3F;
@@ -315,20 +316,20 @@ namespace NW4RTools {
currentMaterial.ChanCtrls[1].FlagC = 0;
currentMaterial.ChanCtrls[1].FlagA = 0;
- if (Lightmap == ObjImporter.LightmapType.None) {
- currentMaterial.TexCoordGenCount = 1;
- currentMaterial.ChanCount = 1;
- currentMaterial.TevStageCount = 2;
- currentMaterial.IndStageCount = 0;
-
- // This might need changing
- currentMaterial.CullMode = 2;
+ if (Lightmap == ObjImporter.LightmapType.None) {
+ currentMaterial.TexCoordGenCount = 1;
+ currentMaterial.ChanCount = 1;
+ currentMaterial.TevStageCount = 2;
+ currentMaterial.IndStageCount = 0;
+
+ // This might need changing
+ currentMaterial.CullMode = 2;
currentMaterial.LightSetID = 1;
- currentMaterial.SRTSettings[0] = new SRTSettingInfo();
-
- // Default display lists, taken from test_lift
+ currentMaterial.SRTSettings[0] = new SRTSettingInfo();
+
+ // Default display lists, taken from test_lift
var pixDL = new DisplayListWriter();
pixDL.LoadBPReg(0xF31EFF80);
pixDL.LoadBPReg(0x40000017);
@@ -469,10 +470,10 @@ namespace NW4RTools {
Shader thisShader = CreateShader();
CurrentModel.Shaders.Add(parsed[1], thisShader);
- currentMaterial.ShaderRef = thisShader;
-
- break;
-
+ currentMaterial.ShaderRef = thisShader;
+
+ break;
+
case "map_Kd":
var rawTexName = string.Join(" ", parsed, 1, parsed.Length - 1);
// TODO: fix this to use the mtllib path
@@ -512,9 +513,9 @@ namespace NW4RTools {
currentMaterial.TextureInfos.Add(lm01);
currentMaterial.TextureInfos.Add(lm02);
}
-
- break;
-
+
+ break;
+
}
}
diff --git a/NW4RTools/Texture.cs b/NW4RTools/Texture.cs
index f2cf231..249af79 100644
--- a/NW4RTools/Texture.cs
+++ b/NW4RTools/Texture.cs
@@ -437,8 +437,10 @@ namespace NW4RTools {
byte val = data.ReadByte();
for (int inX = 0; inX < 4; inX++) {
- uint *pPixel = (uint*)pRow + x + (iBlockX * 4) + inX;
- *pPixel = clrArray[(val >> 6) & 3];
+ if ((y + (iBlockY * 4) + inY) < height && (x + (iBlockX * 4) + inX) < width) {
+ uint *pPixel = (uint*)pRow + x + (iBlockX * 4) + inX;
+ *pPixel = clrArray[(val >> 6) & 3];
+ }
val <<= 2;
}
}
diff --git a/TestApp/Main.cs b/TestApp/Main.cs
index a61577f..76329b7 100755
--- a/TestApp/Main.cs
+++ b/TestApp/Main.cs
@@ -2,6 +2,8 @@ using System;
using System.IO;
using System.Collections.Generic;
using NW4RTools;
+using NW4RTools.Models;
+using NW4RTools.Models.Animation;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
@@ -9,6 +11,21 @@ using OpenTK.Graphics.OpenGL;
namespace TestApp {
class MainClass {
public static void Main(string[] args) {
+ ResFile shits = BrresReader.LoadFile(File.ReadAllBytes("Z:/stuff/Games/Newer/bros.brres"));
+ ColladaExporter.WriteModel(File.OpenWrite("Z:/stuff/Games/Newer/bros.dae"), shits, "bros");
+ //ResFile shits = BrresReader.LoadFile(File.ReadAllBytes("/home/me/Games/Newer/bros.brres"));
+ //ColladaExporter.WriteModel(File.OpenWrite("/home/me/Games/Newer/bros.dae"), shits, "bros");
+ return;
+
+ striphammer();
+ return;
+
+ fuckskawo();
+ return;
+
+ ewater();
+ return;
+
blah(args);
return;
@@ -23,13 +40,13 @@ namespace TestApp {
//string filename = "crapmap", resmdlname = "CrapMap";
/*string filename = "SMGoldwood";
- ResFile rf = new ResFile();
+ ResFile rf = new ResFile();
- ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "GoldwoodBase.obj"), rf, "GoldwoodBase", ObjImporter.LightmapType.Map);
- ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "BrownTree.obj"), rf, "BrownTree", ObjImporter.LightmapType.MapObj);
- ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "RedTree.obj"), rf, "RedTree", ObjImporter.LightmapType.MapObj);
+ ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "GoldwoodBase.obj"), rf, "GoldwoodBase", ObjImporter.LightmapType.Map);
+ ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "BrownTree.obj"), rf, "BrownTree", ObjImporter.LightmapType.MapObj);
+ ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "RedTree.obj"), rf, "RedTree", ObjImporter.LightmapType.MapObj);
- File.WriteAllBytes(mdlPath + "SMGoldwood.brres", BrresWriter.WriteFile(rf));*/
+ File.WriteAllBytes(mdlPath + "SMGoldwood.brres", BrresWriter.WriteFile(rf));*/
string filename = "DemoMap";
@@ -58,7 +75,7 @@ namespace TestApp {
/*var texs = rf.GetGroup<Texture>("Textures(NW4R)");
// wtf C#?!
foreach (var kv in (IEnumerable<KeyValuePair<string,Texture>>)texs) {
- kv.Value.BaseImage.Save(mdlPath + "images/" + kv.Key + ".png");
+ kv.Value.BaseImage.Save(mdlPath + "images/" + kv.Key + ".png");
}
//var objFile = File.Open(mdlPath + mdlName + ".obj", FileMode.OpenOrCreate);
@@ -69,6 +86,38 @@ namespace TestApp {
objFile.Close();*/
}
+ private static void striphammer() {
+ string mdlPath = "/home/me/Games/Newer/ISO/files/Object/hammerM/g3d/";
+
+ ResFile rf = BrresReader.LoadFile(File.ReadAllBytes(mdlPath + "bros.brres"));
+
+ var mgrp = rf.GetModelGroup();
+ var mremove = new List<string>();
+ foreach (var k in mgrp.Keys)
+ if (k != "bros_hammer")
+ mremove.Add(k);
+ foreach (var k in mremove)
+ mgrp.Remove(k);
+
+ var tgrp = rf.GetTextureGroup();
+ var texremove = new List<string>();
+ var texkeep = new Dictionary<string, bool>();
+ texkeep.Add("bros_hammer", true);
+ texkeep.Add("bros_hammer_env", true);
+ texkeep.Add("bros_hammer_handle", true);
+ texkeep.Add("lm_01e", true);
+ texkeep.Add("lm_02e", true);
+ foreach (var k in tgrp.Keys)
+ if (!texkeep.ContainsKey(k))
+ texremove.Add(k);
+ foreach (var k in texremove)
+ tgrp.Remove(k);
+
+ rf.Remove("AnmChr(NW4R)");
+
+ File.WriteAllBytes(mdlPath + "hammer.brres", BrresWriter.WriteFile(rf));
+
+ }
private static void skawo() {
string mdlPath = "/home/me/Games/Newer/ModelRev/";
@@ -113,7 +162,7 @@ namespace TestApp {
/*var texs = rf.GetGroup<Texture>("Textures(NW4R)");
// wtf C#?!
foreach (var kv in (IEnumerable<KeyValuePair<string,Texture>>)texs) {
- kv.Value.Images[0].Save(mdlPath + "images/" + kv.Key + ".png");
+ kv.Value.Images[0].Save(mdlPath + "images/" + kv.Key + ".png");
}*/
//var objFile = File.Open(mdlPath + "lift_han_wood_M.dae", FileMode.OpenOrCreate);
@@ -123,11 +172,7 @@ namespace TestApp {
private static void blah(string[] args) {
- string mdlPath;
- if (Directory.Exists("/home/me"))
- mdlPath = "/home/me/Games/Newer/WaterL/";
- else
- mdlPath = "Z:/stuff/Games/Newer/WaterL/";
+ string mdlPath = getPath();
ResFile rf = BrresReader.LoadFile(File.ReadAllBytes(mdlPath + "CS_W4.brres"));
File.WriteAllBytes(mdlPath + "CS_W4a.brres", BrresWriter.WriteFile(rf));
@@ -143,6 +188,249 @@ namespace TestApp {
File.WriteAllBytes(mdlPath + "CS_W4e.brres", BrresWriter.WriteFile(rf5));
}
}
+
+ private static void ewater() {
+ string mdlPath = getPath();
+
+ ResFile rf = BrresReader.LoadFile(File.ReadAllBytes(mdlPath + "CS_W4.brres"));
+ Model m = rf.GetModelGroup()["CS_W4"];
+
+ foreach (var kv in m.Shapes) {
+ var s = kv.Value;
+ Console.WriteLine("{0} : {1}",
+ kv.Key,
+ m.VtxPosData.GetKeyForValue(s.PosData));
+ }
+
+ var tgrp = rf.GetTextureGroup();
+ var texremove = new List<string>();
+ var texkeep = new Dictionary<string, bool>();
+ texkeep.Add("W3a_water01", true);
+ texkeep.Add("water_wave1mm", true);
+ texkeep.Add("water01", true);
+ texkeep.Add("texMask", true);
+ foreach (var k in tgrp.Keys)
+ if (!texkeep.ContainsKey(k))
+ texremove.Add(k);
+ foreach (var k in texremove)
+ tgrp.Remove(k);
+
+ rf.Remove("AnmClr(NW4R)");
+ rf.Remove("AnmChr(NW4R)");
+
+ var tsanmg = rf.GetGroup<TextureSRTAnim>("AnmTexSrt(NW4R)");
+ var tsanm = tsanmg["CS_W4"];
+ tsanmg.RemoveAt(0);
+ tsanmg.Add("KpBG", tsanm);
+
+ tsanm.Nodes.Remove("mtCloudA");
+ tsanm.Nodes.Remove("mtCloudB");
+ tsanm.Nodes.Remove("mtWater_nami");
+
+ rf.GetModelGroup().RemoveAt(0);
+ rf.GetModelGroup()["KpBG"] = m;
+
+ // Make bytecode
+ m.MatrixIDtoNodeID = new int[1];
+ m.MatrixIDtoNodeID[0] = 0;
+
+ // Now put together the NodeTree
+ var nodeTreeInsn = new ByteCode.AssignNodeToParentMtxInstruction();
+ nodeTreeInsn.NodeID = 0;
+ nodeTreeInsn.ParentMatrixID = 0;
+
+ var done = new ByteCode.DoneInstruction();
+
+ var nodeTree = new ByteCode();
+ nodeTree.Instructions.Add(nodeTreeInsn);
+ nodeTree.Instructions.Add(done);
+
+ m.Bytecode["NodeTree"] = nodeTree;
+
+ // Also, DrawOpa
+ var drawOpa = new ByteCode();
+ var shapeInsn = new ByteCode.DrawShapeInstruction();
+ shapeInsn.ShapeID = 0;
+ shapeInsn.NodeID = 0;
+ shapeInsn.MaterialID = 0;
+ drawOpa.Instructions.Add(shapeInsn);
+ drawOpa.Instructions.Add(done);
+ m.Bytecode["DrawOpa"] = drawOpa;
+
+ var drawXlu = new ByteCode();
+ drawXlu.Instructions.Add(done);
+ m.Bytecode["DrawXlu"] = drawXlu;
+
+
+ // Clean up other shit
+ var seashape = m.Shapes["polygon106"];
+ var posd = seashape.PosData;
+ var nrmd = seashape.NrmData;
+ var clrd = seashape.ClrData;
+ var tcd = seashape.TexCoordData;
+
+ var nnod = new ResDict<Node>();
+ var nshp = new ResDict<Shape>();
+ var nshd = new ResDict<Shader>();
+ var nmat = new ResDict<Material>();
+ var npos = new ResDict<VertexPosData>();
+ var nnrm = new ResDict<VertexNrmData>();
+ var nclr = new ResDict<VertexClrData>();
+ var ntc = new ResDict<VertexTexCoordData>();
+
+ Node rn = m.Nodes["CS_W4"];
+ rn.FirstChild = null;
+ nnod["RootNode"] = rn;
+ nshp["waterpoly"] = seashape;
+ nshd["mtWater"] = m.Shaders["mtWater"];
+ nmat["mtWater"] = m.Materials["mtWater"];
+
+ if (posd != null) {
+ npos[m.VtxPosData.GetKeyForValue(posd)] = posd;
+ }
+
+ if (nrmd != null) {
+ nnrm[m.VtxNrmData.GetKeyForValue(nrmd)] = nrmd;
+ }
+
+ foreach (var t in clrd) {
+ if (t != null) {
+ nclr[m.VtxClrData.GetKeyForValue(t)] = t;
+ }
+ }
+
+ foreach (var t in tcd) {
+ if (t != null) {
+ ntc[m.VtxTexCoordData.GetKeyForValue(t)] = t;
+ }
+ }
+
+ m.Nodes = nnod;
+ m.Shapes = nshp;
+ m.Shaders = nshd;
+ m.Materials = nmat;
+ m.VtxPosData = npos;
+ m.VtxNrmData = nnrm;
+ m.VtxClrData = nclr;
+ m.VtxTexCoordData = ntc;
+
+ m.PairingLookupByTexture = new ResDict<List<TexMatPairing>>();
+ m.PairingLookupByPalette = new ResDict<List<TexMatPairing>>();
+
+ // NEW
+ var dl = new DisplayListWriter();
+ dl.BeginPrimitives(PrimitiveType.Quads, 0, 4);
+ dl.WriteByte(0);
+ dl.WriteByte(0);
+ dl.WriteByte(1);
+ dl.WriteByte(1);
+ dl.WriteByte(2);
+ dl.WriteByte(2);
+ dl.WriteByte(3);
+ dl.WriteByte(3);
+ dl.End();
+ seashape.DisplayList2 = dl.GetBuffer();
+ seashape.DLBufferSize2 = (uint)seashape.DisplayList2.Length;
+ var shape = seashape;
+
+ float w = 200000, h = 100000;
+ float sw = 600, sh = 600;
+ float ow = -480, oh = 480;
+
+ posd.EntryCount = 4;
+ posd.Data = new float[][] {
+ new float[] { ow, (-h) + oh, -40 },
+ new float[] { ow, oh, -40 },
+ new float[] { ow + w, oh, -40 },
+ new float[] { ow + w, (-h) + oh, -40 }
+ };
+ posd.EntrySize = 12;
+ posd.Fraction = 0;
+ posd.ComponentType = VertexSettings.CompType.Float32;
+ posd.Save();
+
+ tcd[0].EntryCount = 4;
+ tcd[0].Fraction = 0;
+ tcd[0].Data = new float[][] {
+ new float[] { 0, 0 },
+ new float[] { sw, 0 },
+ new float[] { sw, sh },
+ new float[] { 0, sh }
+ };
+ tcd[0].Save();
+ /* posd.Data = new float[][] {
+ new float[] { 0, -40, h },
+ new float[] { 0, -40, 0 },
+ new float[] { w, -40, 0 },
+ new float[] { w, -40, h }
+ };*/
+
+ var vs = new VertexSettings();
+ vs.PositionDesc = VertexSettings.DescType.Index8;
+ vs.PositionFormat = VertexSettings.CompType.Float32;
+ vs.PositionCount = VertexSettings.CompCount.Position3;
+
+ vs.TexCoordDesc[0] = VertexSettings.DescType.Index8;
+ vs.TexCoordFormat[0] = VertexSettings.CompType.Int16;
+ vs.TexCoordCount[0] = VertexSettings.CompCount.TexCoord2;
+ vs.TexCoordFrac[0] = 0;
+
+ uint vd1, vd2, vat1, vat2, vat3;
+ vs.GetDesc(out vd1, out vd2);
+ vs.GetAttrFmt(out vat1, out vat2, out vat3);
+
+ byte vtxSpecs = 1 << 4;
+ // setting up Unk in the hopes it will work, I think this is what it's for..
+ var unkStream = new OutputStream();
+ unkStream.WriteUInt32(vd1);
+ unkStream.WriteUInt32(vd2);
+ unkStream.WriteUInt32(vtxSpecs);
+ shape.Unk = unkStream.GetBuffer();
+
+ // now make the display list
+ var dl1 = new DisplayListWriter();
+ dl1.AddPadding(10);
+ dl1.LoadCPReg(0x50, vd1);
+ dl1.LoadCPReg(0x60, vd2);
+ dl1.LoadXFReg(0x1008, new byte[] { 0x00, 0x00, 0x00, vtxSpecs });
+ dl1.Nop();
+ dl1.LoadCPReg(0x70, vat1);
+ dl1.LoadCPReg(0x80, vat2);
+ dl1.LoadCPReg(0x90, vat3);
+
+ // extend it
+ // should it be bigger if more texcoords are used? maybe...
+ dl1.PadToSize(0x80);
+ dl1.End();
+
+ shape.DLBufferSize1 = 0xE0;
+ shape.DisplayList1 = dl1.GetBuffer();
+
+
+
+ var texmask = tgrp["texMask"].Images[0];
+ var g = System.Drawing.Graphics.FromImage(texmask);
+ g.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.White), 0, 0, texmask.Width, texmask.Height);
+ g.Dispose();
+
+
+ // END NEW
+
+ File.WriteAllBytes(mdlPath + "Water.brres", BrresWriter.WriteFile(rf));
+ }
+
+
+ private static string getPath() {
+ if (Directory.Exists("/home/me"))
+ return "/home/me/Games/Newer/WaterL/";
+ else
+ return "Z:/stuff/Games/Newer/WaterL/";
+ }
+
+ private static void fuckskawo() {
+ var rf = BrresReader.LoadFile(File.ReadAllBytes("/home/me/Games/Newer/Pakku/pakkun/g3d/pakkun.brres"));
+ File.WriteAllBytes("/home/me/Games/Newer/Pakku/pakkun/g3d/pakkuRewrite.brres", BrresWriter.WriteFile(rf));
+ }
}
}