-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
281 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,194 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using Warcraft.NET.Attribute; | ||
using Warcraft.NET.Extensions; | ||
using Warcraft.NET.Files.Interfaces; | ||
using Warcraft.NET.Files.phys.Chunks; | ||
using Warcraft.NET.Files.Structures; | ||
|
||
namespace Warcraft.NET.Files.phys | ||
namespace Warcraft.NET.Files.SKIN | ||
{ | ||
[AutoDocFile("skin")] | ||
public class Skin | ||
public class Skin | ||
{ | ||
public List<ushort> Vertices{ get; set; } //index into M2s vertex list with offset <globalVertexOffset> | ||
public List<M2Triangle> Triangles { get; set; } //3 indices per entry into vertices | ||
public List<BoneStruct> BoneIndices { get; set; } | ||
public List<M2SkinSection> Submeshes { get; set; } | ||
public List<M2Batch> TextureUnits { get; set; } | ||
|
||
public UInt32 magic; | ||
|
||
public M2Array vertices; | ||
public M2Array indices; | ||
public M2Array bones; | ||
public M2Array submeshes; | ||
public M2Array batches; | ||
public UInt32 globalVertexOffset; | ||
public M2Array shadow_batches; | ||
|
||
public UInt32 unk0; | ||
public UInt32 unk1; | ||
public UInt32 globalVertexOffset; //start offset into M2.Vertices -> something else in wotlk | ||
|
||
public List<M2ShadowBatch> ShadowBatches; | ||
|
||
public byte[] unk0; //Padding? | ||
|
||
public bool wotlk = false; | ||
|
||
public Skin(byte[] inData) | ||
{ | ||
using (var ms = new MemoryStream(inData)) | ||
using (var br = new BinaryReader(ms)) | ||
{ | ||
magic = br.ReadUInt32(); | ||
vertices = new M2Array(br.ReadUInt32(),br.ReadUInt32()); | ||
indices = new M2Array(br.ReadUInt32(), br.ReadUInt32()); | ||
bones = new M2Array(br.ReadUInt32(), br.ReadUInt32()); | ||
submeshes = new M2Array(br.ReadUInt32(), br.ReadUInt32()); | ||
batches = new M2Array(br.ReadUInt32(), br.ReadUInt32()); | ||
var magic = br.ReadUInt32(); | ||
var nVertices = br.ReadUInt32(); | ||
var ofsVertices = br.ReadUInt32(); | ||
var nIndices = br.ReadUInt32(); | ||
var ofsIndices = br.ReadUInt32(); | ||
if (ofsVertices == 48) | ||
{ | ||
wotlk = true; | ||
} | ||
var nBones = br.ReadUInt32(); | ||
var ofsBones = br.ReadUInt32(); | ||
var nSubmeshes = br.ReadUInt32(); | ||
var ofsSubmeshes = br.ReadUInt32(); | ||
var nBatches = br.ReadUInt32(); | ||
var ofsBatches = br.ReadUInt32(); | ||
globalVertexOffset = br.ReadUInt32(); | ||
shadow_batches = new M2Array(br.ReadUInt32(), br.ReadUInt32()); | ||
unk0 = br.ReadUInt32(); | ||
unk1 = br.ReadUInt32(); | ||
|
||
ShadowBatches = new List<M2ShadowBatch>(); | ||
unk0 = new byte[8]; | ||
if (!wotlk) | ||
{ | ||
var nShadow_batches = br.ReadUInt32(); | ||
var ofsShadow_batches = br.ReadUInt32(); | ||
unk0 = br.ReadBytes(8); | ||
ShadowBatches = ReadStructList<M2ShadowBatch>(nShadow_batches, ofsShadow_batches, br); | ||
} | ||
|
||
Vertices = ReadStructList<ushort>(nVertices, ofsVertices, br); | ||
Triangles = ReadStructList<M2Triangle>(nIndices/3, ofsIndices, br); | ||
BoneIndices = ReadStructList<BoneStruct>(nBones, ofsBones, br); | ||
Submeshes = ReadStructList<M2SkinSection>(nSubmeshes, ofsSubmeshes, br); | ||
TextureUnits = ReadStructList<M2Batch>(nBatches, ofsBatches, br); | ||
|
||
} | ||
} | ||
private List<T> ReadStructList<T>(uint count, uint offset, BinaryReader br) where T : struct | ||
{ | ||
br.BaseStream.Position = offset; | ||
List<T> list = new List<T>(); | ||
|
||
byte[] Serialize() | ||
for (var i = 0; i < count; i++) | ||
list.Add(br.ReadStruct<T>()); | ||
|
||
return list; | ||
} | ||
|
||
public byte[] Serialize(long offset = 0) | ||
{ | ||
return null; | ||
using (var ms = new MemoryStream()) | ||
using (var bw = new BinaryWriter(ms)) | ||
{ | ||
bw.Write(new byte[64]); //placeholder header | ||
foreach (ushort vertex in Vertices) | ||
{ | ||
bw.Write(vertex); | ||
} | ||
|
||
|
||
int _ofsTriangles = (int)bw.BaseStream.Position; | ||
foreach (M2Triangle triangle in Triangles) | ||
{ | ||
bw.WriteStruct(triangle); | ||
} | ||
|
||
|
||
int _ofsBones = (int)bw.BaseStream.Position; | ||
foreach (BoneStruct bone in BoneIndices) | ||
{ | ||
bw.WriteStruct(bone); | ||
|
||
} | ||
|
||
|
||
int _ofsSubmeshes = (int)bw.BaseStream.Position; | ||
foreach (M2SkinSection submesh in Submeshes) | ||
{ | ||
bw.WriteStruct(submesh); | ||
} | ||
|
||
|
||
int _ofsTexUnits = (int)bw.BaseStream.Position; | ||
foreach (M2Batch texUnit in TextureUnits) | ||
{ | ||
bw.WriteStruct(texUnit); | ||
} | ||
|
||
int _ofsShadowBatches = (int)bw.BaseStream.Position; | ||
if (!wotlk) { | ||
foreach (M2ShadowBatch shadowBatch in ShadowBatches) | ||
{ | ||
bw.WriteStruct(shadowBatch); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
||
//Writing header | ||
bw.BaseStream.Position = 0; | ||
bw.Write('S'); | ||
bw.Write('K'); | ||
bw.Write('I'); | ||
bw.Write('N'); | ||
|
||
bw.Write(Vertices.Count); | ||
var _ofsVertices = 64; | ||
if (wotlk) | ||
_ofsVertices = 48; | ||
bw.Write(_ofsVertices); | ||
|
||
bw.Write(Triangles.Count*3); | ||
bw.Write(_ofsTriangles); | ||
|
||
bw.Write(BoneIndices.Count); | ||
bw.Write(_ofsBones); | ||
|
||
bw.Write(Submeshes.Count); | ||
bw.Write(_ofsSubmeshes); | ||
|
||
bw.Write(TextureUnits.Count); | ||
bw.Write(_ofsTexUnits); | ||
|
||
bw.Write(globalVertexOffset); | ||
|
||
if (!wotlk) | ||
{ | ||
bw.Write(ShadowBatches.Count); | ||
bw.Write(_ofsShadowBatches); | ||
bw.Write(unk0); | ||
} | ||
|
||
|
||
return ms.ToArray(); | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public uint GetSize() | ||
{ | ||
return (uint)Serialize().Length; | ||
} | ||
|
||
/* | ||
public byte[] addPadding(byte[] bytes, int size) | ||
{ | ||
// Calculate padding | ||
int paddingSize = (4 - (size % 4)) % 4; | ||
byte[] paddedBytes = new byte[size + paddingSize]; | ||
Array.Copy(bytes, paddedBytes, size); | ||
return paddedBytes; | ||
} | ||
*/ | ||
|
||
} | ||
|
||
|
||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Warcraft.NET.Files.Structures; | ||
|
||
namespace Warcraft.NET.Files.SKIN | ||
{ | ||
public struct M2SkinSection | ||
{ | ||
public UInt16 skinSectionId; // Mesh part ID, see below. | ||
public UInt16 Level; // (level << 16) is added (|ed) to startTriangle and alike to avoid having to increase those fields to uint32s. | ||
public UInt16 vertexStart; // Starting vertex number. | ||
public UInt16 vertexCount; // Number of vertices. | ||
public UInt16 indexStart; // Starting triangle index (that's 3* the number of triangles drawn so far). | ||
public UInt16 indexCount; // Number of triangle indices. | ||
public UInt16 boneCount; // Number of elements in the bone lookup table. Max seems to be 256 in Wrath. Shall be ≠ 0. | ||
public UInt16 boneComboIndex; // Starting index in the bone lookup table. | ||
public UInt16 boneInfluences; // <= 4 | ||
// from <=BC documentation: Highest number of bones needed at one time in this Submesh --Tinyn (wowdev.org) | ||
// In 2.x this is the amount of of bones up the parent-chain affecting the submesh --NaK | ||
// Highest number of bones referenced by a vertex of this submesh. 3.3.5a and suspectedly all other client revisions. -- Skarn | ||
public UInt16 centerBoneIndex; | ||
public C3Vector centerPosition; // Average position of all the vertices in the sub mesh. | ||
//≥BC | ||
public C3Vector sortCenterPosition; // The center of the box when an axis aligned box is built around the vertices in the submesh. | ||
public float sortRadius; // Distance of the vertex farthest from CenterBoundingBox. | ||
} | ||
|
||
public struct BoneStruct | ||
{ | ||
public byte b1; | ||
public byte b2; | ||
public byte b3; | ||
public byte b4; | ||
} | ||
|
||
public struct M2Batch | ||
{ | ||
public byte flags; // Usually 16 for static textures, and 0 for animated textures. &0x1: materials invert something; &0x2: transform &0x4: projected texture; &0x10: something batch compatible; &0x20: projected texture?; &0x40: possibly don't multiply transparency by texture weight transparency to get final transparency value(?) | ||
public sbyte priorityPlane; | ||
public UInt16 shader_id; // See below. | ||
public UInt16 skinSectionIndex; // A duplicate entry of a submesh from the list above. | ||
public UInt16 geosetIndex; // See below. New name: flags2. 0x2 - projected. 0x8 - EDGF chunk in m2 is mandatory and data from is applied to this mesh | ||
public UInt16 colorIndex; // A Color out of the Colors-Block or -1 if none. | ||
public UInt16 materialIndex; // The renderflags used on this texture-unit. | ||
public UInt16 materialLayer; // Capped at 7 (see CM2Scene::BeginDraw) | ||
public UInt16 textureCount; // 1 to 4. See below. Also seems to be the number of textures to load, starting at the texture lookup in the next field (0x10). | ||
public UInt16 textureComboIndex; // Index into Texture lookup table | ||
public UInt16 textureCoordComboIndex; // Index into the texture mapping lookup table. | ||
public UInt16 textureWeightComboIndex; // Index into transparency lookup table. | ||
public UInt16 textureTransformComboIndex; // Index into uvanimation lookup table. | ||
} | ||
|
||
public struct M2ShadowBatch | ||
{ | ||
byte flags; // if auto-generated: M2Batch.flags & 0xFF | ||
byte flags2; // if auto-generated: (renderFlag[i].flags & 0x04 ? 0x01 : 0x00) | ||
// | (!renderFlag[i].blendingmode ? 0x02 : 0x00) | ||
// | (renderFlag[i].flags & 0x80 ? 0x04 : 0x00) | ||
// | (renderFlag[i].flags & 0x400 ? 0x06 : 0x00) | ||
public UInt16 _unknown1; | ||
public UInt16 submesh_id; | ||
public UInt16 texture_id; // already looked-up | ||
public UInt16 color_id; | ||
public UInt16 transparency_id; // already looked-up | ||
} | ||
|
||
public struct M2Triangle //Left handed | ||
{ | ||
public ushort V1; | ||
public ushort V3; | ||
public ushort V2; | ||
} | ||
} |