private static unsafe void WritePrimitive(MDL0PolygonNode poly, NewPrimitive prim, XmlWriter writer) { PrimitiveManager manager = poly._manager; int count; int elements = 0, stride = 0; int set; bool first; ushort *pData = (ushort *)prim._indices.Address; ushort *pVert = (ushort *)poly._manager._indices.Address; switch (prim._type) { case GLPrimitiveType.Triangles: writer.WriteStartElement("triangles"); stride = 3; break; case GLPrimitiveType.Lines: writer.WriteStartElement("lines"); stride = 2; break; case GLPrimitiveType.Points: writer.WriteStartElement("points"); stride = 1; break; } count = prim._elementCount / stride; if (poly._material != null) { writer.WriteAttributeString("material", poly._material.Name); } writer.WriteAttributeString("count", count.ToString()); for (int i = 0; i < 12; i++) { if (manager._faceData[i] == null) { continue; } writer.WriteStartElement("input"); switch (i) { case 0: writer.WriteAttributeString("semantic", "VERTEX"); writer.WriteAttributeString("source", "#" + poly._name + "_Vertices"); break; case 1: writer.WriteAttributeString("semantic", "NORMAL"); writer.WriteAttributeString("source", "#" + poly._name + "_Normals"); break; case 2: case 3: set = i - 2; writer.WriteAttributeString("semantic", "COLOR"); writer.WriteAttributeString("source", "#" + poly._name + "_Colors" + set.ToString()); writer.WriteAttributeString("set", set.ToString()); break; default: set = i - 4; writer.WriteAttributeString("semantic", "TEXCOORD"); writer.WriteAttributeString("source", "#" + poly._name + "_UVs" + set.ToString()); writer.WriteAttributeString("set", set.ToString()); break; } writer.WriteAttributeString("offset", elements.ToString()); writer.WriteEndElement(); //input elements++; } for (int i = 0; i < count; i++) { writer.WriteStartElement("p"); first = true; for (int x = 0; x < stride; x++) { int index = *pData++; for (int y = 0; y < elements; y++) { if (first) { first = false; } else { writer.WriteString(" "); } if (y == 0) { writer.WriteString(pVert[index].ToString()); } else { writer.WriteString(index.ToString()); } } } writer.WriteEndElement(); //p } writer.WriteEndElement(); //primitive }
internal void ExtractPrimitives(byte *pData, ref ElementDescriptor desc, byte **pOut, byte **pAssets) { int count; ushort index = 0, temp; byte * pTemp = pData; //Get element count for each primitive type int d3 = 0, d2 = 0, d1 = 0; ushort *p3, p2, p1; //Get counts for each primitive type, and assign face points CountTop: switch ((GXListCommand)(*pTemp++)) { //Fill weight cache case GXListCommand.LoadIndexA: desc.SetNode(ref pTemp); goto CountTop; //Texture matrices? Not sure what to do here... case GXListCommand.LoadIndexB: case GXListCommand.LoadIndexC: case GXListCommand.LoadIndexD: pTemp += 4; goto CountTop; case GXListCommand.DrawQuads: count = *(bushort *)pTemp; d3 += count / 2 * 3; break; case GXListCommand.DrawTriangles: count = *(bushort *)pTemp; d3 += count; break; case GXListCommand.DrawTriangleFan: case GXListCommand.DrawTriangleStrip: count = *(bushort *)pTemp; d3 += (count - 2) * 3; break; case GXListCommand.DrawLines: count = *(bushort *)pTemp; d2 += count; break; case GXListCommand.DrawLineStrip: count = *(bushort *)pTemp; d2 += (count - 1) * 2; break; case GXListCommand.DrawPoints: count = *(bushort *)pTemp; d1 += count; break; default: goto Next; } //Extract face points here! pTemp += 2; desc.Run(ref pTemp, pAssets, pOut, count); goto CountTop; Next: //Create primitives if (d3 > 0) { _faces = new NewPrimitive(d3, GLPrimitiveType.Triangles); p3 = (ushort *)_faces._indices.Address; } else { _faces = null; p3 = null; } if (d2 > 0) { _lines = new NewPrimitive(d2, GLPrimitiveType.Lines); p2 = (ushort *)_lines._indices.Address; } else { _lines = null; p2 = null; } if (d1 > 0) { _points = new NewPrimitive(d1, GLPrimitiveType.Points); p1 = (ushort *)_points._indices.Address; } else { _points = null; p1 = null; } //Extract indices in reverse order, this way we get CCW winding. Top: switch ((GXListCommand)(*pData++)) { case GXListCommand.LoadIndexA: case GXListCommand.LoadIndexB: case GXListCommand.LoadIndexC: case GXListCommand.LoadIndexD: pData += 4; goto Top; case GXListCommand.DrawQuads: count = *(bushort *)pData; for (int i = 0; i < count; i += 4) { *p3++ = index; *p3++ = (ushort)(index + 2); *p3++ = (ushort)(index + 1); *p3++ = index; *p3++ = (ushort)(index + 3); *p3++ = (ushort)(index + 2); //if ((i & 3) == 2) //{ // *p3++ = index; // *p3++ = index; // *p3++ = (ushort)(index++ - 1); //} //*p3++ = index++; index += 4; } break; case GXListCommand.DrawTriangles: count = *(bushort *)pData; for (int i = 0; i < count; i += 3) { *p3++ = (ushort)(index + 2); *p3++ = (ushort)(index + 1); *p3++ = index; index += 3; } break; case GXListCommand.DrawTriangleFan: count = *(bushort *)pData; temp = index++; for (int i = 2; i < count; i++) { *p3++ = temp; *p3++ = (ushort)(index + 1); *p3++ = index++; } index++; break; case GXListCommand.DrawTriangleStrip: count = *(bushort *)pData; //temp = index; index += 2; for (int i = 2; i < count; i++) { if ((i & 1) == 0) { *p3++ = (ushort)(index - 2); *p3++ = index; *p3++ = (ushort)(index - 1); index++; //*p3++ = temp++; //*p3++ = temp++; //*p3++ = index++; } else { *p3++ = (ushort)(index - 1); *p3++ = index; *p3++ = (ushort)(index - 2); index++; //*p3++ = temp--; //*p3++ = temp++; //*p3++ = index++; } } break; case GXListCommand.DrawLines: count = *(bushort *)pData; for (int i = 0; i < count; i++) { *p2++ = index++; } break; case GXListCommand.DrawLineStrip: count = *(bushort *)pData; for (int i = 1; i < count; i++) { *p2++ = index++; *p2++ = index; } index++; break; case GXListCommand.DrawPoints: count = *(bushort *)pData; for (int i = 0; i < count; i++) { *p1++ = index++; } break; default: return; } pData += 2 + count * desc.Stride; goto Top; }
private static unsafe void WritePrimitive(MDL0ObjectNode poly, NewPrimitive prim, XmlWriter writer) { PrimitiveManager manager = poly._manager; int count; int elements = 0, stride = 0; int set; bool first; uint[] pDataArr = prim._indices; uint pData = 0; ushort* pVert = (ushort*)poly._manager._indices.Address; switch (prim._type) { case BeginMode.Triangles: writer.WriteStartElement("triangles"); stride = 3; break; case BeginMode.Lines: writer.WriteStartElement("lines"); stride = 2; break; case BeginMode.Points: writer.WriteStartElement("points"); stride = 1; break; } count = prim._elementCount / stride; if (poly.UsableMaterialNode != null) writer.WriteAttributeString("material", poly.UsableMaterialNode.Name); writer.WriteAttributeString("count", count.ToString()); List<int> elementType = new List<int>(); for (int i = 0; i < 12; i++) { if (manager._faceData[i] == null) continue; writer.WriteStartElement("input"); switch (i) { case 0: writer.WriteAttributeString("semantic", "VERTEX"); writer.WriteAttributeString("source", "#" + poly._name + "_Vertices"); break; case 1: writer.WriteAttributeString("semantic", "NORMAL"); writer.WriteAttributeString("source", "#" + poly._name + "_Normals"); break; case 2: case 3: set = i - 2; writer.WriteAttributeString("semantic", "COLOR"); writer.WriteAttributeString("source", "#" + poly._name + "_Colors" + set.ToString()); writer.WriteAttributeString("set", set.ToString()); break; default: set = i - 4; writer.WriteAttributeString("semantic", "TEXCOORD"); writer.WriteAttributeString("source", "#" + poly._name + "_UVs" + set.ToString()); writer.WriteAttributeString("set", set.ToString()); break; } writer.WriteAttributeString("offset", elements.ToString()); writer.WriteEndElement(); //input elements++; elementType.Add(i); } writer.WriteStartElement("p"); first = true; for (int i = 0; i < count; i++) { for (int x = 0; x < stride; x++) { int index = (int)pDataArr[pData++]; for (int y = 0; y < elements; y++) { if (first) first = false; else writer.WriteString(" "); if (elementType[y] < 4) if (elementType[y] < 2) if (elementType[y] == 0) writer.WriteString(pVert[index].ToString(CultureInfo.InvariantCulture.NumberFormat)); else writer.WriteString(_normRemap[index].ToString(CultureInfo.InvariantCulture.NumberFormat)); else writer.WriteString(_colorRemap[elementType[y] - 2][index].ToString(CultureInfo.InvariantCulture.NumberFormat)); else writer.WriteString(_uvRemap[elementType[y] - 4][index].ToString(CultureInfo.InvariantCulture.NumberFormat)); } } } writer.WriteEndElement(); //p writer.WriteEndElement(); //primitive }
internal void ExtractPrimitives(MDL0Object* header, ref ElementDescriptor desc, byte** pOut, byte** pAssets) { int count; uint index = 0, temp; byte* pData = (byte*)header->PrimitiveData; byte* pTemp = (byte*)pData; ushort* indices = (ushort*)_indices.Address; IMatrixNode[] cache = _polygon.Model._linker.NodeCache; //Get element count for each primitive type int d3 = 0, d2 = 0, d1 = 0; uint p3 = 0, p2 = 0, p1 = 0; uint[] p1arr = null, p2arr = null, p3arr = null; bool newGroup = true; PrimitiveGroup group = new PrimitiveGroup(); ushort id; //Get counts for each primitive type, and assign face points NextPrimitive: byte cmd = *pTemp++; if (cmd <= 0x38 && cmd >= 0x20) { if (newGroup == false) { _polygon._primGroups.Add(group); group = new PrimitiveGroup() { _offset = (uint)((pTemp - 1) - pData) }; newGroup = true; } if (!group._nodes.Contains(id = *(bushort*)pTemp) && id != ushort.MaxValue) group._nodes.Add(id); } //Switch by primitive type and increment as well so we can read the count. switch ((GXListCommand)cmd) { //Fill weight cache case GXListCommand.LoadIndexA: //Positions group._nodeOffsets.Add(new NodeOffset((uint)(pTemp - pData) - group._offset, cache[*(bushort*)pTemp])); //Set weight node for facepoint extraction desc.SetNode(ref pTemp, (byte*)pData); goto NextPrimitive; case GXListCommand.LoadIndexB: //Normals case GXListCommand.LoadIndexC: //UVs group._nodeOffsets.Add(new NodeOffset((uint)(pTemp - pData) - group._offset, cache[*(bushort*)pTemp])); pTemp += 4; //Skip goto NextPrimitive; case GXListCommand.LoadIndexD: //Lights Console.WriteLine("There are lights in here!"); pTemp += 4; //Skip goto NextPrimitive; case GXListCommand.DrawQuads: if (newGroup == true) newGroup = false; d3 += (count = *(bushort*)pTemp) / 2 * 3; group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.Quads, Entries = (ushort)count }); break; case GXListCommand.DrawTriangles: if (newGroup == true) newGroup = false; d3 += (count = *(bushort*)pTemp); group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.TriangleList, Entries = (ushort)count }); break; case GXListCommand.DrawTriangleFan: if (newGroup == true) newGroup = false; d3 += ((count = *(bushort*)pTemp) - 2) * 3; group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.TriangleFan, Entries = (ushort)count }); break; case GXListCommand.DrawTriangleStrip: if (newGroup == true) newGroup = false; d3 += ((count = *(bushort*)pTemp) - 2) * 3; group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.TriangleStrip, Entries = (ushort)count }); break; case GXListCommand.DrawLines: if (newGroup == true) newGroup = false; d2 += (count = *(bushort*)pTemp); group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.Lines, Entries = (ushort)count }); break; case GXListCommand.DrawLineStrip: if (newGroup == true) newGroup = false; d2 += ((count = *(bushort*)pTemp) - 1) * 2; group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.LineStrip, Entries = (ushort)count }); break; case GXListCommand.DrawPoints: if (newGroup == true) newGroup = false; d1 += (count = *(bushort*)pTemp); group._headers.Add(new PrimitiveHeader() { Type = WiiPrimitiveType.Points, Entries = (ushort)count }); break; default: _polygon._primGroups.Add(group); goto Next; //No more primitives. } pTemp += 2; //Extract facepoints here! desc.Run(ref pTemp, pAssets, pOut, count, group, ref indices, _polygon.Model._linker.NodeCache); goto NextPrimitive; Next: //Create primitives if (d3 > 0) { _triangles = new NewPrimitive(d3, BeginMode.Triangles); p3arr = _triangles._indices; } else _triangles = null; if (d2 > 0) { _lines = new NewPrimitive(d2, BeginMode.Lines); p2arr = _lines._indices; } else _lines = null; if (d1 > 0) { _points = new NewPrimitive(d1, BeginMode.Points); p1arr = _points._indices; } else _points = null; //Extract indices in reverse order, this way we get CCW winding. Top: switch ((GXListCommand)(*pData++)) { case GXListCommand.LoadIndexA: case GXListCommand.LoadIndexB: case GXListCommand.LoadIndexC: case GXListCommand.LoadIndexD: pData += 4; //Skip goto Top; case GXListCommand.DrawQuads: count = *(bushort*)pData; for (int i = 0; i < count; i += 4) { p3arr[p3++] = index; p3arr[p3++] = (uint)(index + 2); p3arr[p3++] = (uint)(index + 1); p3arr[p3++] = index; p3arr[p3++] = (uint)(index + 3); p3arr[p3++] = (uint)(index + 2); index += 4; } break; case GXListCommand.DrawTriangles: count = *(bushort*)pData; for (int i = 0; i < count; i += 3) { p3arr[p3++] = (uint)(index + 2); p3arr[p3++] = (uint)(index + 1); p3arr[p3++] = index; index += 3; } break; case GXListCommand.DrawTriangleFan: count = *(bushort*)pData; temp = index++; for (int i = 2; i < count; i++) { p3arr[p3++] = temp; p3arr[p3++] = (uint)(index + 1); p3arr[p3++] = index++; } index++; break; case GXListCommand.DrawTriangleStrip: count = *(bushort*)pData; index += 2; for (int i = 2; i < count; i++) { p3arr[p3++] = index; p3arr[p3++] = (uint)(index - 1 - (i & 1)); p3arr[p3++] = (uint)((index++) - 2 + (i & 1)); } break; case GXListCommand.DrawLines: count = *(bushort*)pData; for (int i = 0; i < count; i++) p2arr[p2++] = index++; break; case GXListCommand.DrawLineStrip: count = *(bushort*)pData; for (int i = 1; i < count; i++) { p2arr[p2++] = index++; p2arr[p2++] = index; } index++; break; case GXListCommand.DrawPoints: count = *(bushort*)pData; for (int i = 0; i < count; i++) p1arr[p1++] = index++; break; default: return; } pData += 2 + count * desc.Stride; goto Top; }