コード例 #1
0
        public void BuildFromScratch(Collada form)
        {
            _isImport = true;

            _influences.Clean();
            _influences.Sort();

            CleanTextures();

            _linker = ModelLinker.Prepare(this);
            int size = ModelEncoder.CalcSize(form, _linker);

            FileMap uncompMap = FileMap.FromTempFile(size);

            ModelEncoder.Build(form, _linker, (MDL0Header*)uncompMap.Address, size, true);

            _replSrc.Close();
            _replUncompSrc.Close();
            _replSrc = _replUncompSrc = new DataSource(uncompMap.Address, size);
            _replSrc.Map = _replUncompSrc.Map = uncompMap;

            IsDirty = false;
            _reopen = true;
            _isImport = false;
        }
コード例 #2
0
        //Write assets will only be used for model imports.
        private static void WriteAssets(Collada form, ModelLinker linker, ref byte* pData)
        {
            int index;
            MDL0Node model = linker.Model;

            if (linker._vertices != null && linker._vertices.Count != 0)
            {
                model.LinkGroup(new MDL0GroupNode(MDLResourceType.Vertices));
                model._vertGroup._parent = model;

                index = 0;
                foreach (VertexCodec c in linker._vertices)
                {
                    MDL0VertexNode node = new MDL0VertexNode();

                    node._name = model.Name + "_" + model._objList[index]._name;
                    if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null)
                        node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name;

                    if (form != null)
                        form.Say("Writing Vertices - " + node.Name);

                    MDL0VertexData* header = (MDL0VertexData*)pData;
                    header->_dataLen = c._dataLen.Align(0x20) + 0x40;
                    header->_dataOffset = 0x40;
                    header->_index = index++;
                    header->_isXYZ = c._hasZ ? 1 : 0;
                    header->_type = (int)c._type;
                    header->_divisor = (byte)c._scale;
                    header->_entryStride = (byte)c._dstStride;
                    header->_numVertices = (short)c._dstCount;
                    header->_eMin = c._min;
                    header->_eMax = c._max;
                    header->_pad1 = header->_pad2 = 0;

                    c.Write(pData + 0x40);

                    node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen);
                    model._vertGroup.AddChild(node, false);

                    pData += header->_dataLen;
                }
            }

            if (linker._normals != null && linker._normals.Count != 0)
            {
                model.LinkGroup(new MDL0GroupNode(MDLResourceType.Normals));
                model._normGroup._parent = model;

                index = 0;
                foreach (VertexCodec c in linker._normals)
                {
                    MDL0NormalNode node = new MDL0NormalNode();

                    node._name = model.Name + "_" + model._objList[index]._name;
                    if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null)
                        node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name;

                    if (form != null)
                        form.Say("Writing Normals - " + node.Name);

                    MDL0NormalData* header = (MDL0NormalData*)pData;
                    header->_dataLen = c._dataLen.Align(0x20) + 0x20;
                    header->_dataOffset = 0x20;
                    header->_index = index++;
                    header->_isNBT = 0;
                    header->_type = (int)c._type;
                    header->_divisor = (byte)c._scale;
                    header->_entryStride = (byte)c._dstStride;
                    header->_numVertices = (ushort)c._dstCount;

                    c.Write(pData + 0x20);

                    node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen);
                    model._normGroup.AddChild(node, false);

                    pData += header->_dataLen;
                }
            }

            if (linker._colors != null && linker._colors.Count != 0)
            {
                model.LinkGroup(new MDL0GroupNode(MDLResourceType.Colors));
                model._colorGroup._parent = model;

                index = 0;
                foreach (ColorCodec c in linker._colors)
                {
                    MDL0ColorNode node = new MDL0ColorNode();

                    node._name = model.Name + "_" + model._objList[index]._name;
                    if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null)
                        node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name;

                    if (form != null)
                        form.Say("Writing Colors - " + node.Name);

                    MDL0ColorData* header = (MDL0ColorData*)pData;
                    header->_dataLen = c._dataLen.Align(0x20) + 0x20;
                    header->_dataOffset = 0x20;
                    header->_index = index++;
                    header->_isRGBA = c._hasAlpha ? 1 : 0;
                    header->_format = (int)c._outType;
                    header->_entryStride = (byte)c._dstStride;
                    header->_pad = 0;
                    header->_numEntries = (ushort)c._dstCount;

                    c.Write(pData + 0x20);

                    node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen);
                    model._colorGroup.AddChild(node, false);

                    pData += header->_dataLen;
                }
            }

            if (linker._uvs != null && linker._uvs.Count != 0)
            {
                model.LinkGroup(new MDL0GroupNode(MDLResourceType.UVs));
                model._uvGroup._parent = model;

                index = 0;
                foreach (VertexCodec c in linker._uvs)
                {
                    MDL0UVNode node = new MDL0UVNode() { _name = "#" + index };

                    if (form != null)
                        form.Say("Writing UVs - " + node.Name);

                    MDL0UVData* header = (MDL0UVData*)pData;
                    header->_dataLen = c._dataLen.Align(0x20) + 0x40;
                    header->_dataOffset = 0x40;
                    header->_index = index++;
                    header->_format = (int)c._type;
                    header->_divisor = (byte)c._scale;
                    header->_isST = 1;
                    header->_entryStride = (byte)c._dstStride;
                    header->_numEntries = (ushort)c._dstCount;
                    header->_min = (Vector2)c._min;
                    header->_max = (Vector2)c._max;
                    header->_pad1 = header->_pad2 = header->_pad3 = header->_pad4 = 0;

                    c.Write(pData + 0x40);

                    node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen);
                    model._uvGroup.AddChild(node, false);

                    pData += header->_dataLen;
                }
            }

            //Clean groups
            if (model._vertList != null && model._vertList.Count > 0)
            {
                model._children.Add(model._vertGroup);
                linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._vertGroup.Name)] = model._vertGroup;
            }
            else
                model.UnlinkGroup(model._vertGroup);

            if (model._normList != null && model._normList.Count > 0)
            {
                model._children.Add(model._normGroup);
                linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._normGroup.Name)] = model._normGroup;
            }
            else
                model.UnlinkGroup(model._normGroup);

            if (model._uvList != null && model._uvList.Count > 0)
            {
                model._children.Add(model._uvGroup);
                linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._uvGroup.Name)] = model._uvGroup;
            }
            else
                model.UnlinkGroup(model._uvGroup);

            if (model._colorList != null && model._colorList.Count > 0)
            {
                model._children.Add(model._colorGroup);
                linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._colorGroup.Name)] = model._colorGroup;
            }
            else
                model.UnlinkGroup(model._colorGroup);

            //Link sets
            if (model._objList != null)
            foreach (MDL0ObjectNode poly in model._objList)
            {
                if (poly._elementIndices[0] != -1 && model._vertList != null && model._vertList.Count > poly._elementIndices[0])
                    poly._vertexNode = (MDL0VertexNode)model._vertGroup._children[poly._elementIndices[0]];
                if (poly._elementIndices[1] != -1 && model._normList != null && model._normList.Count > poly._elementIndices[1])
                    poly._normalNode = (MDL0NormalNode)model._normGroup._children[poly._elementIndices[1]];
                for (int i = 2; i < 4; i++)
                    if (poly._elementIndices[i] != -1 && model._colorList != null && model._colorList.Count > poly._elementIndices[i])
                        poly._colorSet[i - 2] = (MDL0ColorNode)model._colorGroup._children[poly._elementIndices[i]];
                for (int i = 4; i < 12; i++)
                    if (poly._elementIndices[i] != -1 && model._uvList != null && model._uvList.Count > poly._elementIndices[i])
                        poly._uvSet[i - 4] = (MDL0UVNode)model._uvGroup._children[poly._elementIndices[i]];
            }
        }
コード例 #3
0
        public static int CalcSize(Collada form, ModelLinker linker)
        {
            MDL0Node model = linker.Model;
            model._needsNrmMtxArray = model._needsTexMtxArray = false;
            model._numFacepoints = model._numFaces = 0;

            int headerLen,
                groupLen = 0,
                tableLen = 0,
                texLen = 0,
                boneLen = 0,
                dataLen = 0,
                defLen = 0,
                assetLen = 0,
                treeLen = 0,
                mixLen = 0,
                opaLen = 0,
                xluLen = 0;

            int aInd, aLen;

            //Get header length
            switch (linker.Version)
            {
                case 0x08:
                case 0x09: headerLen = 0x80; break;
                case 0x0A: headerLen = 0x88; break;
                case 0x0B: headerLen = 0x8C; break;
                default: headerLen = 0x80;
                    //Unsupported version. Change to 9 as default.
                    linker.Version = 9; break;
            }

            //Assign node indices
            AssignNodeIndices(linker);

            //Get table length
            tableLen = (linker._nodeCount + 1) << 2;

            //Get group/data length
            List<MDLResourceType> iList = ModelLinker.IndexBank[linker.Version];
            foreach (MDLResourceType resType in iList)
            {
                IEnumerable entryList = null;
                int entries = 0;

                switch (resType)
                {
                    case MDLResourceType.Definitions:

                        //NodeTree
                        treeLen = linker.BoneCache.Length * 5;

                        //NodeMix
                        foreach (Influence i in model._influences._influences)
                        {
                            mixLen += 4;
                            foreach (BoneWeight w in i._weights)
                                if (w.Bone != null && w.Weight != 0 && w.Bone._nodeIndex < linker.NodeCache.Length && w.Bone._nodeIndex >= 0 && linker.NodeCache[w.Bone._nodeIndex] is MDL0BoneNode)
                                    mixLen += 6;
                        }
                        foreach (MDL0BoneNode b in linker.BoneCache)
                            if (b._weightCount > 0)
                                mixLen += 5;

                        //DrawOpa and DrawXlu
                        //Get assigned materials and categorize
                        if (model._objList != null)
                            for (int i = 0; i < model._objList.Count; i++)
                            {
                                //Entries are ordered by material, not by polygon.
                                //Using the material's attached polygon list is untrustable if the definitions were corrupt on parse.
                                MDL0ObjectNode poly = model._objList[i] as MDL0ObjectNode;

                                model._numFaces += poly._numFaces;
                                model._numFacepoints += poly._numFacepoints;

                                if (poly.OpaMaterialNode != null)
                                    opaLen += 8;
                                if (poly.XluMaterialNode != null)
                                    xluLen += 8;
                            }

                        //Add terminate byte and set model def flags
                        if (model._hasTree = (treeLen > 0)) { treeLen++; entries++; }
                        if (model._hasMix = (mixLen > 0)) { mixLen++; entries++; }
                        if (model._hasOpa = (opaLen > 0)) { opaLen++; entries++; }
                        if (model._hasXlu = (xluLen > 0)) { xluLen++; entries++; }

                        //Align data
                        defLen += (treeLen + mixLen + opaLen + xluLen).Align(4);

                        break;

                    case MDLResourceType.Vertices:
                        if (model._vertList != null)
                        {
                            entryList = model._vertList;
                            break;
                        }
                        else
                        {
                            aInd = 0; //Set the ID
                            aLen = 1; //Offset count
                        }

                    EvalAssets:

                        List<ResourceNode> polyList = model._objList;
                        if (polyList == null)
                            break;

                        string str = "";

                        bool direct = linker._forceDirectAssets[aInd];

                        //Create asset lists
                        IList aList;
                        switch (aInd) //Switch by the set ID
                        {
                            case 0: aList = linker._vertices = new List<VertexCodec>(polyList.Count); str = "Vertices "; break;
                            case 1: aList = linker._normals = new List<VertexCodec>(polyList.Count); str = "Normals "; break;
                            case 2: aList = linker._colors = new List<ColorCodec>(polyList.Count); str = "Colors "; break;
                            default: aList = linker._uvs = new List<VertexCodec>(polyList.Count); str = "UVs "; break;
                        }

                        aLen += aInd;
                        for (int i = 0; i < polyList.Count; i++)
                        {
                            MDL0ObjectNode obj = polyList[i] as MDL0ObjectNode;
                            for (int x = aInd; x < aLen; x++)
                                if (obj._manager._faceData[x] != null)
                                {
                                    //Remap color nodes
                                    if ((x == 2 || x == 3))
                                    {
                                        if (Collada._importOptions._rmpClrs)
                                        {
                                            obj._elementIndices[x] = -1;
                                            foreach (MDL0ObjectNode thatObj in polyList.OrderBy(c => -((MDL0ObjectNode)c)._manager.GetColors(x - 2, false).Length))
                                            {
                                                //Only compare up to the current object
                                                if (thatObj == obj)
                                                    break;

                                                var thatArr = thatObj._manager.GetColors(x - 2, false);
                                                var thisArr = obj._manager.GetColors(x - 2, false);
                                                bool equals = true;
                                                if (thisArr.Length == thatArr.Length)
                                                {
                                                    for (int n = 0; n < thisArr.Length; n++)
                                                        if (thisArr[n] != thatArr[n])
                                                        {
                                                            equals = false;
                                                            break;
                                                        }
                                                }
                                                else
                                                {
                                                    foreach (RGBAPixel px in thisArr)
                                                    {
                                                        if (Array.IndexOf(thatArr, px) < 0)
                                                        {
                                                            equals = false;
                                                            break;
                                                        }
                                                    }
                                                }

                                                if (equals)
                                                {
                                                    //Found a match
                                                    obj._elementIndices[x] = thatObj._elementIndices[x];
                                                    obj._manager._newClrObj[x - 2] = thatObj.Index;
                                                    break;
                                                }
                                            }
                                            if (obj._elementIndices[x] != -1)
                                                continue;
                                        }
                                        else
                                            obj._manager._newClrObj[x - 2] = i;
                                    }

                                    obj._elementIndices[x] = (short)aList.Count;

                                    if (form != null)
                                        form.Say("Encoding " + str + (x - aInd) + " for Object " + i + ": " + obj.Name);

                                    VertexCodec vert;
                                    switch (aInd)
                                    {
                                        case 0:
                                            vert = new VertexCodec(obj._manager.GetVertices(false), false, Collada._importOptions._fltVerts);
                                            aList.Add(vert);
                                            if (!direct)
                                                assetLen += vert._dataLen.Align(0x20) + 0x40;
                                            break;
                                        case 1:
                                            vert = new VertexCodec(obj._manager.GetNormals(false), false, Collada._importOptions._fltNrms);
                                            aList.Add(vert);
                                            if (!direct)
                                                assetLen += vert._dataLen.Align(0x20) + 0x20;
                                            break;
                                        case 2:
                                            ColorCodec col = new ColorCodec(obj._manager.GetColors(x - 2, false));
                                            aList.Add(col);
                                            if (!direct)
                                                assetLen += col._dataLen.Align(0x20) + 0x20;
                                            break;
                                        default:
                                            vert = new VertexCodec(obj._manager.GetUVs(x - 4, false), Collada._importOptions._fltUVs);
                                            aList.Add(vert);
                                            if (!direct)
                                                assetLen += vert._dataLen.Align(0x20) + 0x40;
                                            break;
                                    }
                                }
                                else
                                    obj._elementIndices[x] = -1;
                        }
                        if (!direct)
                            entries = aList.Count;
                        break;
                    case MDLResourceType.Normals:
                        if (model._normList != null)
                            entryList = model._normList;
                        else
                        {
                            aInd = 1; //Set the ID
                            aLen = 1; //Offset count
                            goto EvalAssets;
                        }
                        break;
                    case MDLResourceType.Colors:
                        if (model._colorList != null)
                            entryList = model._colorList;
                        else
                        {
                            if (Collada._importOptions._useOneNode)
                            {
                                HashSet<RGBAPixel> pixels = new HashSet<RGBAPixel>();
                                foreach (MDL0ObjectNode obj in model._objList)
                                {
                                    for (int i = 0; i < 2; i++)
                                    {
                                        var arr = obj._manager.GetColors(i, false);
                                        if (arr.Length > 0)
                                        {
                                            obj._elementIndices[i + 2] = 0;
                                            foreach (RGBAPixel p in arr)
                                                pixels.Add(p);
                                        }
                                        else
                                            obj._elementIndices[i + 2] = -1;
                                    }
                                }
                                var le = pixels.ToList(); le.Sort();
                                Collada._importOptions._singleColorNodeEntries = le.ToArray();

                                ColorCodec col = new ColorCodec(Collada._importOptions._singleColorNodeEntries);
                                linker._colors = new List<ColorCodec>() { col };
                                assetLen += col._dataLen.Align(0x20) + 0x20;
                                entries = 1;
                            }
                            else
                            {
                                aInd = 2; //Set the ID
                                aLen = 2; //Offset count
                                goto EvalAssets;
                            }
                        }
                        break;
                    case MDLResourceType.UVs:
                        if (model._uvList != null)
                            entryList = model._uvList;
                        else
                        {
                            aInd = 4; //Set the ID
                            aLen = 8; //Offset count
                            goto EvalAssets;
                        }
                        break;

                    case MDLResourceType.Bones:
                        int index = 0;
                        foreach (MDL0BoneNode b in linker.BoneCache)
                        {
                            if (form != null)
                                form.Say("Calculating the size of the Bones - " + b.Name);

                            b._entryIndex = index++;
                            boneLen += b.CalculateSize(true);
                        }
                        entries = linker.BoneCache.Length;
                        break;

                    case MDLResourceType.Materials:
                        if (model._matList != null)
                            entries = model._matList.Count;
                        break;

                    case MDLResourceType.Objects:
                        if (model._objList != null)
                        {
                            entryList = model._objList;
                            if (model._objList.Count > 0)
                            {
                                model._needsNrmMtxArray = true;
                                foreach (MDL0ObjectNode n in model._objList)
                                    if (n.HasTexMtx)
                                        model._needsTexMtxArray = true;
                            }
                        }
                        break;

                    case MDLResourceType.Shaders:
                        if ((entryList = model.GetUsedShaders()) != null && model._matList != null)
                            entries = model._matList.Count;
                        break;

                    case MDLResourceType.Textures:
                        if (model._texList != null)
                        {
                            foreach (MDL0TextureNode tex in model._texList)
                                texLen += (tex._references.Count * 8) + 4;

                            linker._texCount = entries = model._texList.Count;
                        }
                        break;

                    case MDLResourceType.Palettes:
                        if (model._pltList != null)
                        {
                            foreach (MDL0TextureNode pal in model._pltList)
                                texLen += (pal._references.Count * 8) + 4;

                            linker._palCount = entries = model._pltList.Count;
                        }
                        break;
                }

                if (entryList != null)
                {
                    int index = 0;
                    foreach (MDL0EntryNode e in entryList)
                    {
                        if (form != null)
                            if (resType == MDLResourceType.Objects)
                                form.Say("Encoding the " + resType.ToString() + " - " + e.Name);
                            else
                                form.Say("Calculating the size of the " + resType.ToString() + " - " + e.Name);

                        e._entryIndex = index++;
                        dataLen += e.CalculateSize(true);
                    }
                    if (entries == 0)
                        entries = index;
                }

                if (entries > 0)
                    groupLen += (entries * 0x10) + 0x18;
            }

            //Align the materials perfectly using the data length
            int temp = 0;
            if (model._matList != null && iList.IndexOf(MDLResourceType.Materials) != -1)
            {
                int index = 0;
                MDL0MaterialNode prev = null;
                foreach (MDL0MaterialNode e in model._matList)
                {
                    if (form != null)
                        form.Say("Calculating the size of the Materials - " + e.Name);

                    e._entryIndex = index++;

                    if (index == 1)
                    {
                        if ((temp = (e._mdlOffset = headerLen + tableLen + groupLen + texLen + defLen + boneLen).Align(0x10)) != e._mdlOffset)
                            e._dataAlign = temp - e._mdlOffset;
                    }
                    else
                        e._mdlOffset = (prev = ((MDL0MaterialNode)model._matList[index - 1]))._mdlOffset + prev._calcSize;

                    dataLen += e.CalculateSize(true);
                }
            }

            return
            (linker._headerLen = headerLen) +
            (linker._tableLen = tableLen) +
            (linker._groupLen = groupLen) +
            (linker._texLen = texLen) +
            (linker._defLen = defLen) +
            (linker._boneLen = boneLen) +
            (linker._assetLen = assetLen) +
            (linker._dataLen = dataLen) +
            (linker.Version > 9 ? model._userEntries.GetSize() : 0);
        }
コード例 #4
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);
            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 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
            *props = new MDL0Props(linker.Version, linker.Model._numFacepoints, linker.Model._numFaces, linker.Model._numNodes, linker.Model._scalingRule, linker.Model._texMtxMode, linker.Model._needsNrmMtxArray, linker.Model._needsTexMtxArray, linker.Model._enableExtents, linker.Model._envMtxMode, linker.Model.BoxMin, linker.Model.BoxMax);
        }