public void Initialize(IModel model, DecoderShell shell)
            {
                PrimitiveManager m;

                if (_weighted)
                {
                    m = DecodePrimitivesWeighted(_bindMatrix, _g, _skin, _scene, model.Influences, BoneType);
                }
                else
                {
                    m = DecodePrimitivesUnweighted(_bindMatrix, _g);
                }

                switch (ModelType)
                {
                case ImportType.MDL0:
                    CreateMDL0Object(_inst, _node, _parent, m, (MDL0Node)model, shell);
                    break;
                }
            }
        private static void CreateMDL0Object(
            InstanceEntry inst,
            NodeEntry node,
            ResourceNode parent,
            PrimitiveManager manager,
            MDL0Node model,
            DecoderShell shell)
        {
            if (manager != null)
            {
                Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id);

                MDL0ObjectNode poly = new MDL0ObjectNode()
                {
                    _manager   = manager,
                    _name      = node._name != null ? node._name : node._id,
                    _drawCalls = new BindingList <DrawCall>()
                };

                //Attach material
                if (inst._material != null)
                {
                    foreach (MaterialEntry mat in shell._materials)
                    {
                        if (mat._id == inst._material._target)
                        {
                            poly._drawCalls.Add(new DrawCall(poly)
                            {
                                MaterialNode = mat._node as MDL0MaterialNode
                            });
                        }
                    }
                }

                model._numTriangles  += poly._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += poly._numFacepoints = manager._pointCount;

                poly._parent = model._objGroup;
                model._objList.Add(poly);

                model.ResetToBindState();

                //Attach single-bind
                if (parent != null && parent is MDL0BoneNode)
                {
                    MDL0BoneNode bone = (MDL0BoneNode)parent;
                    poly.DeferUpdateAssets();
                    poly.MatrixNode = bone;

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = bone;
                    }
                }
                else if (model._boneList.Count == 0)
                {
                    Error = String.Format("There was a problem rigging {0} to a single bone.", poly._name);

                    Box          box  = poly.GetBox();
                    MDL0BoneNode bone = new MDL0BoneNode()
                    {
                        Scale       = Vector3.One,
                        Translation = (box.Max + box.Min) / 2.0f,
                        _name       = "TransN_" + poly.Name,
                        Parent      = TempRootBone,
                    };

                    poly.DeferUpdateAssets();
                    poly.MatrixNode = bone;
                    ((MDL0BoneNode)TempRootBone).RecalcBindState(true, false, false);

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = bone;
                    }
                }
                else
                {
                    Error = String.Format("There was a problem checking if {0} is rigged to a single bone.", poly._name);

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = model._boneList[0] as MDL0BoneNode;
                    }

                    IMatrixNode mtxNode    = null;
                    bool        singlebind = true;

                    foreach (Vertex3 v in poly._manager._vertices)
                    {
                        if (v.MatrixNode != null)
                        {
                            if (mtxNode == null)
                            {
                                mtxNode = v.MatrixNode;
                            }

                            if (v.MatrixNode != mtxNode)
                            {
                                singlebind = false;
                                break;
                            }
                        }
                    }

                    if (singlebind && poly._matrixNode == null)
                    {
                        //Reassign reference entries
                        if (poly._manager._vertices[0].MatrixNode != null)
                        {
                            poly._manager._vertices[0].MatrixNode.Users.Add(poly);
                        }

                        foreach (Vertex3 v in poly._manager._vertices)
                        {
                            if (v.MatrixNode != null)
                            {
                                v.MatrixNode.Users.Remove(v);
                            }
                        }

                        poly._nodeId = -2; //Continued on polygon rebuild
                    }
                }
            }
        }
        public IModel ImportModel(string filePath, ImportType type)
        {
            IModel model = null;

            ModelType = type;

            BoneType = ModelType == ImportType.MDL0 ? typeof(MDL0BoneNode) : null;

            //TransformMatrix = Matrix.TransformMatrix(_importOptions._modifyScale, _importOptions._modifyRotation, new Vector3());

            switch (type)
            {
            case ImportType.MDL0:
                MDL0Node m = new MDL0Node()
                {
                    _name    = Path.GetFileNameWithoutExtension(filePath),
                    _version = _importOptions._modelVersion.Clamp(8, 11)
                };
                if (_importOptions._setOrigPath)
                {
                    m._originalPath = filePath;
                }
                m.BeginImport();
                model = m;
                break;
            }

            CurrentModel = model;

            Error = "There was a problem reading the model.";
            using (DecoderShell shell = DecoderShell.Import(filePath))
                try
                {
                    Error = "There was a problem reading texture entries.";

                    //Extract images, removing duplicates
                    foreach (ImageEntry img in shell._images)
                    {
                        string name = img._path != null?
                                      Path.GetFileNameWithoutExtension(img._path) :
                                          img._name != null ? img._name : img._id;

                        switch (type)
                        {
                        case ImportType.MDL0:
                            img._node = ((MDL0Node)model).FindOrCreateTexture(name);
                            break;
                        }
                    }

                    Error = "There was a problem creating a default shader.";

                    //Create a shader
                    ResourceNode shader = null;
                    switch (type)
                    {
                    case ImportType.MDL0:
                        MDL0Node       m        = (MDL0Node)model;
                        MDL0ShaderNode shadNode = new MDL0ShaderNode()
                        {
                            _ref0 = 0,
                            _ref1 = -1,
                            _ref2 = -1,
                            _ref3 = -1,
                            _ref4 = -1,
                            _ref5 = -1,
                            _ref6 = -1,
                            _ref7 = -1,
                        };

                        shadNode._parent = m._shadGroup;
                        m._shadList.Add(shadNode);

                        switch (_importOptions._mdlType)
                        {
                        case ImportOptions.MDLType.Character:
                            for (int i = 0; i < 3; i++)
                            {
                                switch (i)
                                {
                                case 0:
                                    shadNode.AddChild(new MDL0TEVStageNode(0x28F8AF, 0x08F2F0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap0, TexCoordID.TexCoord0, ColorSelChan.LightChannel0, true));
                                    break;

                                case 1:
                                    shadNode.AddChild(new MDL0TEVStageNode(0x08FEB0, 0x081FF0, 0, TevKColorSel.ConstantColor1_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap7, TexCoordID.TexCoord7, ColorSelChan.LightChannel0, false));
                                    break;

                                case 2:
                                    shadNode.AddChild(new MDL0TEVStageNode(0x0806EF, 0x081FF0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap7, TexCoordID.TexCoord7, ColorSelChan.Zero, false));
                                    break;
                                }
                            }
                            break;

                        case ImportOptions.MDLType.Stage:
                            shadNode.AddChild(new MDL0TEVStageNode(0x28F8AF, 0x08F2F0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap0, TexCoordID.TexCoord0, ColorSelChan.LightChannel0, true));
                            break;
                        }

                        shader = shadNode;

                        break;
                    }

                    Error = "There was a problem extracting materials.";

                    //Extract materials
                    foreach (MaterialEntry mat in shell._materials)
                    {
                        List <ImageEntry> imgEntries = new List <ImageEntry>();

                        //Find effect
                        if (mat._effect != null)
                        {
                            foreach (EffectEntry eff in shell._effects)
                            {
                                if (eff._id == mat._effect) //Attach textures and effects to material
                                {
                                    if (eff._shader != null)
                                    {
                                        foreach (LightEffectEntry l in eff._shader._effects)
                                        {
                                            if (l._type == LightEffectType.diffuse && l._texture != null)
                                            {
                                                string path = l._texture;
                                                foreach (EffectNewParam p in eff._newParams)
                                                {
                                                    if (p._sid == l._texture)
                                                    {
                                                        path = p._sampler2D._url;
                                                        if (!String.IsNullOrEmpty(p._sampler2D._source))
                                                        {
                                                            foreach (EffectNewParam p2 in eff._newParams)
                                                            {
                                                                if (p2._sid == p._sampler2D._source)
                                                                {
                                                                    path = p2._path;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }

                                                foreach (ImageEntry img in shell._images)
                                                {
                                                    if (img._id == path)
                                                    {
                                                        imgEntries.Add(img);
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        switch (type)
                        {
                        case ImportType.MDL0:
                            MDL0MaterialNode matNode = new MDL0MaterialNode();

                            MDL0Node m = (MDL0Node)model;
                            matNode._parent = m._matGroup;
                            m._matList.Add(matNode);

                            matNode._name      = mat._name != null ? mat._name : mat._id;
                            matNode.ShaderNode = shader as MDL0ShaderNode;

                            mat._node     = matNode;
                            matNode._cull = _importOptions._culling;

                            foreach (ImageEntry img in imgEntries)
                            {
                                MDL0MaterialRefNode mr = new MDL0MaterialRefNode();
                                (mr._texture = img._node as MDL0TextureNode)._references.Add(mr);
                                mr._name = mr._texture.Name;
                                matNode._children.Add(mr);
                                mr._parent  = matNode;
                                mr._minFltr = mr._magFltr = 1;
                                mr._uWrap   = mr._vWrap = (int)_importOptions._wrap;
                            }
                            break;
                        }
                    }

                    Say("Extracting scenes...");

                    List <ObjectInfo> _objects  = new List <ObjectInfo>();
                    ResourceNode      boneGroup = null;
                    switch (type)
                    {
                    case ImportType.MDL0:
                        boneGroup = ((MDL0Node)model)._boneGroup;
                        break;
                    }

                    //Extract bones and objects and create bone tree
                    foreach (SceneEntry scene in shell._scenes)
                    {
                        foreach (NodeEntry node in scene._nodes)
                        {
                            EnumNode(node, boneGroup, scene, model, shell, _objects, TransformMatrix, Matrix.Identity);
                        }
                    }

                    //Add root bone if there are no bones
                    if (boneGroup.Children.Count == 0)
                    {
                        switch (type)
                        {
                        case ImportType.MDL0:
                            MDL0BoneNode bone = new MDL0BoneNode();
                            bone.Scale = new Vector3(1);
                            bone.RecalcBindState(false, false);
                            bone._name   = "TopN";
                            TempRootBone = bone;
                            break;
                        }
                    }

                    //Create objects
                    foreach (ObjectInfo obj in _objects)
                    {
                        NodeEntry node = obj._node;
                        string    w    = obj._weighted ? "" : "un";
                        string    w2   = obj._weighted ? "\nOne or more vertices may not be weighted correctly." : "";
                        string    n    = node._name != null ? node._name : node._id;

                        Error = String.Format("There was a problem decoding {0}weighted primitives for the object {1}.{2}", w, n, w2);

                        Say(String.Format("Decoding {0}weighted primitives for {1}...", w, n));

                        obj.Initialize(model, shell);
                    }

                    //Finish
                    switch (type)
                    {
                    case ImportType.MDL0:
                        MDL0Node mdl0 = (MDL0Node)model;
                        if (TempRootBone != null)
                        {
                            mdl0._boneGroup._children.Add(TempRootBone);
                            TempRootBone._parent = mdl0._boneGroup;
                        }
                        FinishMDL0(mdl0);
                        break;
                    }
                }
#if !DEBUG
            catch (Exception x)
            {
                MessageBox.Show("Cannot continue importing this model.\n" + Error + "\n\nException:\n" + x.ToString());
                model = null;
                Close();
            }
#endif
            finally
            {
                //Clean up the mess we've made
                GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            }

            CurrentModel = null;
            Error        = null;

            return(model);
        }
        private void EnumNode(
            NodeEntry node,
            ResourceNode parent,
            SceneEntry scene,
            IModel model,
            DecoderShell shell,
            List <ObjectInfo> objects,
            Matrix bindMatrix,
            Matrix parentInvMatrix)
        {
            bindMatrix *= node._matrix;

            if (node._type == NodeType.JOINT ||
                (node._type == NodeType.NONE && node._instances.Count == 0))
            {
                Error = "There was a problem creating a new bone.";

                Influence inf = null;

                switch (ModelType)
                {
                case ImportType.MDL0:
                    MDL0BoneNode bone = new MDL0BoneNode();
                    bone._name = node._name != null ? node._name : node._id;

                    bone._bindState = node._matrix.Derive();
                    node._node      = bone;

                    parent._children.Add(bone);
                    bone._parent = parent;

                    bone.RecalcBindState(false, false);
                    bone.CalcFlags();

                    parent = bone;

                    inf = new Influence(bone);
                    break;
                }

                if (inf != null)
                {
                    model.Influences._influences.Add(inf);
                }
            }

            //parentInvMatrix *= node._matrix.Invert();
            foreach (NodeEntry e in node._children)
            {
                EnumNode(e, parent, scene, model, shell, objects, bindMatrix, parentInvMatrix);
            }

            foreach (InstanceEntry inst in node._instances)
            {
                if (inst._type == InstanceType.Controller)
                {
                    foreach (SkinEntry skin in shell._skins)
                    {
                        if (skin._id == inst._url)
                        {
                            foreach (GeometryEntry g in shell._geometry)
                            {
                                if (g._id == skin._skinSource)
                                {
                                    objects.Add(new ObjectInfo(true, g, bindMatrix, skin, scene, inst, parent, node));
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
                else if (inst._type == InstanceType.Geometry)
                {
                    foreach (GeometryEntry g in shell._geometry)
                    {
                        if (g._id == inst._url)
                        {
                            objects.Add(new ObjectInfo(false, g, bindMatrix, null, null, inst, parent, node));
                            break;
                        }
                    }
                }
                else
                {
                    foreach (NodeEntry e in shell._nodes)
                    {
                        if (e._id == inst._url)
                        {
                            EnumNode(e, parent, scene, model, shell, objects, bindMatrix, parentInvMatrix);
                        }
                    }
                }
            }
        }
Beispiel #5
0
        static void Weight(PrimitiveManager manager, SkinEntry skin, DecoderShell shell, GeometryEntry geo, InfluenceManager iMan)
        {
            MDL0BoneNode[] boneList;
            MDL0BoneNode   bone = null;
            int            boneCount;

            string[]       jointStrings = null;
            byte *         pCmd         = stackalloc byte[4];
            int            cmdCount     = skin._weightInputs.Count;
            float          weight       = 0;
            float *        pWeights     = null;
            Vector3 *      pVert        = null;
            ushort *       pVInd        = (ushort *)manager._indices.Address;
            List <Vertex3> vertList     = new List <Vertex3>(skin._weightCount);

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Find joint source
            foreach (InputEntry inp in skin._jointInputs)
            {
                if (inp._semantic == SemanticType.JOINT)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            jointStrings = src._arrayData as string[];
                            break;
                        }
                    }
                    break;
                }
            }

            //Populate bone list
            boneCount = jointStrings.Length;
            boneList  = new MDL0BoneNode[boneCount];
            for (int i = 0; i < boneCount; i++)
            {
                boneList[i] = shell.FindNode(jointStrings[i])._node as MDL0BoneNode;
            }

            //Build command list
            foreach (InputEntry inp in skin._weightInputs)
            {
                switch (inp._semantic)
                {
                case SemanticType.JOINT:
                    pCmd[inp._offset] = 1;
                    break;

                case SemanticType.WEIGHT:
                    pCmd[inp._offset] = 2;

                    //Get weight source
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pWeights = (float *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }

                    break;

                default:
                    pCmd[inp._offset] = 0;
                    break;
                }
            }

            //Construct Vertex from new weight
            for (int i = 0; i < skin._weightCount; i++)
            {
                //Create influence
                int       iCount = skin._weights.Length / cmdCount;
                Influence inf    = new Influence(iCount);
                fixed(int *p = skin._weights[i])
                {
                    int *iPtr = p;

                    for (int x = 0; x < iCount; x++)
                    {
                        for (int z = 0; z < cmdCount; z++, iPtr++)
                        {
                            if (pCmd[z] == 1)
                            {
                                bone = boneList[*iPtr];
                            }
                            else if (pCmd[z] == 2)
                            {
                                weight = pWeights[*iPtr];
                            }
                        }

                        inf._weights[x] = new BoneWeight(bone, weight);
                    }
                }

                //Match with manager
                inf = iMan.AddOrCreateInf(inf);

                //Create Vertex and look for match
                Vertex3 v     = new Vertex3(pVert[*pVInd], inf);
                int     index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[i]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                //Assign new index
                *pVInd++ = (ushort)index;
            }
        }
        private void EnumNode(NodeEntry node, ResourceNode parent, SceneEntry scene, MDL0Node model, DecoderShell shell)
        {
            MDL0BoneNode bone = null;
            Influence inf = null;

            if (node._type == NodeType.JOINT)
            {
                Error = "There was a problem creating a new bone.";

                bone = new MDL0BoneNode();
                bone._name = node._name != null ? node._name : node._id;

                bone._bindState = node._transform;
                node._node = bone;

                parent._children.Add(bone);
                bone._parent = parent;

                bone.RecalcBindState();
                bone.CalcFlags();

                foreach (NodeEntry e in node._children)
                    EnumNode(e, bone, scene, model, shell);

                inf = new Influence(bone);
                model._influences._influences.Add(inf);
            }
            else
                foreach (NodeEntry e in node._children)
                    EnumNode(e, parent, scene, model, shell);

            foreach (InstanceEntry inst in node._instances)
            {
                if (inst._type == InstanceType.Controller)
                {
                    foreach (SkinEntry skin in shell._skins)
                        if (skin._id == inst._url)
                        {
                            foreach (GeometryEntry g in shell._geometry)
                                if (g._id == skin._skinSource)
                                {
                                    Error = @"
                                    There was a problem decoding weighted primitives for the object " + (node._name != null ? node._name : node._id) +
                                    ".\nOne or more vertices may not be weighted correctly.";
                                    Say("Decoding weighted primitives for " + (g._name != null ? g._name : g._id) + "...");
                                    CreateObject(inst, node, parent, DecodePrimitivesWeighted(node, g, skin, scene, model._influences, ref Error), model, shell);
                                    break;
                                }
                            break;
                        }
                }
                else if (inst._type == InstanceType.Geometry)
                {
                    foreach (GeometryEntry g in shell._geometry)
                        if (g._id == inst._url)
                        {
                            Error = "There was a problem decoding unweighted primitives for the object " + (node._name != null ? node._name : node._id) + ".";
                            Say("Decoding unweighted primitives for " + (g._name != null ? g._name : g._id) + "...");
                            CreateObject(inst, node, parent, DecodePrimitivesUnweighted(node, g), model, shell);
                            break;
                        }
                }
                else
                {
                    foreach (NodeEntry e in shell._nodes)
                        if (e._id == inst._url)
                            EnumNode(e, parent, scene, model, shell);
                }
            }
        }
        private void CreateObject(InstanceEntry inst, NodeEntry node, ResourceNode parent, PrimitiveManager manager, MDL0Node model, DecoderShell shell)
        {
            if (manager != null)
            {
                Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id);
                int i = 0;
                foreach (Vertex3 v in manager._vertices)
                    v._index = i++;

                MDL0ObjectNode poly = new MDL0ObjectNode() { _manager = manager };
                poly._manager._polygon = poly;
                poly._name = node._name != null ? node._name : node._id;

                //Attach single-bind
                if (parent != null && parent is MDL0BoneNode)
                    poly.MatrixNode = (MDL0BoneNode)parent;

                //Attach material
                if (inst._material != null)
                    foreach (MaterialEntry mat in shell._materials)
                        if (mat._id == inst._material._target)
                        {
                            (poly._opaMaterial = (mat._node as MDL0MaterialNode))._objects.Add(poly);
                            break;
                        }

                model._numFaces += poly._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += poly._numFacepoints = manager._pointCount;

                poly._parent = model._objGroup;
                model._objList.Add(poly);
            }
        }