示例#1
0
        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;
        }