예제 #1
0
        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);
        }
예제 #2
0
        public static void AssignParent(MDL0BoneNode pBone, ModelBone child, MDL0BoneNode cBone, ModelBone parent)
        {
            if (pBone._entryIndex == child._parentBoneIndex)
            {
                //Link child to its parent
                (cBone._parent = pBone)._children.Add(cBone);

                //Convert the world point into a local point relative to the bone's parent
                Matrix m = (Matrix.TranslationMatrix(child._wPos) * Matrix.Invert(Matrix.TranslationMatrix(parent._wPos)));

                //Derive to state and recalc bind matrices
                cBone._bindState = m.Derive();
                cBone.RecalcBindState();
            }
            else //Parent not found, continue searching children.
                foreach (MDL0BoneNode pMatch in pBone._children)
                    AssignParent(pMatch, child, cBone, parent);
        }
        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);
                }
            }
        }