public ElementDescriptor(MDL0Polygon *polygon)
        {
            MDL0Header *model = (MDL0Header *)((byte *)polygon + polygon->_mdl0Offset);
            byte *      pData = (byte *)polygon->DefList;
            byte *      pCom;
            ElementDef *pDef;
            int         fmtLo, fmtHi;
            int         grp0, grp1, grp2;
            int         format;

            //Create remap table for vertex weights
            RemapTable = new UnsafeBuffer(polygon->_numVertices * 4);
            RemapSize  = 0;
            Stride     = 0;

            //Read element descriptor from polygon display list
            //Use direct access instead!
            //May change depending on file version

            fmtLo = *(bint *)(pData + 12);
            fmtHi = *(bint *)(pData + 18);
            grp0  = *(bint *)(pData + 34);
            grp1  = *(bint *)(pData + 40);
            grp2  = *(bint *)(pData + 46);

            //grp1 = *(buint*)(pData + 40);
            //grp1 |= (ulong)(*(buint*)(pData + 46)) << 32;


            //Build extract script.
            //What we're doing is assigning extract commands for elements in the polygon, in true order.
            //This allows us to process the polygon blindly, assuming that the definition is accurate.
            //Theoretically, this should offer a significant speed bonus.
            fixed(int *pDefData = Defs)
            fixed(byte *pComData = Commands)
            {
                pCom = pComData;
                pDef = (ElementDef *)pDefData;

                //Pos/Norm weight
                if (Weighted = (fmtLo & 1) != 0)
                {
                    *pCom++ = (byte)DecodeOp.PosWeight;
                    Stride++;
                }

                //Tex matrix
                for (int i = 0; i < 8; i++)
                {
                    if (((fmtLo >> (i + 1)) & 1) != 0)
                    {
                        *pCom++ = (byte)(DecodeOp.TexMtx0 + i);
                        Stride++;
                    }
                }

                //Positions
                format = ((fmtLo >> 9) & 3) - 1;
                if (format >= 0)
                {
                    pDef->Input = (byte)format;
                    pDef->Type  = 0;
                    if (format == 0)
                    {
                        throw new NotSupportedException("Direct mode is not suported for polygons!");
                        //pDef->Scale = (byte)((grp0 >> 4) & 0x1F);
                        //pDef->Output = (byte)(((grp0 >> 1) & 0x7) + ((grp0 & 1) == 0 ? ElementCodec.CodecType.XY : ElementCodec.CodecType.XYZ));
                        //pCom[NumCommands++] = (byte)DecodeOp.ElementDirect;
                    }
                    else
                    {
                        Stride      += format;
                        pDef->Output = 12;
                        *pCom++ = (byte)DecodeOp.ElementIndexed;
                    }
                    pDef++;
                }

                //Normals
                format = ((fmtLo >> 11) & 3) - 1;
                if (format >= 0)
                {
                    pDef->Input = (byte)format;
                    pDef->Type  = 1;
                    if (format == 0)
                    {
                        throw new NotSupportedException("Direct mode is not suported for polygons!");
                        //pDef->Scale = 0; //Implied?
                        //pDef->Output = (byte)(((grp0 >> 10) & 0x7) + ((grp0 & (1 << 10)) == 0 ? ElementCodec.CodecType.XYZ : ElementCodec.CodecType.XYZ));
                        //pCom[NumCommands++] = (byte)DecodeOp.ElementDirect;
                    }
                    else
                    {
                        Stride      += format;
                        pDef->Output = 12;
                        *pCom++ = (byte)DecodeOp.ElementIndexed;
                    }
                    pDef++;
                }

                //Colors
                for (int i = 0; i < 2; i++)
                {
                    format = ((fmtLo >> (i * 2 + 13)) & 3) - 1;
                    if (format >= 0)
                    {
                        pDef->Input = (byte)format;
                        pDef->Type  = (byte)(i + 2);
                        if (format == 0)
                        {
                            throw new NotSupportedException("Direct mode is not suported for polygons!");
                            //pDef->Output = (byte)((grp0 >> (i * 4 + 14)) & 7);
                            //pCom[NumCommands++] = (byte)DecodeOp.ElementDirect;
                        }
                        else
                        {
                            Stride      += format;
                            pDef->Output = 4;
                            *pCom++ = (byte)DecodeOp.ElementIndexed;
                        }
                        pDef++;
                    }
                }

                //UVs
                for (int i = 0; i < 8; i++)
                {
                    format = ((fmtHi >> (i * 2)) & 3) - 1;
                    if (format >= 0)
                    {
                        pDef->Input = (byte)format;
                        pDef->Type  = (byte)(i + 4);
                        if (format == 0)
                        {
                            throw new NotSupportedException("Direct mode is not suported for polygons!");
                            //Needs work!
                            //if (i == 0)
                            //{
                            //    pDef->Output = (byte)(((grp0 >> 22) & 7) + ((grp0 & 22) == 0 ? ElementCodec.CodecType.S : ElementCodec.CodecType.ST));
                            //    pDef->Scale = (byte)((grp0 >> 25) & 0x1F);
                            //}
                            //else
                            //{
                            //    pDef->Output = (byte)((int)((grp1 >> (i * 9 + 1)) & 7) + ((grp1 & ((ulong)1 << (i * 9 + 1))) == 0 ? ElementCodec.CodecType.S : ElementCodec.CodecType.ST));
                            //    pDef->Scale = (byte)((grp1 >> (i * 9 + 4)) & 0x1F);
                            //}
                            //pCom[NumCommands++] = (byte)DecodeOp.ElementDirect;
                        }
                        else
                        {
                            Stride      += format;
                            pDef->Output = 8;
                            *pCom++ = (byte)DecodeOp.ElementIndexed;
                        }
                        pDef++;
                    }
                }

                *pCom = 0;
            }
        }
Exemple #2
0
        internal static unsafe void Build(Collada form, ModelLinker linker, MDL0Header *header, int length, bool force)
        {
            byte *groupAddr = (byte *)header + linker._headerLen + linker._tableLen;
            byte *dataAddr  = groupAddr + linker._groupLen + linker._texLen; //Definitions start here
            byte *assetAddr = dataAddr + linker._defLen + linker._boneLen + linker._dataLen;

            linker.Header = header;

            if (form != null)
            {
                form.Say("Writing header...");
            }

            //Create new model header
            *header = new MDL0Header(length, linker.Version);

            if (form != null)
            {
                form.Say("Writing node table...");
            }

            //Write node table, assign node ids
            WriteNodeTable(linker);

            if (form != null)
            {
                form.Say("Writing definitions...");
            }

            //Write def table
            WriteDefs(linker, ref groupAddr, ref dataAddr);

            //Set format list for each polygon's UVAT groups
            SetFormatLists(linker);

            //Write assets first, but only if the model is an import
            if (linker.Model._isImport)
            {
                WriteAssets(form, linker, ref assetAddr);
            }

            //Write groups
            linker.Write(form, ref groupAddr, ref dataAddr, force);

            //Write user entries
            if (linker.Model._userEntries.Count > 0 && linker.Version > 9)
            {
                header->UserDataOffset = (int)dataAddr - (int)header;
                linker.Model._userEntries.Write(header->UserData);
            }
            else
            {
                header->UserDataOffset = 0;
            }

            //Write textures
            WriteTextures(linker, ref groupAddr);

            //Set box min and box max
            if (linker.Model._isImport)
            {
                SetBox(linker);
            }

            //Store group offsets
            linker.Finish();

            //Set new properties
            *header->Properties = new MDL0Props(linker.Version, linker.Model._numFacepoints, linker.Model._numTriangles, linker.Model._numNodes, linker.Model._scalingRule, linker.Model._texMtxMode, linker.Model._needsNrmMtxArray, linker.Model._needsTexMtxArray, linker.Model._enableExtents, linker.Model._envMtxMode, linker.Model._extents.Min, linker.Model._extents.Max);
        }
        internal static unsafe void Build(Collada form, ModelLinker linker, MDL0Header *header, int length, bool force)
        {
            byte *groupAddr = (byte *)header + linker._headerLen + linker._tableLen;
            byte *dataAddr  = groupAddr + linker._groupLen + linker._texLen; //Definitions start here
            byte *assetAddr = dataAddr + linker._defLen + linker._boneLen + linker._dataLen;

            linker.Header = header;

            if (form != null)
            {
                form.Say("Writing header...");
            }

            //Create new model header
            *header = new MDL0Header(length, linker.Version);
            MDL0Props *props = header->Properties;

            if (form != null)
            {
                form.Say("Writing node table...");
            }

            //Write node table, assign node ids
            WriteNodeTable(linker);

            if (form != null)
            {
                form.Say("Writing definitions...");
            }

            //Write def table
            WriteDefs(linker, ref groupAddr, ref dataAddr);

            //Set format list for each polygon's UVAT groups
            SetFormatLists(linker);

            //Write assets first, but only if the model is an import
            if (linker.Model._isImport)
            {
                WriteAssets(form, linker, ref assetAddr);
            }

            //Write groups
            linker.Write(form, ref groupAddr, ref dataAddr, force);

            //Write Part2 Entries
            if (linker.Model._part2Entries.Count > 0 && linker.Version != 9)
            {
                header->_part2Offset = (int)dataAddr - (int)header;
                Part2Data *part2 = header->Part2;
                if (part2 != null)
                {
                    part2->_totalLen = 0x1C + linker.Model._part2Entries.Count * 0x2C;
                    ResourceGroup *pGroup = part2->Group;
                    *pGroup = new ResourceGroup(linker.Model._part2Entries.Count);
                    ResourceEntry *pEntry = &pGroup->_first + 1;
                    byte *         pData  = (byte *)pGroup + pGroup->_totalSize;
                    foreach (string s in linker.Model._part2Entries)
                    {
                        (pEntry++)->_dataOffset = (int)pData - (int)pGroup;
                        Part2DataEntry *p = (Part2DataEntry *)pData;
                        *p = new Part2DataEntry(1);
                        pData += 0x1C;
                    }
                }
            }
            else
            {
                header->_part2Offset = 0;
            }

            //Write textures
            WriteTextures(linker, ref groupAddr);

            //Set box min and box max
            if (linker.Model._isImport)
            {
                SetBox(linker);
            }

            //Store group offsets
            linker.Finish();

            //Set new properties
            *props = new MDL0Props(linker.Version, linker.Model._numVertices, linker.Model._numFaces, linker.Model._numNodes, linker.Model._unk1, linker.Model._unk2, linker.Model._unk3, linker.Model._unk4, linker.Model._unk5, linker.Model._unk6, linker.Model.BoxMin, linker.Model.BoxMax);
        }
Exemple #4
0
 internal static unsafe void Build(ModelLinker linker, MDL0Header *header, int length, bool force)
 {
     Build(null, linker, header, length, force);
 }
        //protected override int OnCalculateSize(bool force)
        //{
        //    int size = 0;
        //    //Definitions

        //    foreach (ResourceNode node in Children)
        //    {
        //        size += node.CalculateSize(force);
        //    }

        //    return size;
        //}

        protected internal override void PostProcess(VoidPtr bresAddress, VoidPtr dataAddress, int dataLength, StringTable stringTable)
        {
            base.PostProcess(bresAddress, dataAddress, dataLength, stringTable);

            MDL0Header *   header = (MDL0Header *)dataAddress;
            ResourceGroup *pGroup, sGroup;
            ResourceEntry *pEntry, sEntry;
            bint *         offsets = header->Offsets;
            int            index, sIndex;

            //Model name
            header->StringOffset = (int)((byte *)stringTable[Name] + 4 - (byte *)header);

            //Post-process groups, using linker lists
            List <MDLResourceType> gList = ModelLinker.IndexBank[_version];

            foreach (MDL0GroupNode node in Children)
            {
                MDLResourceType type = (MDLResourceType)Enum.Parse(typeof(MDLResourceType), node.Name);
                if (((index = gList.IndexOf(type)) >= 0) && (type != MDLResourceType.Shaders))
                {
                    node.PostProcess(dataAddress, dataAddress + offsets[index], stringTable);
                }
            }

            //Post-process definitions
            index          = gList.IndexOf(MDLResourceType.Defs);
            pGroup         = (ResourceGroup *)(dataAddress + offsets[index]);
            pGroup->_first = new ResourceEntry(0xFFFF, 0, 0, 0);
            pEntry         = &pGroup->_first + 1;
            index          = 1;
            if (_hasTree)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["NodeTree"]);
            }
            if (_hasMix)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["NodeMix"]);
            }
            if (_hasOpa)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["DrawOpa"]);
            }
            if (_hasXlu)
            {
                ResourceEntry.Build(pGroup, index++, (byte *)pGroup + (pEntry++)->_dataOffset, (BRESString *)stringTable["DrawXlu"]);
            }

            //Link shader names using material list
            index  = offsets[gList.IndexOf(MDLResourceType.Materials)];
            sIndex = offsets[gList.IndexOf(MDLResourceType.Shaders)];
            if ((index > 0) && (sIndex > 0))
            {
                pGroup = (ResourceGroup *)(dataAddress + index);
                sGroup = (ResourceGroup *)(dataAddress + sIndex);
                pEntry = &pGroup->_first + 1;
                sEntry = &sGroup->_first + 1;

                sGroup->_first = new ResourceEntry(0xFFFF, 0, 0, 0);
                index          = pGroup->_numEntries;
                for (int i = 1; i <= index; i++)
                {
                    ResourceEntry.Build(sGroup, i, (byte *)sGroup + (sEntry++)->_dataOffset, (BRESString *)((byte *)pGroup + (pEntry++)->_stringOffset - 4));
                }
            }
        }