private void SetScale(PICAAttributeName Name, float Scale) { switch (Name) { case PICAAttributeName.Position: Scales0.X = Scale; break; case PICAAttributeName.Normal: Scales0.Y = Scale; break; case PICAAttributeName.Tangent: Scales0.Z = Scale; break; case PICAAttributeName.Color: Scales0.W = Scale; break; case PICAAttributeName.TexCoord0: Scales1.X = Scale; break; case PICAAttributeName.TexCoord1: Scales1.Y = Scale; break; case PICAAttributeName.TexCoord2: Scales1.Z = Scale; break; case PICAAttributeName.BoneWeight: Scales1.W = Scale; break; } }
public GFMesh(BinaryReader Reader) : this() { GFSection MeshSection = new GFSection(Reader); long Position = Reader.BaseStream.Position; uint NameHash = Reader.ReadUInt32(); string NameStr = Reader.ReadPaddedString(0x40); Name = NameStr; Reader.ReadUInt32(); BBoxMinVector = Reader.ReadVector4(); //Is it right? seems to be 0, 0, 0, 1 BBoxMaxVector = Reader.ReadVector4(); //Is it right? seems to be 0, 0, 0, 1 uint SubMeshesCount = Reader.ReadUInt32(); BoneIndicesPerVertex = Reader.ReadInt32(); Reader.BaseStream.Seek(0x10, SeekOrigin.Current); //Padding List <uint[]> CmdList = new List <uint[]>(); uint CommandsLength; uint CommandIndex; uint CommandsCount; uint Padding; do { CommandsLength = Reader.ReadUInt32(); CommandIndex = Reader.ReadUInt32(); CommandsCount = Reader.ReadUInt32(); Padding = Reader.ReadUInt32(); uint[] Commands = new uint[CommandsLength >> 2]; for (int Index = 0; Index < Commands.Length; Index++) { Commands[Index] = Reader.ReadUInt32(); } CmdList.Add(Commands); }while (CommandIndex < CommandsCount - 1); SubMeshSize[] SMSizes = new SubMeshSize[SubMeshesCount]; //Add SubMesh with Hash, Name and Bone Indices. //The rest is added latter (because the data is split inside the file). for (int MeshIndex = 0; MeshIndex < SubMeshesCount; MeshIndex++) { GFSubMesh SM = new GFSubMesh(); uint SMNameHash = Reader.ReadUInt32(); SM.Name = Reader.ReadIntLengthString(); SM.BoneIndicesCount = Reader.ReadByte(); for (int Bone = 0; Bone < 0x1f; Bone++) { SM.BoneIndices[Bone] = Reader.ReadByte(); } SMSizes[MeshIndex] = new SubMeshSize() { VerticesCount = Reader.ReadInt32(), IndicesCount = Reader.ReadInt32(), VerticesLength = Reader.ReadInt32(), IndicesLength = Reader.ReadInt32() }; SubMeshes.Add(SM); } for (int MeshIndex = 0; MeshIndex < SubMeshesCount; MeshIndex++) { GFSubMesh SM = SubMeshes[MeshIndex]; uint[] EnableCommands = CmdList[MeshIndex * 3 + 0]; uint[] DisableCommands = CmdList[MeshIndex * 3 + 1]; uint[] IndexCommands = CmdList[MeshIndex * 3 + 2]; PICACommandReader CmdReader; CmdReader = new PICACommandReader(EnableCommands); PICAVectorFloat24[] Fixed = new PICAVectorFloat24[12]; ulong BufferFormats = 0; ulong BufferAttributes = 0; ulong BufferPermutation = 0; int AttributesCount = 0; int AttributesTotal = 0; int FixedIndex = 0; while (CmdReader.HasCommand) { PICACommand Cmd = CmdReader.GetCommand(); uint Param = Cmd.Parameters[0]; switch (Cmd.Register) { case PICARegister.GPUREG_ATTRIBBUFFERS_FORMAT_LOW: BufferFormats |= (ulong)Param << 0; break; case PICARegister.GPUREG_ATTRIBBUFFERS_FORMAT_HIGH: BufferFormats |= (ulong)Param << 32; break; case PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG1: BufferAttributes |= Param; break; case PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG2: BufferAttributes |= (ulong)(Param & 0xffff) << 32; SM.VertexStride = (byte)(Param >> 16); AttributesCount = (int)(Param >> 28); break; case PICARegister.GPUREG_FIXEDATTRIB_INDEX: FixedIndex = (int)Param; break; case PICARegister.GPUREG_FIXEDATTRIB_DATA0: Fixed[FixedIndex].Word0 = Param; break; case PICARegister.GPUREG_FIXEDATTRIB_DATA1: Fixed[FixedIndex].Word1 = Param; break; case PICARegister.GPUREG_FIXEDATTRIB_DATA2: Fixed[FixedIndex].Word2 = Param; break; case PICARegister.GPUREG_VSH_NUM_ATTR: AttributesTotal = (int)(Param + 1); break; case PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW: BufferPermutation |= (ulong)Param << 0; break; case PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH: BufferPermutation |= (ulong)Param << 32; break; } } for (int Index = 0; Index < AttributesTotal; Index++) { if (((BufferFormats >> (48 + Index)) & 1) != 0) { PICAAttributeName Name = (PICAAttributeName)((BufferPermutation >> Index * 4) & 0xf); float Scale = Name == PICAAttributeName.Color || Name == PICAAttributeName.BoneWeight ? Scales[1] : 1; SM.FixedAttributes.Add(new PICAFixedAttribute() { Name = Name, Value = Fixed[Index] * Scale }); } else { int PermutationIdx = (int)((BufferAttributes >> Index * 4) & 0xf); int AttributeName = (int)((BufferPermutation >> PermutationIdx * 4) & 0xf); int AttributeFmt = (int)((BufferFormats >> PermutationIdx * 4) & 0xf); PICAAttribute Attrib = new PICAAttribute() { Name = (PICAAttributeName)AttributeName, Format = (PICAAttributeFormat)(AttributeFmt & 3), Elements = (AttributeFmt >> 2) + 1, Scale = Scales[AttributeFmt & 3] }; if (Attrib.Name == PICAAttributeName.BoneIndex) { Attrib.Scale = 1; } SM.Attributes.Add(Attrib); } } CmdReader = new PICACommandReader(IndexCommands); uint BufferAddress = 0; uint BufferCount = 0; while (CmdReader.HasCommand) { PICACommand Cmd = CmdReader.GetCommand(); uint Param = Cmd.Parameters[0]; switch (Cmd.Register) { case PICARegister.GPUREG_INDEXBUFFER_CONFIG: BufferAddress = Param; break; case PICARegister.GPUREG_NUMVERTICES: BufferCount = Param; break; case PICARegister.GPUREG_PRIMITIVE_CONFIG: SM.PrimitiveMode = (PICAPrimitiveMode)(Param >> 8); break; } } SM.RawBuffer = Reader.ReadBytes(SMSizes[MeshIndex].VerticesLength); SM.Indices = new ushort[BufferCount]; long IndexAddress = Reader.BaseStream.Position; for (int Index = 0; Index < BufferCount; Index++) { if ((BufferAddress >> 31) != 0) { SM.Indices[Index] = Reader.ReadUInt16(); } else { SM.Indices[Index] = Reader.ReadByte(); } } Reader.BaseStream.Seek(IndexAddress + SMSizes[MeshIndex].IndicesLength, SeekOrigin.Begin); } Reader.BaseStream.Seek(Position + MeshSection.Length, SeekOrigin.Begin); }