diff options
| author | Treeki <treeki@gmail.com> | 2012-09-23 17:43:33 +0200 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2012-09-23 17:43:33 +0200 | 
| commit | c9bfbf84244c8aa4e26ece994ef6b93386c708e3 (patch) | |
| tree | d267d5732bed21c666750263d2ca62dcdfa9e44f /NW4RTools | |
| parent | 31380b4bb93d1fb65faff8f71753de80fb0a8c9d (diff) | |
| download | nw4rtools-c9bfbf84244c8aa4e26ece994ef6b93386c708e3.tar.gz nw4rtools-c9bfbf84244c8aa4e26ece994ef6b93386c708e3.zip  | |
tons of junk I'll clean up eventually
Diffstat (limited to 'NW4RTools')
| -rwxr-xr-x | NW4RTools/BrresReader.cs | 33 | ||||
| -rwxr-xr-x | NW4RTools/BrresWriter.cs | 548 | ||||
| -rw-r--r-- | NW4RTools/ColladaExporter.cs | 22 | ||||
| -rw-r--r-- | NW4RTools/Models/Animation/CharacterAnim.cs | 6 | ||||
| -rwxr-xr-x | NW4RTools/Models/ByteCode.cs | 2 | ||||
| -rw-r--r-- | NW4RTools/ObjExporter.cs | 19 | ||||
| -rwxr-xr-x | NW4RTools/ObjImporter.cs | 53 | ||||
| -rw-r--r-- | NW4RTools/Texture.cs | 6 | 
8 files changed, 379 insertions, 310 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;  									}  								}  | 
