//This sets up how to read the facepoints that are going to be written.
        public void WriteVertexDescriptor(FacepointAttribute[] attributes, MDL0ObjectNode obj)
        {
            XFNormalFormat nrmFmt = XFNormalFormat.None;
            int numColors = 0;
            int numUVs = 0;

            uint posNrmMtxId = 0;
            uint texMtxIdMask = 0;
            uint pos = 0;
            uint nrm = 0;
            uint col0 = 0;
            uint col1 = 0;
            uint tex0 = 0;
            uint tex1 = 0;
            uint tex2 = 0;
            uint tex3 = 0;
            uint tex4 = 0;
            uint tex5 = 0;
            uint tex6 = 0;
            uint tex7 = 0;

            foreach (FacepointAttribute attrPtr in attributes)
                switch (attrPtr._attr)
                {
                    case GXAttribute.PosNrmMtxId:
                        posNrmMtxId = (uint)attrPtr._type;
                        break;

                    case GXAttribute.Tex0MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~1) | ((uint)attrPtr._type << 0);
                        break;
                    case GXAttribute.Tex1MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~2) | ((uint)attrPtr._type << 1);
                        break;
                    case GXAttribute.Tex2MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~4) | ((uint)attrPtr._type << 2);
                        break;
                    case GXAttribute.Tex3MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~8) | ((uint)attrPtr._type << 3);
                        break;
                    case GXAttribute.Tex4MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~16) | ((uint)attrPtr._type << 4);
                        break;
                    case GXAttribute.Tex5MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~32) | ((uint)attrPtr._type << 5);
                        break;
                    case GXAttribute.Tex6MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~64) | ((uint)attrPtr._type << 6);
                        break;
                    case GXAttribute.Tex7MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~128) | ((uint)attrPtr._type << 7);
                        break;

                    case GXAttribute.Position:
                        pos = (uint)attrPtr._type;
                        break;

                    case GXAttribute.Normal:
                        if (attrPtr._type != XFDataFormat.None)
                        {
                            nrm = (uint)attrPtr._type;
                            nrmFmt = XFNormalFormat.XYZ;
                        }
                        break;

                    case GXAttribute.NBT:
                        if (attrPtr._type != XFDataFormat.None)
                        {
                            nrm = (uint)attrPtr._type;
                            nrmFmt = XFNormalFormat.NBT;
                        }
                        break;

                    case GXAttribute.Color0: col0 = (uint)attrPtr._type; numColors += (col0 != 0 ? 1 : 0); break;
                    case GXAttribute.Color1: col1 = (uint)attrPtr._type; numColors += (col1 != 0 ? 1 : 0); break;

                    case GXAttribute.Tex0: tex0 = (uint)attrPtr._type; numUVs += (tex0 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex1: tex1 = (uint)attrPtr._type; numUVs += (tex1 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex2: tex2 = (uint)attrPtr._type; numUVs += (tex2 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex3: tex3 = (uint)attrPtr._type; numUVs += (tex3 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex4: tex4 = (uint)attrPtr._type; numUVs += (tex4 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex5: tex5 = (uint)attrPtr._type; numUVs += (tex5 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex6: tex6 = (uint)attrPtr._type; numUVs += (tex6 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex7: tex7 = (uint)attrPtr._type; numUVs += (tex7 != 0 ? 1 : 0); break;
                }

            obj._vertexFormat._lo = ShiftVtxLo(posNrmMtxId, texMtxIdMask, pos, nrm, col0, col1);
            obj._vertexFormat._hi = ShiftVtxHi(tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7);
            obj._vertexSpecs = new XFVertexSpecs(numColors, numUVs, nrmFmt);
        }
 internal void WriteFacepoint(Facepoint f, PrimitiveGroup g, FacepointAttribute[] desc, ref VoidPtr address, MDL0ObjectNode node)
 {
     foreach (FacepointAttribute d in desc)
         switch (d._attr)
         {
             case GXAttribute.PosNrmMtxId:
                 if (d._type == XFDataFormat.Direct)
                     *(byte*)address++ = (byte)(3 * g._nodes.IndexOf(f.NodeID));
                 break;
             case GXAttribute.Tex0MtxId:
             case GXAttribute.Tex1MtxId:
             case GXAttribute.Tex2MtxId:
             case GXAttribute.Tex3MtxId:
             case GXAttribute.Tex4MtxId:
             case GXAttribute.Tex5MtxId:
             case GXAttribute.Tex6MtxId:
             case GXAttribute.Tex7MtxId:
                 if (d._type == XFDataFormat.Direct)
                     *(byte*)address++ = (byte)(30 + (3 * g._nodes.IndexOf(f.NodeID)));
                 break;
             case GXAttribute.Position:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         byte* addr = (byte*)address;
                         node.Model._linker._vertices[node._elementIndices[0]].Write(ref addr, f._vertexIndex);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._vertexIndex;
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._vertexIndex;
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Normal:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         byte* addr = (byte*)address;
                         node.Model._linker._normals[node._elementIndices[1]].Write(ref addr, f._normalIndex);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._normalIndex;
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._normalIndex;
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Color0:
             case GXAttribute.Color1:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         int index = (int)d._attr - 11;
                         byte* addr = (byte*)address;
                         node.Model._linker._colors[node._elementIndices[index + 2]].Write(ref addr, f._colorIndices[index]);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null)
                             *(byte*)address++ = 0;
                         else
                             *(byte*)address++ = (byte)f._colorIndices[(int)d._attr - 11];
                         break;
                     case XFDataFormat.Index16:
                         if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null)
                             *(bushort*)address = 0;
                         else
                             *(bushort*)address = (ushort)f._colorIndices[(int)d._attr - 11];
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Tex0:
             case GXAttribute.Tex1:
             case GXAttribute.Tex2:
             case GXAttribute.Tex3:
             case GXAttribute.Tex4:
             case GXAttribute.Tex5:
             case GXAttribute.Tex6:
             case GXAttribute.Tex7:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         int index = (int)d._attr - 13;
                         byte* addr = (byte*)address;
                         node.Model._linker._uvs[node._elementIndices[index + 4]].Write(ref addr, f._UVIndices[index]);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._UVIndices[(int)d._attr - 13];
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._UVIndices[(int)d._attr - 13];
                         address += 2;
                         break;
                 }
                 break;
         }
 }