示例#1
0
        public void ImportFolder(string inFolder)
        {
            DirectoryInfo dir = new DirectoryInfo(inFolder);

            FileInfo[] files;

            files = dir.GetFiles();
            foreach (FileInfo info in files)
            {
                string ext = Path.GetExtension(info.FullName).ToUpper();
                if (ext == ".PNG" || ext == ".TGA" || ext == ".BMP" || ext == ".JPG" || ext == ".JPEG" || ext == ".GIF" || ext == ".TIF" || ext == ".TIFF")
                {
                    using (TextureConverterDialog dlg = new TextureConverterDialog())
                    {
                        dlg.ImageSource = info.FullName;
                        dlg.ShowDialog(null, this);
                    }
                }
                else if (ext == ".TEX0")
                {
                    TEX0Node node = NodeFactory.FromFile(null, info.FullName) as TEX0Node;
                    GetOrCreateFolder <TEX0Node>().AddChild(node);
                }
                else if (ext == ".MDL0")
                {
                    MDL0Node node = NodeFactory.FromFile(null, info.FullName) as MDL0Node;
                    GetOrCreateFolder <MDL0Node>().AddChild(node);
                }
                else if (ext == ".CHR0")
                {
                    CHR0Node node = NodeFactory.FromFile(null, info.FullName) as CHR0Node;
                    GetOrCreateFolder <CHR0Node>().AddChild(node);
                }
                else if (ext == ".CLR0")
                {
                    CLR0Node node = NodeFactory.FromFile(null, info.FullName) as CLR0Node;
                    GetOrCreateFolder <CLR0Node>().AddChild(node);
                }
                else if (ext == ".SRT0")
                {
                    SRT0Node node = NodeFactory.FromFile(null, info.FullName) as SRT0Node;
                    GetOrCreateFolder <SRT0Node>().AddChild(node);
                }
                else if (ext == ".SHP0")
                {
                    SHP0Node node = NodeFactory.FromFile(null, info.FullName) as SHP0Node;
                    GetOrCreateFolder <SHP0Node>().AddChild(node);
                }
                else if (ext == ".PAT0")
                {
                    PAT0Node node = NodeFactory.FromFile(null, info.FullName) as PAT0Node;
                    GetOrCreateFolder <PAT0Node>().AddChild(node);
                }
                else if (ext == ".VIS0")
                {
                    VIS0Node node = NodeFactory.FromFile(null, info.FullName) as VIS0Node;
                    GetOrCreateFolder <VIS0Node>().AddChild(node);
                }
            }
        }
 public void AddTarget(MDL0Node model)
 {
     if (!_targetModels.Contains(model))
         _targetModels.Add(model);
     modelPanel.AddTarget(model);
     model.ApplyCHR(null, 0);
     model._renderBones = true;
 }
示例#3
0
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            MDL0Node model = (context.Instance as MovesetEntry).Model;

            if (model != null)
            {
                return(new StandardValuesCollection(model._linker.BoneCache.Select(n => n.ToString()).ToList()));
            }
            return(null);
        }
        public DialogResult ShowDialog(MDL0Node internalModel, MDL0Node externalModel)
        {
            _internalModel = internalModel;
            _externalModel = externalModel;
            _externalModel._renderBones = false;

            comboBox1.Items.AddRange(_externalModel.FindChild("Objects", true).Children.ToArray());
            comboBox2.Items.AddRange(_internalModel._linker.BoneCache);

            comboBox1.SelectedIndex = comboBox2.SelectedIndex = comboBox3.SelectedIndex = 0;
            _parent = (MDL0BoneNode)comboBox2.SelectedItem;

            return base.ShowDialog(null);
        }
        public void Port(MDL0Node baseModel)
        {
            MDL0Node model;

            OpenFileDialog dlgOpen = new OpenFileDialog();

            dlgOpen.Filter = "MDL0 Model (*.mdl0)|*.mdl0";
            dlgOpen.Title  = "Select the model this animation is for...";

            if (dlgOpen.ShowDialog() == DialogResult.OK)
            {
                if ((model = (MDL0Node)NodeFactory.FromFile(null, dlgOpen.FileName)) != null)
                {
                    Port(baseModel, model);
                }
            }
        }
        protected override bool OnInitialize()
        {
            //if (_name == null)
            _name = String.Format("Shader{0}", Index);

            //Attach to materials
            MDL0Node model   = Model;
            byte *   pHeader = (byte *)Header;

            if ((model != null) && (model._matList != null))
            {
                foreach (MDL0MaterialNode mat in model._matList)
                {
                    MDL0Material *mHeader = mat.Header;
                    if (((byte *)mHeader + mHeader->_shaderOffset) == pHeader)
                    {
                        mat._shader = this;
                        _materials.Add(mat);
                    }
                }
            }

            return(false);
        }
        public static unsafe void PMD2MDL0(MDL0Node model)
        {
            model._version = 9;
            model._isImport = true;
            Collada._importOptions = BrawlLib.Properties.Settings.Default.ColladaImportOptions;
            Collada._importOptions._forceCCW = true;
            Collada._importOptions._fltVerts = true;
            Collada._importOptions._fltNrms = true;
            Collada._importOptions._fltUVs = true;

            model.InitGroups();

            List<MDL0BoneNode> BoneCache = new List<MDL0BoneNode>();

            int index = 0;
            if (!String.IsNullOrWhiteSpace(_header._modelNameEnglish))
                model.Name = _header._modelNameEnglish;
            else
                model.Name = _header._modelName;

            if (!String.IsNullOrWhiteSpace(_header._commentEnglish))
                MessageBox.Show(_header._commentEnglish);
            else
                MessageBox.Show(_header._comment);

            ModelBone parent = null;
            foreach (ModelBone b in _bones)
            {
                MDL0BoneNode bone = new MDL0BoneNode();

                if (!String.IsNullOrWhiteSpace(b._boneNameEnglish))
                    bone._name = b._boneNameEnglish;
                else
                    bone._name = b._boneName;

                bone._entryIndex = index++;

                if (b._parentBoneIndex != ushort.MaxValue)
                {
                    parent = _bones[b._parentBoneIndex];
                    foreach (MDL0BoneNode v in model._boneGroup._children)
                        AssignParent(v, b, bone, parent);
                }
                else
                {
                    bone.Parent = model._boneGroup;
                    bone._bindState._scale = new Vector3(1.0f);
                    bone._bindState._translate = new Vector3(b._wPos[0], b._wPos[1], b._wPos[2]);
                    bone._bindState.CalcTransforms();
                    bone.RecalcBindState();
                }

                BoneCache.Add(bone);
            }

            MDL0ShaderNode texSpa = null, tex = null, colorSpa = null, color = null;

            index = 0;
            foreach (ModelMaterial m in _materials)
            {
                MDL0MaterialNode mn = new MDL0MaterialNode();
                mn.Name = "Material" + index++;

                MDL0MaterialRefNode texRef = null;
                MDL0MaterialRefNode spaRef = null;

                if (!String.IsNullOrEmpty(m._textureFileName))
                    if (m._textureFileName.Contains('*'))
                    {
                        string[] names = m._textureFileName.Split('*');
                        if (!String.IsNullOrEmpty(names[0]))
                        {
                            texRef = new MDL0MaterialRefNode();
                            texRef.Name = names[0].Substring(0, names[0].IndexOf('.'));
                        }
                        if (!String.IsNullOrEmpty(names[1]))
                        {
                            spaRef = new MDL0MaterialRefNode();
                            spaRef.Name = names[1].Substring(0, names[1].IndexOf('.'));
                            spaRef.MapMode = MDL0MaterialRefNode.MappingMethod.EnvCamera;
                            spaRef.UWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.VWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.Projection = Wii.Graphics.TexProjection.STQ;
                            spaRef.InputForm = Wii.Graphics.TexInputForm.ABC1;
                            spaRef.Coordinates = Wii.Graphics.TexSourceRow.Normals;
                            spaRef.Normalize = true;
                        }
                    }
                    else
                    {
                        texRef = new MDL0MaterialRefNode();
                        texRef.Name = m._textureFileName.Substring(0, m._textureFileName.IndexOf('.'));
                        texRef.Coordinates = Wii.Graphics.TexSourceRow.TexCoord0;
                    }

                if (texRef != null)
                {
                    (texRef._texture = model.FindOrCreateTexture(texRef.Name))._references.Add(texRef);
                    texRef._parent = mn;
                    mn._children.Add(texRef);
                }
                if (spaRef != null)
                {
                    (spaRef._texture = model.FindOrCreateTexture(spaRef.Name))._references.Add(spaRef);
                    spaRef._parent = mn;
                    mn._children.Add(spaRef);
                }

                mn._chan1._matColor = new RGBAPixel((byte)(m._diffuseColor[0] * 255), (byte)(m._diffuseColor[1] * 255), (byte)(m._diffuseColor[2] * 255), 255);
                mn._chan1.ColorMaterialSource = GXColorSrc.Register;

                if (texRef != null && spaRef != null)
                {
                    if (texSpa == null)
                    {
                        MDL0ShaderNode n = TexSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        texSpa = n;
                    }
                    mn.ShaderNode = texSpa;
                }
                else if (texRef != null)
                {
                    if (tex == null)
                    {
                        MDL0ShaderNode n = TexShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        tex = n;
                    }
                    mn.ShaderNode = tex;
                }
                else if (spaRef != null)
                {
                    if (colorSpa == null)
                    {
                        MDL0ShaderNode n = ColorSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        colorSpa = n;
                    }
                    mn.ShaderNode = colorSpa;
                }
                else
                {
                    if (color == null)
                    {
                        MDL0ShaderNode n = ColorShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        color = n;
                    }
                    mn.ShaderNode = color;
                }

                mn._parent = model._matGroup;
                model._matList.Add(mn);
            }

            model._numFaces = 0;
            model._numFacepoints = 0;

            int x = 0;
            int offset = 0;
            foreach (ModelMaterial m in _materials)
            {
                PrimitiveManager manager = new PrimitiveManager() { _pointCount = (int)m._faceVertCount };
                MDL0ObjectNode p = new MDL0ObjectNode() { _manager = manager, _opaMaterial = (MDL0MaterialNode)model._matList[x] };
                p._opaMaterial._objects.Add(p);
                p._manager._vertices = new List<Vertex3>();
                p.Name = "polygon" + x++;
                p._parent = model._objGroup;

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

                p._manager._indices = new UnsafeBuffer((int)m._faceVertCount * 2);
                p._manager._faceData[0] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[1] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[4] = new UnsafeBuffer((int)m._faceVertCount * 8);

                p._manager._dirty[0] = true;
                p._manager._dirty[1] = true;
                p._manager._dirty[4] = true;

                ushort* Indices = (ushort*)p._manager._indices.Address;
                Vector3* Vertices = (Vector3*)p._manager._faceData[0].Address;
                Vector3* Normals = (Vector3*)p._manager._faceData[1].Address;
                Vector2* UVs = (Vector2*)p._manager._faceData[4].Address;

                manager._triangles = new NewPrimitive((int)m._faceVertCount, BeginMode.Triangles);
                uint[] pTriarr = manager._triangles._indices;
                uint pTri = 0;

                index = 0;
                List<int> usedVertices = new List<int>();
                List<int> vertexIndices = new List<int>();
                for (int s = offset, l = 0; l < (int)m._faceVertCount; l++, s++)
                {
                    ushort i = _faceIndices[s];
                    ModelVertex mv = _vertices[i];
                    ushort j = 0;
                    if (!usedVertices.Contains(i))
                    {
                        Influence inf;
                        BoneWeight weight1 = null, weight2 = null;

                        float weight = ((float)mv._boneWeight / 100.0f).Clamp(0.0f, 1.0f);

                        if (weight > 0.0f && weight < 1.0f)
                        {
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]], weight);
                            weight2 = new BoneWeight(BoneCache[mv._boneIndex[1]], 1.0f - weight);
                        }
                        else if (weight == 0.0f)
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[1]]);
                        else
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]]);

                        if (weight2 != null)
                            inf = new Influence(new List<BoneWeight> { weight1, weight2 });
                        else
                            inf = new Influence(new List<BoneWeight> { weight1 });

                        Vector3 t = new Vector3();
                        Vertex3 v;
                        t._x = mv._position[0];
                        t._y = mv._position[1];
                        t._z = mv._position[2];
                        if (inf._weights.Count > 1)
                        {
                            inf = model._influences.FindOrCreate(inf, true);
                            inf.CalcMatrix();
                            v = new Vertex3(t, inf);
                        }
                        else
                        {
                            MDL0BoneNode bone = inf._weights[0].Bone;
                            v = new Vertex3(t * bone._inverseBindMatrix, bone);
                        }

                        p._manager._vertices.Add(v);
                        vertexIndices.Add(usedVertices.Count);
                        usedVertices.Add(i);
                        j = (ushort)(usedVertices.Count - 1);
                    }
                    else
                        j = (ushort)vertexIndices[usedVertices.IndexOf(i)];

                    *Indices++ = j;
                    pTriarr[pTri++] = (uint)l;
                    *Vertices++ = p._manager._vertices[j]._position;
                    *Normals++ = mv._normal;
                    *UVs++ = mv._texCoord;
                }
                model._objList.Add(p);
                offset += (int)m._faceVertCount;
            }

            //Check each polygon to see if it can be rigged to a single influence
            if (model._objList != null && model._objList.Count != 0)
                foreach (MDL0ObjectNode p in model._objList)
                {
                    IMatrixNode node = null;
                    bool singlebind = true;

                    foreach (Vertex3 v in p._manager._vertices)
                        if (v._matrixNode != null)
                        {
                            if (node == null)
                                node = v._matrixNode;

                            if (v._matrixNode != node)
                            {
                                singlebind = false;
                                break;
                            }
                        }

                    if (singlebind && p._matrixNode == null)
                    {
                        //Increase reference count ahead of time for rebuild
                        if (p._manager._vertices[0]._matrixNode != null)
                            p._manager._vertices[0]._matrixNode.ReferenceCount++;

                        foreach (Vertex3 v in p._manager._vertices)
                            if (v._matrixNode != null)
                                v._matrixNode.ReferenceCount--;

                        p._nodeId = -2; //Continued on polygon rebuild
                    }
                }

            //foreach (MDL0ObjectNode p in model._objList)
            //    foreach (MDL0MaterialNode m in model._matList)
            //    {
            //        MDL0MaterialNode m2 = p.OpaMaterialNode;

            //        if (m2 == null || m2.ShaderNode != m.ShaderNode || m2.Children.Count != m.Children.Count)
            //            continue;

            //        for (int i = 0; i < m.Children.Count; i++)
            //            if (m2.Children[i].Name != m.Children[i].Name)
            //                continue;

            //        p.OpaMaterialNode = m;
            //        break;
            //    }
            //for (int i = 0; i < model._matList.Count; i++)
            //    if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0)
            //        model._matList.RemoveAt(i--);

            model.CleanGroups();
            model.BuildFromScratch(null);
        }
示例#8
0
        public void LoadModel(MDL0Node model)
        {
            model.Populate();
            model._renderAttribs._renderBones = false;
            model._renderAttribs._renderPolygons = true;
            model._renderAttribs._renderWireframe = false;
            model._renderAttribs._renderVertices = false;
            model.ApplyCHR(null, 0);
            model.ApplySRT(null, 0);

            if (UseExceptions) foreach (string texname in TexturesToDisable) {
                MDL0TextureNode tex = model.TextureGroup.FindChild(texname, false) as MDL0TextureNode;
                if (tex != null) {
                    tex.Enabled = false;
                }
            }

            modelPanel1.ClearAll();
            modelPanel1.AddTarget((IRenderedObject)model);

            if (UseExceptions && PolygonsToDisable.ContainsKey(_charString)) {
                foreach (int polygonNum in PolygonsToDisable[_charString]) {
                    MDL0ObjectNode poly = model.PolygonGroup.FindChild("polygon" + polygonNum, false) as MDL0ObjectNode;
                    if (poly != null) poly.IsRendering = false;
                }
            }

            Box box = model.GetBox();
            Vector3 min = box.Min, max = box.Max;
            if (ZoomOut) {
                min._x += 20;
                max._x -= 20;
            }
            modelPanel1.SetCamWithBox(min, max);
        }
        private static unsafe void WriteGeometry(MDL0Node model, XmlWriter writer)
        {
            ResourceNode grp = model._objGroup;
            if (grp == null)
                return;

            writer.WriteStartElement("library_geometries");

            foreach (MDL0ObjectNode poly in grp.Children)
            {
                PrimitiveManager manager = poly._manager;

                //Geometry
                writer.WriteStartElement("geometry");
                writer.WriteAttributeString("id", poly.Name);
                writer.WriteAttributeString("name", poly.Name);

                //Mesh
                writer.WriteStartElement("mesh");

                //Write vertex data first
                WriteVertices(poly.Name, manager._vertices, poly.MatrixNode, writer);

                //Face assets
                for (int i = 0; i < 12; i++)
                {
                    if (manager._faceData[i] == null)
                        continue;

                    switch (i)
                    {
                        case 0:
                            break;

                        case 1:
                            WriteNormals(poly.Name, writer, manager);
                            break;

                        case 2:
                        case 3:
                            WriteColors(poly.Name, manager, i - 2, writer);
                            break;

                        default:
                            WriteUVs(poly.Name, manager, i - 4, writer);
                            break;
                    }
                }

                //Vertices
                writer.WriteStartElement("vertices");
                writer.WriteAttributeString("id", poly.Name + "_Vertices");
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "POSITION");
                writer.WriteAttributeString("source", "#" + poly.Name + "_Positions");
                writer.WriteEndElement(); //input
                writer.WriteEndElement(); //vertices

                //Faces
                if (manager._triangles != null)
                    WritePrimitive(poly, manager._triangles, writer);
                if (manager._lines != null)
                    WritePrimitive(poly, manager._lines, writer);
                if (manager._points != null)
                    WritePrimitive(poly, manager._points, writer);

                writer.WriteEndElement(); //mesh
                writer.WriteEndElement(); //geometry
            }

            writer.WriteEndElement();
        }
示例#10
0
        private static unsafe void WriteControllers(MDL0Node model, XmlWriter writer)
        {
            if (model._objList == null)
                return;

            writer.WriteStartElement("library_controllers");

            int g = 0;
            //List<MDL0BoneNode> boneSet = new List<MDL0BoneNode>();

            MDL0BoneNode[] bones = new MDL0BoneNode[model._linker.BoneCache.Length];
            model._linker.BoneCache.CopyTo(bones, 0);

            //foreach (MDL0BoneNode b in model._linker.BoneCache)
            //{
            //    b._nodeIndex = g++;
            //    boneSet.Add(b);
            //}

            HashSet<float> temp = new HashSet<float>();
            Matrix m;
            bool first;

            foreach (MDL0ObjectNode poly in model._objList)
            {
                List<Vertex3> verts = poly._manager._vertices;

                writer.WriteStartElement("controller");
                writer.WriteAttributeString("id", poly.Name + "_Controller");
                writer.WriteStartElement("skin");
                writer.WriteAttributeString("source", "#" + poly.Name);

                writer.WriteStartElement("bind_shape_matrix");

                //Set bind pose matrix
                //if (poly._singleBind != null)
                //    m = poly._singleBind.Matrix;
                //else
                    m = Matrix.Identity;

                writer.WriteString(WriteMatrix(m));

                writer.WriteEndElement();

                //Get list of used bones and weights

                //int index = 0;
                if (poly._matrixNode != null)
                {
                    foreach (BoneWeight w in poly._matrixNode.Weights)
                    {
                        //if (!boneSet.Contains(w.Bone))
                        //{
                        //    boneSet.Add(w.Bone);
                        //    w.Bone._nodeIndex = index++;
                        //}
                        //if (!weightSet.Contains(w.Weight))
                            temp.Add(w.Weight);
                    }
                }
                else
                {
                    foreach (Vertex3 v in verts)
                        foreach (BoneWeight w in v._matrixNode.Weights)
                        {
                            //if (!boneSet.Contains(w.Bone))
                            //{
                            //    boneSet.Add(w.Bone);
                            //    w.Bone._nodeIndex = index++;
                            //}
                            //if (!weightSet.Contains(w.Weight))
                                temp.Add(w.Weight);
                        }
                }

                float[] weightSet = new float[temp.Count];
                temp.CopyTo(weightSet);

                //Write joint source
                writer.WriteStartElement("source");
                writer.WriteAttributeString("id", poly.Name + "_Joints");

                //Node array
                writer.WriteStartElement("Name_array");
                writer.WriteAttributeString("id", poly.Name + "_JointArr");
                //writer.WriteAttributeString("count", boneSet.Count.ToString());
                writer.WriteAttributeString("count", bones.Length.ToString());

                first = true;
                //foreach (MDL0BoneNode b in boneSet)
                foreach (MDL0BoneNode b in bones)
                {
                    if (first)
                        first = false;
                    else
                        writer.WriteString(" ");
                    writer.WriteString(b.Name);
                }
                writer.WriteEndElement(); //Name_array

                //Technique
                writer.WriteStartElement("technique_common");
                writer.WriteStartElement("accessor");
                writer.WriteAttributeString("source", String.Format("#{0}_JointArr", poly.Name));
                //writer.WriteAttributeString("count", boneSet.Count.ToString());
                writer.WriteAttributeString("count", bones.Length.ToString());
                writer.WriteStartElement("param");
                writer.WriteAttributeString("name", "JOINT");
                writer.WriteAttributeString("type", "Name");
                writer.WriteEndElement(); //param
                writer.WriteEndElement(); //accessor
                writer.WriteEndElement(); //technique

                writer.WriteEndElement(); //joint source

                //Inverse matrices source
                writer.WriteStartElement("source");
                writer.WriteAttributeString("id", poly.Name + "_Matrices");

                writer.WriteStartElement("float_array");
                writer.WriteAttributeString("id", poly.Name + "_MatArr");
                //writer.WriteAttributeString("count", (boneSet.Count * 16).ToString());
                writer.WriteAttributeString("count", (bones.Length * 16).ToString());

                first = true;
                foreach (MDL0BoneNode b in bones)
                {
                    if (first)
                        first = false;
                    else
                        writer.WriteString(" ");
                    writer.WriteString(WriteMatrix(b.InverseBindMatrix));
                }
                writer.WriteEndElement(); //float_array

                //Technique
                writer.WriteStartElement("technique_common");
                writer.WriteStartElement("accessor");
                writer.WriteAttributeString("source", String.Format("#{0}_MatArr", poly.Name));
                //writer.WriteAttributeString("count", boneSet.Count.ToString());
                writer.WriteAttributeString("count", bones.Length.ToString());
                writer.WriteAttributeString("stride", "16");
                writer.WriteStartElement("param");
                writer.WriteAttributeString("type", "float4x4");
                writer.WriteEndElement(); //param
                writer.WriteEndElement(); //accessor
                writer.WriteEndElement(); //technique

                writer.WriteEndElement(); //source

                //Weights source
                writer.WriteStartElement("source");
                writer.WriteAttributeString("id", poly.Name + "_Weights");

                writer.WriteStartElement("float_array");
                writer.WriteAttributeString("id", poly.Name + "_WeightArr");
                writer.WriteAttributeString("count", weightSet.Length.ToString());
                first = true;

                foreach (float f in weightSet)
                {
                    if (first)
                        first = false;
                    else
                        writer.WriteString(" ");
                    writer.WriteValue(f);
                }
                writer.WriteEndElement();

                //Technique
                writer.WriteStartElement("technique_common");
                writer.WriteStartElement("accessor");
                writer.WriteAttributeString("source", String.Format("#{0}_WeightArr", poly.Name));
                writer.WriteAttributeString("count", weightSet.Length.ToString());
                writer.WriteStartElement("param");
                writer.WriteAttributeString("type", "float");
                writer.WriteEndElement(); //param
                writer.WriteEndElement(); //accessor
                writer.WriteEndElement(); //technique

                writer.WriteEndElement(); //source

                //Joint bindings
                writer.WriteStartElement("joints");
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "JOINT");
                writer.WriteAttributeString("source", String.Format("#{0}_Joints", poly.Name));
                writer.WriteEndElement(); //input
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "INV_BIND_MATRIX");
                writer.WriteAttributeString("source", String.Format("#{0}_Matrices", poly.Name));
                writer.WriteEndElement(); //input
                writer.WriteEndElement(); //joints

                //Vertex weights, one for each vertex in geometry
                writer.WriteStartElement("vertex_weights");
                writer.WriteAttributeString("count", verts.Count.ToString());
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "JOINT");
                writer.WriteAttributeString("offset", "0");
                writer.WriteAttributeString("source", String.Format("#{0}_Joints", poly.Name));
                writer.WriteEndElement(); //input
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "WEIGHT");
                writer.WriteAttributeString("offset", "1");
                writer.WriteAttributeString("source", String.Format("#{0}_Weights", poly.Name));
                writer.WriteEndElement(); //input

                writer.WriteStartElement("vcount");
                first = true;
                if (poly._matrixNode != null)
                    for (int i = 0; i < verts.Count; i++)
                    {
                        if (first)
                            first = false;
                        else
                            writer.WriteString(" ");
                        writer.WriteString(poly._matrixNode.Weights.Count.ToString(CultureInfo.InvariantCulture.NumberFormat));
                    }
                else
                    foreach (Vertex3 v in verts)
                    {
                        if (first)
                            first = false;
                        else
                            writer.WriteString(" ");
                        writer.WriteString(v._matrixNode.Weights.Count.ToString(CultureInfo.InvariantCulture.NumberFormat));
                    }

                writer.WriteEndElement(); //vcount

                writer.WriteStartElement("v");

                first = true;
                if (poly._matrixNode != null)
                    for (int i = 0; i < verts.Count; i++)
                        foreach (BoneWeight w in poly._matrixNode.Weights)
                        {
                            if (first)
                                first = false;
                            else
                                writer.WriteString(" ");
                            //writer.WriteString(w.Bone._nodeIndex.ToString());
                            writer.WriteString(Array.IndexOf(bones, w.Bone).ToString(CultureInfo.InvariantCulture.NumberFormat));
                            writer.WriteString(" ");
                            writer.WriteString(Array.IndexOf(weightSet, w.Weight).ToString(CultureInfo.InvariantCulture.NumberFormat));
                        }
                else
                    foreach (Vertex3 v in verts)
                        foreach (BoneWeight w in v._matrixNode.Weights)
                        {
                            if (first)
                                first = false;
                            else
                                writer.WriteString(" ");
                            //writer.WriteString(w.Bone._nodeIndex.ToString());
                            writer.WriteString(Array.IndexOf(bones, w.Bone).ToString(CultureInfo.InvariantCulture.NumberFormat));
                            writer.WriteString(" ");
                            writer.WriteString(Array.IndexOf(weightSet, w.Weight).ToString(CultureInfo.InvariantCulture.NumberFormat));
                        }

                writer.WriteEndElement(); //v

                writer.WriteEndElement(); //vertex_weights

                writer.WriteEndElement(); //skin
                writer.WriteEndElement(); //controller

                //boneSet.Clear();
                //weightSet.Clear();
            }

            writer.WriteEndElement();
        }
示例#11
0
        private static unsafe void WriteNodes(MDL0Node model, XmlWriter writer)
        {
            if (model._boneList != null)
                foreach (MDL0BoneNode bone in model._boneList)
                    WriteBone(bone, writer);

            if (model._objList != null)
                foreach (MDL0ObjectNode poly in model._objList)
                    //if (poly._singleBind == null) //Single bind objects will be written under their bone
                        WritePolyInstance(poly, writer);
        }
示例#12
0
        private static void WriteImages(MDL0Node model, XmlWriter writer)
        {
            if (model._texList == null)
                return;

            writer.WriteStartElement("library_images");
            {
                foreach (MDL0TextureNode tex in model._texList)
                {
                    writer.WriteStartElement("image");
                    {
                        writer.WriteAttributeString("id", tex.Name + "-image");
                        writer.WriteAttributeString("name", tex.Name);
                        writer.WriteStartElement("init_from");
                        {
                            writer.WriteStartElement("ref");
                            {
                                writer.WriteString(String.Format("{0}.png", tex.Name));
                            }
                            writer.WriteEndElement(); //ref
                        }
                        writer.WriteEndElement(); //init_from
                    }
                    writer.WriteEndElement(); //image
                }
            }
            writer.WriteEndElement(); //library_images
        }
        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);
            }
        }
 private void UpdateModel(MDL0Node model)
 {
     if (_chr0 != null && playCHR0ToolStripMenuItem.Checked)
         model.ApplyCHR(_chr0, _animFrame);
     else
         model.ApplyCHR(null, 0);
     if (_srt0 != null && playSRT0ToolStripMenuItem.Checked)
         model.ApplySRT(_srt0, _animFrame);
     else
         model.ApplySRT(null, 0);
     if (_shp0 != null && playSHP0ToolStripMenuItem.Checked)
         model.ApplySHP(_shp0, _animFrame);
     else
         model.ApplySHP(null, 0);
     if (_pat0 != null && playPAT0ToolStripMenuItem.Checked)
         model.ApplyPAT(_pat0, _animFrame);
     else
         model.ApplyPAT(null, 0);
     if (_vis0 != null && playVIS0ToolStripMenuItem.Checked)
         if (model == TargetModel)
             ReadVIS0();
         else
             model.ApplyVIS(_vis0, _animFrame);
     if (_scn0 != null)// && playSCN0ToolStripMenuItem.Checked)
         model.SetSCN0Frame(_animFrame);
     else
         model.SetSCN0Frame(0);
     if (_clr0 != null && playCLR0ToolStripMenuItem.Checked)
         model.ApplyCLR(_clr0, _animFrame);
     else
         model.ApplyCLR(null, 0);
 }
 public void Show(MDL0Node model)
 {
     Show(null, model);
 }
示例#16
0
        internal void Parse(MDL0Node model)
        {
            Influence   inf;
            ModelLinker linker = model._linker;

            switch (_type)
            {
            case MDLResourceType.Definitions:
                if (linker.Defs != null)
                {
                    ExtractGroup(linker.Defs, typeof(MDL0DefNode));
                }
                break;

            case MDLResourceType.Bones:
                //Break if there are no bones defined
                if (linker.Bones == null)
                {
                    break;
                }

                //Parse bones from raw data (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.
                ExtractGroup(linker.Bones, typeof(MDL0BoneNode));

                //Cache flat list
                linker.BoneCache = _children.ToArray();

                //Make sure the node cache is the correct size
                int highest = 0;
                foreach (MDL0BoneNode b in linker.BoneCache)
                {
                    if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest)
                    {
                        highest = b._nodeIndex;
                    }
                }
                if (highest >= linker.NodeCache.Length)
                {
                    linker.NodeCache = new IMatrixNode[highest + 1];
                }

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

                //Assign children using each bones' parent offset in case NodeTree is corrupted
                foreach (MDL0BoneNode b in linker.BoneCache)
                {
                    b._parent._children.Add(b);
                }

                //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;

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

                            if (bone.Header->_parentOffset == 0)
                            {
                                if (!_children.Contains(bone))
                                {
                                    nodeTreeError = true;
                                    continue;
                                }
                            }
                            else
                            {
                                ResourceNode n = linker.NodeCache[index] as ResourceNode;
                                if (n == null || bone._parent != n || !n._children.Contains(bone))
                                {
                                    nodeTreeError = true;
                                    continue;
                                }
                            }
                            pData += 5;
                            goto Top;
                        }
                    }
                    else
                    if (p.Name == "NodeMix")
                    {
                        //Use node mix to create weight groups
                        byte *pData = (byte *)p.Data;

Top:
                        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._weights.Add(new BoneWeight(b, nEntry->_value));
                                }
                                else
                                {
                                    nullIndices.Add(i);
                                    nullCount++;
                                }
                            }

                            bool d = false;
                            if (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)
                                {
                                    d = true;
                                }
                                else
                                {
                                    inf._weights = newWeights;
                                }
                            }

                            //Add influence to model object, while adding it to the cache.
                            if (!d)
                            {
                                ((Influence)(linker.NodeCache[index] = model._influences.FindOrCreate(inf, true)))._index = index;
                            }

                            //Move data pointer to next entry
                            pData = (byte *)nEntry;
                            goto Top;

                        //Type 5 is for primary influences
                        case 5:
                            pData += 5;
                            goto Top;
                        }
                    }
                }

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

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

                break;

            case MDLResourceType.Materials:
                if (linker.Materials != null)
                {
                    ExtractGroup(linker.Materials, typeof(MDL0MaterialNode));
                }
                break;

            case MDLResourceType.Shaders:
                if (linker.Shaders != null)
                {
                    ExtractGroup(linker.Shaders, typeof(MDL0ShaderNode));
                }
                break;

            case MDLResourceType.Vertices:
                if (linker.Vertices != null)
                {
                    ExtractGroup(linker.Vertices, typeof(MDL0VertexNode));
                }
                break;

            case MDLResourceType.Normals:
                if (linker.Normals != null)
                {
                    ExtractGroup(linker.Normals, typeof(MDL0NormalNode));
                }
                break;

            case MDLResourceType.UVs:
                if (linker.UVs != null)
                {
                    ExtractGroup(linker.UVs, typeof(MDL0UVNode));
                }
                break;

            case MDLResourceType.FurLayerCoords:
                if (linker.FurLayerCoords != null)
                {
                    ExtractGroup(linker.FurLayerCoords, typeof(MDL0FurPosNode));
                }
                break;

            case MDLResourceType.FurVectors:
                if (linker.FurVectors != null)
                {
                    ExtractGroup(linker.FurVectors, typeof(MDL0FurVecNode));
                }
                break;

            case MDLResourceType.Objects:
                //Break if no polygons defined
                if (linker.Polygons == null)
                {
                    break;
                }

                //Extract
                ExtractGroup(linker.Polygons, typeof(MDL0ObjectNode));

                //Attach materials to polygons.
                //This assumes that materials have already been parsed.

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

                //Find DrawOpa or DrawXlu entry in Definition list
                foreach (ResourcePair p in *linker.Defs)
                {
                    if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu"))
                    {
                        bool   opa    = p.Name == "DrawOpa";
                        ushort dIndex = 0;
                        byte * pData  = (byte *)p.Data;
                        while (*pData++ == 4)
                        {
                            //Get polygon from index
                            dIndex = *(bushort *)(pData + 2);
                            if (dIndex >= _children.Count || dIndex < 0)
                            {
                                model._errors.Add("Object index was greater than the actual object count.");
                                SignalPropertyChange();
                                dIndex = 0;
                            }
                            poly            = _children[dIndex] as MDL0ObjectNode;
                            poly._drawIndex = pData[6];
                            //Get material from index
                            mat = matList[*(bushort *)pData] as MDL0MaterialNode;
                            //Get bone from index and assign
                            int boneIndex = *(bushort *)(pData + 4);
                            if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length)
                            {
                                poly.BoneNode = linker.BoneCache[boneIndex] as MDL0BoneNode;
                            }
                            //Assign material to polygon
                            if (opa)
                            {
                                poly.OpaMaterialNode = mat;
                            }
                            else
                            {
                                poly.XluMaterialNode = mat;
                            }
                            //Increment pointer
                            pData += 7;
                        }
                    }
                }

                foreach (MDL0ObjectNode m in _children)
                {
                    int max = Maths.Max(
                        m.OpaMaterialNode != null ? m.OpaMaterialNode.Children.Count : 0,
                        m.XluMaterialNode != null ? m.XluMaterialNode.Children.Count : 0,
                        m.OpaMaterialNode != null && m.OpaMaterialNode.MetalMaterial != null ? m.OpaMaterialNode.MetalMaterial.Children.Count : 0,
                        m.XluMaterialNode != null && m.XluMaterialNode.MetalMaterial != null ? m.XluMaterialNode.MetalMaterial.Children.Count : 0);

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

                    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();
                    }
                }
                break;

            case MDLResourceType.Colors:
                if (linker.Colors != null)
                {
                    ExtractGroup(linker.Colors, typeof(MDL0ColorNode));
                }
                break;

            case MDLResourceType.Textures:
                if (linker.Textures != null)
                {
                    ExtractGroup(linker.Textures, typeof(MDL0TextureNode));
                }
                break;

            case MDLResourceType.Palettes:
                if (linker.Palettes != null)
                {
                    ExtractGroup(linker.Palettes, typeof(MDL0TextureNode));
                }
                break;
            }
        }
 public void Show(IWin32Window owner, MDL0Node model)
 {
     _models.Add(model);
     base.Show(owner);
 }
        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);
                }
            }
        }
示例#19
0
        public static MDL0Node ImportModel(string filepath)
        {
            filepath = Path.GetFullPath(filepath);
            if (!File.Exists(filepath))
                throw new FileNotFoundException("PMD model file " + filepath + " not found.");

            MDL0Node model = null;
            using (FileStream fs = new FileStream(filepath, FileMode.Open))
            {
                BinaryReader reader = new BinaryReader(fs);
                string magic = encoder.GetString(reader.ReadBytes(3));
                if (magic != "Pmd")
                    throw new FileLoadException("Model format not recognized.");

                float version = BitConverter.ToSingle(reader.ReadBytes(4), 0);
                if (version == 1.0f)
                    model = new MDL0Node();
                else
                    throw new Exception("Version " + version.ToString() + " models are not supported.");

                if (model != null)
                {
                    Read(reader, CoordinateType.LeftHanded); //Will flip model backwards if right handed
                    PMD2MDL0(model);
                }
                fs.Close();
            }
            return model;
        }
示例#20
0
        internal void Parse(MDL0Node model)
        {
            Influence   inf;
            ModelLinker linker = model._linker;

            switch (_type)
            {
            case MDLResourceType.Bones:
                //Break if there are no bones defined
                if (linker.Bones == null)
                {
                    break;
                }

                //Parse bones from raw data (flat list).
                //Bones re-assign parents in their Initialize block, so parents are true.
                ExtractGroup(linker.Bones, typeof(MDL0BoneNode));

                //Cache flat list
                linker.BoneCache = _children.ToArray();

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

                //Populate node cache
                MDL0BoneNode bone = null;
                int          index;
                int          count = linker.BoneCache.Length;
                for (int i = 0; i < count; i++)
                {
                    //bone = linker.BoneCache[i] as MDL0BoneNode;
                    linker.NodeCache[(bone = linker.BoneCache[i] as MDL0BoneNode)._nodeIndex] = bone;
                }

                //Now that bones and primary influences have been cached, we can create weighted influences.

                foreach (ResourcePair p in *linker.Defs)
                {
                    if (p.Name == "NodeTree")
                    {
                        //Use node tree to rebuild bone heirarchy
                        byte *pData = (byte *)p.Data;

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

                            if (bone.Header->_parentOffset == 0)
                            {
                                _children.Add(bone);
                            }
                            else
                            {
                                (bone._parent = linker.NodeCache[index] as ResourceNode)._children.Add(bone);
                            }

                            pData += 5;
                            goto Top;
                        }
                    }
                    else if (p.Name == "NodeMix")
                    {
                        //Use node mix to create weight groups
                        byte *pData = (byte *)p.Data;

Top:
                        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(count);
                            //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.
                            for (int i = 0; i < count; i++, nEntry++)
                            {
                                inf._weights[i] = new BoneWeight(linker.NodeCache[nEntry->_id] as MDL0BoneNode, nEntry->_value);
                            }

                            //Add influence to model object, while adding it to the cache.
                            linker.NodeCache[index] = model._influences.AddOrCreate(inf);

                            //Move data pointer to next entry
                            pData = (byte *)nEntry;
                            goto Top;

                        //Type 5 is for primary influences
                        case 5:
                            pData += 5;
                            goto Top;
                        }
                    }
                }

                break;

            case MDLResourceType.Materials:
                if (linker.Materials != null)
                {
                    ExtractGroup(linker.Materials, typeof(MDL0MaterialNode));
                }
                break;

            case MDLResourceType.Shaders:
                if (linker.Shaders != null)
                {
                    ExtractGroup(linker.Shaders, typeof(MDL0ShaderNode));
                }
                break;

            case MDLResourceType.Polygons:
                //Break if no polygons defined
                if (linker.Polygons == null)
                {
                    break;
                }

                //Extract
                ExtractGroup(linker.Polygons, typeof(MDL0PolygonNode));

                //Attach materials to polygons.
                //This assumes that materials have already been parsed.

                List <ResourceNode> matList = ((MDL0Node)_parent)._matList;
                MDL0PolygonNode     poly;
                MDL0MaterialNode    mat;

                //Find DrawOpa or DrawXlu entry in Definition list
                foreach (ResourcePair p in *linker.Defs)
                {
                    if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu"))
                    {
                        byte *pData = (byte *)p.Data;
                        while (*pData++ == 4)
                        {
                            //Get polygon from index
                            poly = _children[*(bushort *)(pData + 2)] as MDL0PolygonNode;
                            //Get material from index
                            mat = matList[*(bushort *)pData] as MDL0MaterialNode;
                            //Assign material to polygon
                            poly._material = mat;
                            //Add polygon to material reference list
                            mat._polygons.Add(poly);
                            //Increment pointer
                            pData += 7;
                        }
                    }
                }
                break;
            }
        }
示例#21
0
        public void Port(MDL0Node _targetModel, MDL0Node _extModel)
        {
            MDL0BoneNode extBone;
            MDL0BoneNode bone;
            KeyframeEntry kfe;
            float difference = 0;
            foreach (CHR0EntryNode _target in Children)
            {
                extBone = (MDL0BoneNode)_extModel.FindChild(_target.Name, true); //Get external model bone
                bone = (MDL0BoneNode)_targetModel.FindChild(_target.Name, true); //Get target model bone

                for (int x = 0; x < _target.FrameCount; x++)
                    for (int i = 0x13; i < 0x19; i++)
                        if ((kfe = _target.GetKeyframe((KeyFrameMode)i, x)) != null) //Check for a keyframe
                        {
                            if (bone != null && extBone != null)
                                switch (i)
                                {
                                    //Translations
                                    case 0x16: //Trans X
                                        if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._x, 4))
                                            kfe._value = bone._bindState.Translate._x;
                                        else if (bone._bindState.Translate._x < extBone._bindState.Translate._x)
                                            kfe._value -= extBone._bindState.Translate._x - bone._bindState.Translate._x;
                                        else if (bone._bindState.Translate._x > extBone._bindState.Translate._x)
                                            kfe._value += bone._bindState.Translate._x - extBone._bindState.Translate._x;
                                        break;
                                    case 0x17: //Trans Y
                                        if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._y, 4))
                                            kfe._value = bone._bindState.Translate._y;
                                        else if (bone._bindState.Translate._y < extBone._bindState.Translate._y)
                                            kfe._value -= extBone._bindState.Translate._y - bone._bindState.Translate._y;
                                        else if (bone._bindState.Translate._y > extBone._bindState.Translate._y)
                                            kfe._value += bone._bindState.Translate._y - extBone._bindState.Translate._y;
                                        break;
                                    case 0x18: //Trans Z
                                        if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._z, 4))
                                            kfe._value = bone._bindState.Translate._z;
                                        else if (bone._bindState.Translate._z < extBone._bindState.Translate._z)
                                            kfe._value -= extBone._bindState.Translate._z - bone._bindState.Translate._z;
                                        else if (bone._bindState.Translate._z > extBone._bindState.Translate._z)
                                            kfe._value += bone._bindState.Translate._z - extBone._bindState.Translate._z;
                                        break;

                                    //Rotations
                                    //case 0x13: //Rot X
                                    //    difference = bone._bindState.Rotate._x - extBone._bindState.Rotate._x;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 0);
                                    //    break;
                                    //case 0x14: //Rot Y
                                    //    difference = bone._bindState.Rotate._y - extBone._bindState.Rotate._y;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 1);
                                    //    break;
                                    //case 0x15: //Rot Z
                                    //    difference = bone._bindState.Rotate._z - extBone._bindState.Rotate._z;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 2);
                                    //    break;
                                }
                            if (kfe._value == float.NaN || kfe._value == float.PositiveInfinity || kfe._value == float.NegativeInfinity)
                            {
                                kfe.Remove();
                                _target.Keyframes._keyCounts[i]--;
                            }
                        }
            }
            _changed = true;
        }
 public DialogResult ShowDialog(IWin32Window owner, MDL0Node model)
 {
     _models.Add(model);
     try { return base.ShowDialog(owner); }
     finally { _models = null; }
 }
        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();
                    //}
                }
            }
        }
 public void RemoveTarget(MDL0Node model)
 {
     if (_targetModels.Contains(model))
         _targetModels.Remove(model);
     modelPanel.RemoveTarget(model);
 }
示例#25
0
        private static unsafe void WriteMaterials(MDL0Node model, XmlWriter writer)
        {
            ResourceNode node = model._matGroup;
            if (node == null)
                return;

            writer.WriteStartElement("library_materials");
            {
                foreach (MDL0MaterialNode mat in node.Children)
                {
                    if (mat._objects.Count == 0)
                        continue;

                    writer.WriteStartElement("material");
                    {
                        writer.WriteAttributeString("id", mat._name);

                        writer.WriteStartElement("instance_effect");
                        writer.WriteAttributeString("url", String.Format("#{0}-fx", mat._name));
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
        }
        public ArticleInfo(ArticleEntry article, MDL0Node model, bool running)
        {
            _article = article;
            _model = model;
            _running = running;

            _chr0List = new List<CHR0Node>();
            _srt0List = new List<SRT0Node>();
            _shp0List = new List<SHP0Node>();
            _vis0List = new List<VIS0Node>();
            _pat0List = new List<PAT0Node>();
            _clr0List = new List<CLR0Node>();

            _article._info = this;
        }
示例#27
0
        public static void Serialize(MDL0Node model, string outFile)
        {
            model.Populate();
            model.ApplyCHR(null, 0);

            using (FileStream stream = new FileStream(outFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 0x1000, FileOptions.SequentialScan))
            using (XmlWriter writer = XmlWriter.Create(stream, _writerSettings))
            {
                writer.Flush();
                stream.Position = 0;

                writer.WriteStartDocument();
                writer.WriteStartElement("COLLADA", "http://www.collada.org/2008/03/COLLADASchema");
                writer.WriteAttributeString("version", "1.5.0");

                writer.WriteStartElement("asset");
                {
                    writer.WriteStartElement("contributor");
                    writer.WriteElementString("authoring_tool", Application.ProductName);
                    writer.WriteEndElement();

                    writer.WriteStartElement("created");
                    writer.WriteString(DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture) + "Z");
                    writer.WriteEndElement();

                    writer.WriteStartElement("modified");
                    writer.WriteString(DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture) + "Z");
                    writer.WriteEndElement();

                    writer.WriteStartElement("unit");
                    writer.WriteAttributeString("meter", "0.01");
                    writer.WriteAttributeString("name", "centimeter");
                    writer.WriteEndElement();

                    writer.WriteElementString("up_axis", "Y_UP");
                }
                writer.WriteEndElement();

                //Define images
                WriteImages(model, writer);

                //Define materials
                WriteMaterials(model, writer);

                //Define effects
                WriteEffects(model, writer);

                //Define geometry
                //Create a geometry object for each polygon
                WriteGeometry(model, writer);

                //Define controllers
                //Each weighted polygon needs a controller, which assigns weights to each vertex.
                WriteControllers(model, writer);

                //Define scenes
                writer.WriteStartElement("library_visual_scenes");
                {
                    writer.WriteStartElement("visual_scene");
                    {
                        //Attach nodes/bones to scene, starting with TopN
                        //Specify transform for each node
                        //Weighted polygons must use instance_controller
                        //Standard geometry uses instance_geometry

                        writer.WriteAttributeString("id", "RootNode");
                        writer.WriteAttributeString("name", "RootNode");

                        //Define bones and geometry instances
                        WriteNodes(model, writer);
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();

                writer.WriteStartElement("scene");
                {
                    writer.WriteStartElement("instance_visual_scene");
                    writer.WriteAttributeString("url", "#RootNode");
                    writer.WriteEndElement(); //instance visual scene
                }
                writer.WriteEndElement(); //scene

                writer.Close();
            }
        }
 private void UpdateModel(MDL0Node model)
 {
     int frame = CurrentFrame;
     if (_chr0 != null && !(TargetAnimType != AnimType.CHR && !playCHR0ToolStripMenuItem.Checked))
         model.ApplyCHR(_chr0, frame);
     else
         model.ApplyCHR(null, 0);
     if (_srt0 != null && !(TargetAnimType != AnimType.SRT && !playSRT0ToolStripMenuItem.Checked))
         model.ApplySRT(_srt0, frame);
     else
         model.ApplySRT(null, 0);
     if (_shp0 != null && !(TargetAnimType != AnimType.SHP && !playSHP0ToolStripMenuItem.Checked))
         model.ApplySHP(_shp0, frame);
     else
         model.ApplySHP(null, 0);
     if (_pat0 != null && !(TargetAnimType != AnimType.PAT && !playPAT0ToolStripMenuItem.Checked))
         model.ApplyPAT(_pat0, frame);
     else
         model.ApplyPAT(null, 0);
     if (_vis0 != null && !(TargetAnimType != AnimType.VIS && !playVIS0ToolStripMenuItem.Checked))
         if (model == TargetModel)
             ReadVIS0();
         else
             model.ApplyVIS(_vis0, frame);
     if (_clr0 != null && !(TargetAnimType != AnimType.CLR && !playCLR0ToolStripMenuItem.Checked))
         model.ApplyCLR(_clr0, frame);
     else
         model.ApplyCLR(null, 0);
 }
示例#29
0
        private static unsafe void WriteEffects(MDL0Node model, XmlWriter writer)
        {
            ResourceNode node = model._matGroup;
            if (node == null)
                return;

            writer.WriteStartElement("library_effects");

            foreach (MDL0MaterialNode mat in node.Children)
            {
                writer.WriteStartElement("effect");
                {
                    writer.WriteAttributeString("id", mat._name + "-fx");
                    writer.WriteAttributeString("name", mat._name);
                    writer.WriteStartElement("profile_COMMON");
                    {
                        if (mat.Children.Count > 0)
                        {
                            MDL0MaterialRefNode mr = mat.Children[0] as MDL0MaterialRefNode;
                            if (mr._texture != null)
                            {
                                writer.WriteStartElement("newparam");
                                writer.WriteAttributeString("sid", mr._texture.Name + "-surface");
                                {
                                    writer.WriteStartElement("surface");
                                    writer.WriteAttributeString("type", "2D");
                                    {
                                        writer.WriteStartElement("init_from");
                                        {
                                            writer.WriteStartElement("ref");
                                            {
                                                writer.WriteString(mr._texture.Name + "-image");
                                            }
                                            writer.WriteEndElement(); //ref
                                        }
                                        writer.WriteEndElement(); //init_from
                                    }
                                    writer.WriteEndElement(); //surface
                                }
                                writer.WriteEndElement(); //newparam

                                writer.WriteStartElement("newparam");
                                writer.WriteAttributeString("sid", mr._texture.Name + "-sampler");
                                {
                                    writer.WriteStartElement("sampler2D");
                                    {
                                        writer.WriteStartElement("source");
                                        {
                                            writer.WriteString(mr._texture.Name + "-surface");
                                        }
                                        writer.WriteEndElement(); //source
                                        writer.WriteStartElement("instance_image");
                                        writer.WriteAttributeString("url", "#" + mr._texture.Name + "-image");
                                        writer.WriteEndElement(); //instance_image
                                        string wrap = "WRAP";
                                        writer.WriteStartElement("wrap_s");
                                        switch (mr._uWrap)
                                        {
                                            case 0:
                                                wrap = "CLAMP";
                                                break;
                                            case 1:
                                                wrap = "WRAP";
                                                break;
                                            case 2:
                                                wrap = "MIRROR";
                                                break;
                                        }
                                        writer.WriteString(wrap);
                                        writer.WriteEndElement(); //wrap_s
                                        wrap = "REPEAT";
                                        writer.WriteStartElement("wrap_t");
                                        switch (mr._vWrap)
                                        {
                                            case 0:
                                                wrap = "CLAMP";
                                                break;
                                            case 1:
                                                wrap = "WRAP";
                                                break;
                                            case 2:
                                                wrap = "MIRROR";
                                                break;
                                        }
                                        writer.WriteString(wrap);
                                        writer.WriteEndElement(); //wrap_t
                                        writer.WriteStartElement("minfilter");
                                        writer.WriteString(mr.MinFilter.ToString().ToUpper());
                                        writer.WriteEndElement(); //minfilter
                                        writer.WriteStartElement("magfilter");
                                        writer.WriteString(mr.MagFilter.ToString().ToUpper());
                                        writer.WriteEndElement(); //magfilter
                                    }
                                    writer.WriteEndElement(); //sampler2D
                                }
                                writer.WriteEndElement(); //newparam
                            }
                        }
                        writer.WriteStartElement("technique");
                        writer.WriteAttributeString("sid", "COMMON");
                        {
                            writer.WriteStartElement("phong");
                            {
                                writer.WriteStartElement("diffuse");
                                {
                                    if (mat.Children.Count > 0)
                                    {
                                        MDL0MaterialRefNode mr = mat.Children[0] as MDL0MaterialRefNode;
                                        if (mr._texture != null)
                                        {
                                            writer.WriteStartElement("texture");
                                            {
                                                writer.WriteAttributeString("texture", mr._texture.Name + "-sampler");
                                                writer.WriteAttributeString("texcoord", "TEXCOORD" + (mr.TextureCoordId < 0 ? 0 : mr.TextureCoordId));
                                            }
                                            writer.WriteEndElement(); //texture
                                        }
                                    }
                                    else
                                    {

                                    }
                                }
                                writer.WriteEndElement(); //diffuse
                            }
                            writer.WriteEndElement(); //phong
                        }
                        writer.WriteEndElement(); //technique
                    }
                    writer.WriteEndElement(); //profile
                }
                writer.WriteEndElement(); //effect
            }
            writer.WriteEndElement(); //library
        }
        private void ModelChanged(MDL0Node model)
        {
            if (model != null && !_targetModels.Contains(model))
                _targetModels.Add(model);

            if (_targetModel != null)
                _targetModel._isTargetModel = false;

            if (model == null)
                ModelPanel.RemoveTarget(_targetModel);

            if ((_targetModel = model) != null)
            {
                ModelPanel.AddTarget(_targetModel);
                leftPanel.VIS0Indices = _targetModel.VIS0Indices;
                _targetModel._isTargetModel = true;
                ResetVertexColors();
            }
            else
                models.SelectedIndex = 0;

            if (_resetCamera)
            {
                ModelPanel.ResetCamera();
                SetFrame(0);
            }
            else
                _resetCamera = true;

            leftPanel.Reset();
            rightPanel.Reset();

            if (TargetModelChanged != null)
                TargetModelChanged(this, null);

            _updating = true;
            if (_targetModel != null && !_editingAll)
                models.SelectedItem = _targetModel;
            _updating = false;

            if (_targetModel != null)
                RenderBones = _targetModel._renderBones;
        }
示例#31
0
        internal void Port(MDL0Node _targetModel, MDL0Node _extModel)
        {
            MDL0BoneNode  extBone;
            MDL0BoneNode  bone;
            KeyframeEntry kfe;
            float         difference = 0;

            foreach (CHR0EntryNode _target in Children)
            {
                extBone = (MDL0BoneNode)_extModel.FindChild(_target.Name, true);     //Get external model bone
                bone    = (MDL0BoneNode)_targetModel.FindChild(_target.Name, true);  //Get target model bone

                for (int x = 0; x < _target.FrameCount; x++)                         //Loop thru each frame
                {
                    for (int i = 0x13; i < 0x19; i++)                                //Loop thru trans
                    {
                        if ((kfe = _target.GetKeyframe((KeyFrameMode)i, x)) != null) //Check for a keyframe
                        {
                            if (bone != null && extBone != null)
                            {
                                switch (i)
                                {
                                //Translations
                                case 0x16:     //Trans X
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._x, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._x;
                                    }
                                    else if (bone._bindState.Translate._x < extBone._bindState.Translate._x)
                                    {
                                        kfe._value -= extBone._bindState.Translate._x - bone._bindState.Translate._x;
                                    }
                                    else if (bone._bindState.Translate._x > extBone._bindState.Translate._x)
                                    {
                                        kfe._value += bone._bindState.Translate._x - extBone._bindState.Translate._x;
                                    }
                                    break;

                                case 0x17:     //Trans Y
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._y, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._y;
                                    }
                                    else if (bone._bindState.Translate._y < extBone._bindState.Translate._y)
                                    {
                                        kfe._value -= extBone._bindState.Translate._y - bone._bindState.Translate._y;
                                    }
                                    else if (bone._bindState.Translate._y > extBone._bindState.Translate._y)
                                    {
                                        kfe._value += bone._bindState.Translate._y - extBone._bindState.Translate._y;
                                    }
                                    break;

                                case 0x18:     //Trans Z
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._z, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._z;
                                    }
                                    else if (bone._bindState.Translate._z < extBone._bindState.Translate._z)
                                    {
                                        kfe._value -= extBone._bindState.Translate._z - bone._bindState.Translate._z;
                                    }
                                    else if (bone._bindState.Translate._z > extBone._bindState.Translate._z)
                                    {
                                        kfe._value += bone._bindState.Translate._z - extBone._bindState.Translate._z;
                                    }
                                    break;

                                //Rotations
                                case 0x13:     //Rot X
                                    difference  = bone._bindState.Rotate._x - extBone._bindState.Rotate._x;
                                    kfe._value += difference;
                                    if (difference != 0)
                                    {
                                        FixChildren(bone, 0);
                                    }
                                    break;

                                case 0x14:     //Rot Y
                                    difference  = bone._bindState.Rotate._y - extBone._bindState.Rotate._y;
                                    kfe._value += difference;
                                    if (difference != 0)
                                    {
                                        FixChildren(bone, 1);
                                    }
                                    break;

                                case 0x15:     //Rot Z
                                    difference  = bone._bindState.Rotate._z - extBone._bindState.Rotate._z;
                                    kfe._value += difference;
                                    if (difference != 0)
                                    {
                                        FixChildren(bone, 2);
                                    }
                                    break;
                                }
                            }
                            if (kfe._value == float.NaN || kfe._value == float.PositiveInfinity || kfe._value == float.NegativeInfinity)
                            {
                                kfe.Remove();
                                _target.Keyframes._keyCounts[i]--;
                            }
                        }
                    }
                }
            }
            _changed = true;
            IsPorted = true;
        }
        private void ModelChanged(MDL0Node model)
        {
            if (model != null && !_targetModels.Contains(model))
                _targetModels.Add(model);

            if (_targetModel != null)
                _targetModel._isTargetModel = false;

            if (_targetModel != null)
                modelPanel.RemoveTarget(_targetModel);

            if ((_targetModel = model) != null)
            {
                modelPanel.AddTarget(_targetModel);
                listPanel.VIS0Indices = _targetModel.VIS0Indices;
                _targetModel._isTargetModel = true;
                ResetVertexColors();
                hurtboxEditor._mainControl_TargetModelChanged(null, null);
            }

            if (_resetCam)
            {
                modelPanel.ResetCamera();
                RunTime.SetFrame(0);
            }
            else
                _resetCam = true;

            modelListsPanel1.Reset();

            //if (TargetModelChanged != null)
            //    TargetModelChanged(this, null);

            //_updating = true;
            //if (_targetModel != null && !_editingAll)
            //    comboCharacters.SelectedItem = _targetModel;
            //_updating = false;

            if (_targetModel != null)
                RenderBones = _targetModel._renderBones;
        }
示例#33
0
        public static unsafe void MDL02PMD(MDL0Node model)
        {
            _header = new ModelHeader();
            _header._modelName = model.Name;

            //To do: Add the ability to change the comment
            _header._comment = "MDL0 model converted to PMD by Brawlbox.";

            foreach (MDL0MaterialNode m in model._matList)
            {
                ModelMaterial mat = new ModelMaterial();
                mat._textureFileName = m.Children[0].Name;

            }

            _bones = new ModelBone[model._linker.BoneCache.Length];
            for (int i = 0; i < model._linker.BoneCache.Length; i++)
            {
                ModelBone bone = new ModelBone();
                MDL0BoneNode mBone = (MDL0BoneNode)model._linker.BoneCache[i];

                Vector3 wPos = mBone._bindMatrix.GetPoint();
                bone._wPos[0] = wPos._x;
                bone._wPos[1] = wPos._y;
                bone._wPos[2] = wPos._z;

                bone._boneName = mBone.Name;

                bone._boneType = 0;
                bone._parentBoneIndex = (ushort)model._linker.BoneCache.ToList<ResourceNode>().IndexOf(mBone.Parent);

                _bones[i] = bone;
            }
        }
 public DialogResult ShowDialog(MDL0Node model)
 {
     return ShowDialog(null, model);
 }
示例#35
0
 public static void Export(MDL0Node model, string filename)
 {
     filename = Path.GetFullPath(filename);
     using (FileStream fs = new FileStream(filename, FileMode.Create))
     {
         BinaryWriter writer = new BinaryWriter(fs);
         writer.Write(PMDModel.encoder.GetBytes("Pmd"));
         writer.Write(1.0f); //Version
         PMDModel.MDL02PMD(model);
         PMDModel.Write(writer);
         fs.Close();
     }
 }
        public void Port(MDL0Node _targetModel, MDL0Node _extModel)
        {
            MDL0BoneNode  extBone;
            MDL0BoneNode  bone;
            KeyframeEntry kfe;
            float         difference = 0;

            foreach (CHR0EntryNode _target in Children)
            {
                extBone = (MDL0BoneNode)_extModel.FindChild(_target.Name, true);    //Get external model bone
                bone    = (MDL0BoneNode)_targetModel.FindChild(_target.Name, true); //Get target model bone

                for (int x = 0; x < _target.FrameCount; x++)
                {
                    for (int i = 3; i < 9; i++)
                    {
                        if ((kfe = _target.GetKeyframe(i, x)) != null) //Check for a keyframe
                        {
                            if (bone != null && extBone != null)
                            {
                                switch (i)
                                {
                                //Translations
                                case 6:     //Trans X
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._x, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._x;
                                    }
                                    else if (bone._bindState.Translate._x < extBone._bindState.Translate._x)
                                    {
                                        kfe._value -= extBone._bindState.Translate._x - bone._bindState.Translate._x;
                                    }
                                    else if (bone._bindState.Translate._x > extBone._bindState.Translate._x)
                                    {
                                        kfe._value += bone._bindState.Translate._x - extBone._bindState.Translate._x;
                                    }
                                    break;

                                case 7:     //Trans Y
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._y, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._y;
                                    }
                                    else if (bone._bindState.Translate._y < extBone._bindState.Translate._y)
                                    {
                                        kfe._value -= extBone._bindState.Translate._y - bone._bindState.Translate._y;
                                    }
                                    else if (bone._bindState.Translate._y > extBone._bindState.Translate._y)
                                    {
                                        kfe._value += bone._bindState.Translate._y - extBone._bindState.Translate._y;
                                    }
                                    break;

                                case 8:     //Trans Z
                                    if (Math.Round(kfe._value, 4) == Math.Round(extBone._bindState.Translate._z, 4))
                                    {
                                        kfe._value = bone._bindState.Translate._z;
                                    }
                                    else if (bone._bindState.Translate._z < extBone._bindState.Translate._z)
                                    {
                                        kfe._value -= extBone._bindState.Translate._z - bone._bindState.Translate._z;
                                    }
                                    else if (bone._bindState.Translate._z > extBone._bindState.Translate._z)
                                    {
                                        kfe._value += bone._bindState.Translate._z - extBone._bindState.Translate._z;
                                    }
                                    break;

                                    //Rotations
                                    //case 3: //Rot X
                                    //    difference = bone._bindState.Rotate._x - extBone._bindState.Rotate._x;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 0);
                                    //    break;
                                    //case 4: //Rot Y
                                    //    difference = bone._bindState.Rotate._y - extBone._bindState.Rotate._y;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 1);
                                    //    break;
                                    //case 5: //Rot Z
                                    //    difference = bone._bindState.Rotate._z - extBone._bindState.Rotate._z;
                                    //    kfe._value += difference;
                                    //    //if (difference != 0)
                                    //    //    FixChildren(bone, 2);
                                    //    break;
                                }
                            }
                            if (kfe._value == float.NaN || kfe._value == float.PositiveInfinity || kfe._value == float.NegativeInfinity)
                            {
                                kfe.Remove();
                                _target.Keyframes._keyArrays[i]._keyCount--;
                            }
                        }
                    }
                }
            }
            _changed = true;
        }
示例#37
0
        public void Port(MDL0Node baseModel)
        {
            MDL0Node model;

            OpenFileDialog dlgOpen = new OpenFileDialog();
            dlgOpen.Filter = "MDL0 Model (*.mdl0)|*.mdl0";
            dlgOpen.Title = "Select the model this animation is for...";

            if (dlgOpen.ShowDialog() == DialogResult.OK)
                if ((model = (MDL0Node)NodeFactory.FromFile(null, dlgOpen.FileName)) != null)
                    Port(baseModel, model);
        }
示例#38
0
        internal void Parse(MDL0Node model)
        {
            Influence   inf;
            ModelLinker linker = model._linker;

            switch (_type)
            {
            case MDLResourceType.Definitions:
                if (linker.Defs != null)
                {
                    ExtractGroup(linker.Defs, typeof(MDL0DefNode));
                }
                break;

            case MDLResourceType.Bones:
                //Break if there are no bones defined
                if (linker.Bones == null)
                {
                    break;
                }

                //Parse bones from raw data (flat list).
                //Bones re-assign parents in their Initialize block, so parents are true.
                ExtractGroup(linker.Bones, typeof(MDL0BoneNode));

                //Cache flat list
                linker.BoneCache = _children.ToArray();

                //Make sure the node cache is the correct size
                int highest = 0;
                foreach (MDL0BoneNode b in _children)
                {
                    if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest)
                    {
                        highest = b._nodeIndex;
                    }
                }
                if (highest >= linker.NodeCache.Length)
                {
                    linker.NodeCache = new IMatrixNode[highest + 1];
                }

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

                //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;
                }

                //Now that bones and primary influences have been cached, we can create weighted influences.
                foreach (ResourcePair p in *linker.Defs)
                {
                    if (p.Name == "NodeTree")
                    {
                        //Use node tree to rebuild bone heirarchy
                        byte *pData = (byte *)p.Data;

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

                            if (bone.Header->_parentOffset == 0)
                            {
                                _children.Add(bone);
                            }
                            else
                            {
                                (bone._parent = linker.NodeCache[index] as ResourceNode)._children.Add(bone);
                            }

                            pData += 5;
                            goto Top;
                        }
                    }
                    else if (p.Name == "NodeMix")
                    {
                        //Use node mix to create weight groups
                        byte *pData = (byte *)p.Data;

Top:
                        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(count);
                            //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.
                            for (int i = 0; i < count; i++, nEntry++)
                            {
                                if ((linker.NodeCache[nEntry->_id] as MDL0BoneNode) == null)
                                {
                                    Console.WriteLine("Null bone entry!");
                                }
                                else
                                {
                                    inf._weights[i] = new BoneWeight(linker.NodeCache[nEntry->_id] as MDL0BoneNode, nEntry->_value);
                                }
                            }

                            //Add influence to model object, while adding it to the cache.
                            linker.NodeCache[index] = model._influences.AddOrCreate(inf);

                            //Move data pointer to next entry
                            pData = (byte *)nEntry;
                            goto Top;

                        //Type 5 is for primary influences
                        case 5:
                            pData += 5;
                            goto Top;
                        }
                    }
                }
                int z = 0;
                foreach (IMatrixNode m in linker.NodeCache)
                {
                    if (!m.IsPrimaryNode)
                    {
                        ((Influence)m)._permanentID = z; break;
                    }
                    z++;
                }
                break;

            case MDLResourceType.Materials:
                if (linker.Materials != null)
                {
                    ExtractGroup(linker.Materials, typeof(MDL0MaterialNode));
                }
                break;

            case MDLResourceType.Shaders:
                if (linker.Shaders != null)
                {
                    ExtractGroup(linker.Shaders, typeof(MDL0ShaderNode));
                }
                break;

            case MDLResourceType.Vertices:
                if (linker.Vertices != null)
                {
                    ExtractGroup(linker.Vertices, typeof(MDL0VertexNode));
                }
                break;

            case MDLResourceType.Normals:
                if (linker.Normals != null)
                {
                    ExtractGroup(linker.Normals, typeof(MDL0NormalNode));
                }
                break;

            case MDLResourceType.UVs:
                if (linker.UVs != null)
                {
                    ExtractGroup(linker.UVs, typeof(MDL0UVNode));
                }
                break;

            case MDLResourceType.Objects:
                //Break if no polygons defined
                if (linker.Polygons == null)
                {
                    break;
                }

                //Extract
                ExtractGroup(linker.Polygons, typeof(MDL0PolygonNode));

                //Attach materials to polygons.
                //This assumes that materials have already been parsed.

                List <ResourceNode> matList = ((MDL0Node)_parent)._matList;
                MDL0PolygonNode     poly;
                MDL0MaterialNode    mat;

                //Find DrawOpa or DrawXlu entry in Definition list
                foreach (ResourcePair p in *linker.Defs)
                {
                    if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu"))
                    {
                        ushort dIndex = 0;
                        byte * pData  = (byte *)p.Data;
                        while (*pData++ == 4)
                        {
                            //Get polygon from index
                            dIndex = *(bushort *)(pData + 2);
                            if (dIndex >= _children.Count || dIndex < 0)
                            {
                                ((MDL0Node)Parent)._errors.Add("Object index was greater than the actual object count.");
                                SignalPropertyChange();
                                dIndex = 0;
                            }
                            poly = _children[dIndex] as MDL0PolygonNode;
                            //Get material from index
                            mat = matList[*(bushort *)pData] as MDL0MaterialNode;
                            //Get bone from index and assign
                            int boneIndex = *(bushort *)(pData + 4);
                            if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length)
                            {
                                poly.BoneNode = linker.BoneCache[boneIndex] as MDL0BoneNode;
                            }
                            //Assign material to polygon and add polygon to material reference list
                            (poly._material = mat)._polygons.Add(poly);
                            //Increment pointer
                            pData += 7;
                        }
                    }
                }
                break;

            case MDLResourceType.Colors:
                if (linker.Colors != null)
                {
                    ExtractGroup(linker.Colors, typeof(MDL0ColorNode));
                }
                break;

            case MDLResourceType.Textures:
                if (linker.Textures != null)
                {
                    ExtractGroup(linker.Textures, typeof(MDL0TextureNode));
                }
                break;

            case MDLResourceType.Palettes:
                if (linker.Palettes != null)
                {
                    ExtractGroup(linker.Palettes, typeof(MDL0TextureNode));
                }
                break;
            }
        }
        internal void Parse(MDL0Node model)
        {
            Influence inf;
            ModelLinker linker = model._linker;
            switch (_type)
            {
                case MDLResourceType.Definitions:
                    if (linker.Defs != null)
                        ExtractGroup(linker.Defs, typeof(MDL0DefNode));
                    break;

                case MDLResourceType.Bones:
                    //Break if there are no bones defined
                    if (linker.Bones == null)
                        break;

                    //Parse bones from raw data (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.
                    ExtractGroup(linker.Bones, typeof(MDL0BoneNode));

                    //Cache flat list
                    linker.BoneCache = _children.ToArray();

                    //Make sure the node cache is the correct size
                    int highest = 0;
                    foreach (MDL0BoneNode b in linker.BoneCache)
                        if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest)
                            highest = b._nodeIndex;
                    if (highest >= linker.NodeCache.Length)
                        linker.NodeCache = new IMatrixNode[highest + 1];

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

                    //Assign children using each bones' parent offset in case NodeTree is corrupted
                    foreach (MDL0BoneNode b in linker.BoneCache)
                        b._parent._children.Add(b);

                    //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;

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

                                if (bone.Header->_parentOffset == 0)
                                {
                                    if (!_children.Contains(bone))
                                    {
                                        nodeTreeError = true;
                                        continue;
                                    }
                                }
                                else
                                {
                                    ResourceNode n = linker.NodeCache[index] as ResourceNode;
                                    if (n == null || bone._parent != n || !n._children.Contains(bone))
                                    {
                                        nodeTreeError = true;
                                        continue;
                                    }
                                }
                                pData += 5;
                                goto Top;
                            }
                        }
                        else
                            if (p.Name == "NodeMix")
                        {
                            //Use node mix to create weight groups
                            byte* pData = (byte*)p.Data;

                        Top:
                            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._weights.Add(new BoneWeight(b, nEntry->_value));
                                        else
                                        {
                                            nullIndices.Add(i);
                                            nullCount++;
                                        }

                                    bool d = false;
                                    if (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)
                                            d = true;
                                        else
                                            inf._weights = newWeights;
                                    }

                                    //Add influence to model object, while adding it to the cache.
                                    if (!d) ((Influence)(linker.NodeCache[index] = model._influences.FindOrCreate(inf, true)))._index = index;

                                    //Move data pointer to next entry
                                    pData = (byte*)nEntry;
                                    goto Top;

                                //Type 5 is for primary influences
                                case 5:
                                    pData += 5;
                                    goto Top;
                            }
                        }

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

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

                    break;

                case MDLResourceType.Materials:
                    if (linker.Materials != null)
                        ExtractGroup(linker.Materials, typeof(MDL0MaterialNode));
                    break;

                case MDLResourceType.Shaders:
                    if (linker.Shaders != null)
                        ExtractGroup(linker.Shaders, typeof(MDL0ShaderNode));
                    break;

                case MDLResourceType.Vertices:
                    if (linker.Vertices != null)
                        ExtractGroup(linker.Vertices, typeof(MDL0VertexNode));
                    break;

                case MDLResourceType.Normals:
                    if (linker.Normals != null)
                        ExtractGroup(linker.Normals, typeof(MDL0NormalNode));
                    break;

                case MDLResourceType.UVs:
                    if (linker.UVs != null)
                        ExtractGroup(linker.UVs, typeof(MDL0UVNode));
                    break;

                case MDLResourceType.FurLayerCoords:
                    if (linker.FurLayerCoords != null)
                        ExtractGroup(linker.FurLayerCoords, typeof(MDL0FurPosNode));
                    break;

                case MDLResourceType.FurVectors:
                    if (linker.FurVectors != null)
                        ExtractGroup(linker.FurVectors, typeof(MDL0FurVecNode));
                    break;

                case MDLResourceType.Objects:
                    //Break if no polygons defined
                    if (linker.Polygons == null)
                        break;

                    //Extract
                    ExtractGroup(linker.Polygons, typeof(MDL0ObjectNode));

                    //Attach materials to polygons.
                    //This assumes that materials have already been parsed.

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

                    //Find DrawOpa or DrawXlu entry in Definition list
                    foreach (ResourcePair p in *linker.Defs)
                        if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu"))
                        {
                            bool opa = p.Name == "DrawOpa";
                            ushort dIndex = 0;
                            byte* pData = (byte*)p.Data;
                            while (*pData++ == 4)
                            {
                                //Get polygon from index
                                dIndex = *(bushort*)(pData + 2);
                                if (dIndex >= _children.Count || dIndex < 0)
                                {
                                    model._errors.Add("Object index was greater than the actual object count.");
                                    SignalPropertyChange();
                                    dIndex = 0;
                                }
                                poly = _children[dIndex] as MDL0ObjectNode;
                                poly._drawIndex = pData[6];
                                //Get material from index
                                mat = matList[*(bushort*)pData] as MDL0MaterialNode;
                                //Get bone from index and assign
                                int boneIndex = *(bushort*)(pData + 4);
                                if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length)
                                    poly.BoneNode = linker.BoneCache[boneIndex] as MDL0BoneNode;
                                //Assign material to polygon
                                if (opa)
                                    poly.OpaMaterialNode = mat;
                                else
                                    poly.XluMaterialNode = mat;
                                //Increment pointer
                                pData += 7;
                            }
                        }

                    foreach (MDL0ObjectNode m in _children)
                    {
                        int max = Maths.Max(
                        m.OpaMaterialNode != null ? m.OpaMaterialNode.Children.Count : 0,
                        m.XluMaterialNode != null ? m.XluMaterialNode.Children.Count : 0,
                        m.OpaMaterialNode != null && m.OpaMaterialNode.MetalMaterial != null ? m.OpaMaterialNode.MetalMaterial.Children.Count : 0,
                        m.XluMaterialNode != null && m.XluMaterialNode.MetalMaterial != null ? m.XluMaterialNode.MetalMaterial.Children.Count : 0);

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

                        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();
                        }
                    }
                    break;

                case MDLResourceType.Colors:
                    if (linker.Colors != null)
                        ExtractGroup(linker.Colors, typeof(MDL0ColorNode));
                    break;

                case MDLResourceType.Textures:
                    if (linker.Textures != null)
                        ExtractGroup(linker.Textures, typeof(MDL0TextureNode));
                    break;

                case MDLResourceType.Palettes:
                    if (linker.Palettes != null)
                        ExtractGroup(linker.Palettes, typeof(MDL0TextureNode));
                    break;
            }
        }
        public MDL0Node ImportModel(string filePath)
        {
            MDL0Node model = new MDL0Node() { _name = Path.GetFileNameWithoutExtension(filePath) };
            model.InitGroups();
            if (_importOptions._setOrigPath)
                model._originalPath = filePath;

            //Parse the collada file and use the data to create an MDL0
            using (DecoderShell shell = DecoderShell.Import(filePath))
            try
            {
                model._version = _importOptions._modelVersion;

                Error = "There was a problem reading the model.";

                //Extract images, removing duplicates
                foreach (ImageEntry img in shell._images)
                {
                    string name;
                    MDL0TextureNode tex;

                    if (img._path != null)
                        name = Path.GetFileNameWithoutExtension(img._path);
                    else
                        name = img._name != null ? img._name : img._id;

                    tex = model.FindOrCreateTexture(name);
                    img._node = tex;
                }

                //Extract materials and create shaders
                int tempNo = -1;
                foreach (MaterialEntry mat in shell._materials)
                {
                    tempNo += 1;
                    MDL0MaterialNode matNode = new MDL0MaterialNode();

                    matNode._parent = model._matGroup;
                    matNode._name = mat._name != null ? mat._name : mat._id;

                    if (tempNo == 0)
                    {
                        MDL0ShaderNode shadNode = new MDL0ShaderNode();
                        shadNode._parent = model._shadGroup;
                        shadNode._name = "Shader" + tempNo;
                        model._shadList.Add(shadNode);
                    }
                    matNode.Shader = "Shader0";
                    matNode.ShaderNode = (MDL0ShaderNode)model._shadGroup.Children[0];

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

                    //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)
                                                {
                                                    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._index1 = mr._index2 = mr.Index;
                                                    mr._uWrap = mr._vWrap = (int)_importOptions._wrap;
                                                    break;
                                                }
                                        }

                    matNode._numTextures = (byte)matNode.Children.Count;
                    model._matList.Add(matNode);
                }

                Say("Extracting scenes...");

                //Extract scenes
                foreach (SceneEntry scene in shell._scenes)
                {
                    //Parse joints first
                    NodeEntry[] joints = scene._nodes.Where(x => x._type == NodeType.JOINT).ToArray();
                    NodeEntry[] nodes = scene._nodes.Where(x => x._type != NodeType.JOINT).ToArray();
                    foreach (NodeEntry node in joints)
                        EnumNode(node, model._boneGroup, scene, model, shell);
                    foreach (NodeEntry node in nodes)
                        EnumNode(node, model._boneGroup, scene, model, shell);
                }

                //If there are no bones, rig all objects to a single bind.
                if (model._boneGroup._children.Count == 0)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        MDL0BoneNode bone = new MDL0BoneNode();
                        bone.Scale = new Vector3(1);

                        bone._bindMatrix =
                        bone._inverseBindMatrix =
                        Matrix.Identity;

                        switch (i)
                        {
                            case 0:
                                bone._name = "TopN";
                                model._boneGroup._children.Add(bone);
                                bone._parent = model._boneGroup;
                                break;
                            case 1:
                                bone._name = "TransN";
                                model._boneGroup._children[0]._children.Add(bone);
                                bone._parent = model._boneGroup._children[0];
                                bone.ReferenceCount = model._objList.Count;
                                break;
                        }
                    }
                    if (model._objList != null && model._objList.Count != 0)
                        foreach (MDL0ObjectNode poly in model._objList)
                        {
                            poly._nodeId = 0;
                            poly.MatrixNode = (MDL0BoneNode)model._boneGroup._children[0]._children[0];
                        }
                }
                else
                {
                    //Check each polygon to see if it can be rigged to a single influence
                    if (model._objList != null && model._objList.Count != 0)
                        foreach (MDL0ObjectNode p in model._objList)
                        {
                            IMatrixNode node = null;
                            bool singlebind = true;

                            foreach (Vertex3 v in p._manager._vertices)
                                if (v._matrixNode != null)
                                {
                                    if (node == null)
                                        node = v._matrixNode;

                                    if (v._matrixNode != node)
                                    {
                                        singlebind = false;
                                        break;
                                    }
                                }

                            if (singlebind && p._matrixNode == null)
                            {
                                //Increase reference count ahead of time for rebuild
                                if (p._manager._vertices[0]._matrixNode != null)
                                    p._manager._vertices[0]._matrixNode.ReferenceCount++;

                                foreach (Vertex3 v in p._manager._vertices)
                                    if (v._matrixNode != null)
                                        v._matrixNode.ReferenceCount--;

                                p._nodeId = -2; //Continued on polygon rebuild
                            }
                        }
                }

                //Remove original color buffers if option set
                if (_importOptions._ignoreColors)
                {
                    if (model._objList != null && model._objList.Count != 0)
                        foreach (MDL0ObjectNode p in model._objList)
                            for (int x = 2; x < 4; x++)
                                if (p._manager._faceData[x] != null)
                                {
                                    p._manager._faceData[x].Dispose();
                                    p._manager._faceData[x] = null;
                                }
                }

                //Add color buffers if option set
                if (_importOptions._addClrs)
                {
                    RGBAPixel pixel = _importOptions._dfltClr;

                    //Add a color buffer to objects that don't have one
                    if (model._objList != null && model._objList.Count != 0)
                        foreach (MDL0ObjectNode p in model._objList)
                            if (p._manager._faceData[2] == null)
                            {
                                RGBAPixel* pIn = (RGBAPixel*)(p._manager._faceData[2] = new UnsafeBuffer(4 * p._manager._pointCount)).Address;
                                for (int i = 0; i < p._manager._pointCount; i++)
                                    *pIn++ = pixel;
                            }
                }

                //Apply defaults to materials
                if (model._matList != null)
                    foreach (MDL0MaterialNode p in model._matList)
                    {
                        if (_importOptions._mdlType == 0)
                        {
                            p._lSet = 20;
                            p._fSet = 4;
                            p._ssc = 3;

                            p.C1ColorEnabled = true;
                            p.C1AlphaMaterialSource = GXColorSrc.Vertex;
                            p.C1ColorMaterialSource = GXColorSrc.Vertex;
                            p.C1ColorDiffuseFunction = GXDiffuseFn.Clamped;
                            p.C1ColorAttenuation = GXAttnFn.Spotlight;
                            p.C1AlphaEnabled = true;
                            p.C1AlphaDiffuseFunction = GXDiffuseFn.Clamped;
                            p.C1AlphaAttenuation = GXAttnFn.Spotlight;

                            p.C2ColorDiffuseFunction = GXDiffuseFn.Disabled;
                            p.C2ColorAttenuation = GXAttnFn.None;
                            p.C2AlphaDiffuseFunction = GXDiffuseFn.Disabled;
                            p.C2AlphaAttenuation = GXAttnFn.None;
                        }
                        else
                        {
                            p._lSet = 0;
                            p._fSet = 0;
                            p._ssc = 1;

                            p._chan1.Color = new LightChannelControl(1795);
                            p._chan1.Alpha = new LightChannelControl(1795);
                            p._chan2.Color = new LightChannelControl(1795);
                            p._chan2.Alpha = new LightChannelControl(1795);
                        }
                    }

                //Set materials to use register color if option set
                if (_importOptions._useReg && model._objList != null)
                    foreach (MDL0ObjectNode p in model._objList)
                    {
                        MDL0MaterialNode m = p.OpaMaterialNode;
                        if (m != null && p._manager._faceData[2] == null && p._manager._faceData[3] == null)
                        {
                            m.C1MaterialColor = _importOptions._dfltClr;
                            m.C1ColorMaterialSource = GXColorSrc.Register;
                            m.C1AlphaMaterialSource = GXColorSrc.Register;
                        }
                    }

                //Remap materials if option set
                if (_importOptions._rmpMats && model._matList != null && model._objList != null)
                {
                    foreach (MDL0ObjectNode p in model._objList)
                        foreach (MDL0MaterialNode m in model._matList)
                            if (m.Children.Count > 0 &&
                                m.Children[0] != null &&
                                p.OpaMaterialNode != null &&
                                p.OpaMaterialNode.Children.Count > 0 &&
                                p.OpaMaterialNode.Children[0] != null &&
                                m.Children[0].Name == p.OpaMaterialNode.Children[0].Name &&
                                m.C1ColorMaterialSource == p.OpaMaterialNode.C1ColorMaterialSource)
                            {
                                p.OpaMaterialNode = m;
                                break;
                            }

                    //Remove unused materials
                    for (int i = 0; i < model._matList.Count; i++)
                        if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0)
                            model._matList.RemoveAt(i--);
                }

                Error = "There was a problem writing the model.";

                //Clean the model and then build it!
                if (model != null)
                {
                    model.CleanGroups();
                    model.BuildFromScratch(this);
                }
            }
            catch (Exception x)
            {
                MessageBox.Show("Cannot continue importing this model.\n" + Error + "\n\nException:\n" + x.ToString());
                model = null;
                Close();
            }
            finally
            {
                //Clean up the mess we've made
                GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            }
            return model;
        }