public bool Read(HSDReader Reader, HSD_AttributeGroup Attributes) { PrimitiveType = (GXPrimitiveType)Reader.ReadByte(); if (PrimitiveType == 0) { return(false); } Count = Reader.ReadUInt16(); Indices = new GXIndexGroup[Count]; for (int j = 0; j < Count; j++) { GXIndexGroup g = new GXIndexGroup(); g.Indices = new ushort[Attributes.Attributes.Count]; int i = 0; Indices[j] = g; foreach (GXVertexBuffer att in Attributes.Attributes) { switch (att.AttributeType) { case GXAttribType.GX_DIRECT: if (att.Name == GXAttribName.GX_VA_CLR0) { g.Clr0 = ReadGXClr(Reader, (int)att.CompType); } else if (att.Name == GXAttribName.GX_VA_CLR1) { g.Clr1 = ReadGXClr(Reader, (int)att.CompType); } else { g.Indices[i] = Reader.ReadByte(); } break; case GXAttribType.GX_INDEX8: g.Indices[i] = Reader.ReadByte(); break; case GXAttribType.GX_INDEX16: g.Indices[i] = Reader.ReadUInt16(); break; } i++; } } return(true); }
public byte[] ToBuffer(HSD_AttributeGroup Group) { MemoryStream o = new MemoryStream(); HSDWriter Writer = new HSDWriter(o); foreach (GXPrimitiveGroup g in Primitives) { g.Write(Writer, Group); } Writer.Write((byte)0); Writer.Align(0x20); Writer.Close(); byte[] bytes = o.ToArray(); o.Close(); return(bytes); }
public GXDisplayList(byte[] Buffer, HSD_AttributeGroup Group) { if (Buffer == null) { return; } HSDReader Reader = new HSDReader(new MemoryStream(Buffer)); while (Reader.Position() < Buffer.Length) { GXPrimitiveGroup g = new GXPrimitiveGroup(); if (!g.Read(Reader, Group)) { break; } Primitives.Add(g); } Reader.Close(); }
public void Write(HSDWriter Writer, HSD_AttributeGroup Attributes) { Writer.Write((byte)PrimitiveType); Writer.Write((ushort)Indices.Length); foreach (GXIndexGroup ig in Indices) { GXIndexGroup g = ig; int i = 0; foreach (GXVertexBuffer att in Attributes.Attributes) { switch (att.AttributeType) { case GXAttribType.GX_DIRECT: if (att.Name != GXAttribName.GX_VA_CLR0) { Writer.Write((byte)g.Indices[i]); } else if (att.Name == GXAttribName.GX_VA_CLR0) { WriteGXClr(g.Clr0, Writer, att.CompType); } else if (att.Name == GXAttribName.GX_VA_CLR1) { WriteGXClr(g.Clr1, Writer, att.CompType); } break; case GXAttribType.GX_INDEX8: Writer.Write((byte)g.Indices[i]); break; case GXAttribType.GX_INDEX16: Writer.Write(g.Indices[i]); break; } i++; } } }
public static GXVertex[] GetDecodedVertices(GXPrimitiveGroup PrimitiveGroup, HSD_AttributeGroup Group) { // Create Vertex List List <GXVertex> Vertices = new List <GXVertex>(); // Prepare vertex buffers for reading Dictionary <GXVertexBuffer, HSDReader> Buffers = new Dictionary <GXVertexBuffer, HSDReader>(); foreach (GXVertexBuffer buffer in Group.Attributes) { Buffers.Add(buffer, buffer.DataBuffer == null ? null : new HSDReader(new MemoryStream(buffer.DataBuffer))); } // Decode foreach (GXIndexGroup ig in PrimitiveGroup.Indices) { GXVertex Vertex = new GXVertex(); for (int i = 0; i < Group.Attributes.Count; i++) { GXVertexBuffer Attr = Group.Attributes[i]; HSDReader VertexBuffer = Buffers[Attr]; int index = ig.Indices[i]; float[] f = new float[0]; if (VertexBuffer != null) { VertexBuffer.Seek((uint)(Attr.Stride * index)); f = Read(VertexBuffer, Attr.CompType, Attr.Stride); } switch (Attr.Name) { case GXAttribName.GX_VA_PNMTXIDX: Vertex.PMXID = (ushort)index; break; case GXAttribName.GX_VA_TEX0MTXIDX: Vertex.TEX0MTXIDX = (ushort)index; break; case GXAttribName.GX_VA_POS: Vertex.Pos.X = f[0] / (float)Math.Pow(2, Attr.Scale); Vertex.Pos.Y = f[1] / (float)Math.Pow(2, Attr.Scale); Vertex.Pos.Z = f[2] / (float)Math.Pow(2, Attr.Scale); break; case GXAttribName.GX_VA_NRM: Vertex.Nrm.X = f[0] / (float)Math.Pow(2, Attr.Scale); Vertex.Nrm.Y = f[1] / (float)Math.Pow(2, Attr.Scale); Vertex.Nrm.Z = f[2] / (float)Math.Pow(2, Attr.Scale); break; case GXAttribName.GX_VA_TEX0: Vertex.TEX0.X = f[0] / (float)Math.Pow(2, Attr.Scale); Vertex.TEX0.Y = f[1] / (float)Math.Pow(2, Attr.Scale); break; case GXAttribName.GX_VA_TEX1: Vertex.TEX1.X = f[0] / (float)Math.Pow(2, Attr.Scale); Vertex.TEX1.Y = f[1] / (float)Math.Pow(2, Attr.Scale); break; case GXAttribName.GX_VA_CLR0: if (Attr.AttributeType == GXAttribType.GX_DIRECT) { Vertex.Clr0.R = ig.Clr0[0] / 255f; Vertex.Clr0.G = ig.Clr0[1] / 255f; Vertex.Clr0.B = ig.Clr0[2] / 255f; Vertex.Clr0.A = ig.Clr0[3] / 255f; } if (Attr.AttributeType == GXAttribType.GX_INDEX8) { Vertex.Clr0.R = f[0]; Vertex.Clr0.G = f[1]; Vertex.Clr0.B = f[2]; Vertex.Clr0.A = f[3]; } break; case GXAttribName.GX_VA_CLR1: if (Attr.AttributeType == GXAttribType.GX_DIRECT) { Vertex.Clr1.R = ig.Clr1[0] / 255f; Vertex.Clr1.G = ig.Clr1[1] / 255f; Vertex.Clr1.B = ig.Clr1[2] / 255f; Vertex.Clr1.A = ig.Clr1[3] / 255f; } if (Attr.AttributeType == GXAttribType.GX_INDEX8) { Vertex.Clr1.R = f[0]; Vertex.Clr1.G = f[1]; Vertex.Clr1.B = f[2]; Vertex.Clr1.A = f[3]; } break; default: Console.WriteLine("To be implemented: " + Attr.Name); break; } } Vertices.Add(Vertex); } foreach (var b in Buffers) { if (b.Value != null) { b.Value.Dispose(); } } return(Vertices.ToArray()); }
/// <summary> /// Creates a primitive group for the vertex buffer /// </summary> /// <param name="type"></param> /// <param name="Vertices"></param> /// <param name="Attributes"></param> /// <returns></returns> public GXPrimitiveGroup Compress(GXPrimitiveType type, GXVertex[] Vertices, HSD_AttributeGroup Attributes) { GXPrimitiveGroup g = new GXPrimitiveGroup(); g.PrimitiveType = type; g.Indices = new GXIndexGroup[Vertices.Length]; int IndexGroupIndex = 0; foreach (GXVertex v in Vertices) { GXIndexGroup ig = new GXIndexGroup(); ig.Indices = new ushort[Attributes.Attributes.Count]; int i = 0; foreach (GXVertexBuffer b in Attributes.Attributes) { switch (b.AttributeType) { case GXAttribType.GX_DIRECT: if (b.Name == GXAttribName.GX_VA_CLR0) { ig.Clr0 = new byte[] { (byte)(v.Clr0.R * 0xFF), (byte)(v.Clr0.G * 0xFF), (byte)(v.Clr0.B * 0xFF), (byte)(v.Clr0.A * 0xFF) } } ; else if (b.Name == GXAttribName.GX_VA_CLR1) { ig.Clr1 = new byte[] { (byte)(v.Clr1.R * 0xFF), (byte)(v.Clr1.G * 0xFF), (byte)(v.Clr1.B * 0xFF), (byte)(v.Clr1.A * 0xFF) } } ; else if (b.Name == GXAttribName.GX_VA_PNMTXIDX) { ig.Indices[i] = v.PMXID; } if (b.Name == GXAttribName.GX_VA_TEX0MTXIDX) { ig.Indices[i] = v.TEX0MTXIDX; } break; default: switch (b.Name) { case GXAttribName.GX_VA_POS: ig.Indices[i] = GetIndex(b, v.Pos); break; case GXAttribName.GX_VA_NRM: ig.Indices[i] = GetIndex(b, v.Nrm); break; case GXAttribName.GX_VA_TEX0: ig.Indices[i] = GetIndex(b, v.TEX0); break; case GXAttribName.GX_VA_TEX1: ig.Indices[i] = GetIndex(b, v.TEX1); break; case GXAttribName.GX_VA_CLR0: ig.Indices[i] = GetIndex(b, v.Clr0); break; default: throw new Exception("Error Building " + b.Name); } break; } i++; } g.Indices[IndexGroupIndex++] = ig; } return(g); }
/// <summary> /// /// </summary> /// <param name="triList"></param> /// <param name="attrGroup"></param> /// <param name="weights"></param> public HSD_POBJ CreatePOBJ(List <GXVertex> triList, HSD_AttributeGroup attrGroup, List <HSD_JOBJWeight> weights) { TriangleConverter.TriangleConverter converter = new TriangleConverter.TriangleConverter(true, 100, 3, true); int pointCount, faceCount; var groups = converter.GroupPrimitives(triList.ToArray(), out pointCount, out faceCount); HSD_POBJ rootPOBJ = null; HSD_POBJ prevPOBJ = null; foreach (var g in groups) { var jobjweights = new List <HSD_JOBJWeight>(); var pmidToNewID = new Dictionary <ushort, ushort>(); foreach (var n in g._nodes) { pmidToNewID.Add(n, (ushort)(jobjweights.Count * 3)); jobjweights.Add(weights[n / 3]); } GXDisplayList newdl = new GXDisplayList(); foreach (var t in g._triangles) { var newVert = new List <GXVertex>(); for (int p = 0; p < t.Points.Count; p++) { var point = t.Points[p]; point.PMXID = pmidToNewID[point.PMXID]; t.Points[p] = point; newVert.Add(point); //Console.WriteLine(t.points[p].PMID + " " + point.PMXID + " " + pmidToNewID[point.PMXID] + " " + jobjweights.Count); } newdl.Primitives.Add(Compress(GXPrimitiveType.Triangles, newVert.ToArray(), attrGroup)); } foreach (var t in g._tristrips) { var newVert = new List <GXVertex>(); for (int p = 0; p < t.Points.Count; p++) { //Console.WriteLine(t.Points[p].PMXID + " " + g._nodes.Count); var point = t.Points[p]; point.PMXID = pmidToNewID[point.PMXID]; t.Points[p] = point; newVert.Add(point); } newdl.Primitives.Add(Compress(GXPrimitiveType.TriangleStrip, newVert.ToArray(), attrGroup)); } HSD_PointerArray <HSD_JOBJWeight> bindWeights = new HSD_PointerArray <HSD_JOBJWeight>(); bindWeights.Elements = jobjweights.ToArray(); var newpobj = new HSD_POBJ(); newpobj.Flags = POBJ_FLAG.ENVELOPE; newpobj.BindGroups = bindWeights; newpobj.VertexAttributes = attrGroup; newpobj.DisplayListBuffer = newdl.ToBuffer(attrGroup); if (prevPOBJ == null) { rootPOBJ = newpobj; } else { prevPOBJ.Next = newpobj; } prevPOBJ = newpobj; } return(rootPOBJ); }