コード例 #1
0
        //Initialize should only be called from parent group during parse.
        //Bones need not be imported/exported anyways
        protected override bool OnInitialize()
        {
            MDL0Bone *header = Header;

            SetSizeInternal(header->_headerLen);

            //Assign true parent using parent header offset
            int offset = header->_parentOffset;

            //Offsets are always < 0, because parent entries are listed before children
            if (offset < 0)
            {
                //Get address of parent header
                MDL0Bone *pHeader = (MDL0Bone *)((byte *)header + offset);
                //Search bone list for matching header
                foreach (MDL0BoneNode bone in _parent._children)
                {
                    if (pHeader == bone.Header)
                    {
                        _parent = bone; break;
                    }                          //Assign parent and break
                }
            }

            //Conditional name assignment
            if ((_name == null) && (header->_stringOffset != 0))
            {
                _name = header->ResourceString;
            }

            //Assign fields
            _flags     = (BoneFlags)(uint)header->_flags;
            _nodeIndex = header->_nodeId;
            _boneIndex = header->_index;

            _permanentID = header->_index;

            _bindState = _frameState = new FrameState(header->_scale, header->_rotation, header->_translation);
            (_bindState._quaternion = new Quaternion()).FromEuler(header->_rotation);
            _bindMatrix        = _frameMatrix = header->_transform;
            _inverseBindMatrix = _inverseFrameMatrix = header->_transformInv;

            _bMin = header->_boxMin;
            _bMax = header->_boxMax;

            if (header->_part2Offset != 0)
            {
                Part2Data *    part2  = (Part2Data *)((byte *)header + header->_part2Offset);
                ResourceGroup *group  = part2->Group;
                ResourceEntry *pEntry = &group->_first + 1;
                int            count  = group->_numEntries;
                for (int i = 0; i < count; i++)
                {
                    _entries.Add(new String((sbyte *)group + (pEntry++)->_stringOffset));
                }
            }
            //We don't want to process children because not all have been parsed yet.
            //Child assigning will be handled by the parent group.
            return(false);
        }
コード例 #2
0
        public void CalculateOffsets()
        {
            MDL0Bone *header = (MDL0Bone *)WorkingUncompressed.Address;

            //Set first child
            header->_firstChildOffset = _children.Count > 0 ?
                                        (int)Children[0].WorkingUncompressed.Address - (int)header :
                                        0;

            if (Parent != null)
            {
                int index = Index;

                //Parent
                header->_parentOffset = Parent is MDL0BoneNode ?
                                        (int)Parent.WorkingUncompressed.Address - (int)header :
                                        0;

                //Previous sibling
                header->_prevOffset = index == 0 ?
                                      0 :
                                      (int)Parent._children[index - 1].WorkingUncompressed.Address - (int)header;

                //Next sibling
                header->_nextOffset = index == (Parent._children.Count - 1) ?
                                      0 :
                                      (int)Parent._children[index + 1].WorkingUncompressed.Address - (int)header;
            }
        }
コード例 #3
0
        public override void OnRebuild(VoidPtr address, int length, bool force)
        {
            MDL0Bone *header = (MDL0Bone *)address;

            RecalcOffsets(header, address, length);

            if (_refCount > 0 || _weightCount > 0 || InfluencedObjects.Length > 0)
            {
                _flags1 |= BoneFlags.HasGeometry;
            }
            else
            {
                _flags1 &= ~BoneFlags.HasGeometry;
            }

            header->_headerLen    = length;
            header->_index        = _boneIndex = _entryIndex;
            header->_nodeId       = _nodeIndex;
            header->_flags        = (uint)_flags1;
            header->_bbFlags      = (uint)_flags2;
            header->_bbNodeId     = _bbNodeId;
            header->_scale        = _bindState._scale;
            header->_rotation     = _bindState._rotate;
            header->_translation  = _bindState._translate;
            header->_boxMin       = _bMin;
            header->_boxMax       = _bMax;
            header->_transform    = (bMatrix43)_bindMatrix;
            header->_transformInv = (bMatrix43)_inverseBindMatrix;

            _moved = false;
        }
コード例 #4
0
        protected internal override void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            MDL0Bone *header = (MDL0Bone *)dataAddress;

            header->MDL0Address           = mdlAddress;
            header->ResourceStringAddress = stringTable[Name] + 4;

            _userEntries.PostProcess(dataAddress + 0xD0, stringTable);
        }
コード例 #5
0
        protected internal override void OnRebuild(VoidPtr address, int length, bool force)
        {
            MDL0Bone *header = (MDL0Bone *)address;

            RecalcOffsets(header, address, length);

            if (_flags == 0 || flagsChanged)
            {
                CalcFlags();
            }

            header->_headerLen = length;

            //if (!_override)
            header->_index = _boneIndex = _entryIndex;    // - Model._overrideCount;
            //else
            //    header->_index = _boneIndex = Model._linker.BoneCache.Length - 1 + Model._overrideCount++;

            header->_nodeId      = _nodeIndex;
            header->_flags       = (uint)_flags;
            header->_pad1        = 0;
            header->_pad2        = 0;
            header->_scale       = _bindState._scale;
            header->_rotation    = _bindState._rotate;
            header->_translation = _bindState._translate;
            header->_boxMin      = _bMin;
            header->_boxMax      = _bMax;

            //if (_bindMatrix != _frameMatrix)
            //{
            //    header->_transform = (bMatrix43)_frameMatrix;
            //    header->_transformInv = (bMatrix43)_inverseFrameMatrix;
            //}
            //else
            //{
            header->_transform    = (bMatrix43)_bindMatrix;
            header->_transformInv = (bMatrix43)_inverseBindMatrix;
            //}

            _moved = false;
        }
コード例 #6
0
        protected internal override void PostProcess(VoidPtr mdlAddress, VoidPtr dataAddress, StringTable stringTable)
        {
            MDL0Bone *header = (MDL0Bone *)dataAddress;

            header->_mdl0Offset   = (int)mdlAddress - (int)dataAddress;
            header->_stringOffset = (int)stringTable[Name] + 4 - (int)dataAddress;

            //Entry strings
            if (_entries.Count > 0)
            {
                ResourceGroup *pGroup = (ResourceGroup *)((byte *)header + header->_part2Offset + 4);
                ResourceEntry *pEntry = &pGroup->_first;
                int            count  = pGroup->_numEntries;
                (*pEntry++) = new ResourceEntry(0xFFFF, 0, 0, 0, 0);

                for (int i = 0; i < count; i++)
                {
                    Part2DataEntry *entry = (Part2DataEntry *)((byte *)pGroup + (pEntry++)->_dataOffset);
                    entry->_stringOffset = (int)stringTable[_entries[i]] + 4 - ((int)entry + (int)dataAddress);
                    ResourceEntry.Build(pGroup, i + 1, entry, (BRESString *)stringTable[_entries[i]]);
                }
            }
        }
コード例 #7
0
ファイル: MDL0BoneNode.cs プロジェクト: PeterHatch/brawltools
        //Initialize should only be called from parent group during parse.
        //Bones need not be imported/exported anyways
        public override bool OnInitialize()
        {
            MDL0Bone *header = Header;

            SetSizeInternal(header->_headerLen);

            //Conditional name assignment
            if (_name == null && header->_stringOffset != 0)
            {
                _name = header->ResourceString;
            }

            //Assign fields
            _boneFlags      = (BoneFlags)(uint)header->_flags;
            _billboardFlags = (BillboardFlags)(uint)header->_bbFlags;
            _nodeIndex      = header->_nodeId;
            _entryIndex     = header->_index;

            _bbRefNode = !_replaced && _boneFlags.HasFlag(BoneFlags.HasBillboardParent) ?
                         Model._linker.NodeCache[header->_bbNodeId] as MDL0BoneNode : null;

            if (_billboardFlags != BillboardFlags.Off)
            {
                Model._billboardBones.Add(this); //Update mesh in T-Pose
            }
            _bindState         = _frameState = new FrameState(header->_scale, (Vector3)header->_rotation, header->_translation);
            _bindMatrix        = _frameMatrix = header->_transform;
            _inverseBindMatrix = _inverseFrameMatrix = header->_transformInv;

            _extents = header->_extents;

            (_userEntries = new UserDataCollection()).Read(header->UserDataAddress);

            //We don't want to process children because not all have been parsed yet.
            //Child assignments will be handled by the parent group.
            return(false);
        }
コード例 #8
0
        public override void OnRebuild(VoidPtr address, int length, bool force)
        {
            MDL0Bone *header = (MDL0Bone *)address;

            if (Users.Count > 0 || SingleBindObjects.Length > 0)
            {
                _boneFlags |= BoneFlags.HasGeometry;
            }
            else
            {
                _boneFlags &= ~BoneFlags.HasGeometry;
            }

            header->_headerLen    = length;
            header->_index        = _entryIndex;
            header->_nodeId       = _nodeIndex;
            header->_flags        = (uint)_boneFlags;
            header->_bbFlags      = (uint)_billboardFlags;
            header->_bbIndex      = _bbRefNode == null ? 0 : (uint)_bbRefNode._entryIndex;
            header->_scale        = _bindState._scale;
            header->_rotation     = _bindState._rotate;
            header->_translation  = _bindState._translate;
            header->_extents      = _extents;
            header->_transform    = (bMatrix43)_bindMatrix;
            header->_transformInv = (bMatrix43)_inverseBindMatrix;

            if (_userEntries.Count > 0)
            {
                header->_userDataOffset = 0xD0;
                _userEntries.Write(address + 0xD0);
            }
            else
            {
                header->_userDataOffset = 0;
            }
        }
コード例 #9
0
        protected internal override void OnRebuild(VoidPtr address, int length, bool force)
        {
            MDL0Bone *   header = (MDL0Bone *)address;
            MDL0BoneNode bone;
            int          index = 0, offset;

            header->_headerLen   = length;
            header->_index       = _entryIndex;
            header->_nodeId      = _nodeIndex;
            header->_flags       = (uint)_flags;
            header->_pad1        = 0;
            header->_pad2        = 0;
            header->_scale       = _bindState._scale;
            header->_rotation    = _bindState._rotate;
            header->_translation = _bindState._translate;
            header->_boxMin      = _bMin;
            header->_boxMax      = _bMax;

            header->_transform    = _bindMatrix;
            header->_transformInv = _inverseBindMatrix;

            //Sub-entries
            if (_entries.Count > 0)
            {
                header->_part2Offset = 0xD0;
                *(bint *)((byte *)address + 0xD0) = 0x1C + (_entries.Count * 0x2C);
                ResourceGroup *pGroup = (ResourceGroup *)((byte *)address + 0xD4);
                ResourceEntry *pEntry = &pGroup->_first + 1;
                byte *         pData  = (byte *)pGroup + pGroup->_totalSize;

                *pGroup = new ResourceGroup(_entries.Count);

                foreach (string s in _entries)
                {
                    (pEntry++)->_dataOffset = (int)pData - (int)pGroup;
                    MDL0Data7Part4Entry *p = (MDL0Data7Part4Entry *)pData;
                    *p = new MDL0Data7Part4Entry(1);
                    pData += 0x1C;
                }
            }
            else
            {
                header->_part2Offset = 0;
            }

            //Set first child
            if (_children.Count > 0)
            {
                header->_firstChildOffset = length;
            }
            else
            {
                header->_firstChildOffset = 0;
            }

            if (_parent != null)
            {
                index = _parent._children.IndexOf(this);

                //Parent
                if (_parent is MDL0BoneNode)
                {
                    header->_parentOffset = (int)_parent.WorkingUncompressed.Address - (int)address;
                }
                else
                {
                    header->_parentOffset = 0;
                }

                //Prev
                if (index == 0)
                {
                    header->_prevOffset = 0;
                }
                else
                {
                    //Link to prev
                    bone   = _parent._children[index - 1] as MDL0BoneNode;
                    offset = (int)bone.Header - (int)address;
                    header->_prevOffset      = offset;
                    bone.Header->_nextOffset = -offset;
                }

                //Next
                if (index == (_parent._children.Count - 1))
                {
                    header->_nextOffset = 0;
                }
            }
        }
コード例 #10
0
ファイル: Bone.cs プロジェクト: KingAtreyu/super-sawndz
 public Bone(MDL0Bone *pBone)
 {
 }
コード例 #11
0
        internal void Parse(MDL0Node model)
        {
            Influence   inf;
            ModelLinker linker = model._linker;

            int typeIndex = (int)_type;

            fixed(ResourceGroup **gList = &linker.Defs)
            if (gList[typeIndex] != null)
                ExtractGroup(gList[typeIndex], ModelLinker.TypeBank[typeIndex]);
            else
                return;     //Nothing to read

            //Special handling for bones and objects
            if (_type == MDLResourceType.Bones)
            {
                //Bones have been parsed from raw data as a flat list.
                //Bones re-assign parents in their Initialize block, so parents are true.
                //Parents must be assigned now as bones will be moved in memory when assigned as children.

                //Cache flat list
                linker.BoneCache = _children.Select(x => x as MDL0BoneNode).ToArray();

                //Reset children so we can rebuild
                _children.Clear();

                //Assign children using each bones' parent offset in case NodeTree is corrupted.
                //Bone parents are assigned when they are initialized in a flat array.
                foreach (MDL0BoneNode b in linker.BoneCache)
                {
                    MDL0Bone *header = b.Header;

                    //Assign true parent using parent header offset
                    int offset = header->_parentOffset;
                    if (offset != 0)
                    {
                        //Get address of parent header
                        MDL0Bone *pHeader = (MDL0Bone *)((byte *)header + offset);
                        //Search bone list for matching header
                        foreach (MDL0BoneNode b2 in linker.BoneCache)
                        {
                            if (pHeader == b2.Header)
                            {
                                b._parent = b2;
                                break;
                            }
                        }
                    }

                    if (b._boneFlags.HasFlag(BoneFlags.HasBillboardParent))
                    {
                        b._bbRefNode = model._linker.BoneCache[header->_bbIndex] as MDL0BoneNode;
                    }
                }

                //Make sure the node cache is the correct size
                int highest = 0;

                //Add bones to their parent's child lists and find highest node id
                foreach (MDL0BoneNode b in linker.BoneCache)
                {
                    b._parent._children.Add(b);

                    if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest)
                    {
                        highest = b._nodeIndex;
                    }
                }

                if (highest >= linker.NodeCache.Length)
                {
                    linker.NodeCache = new IMatrixNode[highest + 1];
                }

                //Populate node cache
                MDL0BoneNode bone = null;
                int          index;
                int          count = linker.BoneCache.Length;

                for (int i = 0; i < count; i++)
                {
                    linker.NodeCache[(bone = linker.BoneCache[i] as MDL0BoneNode)._nodeIndex] = bone;
                }

                int nullCount = 0;

                bool nodeTreeError = false;

                //Now that bones and primary influences have been cached, we can create weighted influences.
                foreach (ResourcePair p in *linker.Defs)
                {
                    if (p.Name == "NodeTree")
                    {
                        //Double check bone tree using the NodeTree definition.
                        //If the NodeTree is corrupt, the user will be informed that it needs to be rebuilt.
                        byte *pData     = (byte *)p.Data;
                        bool  fixCS0159 = false;

                        List <MDL0BoneNode> bones = linker.BoneCache.ToList();

STop:
                        if (*pData == 2)
                        {
                            bone  = linker.BoneCache[*(bushort *)(pData + 1)] as MDL0BoneNode;
                            index = *(bushort *)(pData + 3); //Parent bone node index

                            if (bone.Header->_parentOffset == 0)
                            {
                                if (!_children.Contains(bone))
                                {
                                    nodeTreeError = true;
                                    continue;
                                }
                                else
                                {
                                    bones.Remove(bone);
                                }
                            }
                            else
                            {
                                MDL0BoneNode parent = linker.NodeCache[index] as MDL0BoneNode;
                                if (parent == null || bone._parent != parent || !parent._children.Contains(bone))
                                {
                                    nodeTreeError = true;
                                    continue;
                                }
                                else
                                {
                                    bones.Remove(bone);
                                }
                            }
                            pData    += 5;
                            fixCS0159 = true;
                        }
                        if (fixCS0159)
                        {
                            fixCS0159 = false;
                            goto STop;
                        }

                        if (bones.Count > 0)
                        {
                            nodeTreeError = true;
                        }
                    }
                    else if (p.Name == "NodeMix")
                    {
                        //Use node mix to create weight groups
                        byte *pData     = (byte *)p.Data;
                        bool  fixCS0159 = false;
TTop:
                        switch (*pData)
                        {
                        //Type 3 is for weighted influences
                        case 3:
                            //Get index/count fields
                            index = *(bushort *)(pData + 1);
                            count = pData[3];
                            //Get data pointer (offset of 4)
                            MDL0NodeType3Entry *nEntry = (MDL0NodeType3Entry *)(pData + 4);
                            //Create influence with specified count
                            inf = new Influence();
                            //Iterate through weights, adding each to the influence
                            //Here, we are referring back to the NodeCache to grab the bone.
                            //Note that the weights do not reference other influences, only bones. There is a good reason for this.
                            MDL0BoneNode b           = null;
                            List <int>   nullIndices = new List <int>();
                            for (int i = 0; i < count; i++, nEntry++)
                            {
                                if (nEntry->_id < linker.NodeCache.Length && (b = (linker.NodeCache[nEntry->_id] as MDL0BoneNode)) != null)
                                {
                                    inf.AddWeight(new BoneWeight(b, nEntry->_value));
                                }
                                else
                                {
                                    nullIndices.Add(i);
                                }
                            }

                            bool noWeights = false;
                            if ((nullCount = nullIndices.Count) > 0)
                            {
                                List <BoneWeight> newWeights = new List <BoneWeight>();
                                for (int i = 0; i < inf.Weights.Count; i++)
                                {
                                    if (!nullIndices.Contains(i))
                                    {
                                        newWeights.Add(inf.Weights[i]);
                                    }
                                }
                                if (newWeights.Count == 0)
                                {
                                    noWeights = true;
                                }
                                else
                                {
                                    inf.SetWeights(newWeights);
                                }
                            }

                            //Add influence to model object, while adding it to the cache.
                            //Don't add user references here, they will be added during each object's initialization
                            if (!noWeights)
                            {
                                ((Influence)(linker.NodeCache[index] = model._influences.FindOrCreate(inf)))._index = index;
                            }

                            //Move data pointer to next entry
                            pData     = (byte *)nEntry;
                            fixCS0159 = true;
                            break;

                        //Type 5 is for primary influences
                        case 5:
                            pData    += 5;
                            fixCS0159 = true;
                            break;
                        }
                        if (fixCS0159)
                        {
                            fixCS0159 = false;
                            goto TTop;
                        }
                    }
                }

                if (nullCount > 0)
                {
                    model._errors.Add("There were " + nullCount + " null weights in NodeMix.");
                }

                if (nodeTreeError)
                {
                    model._errors.Add("The NodeTree definition did not match the bone tree.");
                }
            }

            else if (_type == MDLResourceType.Objects)
            {
                //Attach materials to polygons.
                //This assumes that materials have already been parsed.

                List <ResourceNode> matList = ((MDL0Node)_parent)._matList;
                MDL0ObjectNode      obj;
                MDL0MaterialNode    mat;

                //Find DrawOpa or DrawXlu entry in Definition list
                foreach (ResourcePair p in *linker.Defs)
                {
                    if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu"))
                    {
                        bool isXLU = p.Name == "DrawXlu";

                        ushort objectIndex = 0;
                        byte * pData       = (byte *)p.Data;
                        while (*pData++ == 4)
                        {
                            //Get object with index
                            objectIndex = *(bushort *)(pData + 2);
                            if (objectIndex >= _children.Count || objectIndex < 0)
                            {
                                model._errors.Add("Object index was greater than the actual object count.");
                                objectIndex = 0;
                            }
                            obj = _children[objectIndex] as MDL0ObjectNode;

                            //Get material with index
                            mat = matList[*(bushort *)pData] as MDL0MaterialNode;

                            //Get bone with index
                            int          boneIndex = *(bushort *)(pData + 4);
                            MDL0BoneNode visBone   = null;
                            if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length)
                            {
                                visBone = linker.BoneCache[boneIndex] as MDL0BoneNode;
                            }

                            obj._drawCalls.Add(new DrawCall(obj)
                            {
                                _drawOrder         = pData[6],
                                _isXLU             = isXLU,
                                MaterialNode       = mat,
                                VisibilityBoneNode = visBone,
                            });

                            //Increment pointer
                            pData += 7;
                        }
                    }
                }

                foreach (MDL0ObjectNode m in _children)
                {
                    int max = 0;
                    foreach (DrawCall c in m._drawCalls)
                    {
                        max = Maths.Max(max, c.MaterialNode.Children.Count);
                        if (c.MaterialNode.MetalMaterial != null)
                        {
                            max = Maths.Max(max, c.MaterialNode.MetalMaterial.Children.Count);
                        }
                    }

                    bool hasUnused = false;
                    if (m._manager != null)
                    {
                        for (int i = max; i < 8; i++)
                        {
                            if (m._manager.HasTextureMatrix[i])
                            {
                                m._manager.HasTextureMatrix[i] = false;
                                m._forceRebuild = true;
                                hasUnused       = true;
                            }
                        }
                    }
                    if (hasUnused)
                    {
                        ((MDL0Node)Parent)._errors.Add("Object " + m.Index + " has unused texture matrices.");
                    }

                    //This error doesn't seem to always be true for factory models...
                    //if (m.HasTexMtx && m.HasNonFloatVertices)
                    //{
                    //    ((MDL0Node)Parent)._errors.Add("Object " + m.Index + " has texture matrices and non-float vertices, meaning it will explode in-game.");
                    //    m.SignalPropertyChange();
                    //}
                }
            }
        }
コード例 #12
0
        public void Write(Collada form, ref byte *pGroup, ref byte *pData, bool force)
        {
            MDL0GroupNode  group;
            ResourceGroup *pGrp;
            ResourceEntry *pEntry;
            int            len;

            //Write data in the order it appears
            foreach (MDLResourceType resType in OrderBank)
            {
                if (((group = Groups[(int)resType]) == null) || SpecialRebuildData((int)resType))
                {
                    continue;
                }

                if (resType == MDLResourceType.Bones)
                {
                    if (form != null)
                    {
                        form.Say("Writing Bones");
                    }

                    MDL0Bone *pBone = (MDL0Bone *)pData;
                    foreach (MDL0BoneNode e in BoneCache)
                    {
                        len = e._calcSize;
                        e.Rebuild(pData, len, true);
                        pData += len;
                    }
                    //Loop through after all bones are written
                    //and set header offsets to related bones
                    foreach (MDL0BoneNode e in BoneCache)
                    {
                        e.CalculateOffsets();
                    }
                }
                else if (resType == MDLResourceType.Shaders)
                {
                    MDL0GroupNode mats = Groups[(int)MDLResourceType.Materials];
                    MDL0Material *mHeader;

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

                    //Write data without headers
                    foreach (ResourceNode e in group.Children)
                    {
                        if (((MDL0ShaderNode)e)._materials.Count > 0)
                        {
                            len = e._calcSize;
                            e.Rebuild(pData, len, force);
                            pData += len;
                        }
                    }
                    //Write one header for each material, using same order.
                    if (mats != null)
                    {
                        foreach (MDL0MaterialNode mat in mats.Children)
                        {
                            mHeader = mat.Header;
                            if (mat._shader != null)
                            {
                                len = (int)mat._shader.Header;
                                mHeader->_shaderOffset = len - (int)mHeader;
                            }
                            else
                            {
                                mHeader->_shaderOffset = 0;
                            }
                        }
                    }
                }
                else if (resType == MDLResourceType.Objects || resType == MDLResourceType.Materials)
                {
                    foreach (ResourceNode r in group.Children)
                    {
                        if (form != null)
                        {
                            form.Say("Writing " + resType.ToString() + " - " + r.Name);
                        }

                        len = r._calcSize;
                        r.Rebuild(pData, len, true); //Forced to fix object node ids and align materials
                        pData += len;
                    }
                }
                else
                {
                    bool rebuild = true;

                    if (Model._isImport)
                    {
                        if (group._name == "Vertices" ||
                            group._name == "Normals" ||
                            group._name == "UVs" ||
                            group._name == "Colors")
                        {
                            rebuild = false; //The data has already been written!
                        }
                    }
                    if (rebuild)
                    {
                        foreach (ResourceNode e in group.Children)
                        {
                            //Console.WriteLine("Rebuilding the " + group.Name);

                            if (form != null)
                            {
                                form.Say("Writing the " + resType.ToString() + " - " + e.Name);
                            }

                            len = e._calcSize;
                            e.Rebuild(pData, len, true); //Forced just in case we need to convert to float.
                            pData += len;
                        }
                    }
                }
            }

            //Write relocation offsets in the order of the header
            fixed(ResourceGroup **pOut = &Defs)
            foreach (MDLResourceType resType in IndexBank[Version])
            {
                if (((group = Groups[(int)resType]) == null) || SpecialRebuildData((int)resType))
                {
                    continue;
                }

                pOut[(int)resType] = pGrp = (ResourceGroup *)pGroup;
                pEntry             = &pGrp->_first + 1;
                if (resType == MDLResourceType.Bones)
                {
                    *pGrp = new ResourceGroup(BoneCache.Length);
                    foreach (ResourceNode e in BoneCache)
                    {
                        (pEntry++)->_dataOffset = (int)((byte *)(e.WorkingUncompressed.Address) - pGroup);
                    }
                }
                else if (resType == MDLResourceType.Shaders)
                {
                    MDL0GroupNode mats = Groups[(int)MDLResourceType.Materials];

                    if (mats != null)
                    {
                        //Create a material group with the amount of entries
                        *pGrp = new ResourceGroup(mats.Children.Count);

                        foreach (MDL0MaterialNode mat in mats.Children)
                        {
                            (pEntry++)->_dataOffset = (int)mat._shader.Header - (int)pGrp;
                        }
                    }
                }
                else
                {
                    *pGrp = new ResourceGroup(group.Children.Count);
                    foreach (ResourceNode e in group.Children)
                    {
                        (pEntry++)->_dataOffset = (int)((byte *)(e.WorkingUncompressed.Address) - pGroup);
                    }
                }
                pGroup += pGrp->_totalSize;
            }
        }
コード例 #13
0
        public void RecalcOffsets(MDL0Bone *header, VoidPtr address, int length)
        {
            MDL0BoneNode bone;
            int          index = 0, offset;

            //Sub-entries
            if (_entries.Count > 0)
            {
                header->_part2Offset = 0xD0;
                *(bint *)((byte *)address + 0xD0) = 0x1C + (_entries.Count * 0x2C);
                ResourceGroup *pGroup = (ResourceGroup *)((byte *)address + 0xD4);
                ResourceEntry *pEntry = &pGroup->_first + 1;
                byte *         pData  = (byte *)pGroup + pGroup->_totalSize;

                *pGroup = new ResourceGroup(_entries.Count);

                foreach (string s in _entries)
                {
                    (pEntry++)->_dataOffset = (int)pData - (int)pGroup;
                    Part2DataEntry *p = (Part2DataEntry *)pData;
                    *p = new Part2DataEntry(1);
                    pData += 0x1C;
                }
            }
            else
            {
                header->_part2Offset = 0;
            }

            //Set first child
            if (_children.Count > 0)
            {
                header->_firstChildOffset = length;
            }
            else
            {
                header->_firstChildOffset = 0;
            }

            if (_parent != null)
            {
                index = _parent._children.IndexOf(this);

                //Parent
                if (_parent is MDL0BoneNode)
                {
                    header->_parentOffset = (int)_parent.WorkingUncompressed.Address - (int)address;
                }
                else
                {
                    header->_parentOffset = 0;
                }

                //Prev
                if (index == 0)
                {
                    header->_prevOffset = 0;
                }
                else
                {
                    //Link to prev
                    bone   = _parent._children[index - 1] as MDL0BoneNode;
                    offset = (int)bone.Header - (int)address;
                    header->_prevOffset      = offset;
                    bone.Header->_nextOffset = -offset;
                }

                //Next
                if (index == (_parent._children.Count - 1))
                {
                    header->_nextOffset = 0;
                }
            }
        }
コード例 #14
0
        public void RecalcOffsets(MDL0Bone *header, VoidPtr address, int length)
        {
            MDL0BoneNode bone;
            int          index = 0, offset;

            //Sub-entries
            if (_userEntries.Count > 0)
            {
                header->_userDataOffset = 0xD0;
                _userEntries.Write(address + 0xD0);
            }
            else
            {
                header->_userDataOffset = 0;
            }

            //Set first child
            if (_children.Count > 0)
            {
                header->_firstChildOffset = length;
            }
            else
            {
                header->_firstChildOffset = 0;
            }

            if (_parent != null)
            {
                index = Parent._children.IndexOf(this);

                //Parent
                if (Parent is MDL0BoneNode)
                {
                    header->_parentOffset = (int)Parent.WorkingUncompressed.Address - (int)address;
                }
                else
                {
                    header->_parentOffset = 0;
                }

                //Prev
                if (index == 0)
                {
                    header->_prevOffset = 0;
                }
                else
                {
                    //Link to prev
                    bone   = Parent._children[index - 1] as MDL0BoneNode;
                    offset = (int)bone.Header - (int)address;
                    header->_prevOffset      = offset;
                    bone.Header->_nextOffset = -offset;
                }

                //Next
                if (index == (Parent._children.Count - 1))
                {
                    header->_nextOffset = 0;
                }
            }
        }
コード例 #15
0
        //Initialize should only be called from parent group during parse.
        //Bones need not be imported/exported anyways
        public override bool OnInitialize()
        {
            MDL0Bone *header = Header;

            SetSizeInternal(header->_headerLen);

            //Assign true parent using parent header offset
            int offset = header->_parentOffset;

            //Offsets are always < 0, because parent entries are listed before children
            if (offset < 0)
            {
                //Get address of parent header
                MDL0Bone *pHeader = (MDL0Bone *)((byte *)header + offset);
                //Search bone list for matching header
                foreach (MDL0BoneNode bone in Parent._children)
                {
                    if (pHeader == bone.Header)
                    {
                        _parent = bone;
                        break;
                    }
                }
            }

            //Conditional name assignment
            if ((_name == null) && (header->_stringOffset != 0))
            {
                _name = header->ResourceString;
            }

            //Assign fields
            _flags1           = (BoneFlags)(uint)header->_flags;
            _flags2           = (BillboardFlags)(uint)header->_bbFlags;
            _bbNodeId         = header->_bbNodeId;
            _nodeIndex        = header->_nodeId;
            _boneIndex        = header->_index;
            _headerLen        = header->_headerLen;
            _mdl0Offset       = header->_mdl0Offset;
            _stringOffset     = header->_stringOffset;
            _parentOffset     = header->_parentOffset;
            _firstChildOffset = header->_firstChildOffset;
            _nextOffset       = header->_nextOffset;
            _prevOffset       = header->_prevOffset;
            _userDataOffset   = header->_userDataOffset;

            if (_flags2 != 0 && _flags1.HasFlag(BoneFlags.HasGeometry))
            {
                Model._billboardBones.Add(this); //Update mesh in T-Pose
            }
            _bindState         = _frameState = new FrameState(header->_scale, (Vector3)header->_rotation, header->_translation);
            _bindMatrix        = _frameMatrix = header->_transform;
            _inverseBindMatrix = _inverseFrameMatrix = header->_transformInv;

            _bMin = header->_boxMin;
            _bMax = header->_boxMax;

            (_userEntries = new UserDataCollection()).Read(header->UserDataAddress);

            //We don't want to process children because not all have been parsed yet.
            //Child assigning will be handled by the parent group.
            return(false);
        }