Exemplo n.º 1
0
        public override IResource create(ResourceManager mgr)
        {
            IQModelLoader loader = new IQModelLoader(mgr);
            SkinnedModel  m      = loader.loadFromFile(Path.Combine(path, (string)descriptor["file"]));

            if (m == null)
            {
                return(null);
            }

            JsonObject initTransform = descriptor["initialTransform"];

            if (initTransform != null)
            {
                Vector3 pos   = (Vector3)initTransform["translate"];
                Vector3 rot   = (Vector3)initTransform["rotate"];
                Vector3 scale = (Vector3)initTransform["scale"];

                Matrix4 ori = new Matrix4();
                ori = ori.fromHeadingPitchRoll(rot.X, rot.Y, rot.Z);

                m.myInitialTransform = Matrix4.CreateScale(scale) * ori * Matrix4.CreateTranslation(pos);
            }

            return(m);
        }
Exemplo n.º 2
0
        public override IResource create(ResourceManager mgr)
        {
            BobSkinnedModelLoader loader = new BobSkinnedModelLoader(mgr);
            SkinnedModel          m      = loader.loadFromFile(name);

            return(m);
        }
Exemplo n.º 3
0
        public override IResource create(ResourceManager mgr)
        {
            MS3DModelLoader loader = new MS3DModelLoader(mgr);
            SkinnedModel    m      = loader.loadFromFile(Path.Combine(path, (string)descriptor["file"]));

            if (m == null)
            {
                return(null);
            }

            JsonObject initTransform = descriptor["initialTransform"];

            if (initTransform != null)
            {
                Vector3 pos   = (Vector3)initTransform["translate"];
                Vector3 rot   = (Vector3)initTransform["rotate"];
                Vector3 scale = (Vector3)initTransform["scale"];

                Matrix4 ori = new Matrix4();
                ori = ori.fromHeadingPitchRoll(rot.X, rot.Y, rot.Z);

                m.myInitialTransform = Matrix4.CreateScale(scale) * ori * Matrix4.CreateTranslation(pos);
            }

            JsonObject animations = descriptor["animations"];

            for (int i = 0; i < animations.count(); i++)
            {
                JsonObject ani = animations[i];
                m.animations.Add((string)ani["name"], new Animation((string)ani["name"], (int)ani["start"], (int)ani["end"], loader.fps, (bool)ani["loop"]));
            }

            return(m);
        }
Exemplo n.º 4
0
        Model loadModel(Bob.ModelChunk mc)
        {
            Model model = null;

            if (mc.animated == true)
            {
                model = new SkinnedModel();
            }
            else
            {
                model = new Model();
            }

            loadMaterials(model, mc);
            loadVerts(model, mc);
            loadIndexes(model, mc);
            loadMeshes(model, mc);
            model.size = findSize(mc);

            return(model);
        }
Exemplo n.º 5
0
        public SkinnedModel loadFromFile(string filename)
        {
            Info.print("Loading IQM model {0}", filename);

            if (File.Exists(filename) == false)
            {
                Warn.print("Cannot find file {0}", filename);
                return(null);
            }

            V3N3T2B4W4[] vertexData;
            ushort[]     triangleIndexes;

            IQMHeader myHeader;

            byte[]        myTexts;
            List <String> myComments = new List <String>();

            iqmvertexarray[] myVertArrays;
            iqmjoint[]       myJoints;
            iqmpose[]        myPoses;
            iqmanim[]        myAnimataions;
            iqmbounds[]      myBounds;
            iqmmesh[]        meshData;
            ushort[]         myFrameData;

            SkinnedModel sm = new SkinnedModel();

            System.IO.FileStream   stream = null;
            System.IO.BinaryReader reader = null;
            try
            {
                // Open the specified file as a stream and create a reader
                stream = new System.IO.FileStream(filename, FileMode.Open, FileAccess.Read);
                reader = new System.IO.BinaryReader(stream);

                myHeader.magic   = reader.ReadChars(16);
                myHeader.version = reader.ReadUInt32();
                if (myHeader.version != 2)
                {
                    return(null);
                }
                myHeader.filesize          = reader.ReadUInt32();
                myHeader.flags             = reader.ReadUInt32();
                myHeader.num_text          = reader.ReadUInt32();
                myHeader.ofs_text          = reader.ReadUInt32();
                myHeader.num_meshes        = reader.ReadUInt32();
                myHeader.ofs_meshes        = reader.ReadUInt32();
                myHeader.num_vertexarrays  = reader.ReadUInt32();
                myHeader.num_vertexes      = reader.ReadUInt32();
                myHeader.ofs_vertexarrays  = reader.ReadUInt32();
                myHeader.num_triangles     = reader.ReadUInt32();
                myHeader.ofs_triangles     = reader.ReadUInt32();
                myHeader.ofs_adjacency     = reader.ReadUInt32();
                myHeader.num_joints        = reader.ReadUInt32();
                myHeader.ofs_joints        = reader.ReadUInt32();
                myHeader.num_poses         = reader.ReadUInt32();
                myHeader.ofs_poses         = reader.ReadUInt32();
                myHeader.num_anims         = reader.ReadUInt32();
                myHeader.ofs_anims         = reader.ReadUInt32();
                myHeader.num_frames        = reader.ReadUInt32();
                myHeader.num_framechannels = reader.ReadUInt32();
                myHeader.ofs_frames        = reader.ReadUInt32();
                myHeader.ofs_bounds        = reader.ReadUInt32();
                myHeader.num_comment       = reader.ReadUInt32();
                myHeader.ofs_comment       = reader.ReadUInt32();
                myHeader.num_extensions    = reader.ReadUInt32();
                myHeader.ofs_extensions    = reader.ReadUInt32();

                boneCount = (int)myHeader.num_joints;

                //read text
                myTexts = new byte[myHeader.num_text];
                stream.Seek(myHeader.ofs_text, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_text; i++)
                {
                    myTexts[i] = reader.ReadByte();
                }

                #region read geometry

                //create geometry fields
                for (int m = 0; m < myHeader.num_meshes; m++)
                {
                    sm.myMeshes.Add(new Mesh());
                }

                //read the mesh data
                meshData = new iqmmesh[myHeader.num_meshes];
                stream.Seek(myHeader.ofs_meshes, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_meshes; i++)
                {
                    iqmmesh temp = new iqmmesh();
                    UInt32  n    = reader.ReadUInt32();
                    temp.name     = readNullTerminated(myTexts, n);
                    n             = reader.ReadUInt32();
                    temp.material = readNullTerminated(myTexts, n);
                    String fn = System.IO.Path.GetFileName(temp.material);
                    fn = System.IO.Path.ChangeExtension(fn, ".png");

                    String dir = System.IO.Path.GetDirectoryName(filename);
                    fn = System.IO.Path.Combine(dir, fn);

                    TextureDescriptor td  = new TextureDescriptor(fn);
                    Texture           tex = myResourceManager.getResource(td) as Texture;
                    Material          m   = new Material(temp.material);
                    m.addAttribute(new TextureAttribute("diffuseMap", tex));
                    m.myFeatures |= Material.Feature.Lighting;
                    m.myFeatures |= Material.Feature.DiffuseMap;

                    sm.myMeshes[i].material = m;

                    temp.first_vertex   = reader.ReadUInt32();
                    temp.num_vertexes   = reader.ReadUInt32();
                    temp.first_triangle = reader.ReadUInt32();
                    temp.num_triangles  = reader.ReadUInt32();
                    meshData[i]         = temp;
                }

                //read vertex arrays
                myVertArrays = new iqmvertexarray[myHeader.num_vertexarrays];
                stream.Seek(myHeader.ofs_vertexarrays, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_vertexarrays; i++)
                {
                    iqmvertexarray temp = new iqmvertexarray();
                    temp.type       = (VertexArrayType)reader.ReadUInt32();
                    temp.flags      = reader.ReadUInt32();
                    temp.format     = (VertexArrayFormat)reader.ReadUInt32();
                    temp.size       = reader.ReadUInt32();
                    temp.offset     = reader.ReadUInt32();
                    myVertArrays[i] = temp;
                }

                //read the vertex data
                vertexData = new V3N3T2B4W4[myHeader.num_vertexes];
                for (int i = 0; i < myHeader.num_vertexarrays; i++)
                {
                    iqmvertexarray va = myVertArrays[i];
                    switch (va.type)
                    {
                    case VertexArrayType.IQM_POSITION:
                    {
                        stream.Seek(va.offset, SeekOrigin.Begin);
                        for (int j = 0; j < myHeader.num_vertexes; j++)
                        {
                            Vector3 temp = new Vector3();
                            temp.X = reader.ReadSingle();
                            temp.Y = reader.ReadSingle();
                            temp.Z = reader.ReadSingle();
                            vertexData[j].Position = temp;
                        }
                        break;
                    }

                    case VertexArrayType.IQM_TEXCOORD:
                    {
                        stream.Seek(va.offset, SeekOrigin.Begin);
                        for (int j = 0; j < myHeader.num_vertexes; j++)
                        {
                            Vector2 temp = new Vector2();
                            temp.X = reader.ReadSingle();
                            temp.Y = reader.ReadSingle();
                            vertexData[j].TexCoord = temp;
                        }
                        break;
                    }

                    case VertexArrayType.IQM_NORMAL:
                    {
                        stream.Seek(va.offset, SeekOrigin.Begin);
                        for (int j = 0; j < myHeader.num_vertexes; j++)
                        {
                            Vector3 temp = new Vector3();
                            temp.X = reader.ReadSingle();
                            temp.Y = reader.ReadSingle();
                            temp.Z = reader.ReadSingle();
                            vertexData[j].Normal = temp;
                        }
                        break;
                    }

                    case VertexArrayType.IQM_BLENDINDEXES:
                    {
                        stream.Seek(va.offset, SeekOrigin.Begin);
                        for (int j = 0; j < myHeader.num_vertexes; j++)
                        {
                            Vector4 temp = new Vector4();
                            temp.X = (float)reader.ReadByte();
                            temp.Y = (float)reader.ReadByte();
                            temp.Z = (float)reader.ReadByte();
                            temp.W = (float)reader.ReadByte();
                            vertexData[j].BoneId = temp;
                        }
                        break;
                    }

                    case VertexArrayType.IQM_BLENDWEIGHTS:
                    {
                        stream.Seek(va.offset, SeekOrigin.Begin);
                        for (int j = 0; j < myHeader.num_vertexes; j++)
                        {
                            Vector4 temp = new Vector4();
                            temp.X = ((float)reader.ReadByte()) / 255.0f;
                            temp.Y = ((float)reader.ReadByte()) / 255.0f;
                            temp.Z = ((float)reader.ReadByte()) / 255.0f;
                            temp.W = ((float)reader.ReadByte()) / 255.0f;
                            vertexData[j].BoneWeight = temp;
                        }
                        break;
                    }
                    }
                }

                //read triangles indexes
                triangleIndexes = new ushort[myHeader.num_triangles * 3];
                stream.Seek(myHeader.ofs_triangles, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_triangles * 3; i++)
                {
                    triangleIndexes[i] = (ushort)reader.ReadUInt32();
                }
                #endregion

                #region read animation data
                //read joints
                myJoints = new iqmjoint[myHeader.num_joints];
                stream.Seek(myHeader.ofs_joints, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_joints; i++)
                {
                    iqmjoint temp = new iqmjoint();
                    UInt32   n    = reader.ReadUInt32();
                    temp.name        = readNullTerminated(myTexts, n);
                    temp.parent      = reader.ReadInt32();
                    temp.translate   = new Vector3();
                    temp.translate.X = reader.ReadSingle();
                    temp.translate.Y = reader.ReadSingle();
                    temp.translate.Z = reader.ReadSingle();
                    temp.rotate      = new Quaternion();
                    temp.rotate.X    = reader.ReadSingle();
                    temp.rotate.Y    = reader.ReadSingle();
                    temp.rotate.Z    = reader.ReadSingle();
                    temp.rotate.W    = reader.ReadSingle();
                    temp.rotate.Normalize();
                    temp.scale   = new Vector3();
                    temp.scale.X = reader.ReadSingle();
                    temp.scale.Y = reader.ReadSingle();
                    temp.scale.Z = reader.ReadSingle();
                    myJoints[i]  = temp;
                }

                //read poses
                myPoses = new iqmpose[myHeader.num_poses];
                stream.Seek(myHeader.ofs_poses, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_poses; i++)
                {
                    iqmpose temp = new iqmpose();
                    temp.parent      = reader.ReadInt32();
                    temp.channelmask = reader.ReadUInt32();

                    temp.channeloffset = new float[10];
                    for (int j = 0; j < 10; j++)
                    {
                        temp.channeloffset[j] = reader.ReadSingle();
                    }

                    temp.channelscale = new float[10];
                    for (int j = 0; j < 10; j++)
                    {
                        temp.channelscale[j] = reader.ReadSingle();
                    }

                    myPoses[i] = temp;
                }

                //read animations
                myAnimataions = new iqmanim[myHeader.num_anims];
                stream.Seek(myHeader.ofs_anims, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_anims; i++)
                {
                    iqmanim temp = new iqmanim();
                    UInt32  n    = reader.ReadUInt32();
                    temp.name        = readNullTerminated(myTexts, n);
                    temp.first_frame = reader.ReadUInt32();
                    temp.num_frames  = reader.ReadUInt32();
                    temp.framerate   = reader.ReadSingle();
                    temp.flags       = reader.ReadUInt32();
                    myAnimataions[i] = temp;


                    Animation a = new Animation();
                    a.name = temp.name;
                    a.fps  = temp.framerate;
                    a.loop = true;
                    sm.animations.Add(a.name, a);
                }

                //read frame data
                myFrameData = new ushort[myHeader.num_frames * myHeader.num_framechannels];
                stream.Seek(myHeader.ofs_frames, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_frames * myHeader.num_framechannels; i++)
                {
                    myFrameData[i] = reader.ReadUInt16();
                }

                #endregion

                //read bounds
                myBounds = new iqmbounds[myHeader.num_frames];
                stream.Seek(myHeader.ofs_bounds, SeekOrigin.Begin);
                for (int i = 0; i < myHeader.num_frames; i++)
                {
                    iqmbounds temp = new iqmbounds();
                    temp.bbmins    = new float[3];
                    temp.bbmaxs    = new float[3];
                    temp.bbmins[0] = reader.ReadSingle();
                    temp.bbmins[1] = reader.ReadSingle();
                    temp.bbmins[2] = reader.ReadSingle();
                    temp.bbmaxs[0] = reader.ReadSingle();
                    temp.bbmaxs[1] = reader.ReadSingle();
                    temp.bbmaxs[2] = reader.ReadSingle();
                    temp.xyradius  = reader.ReadSingle();
                    temp.radius    = reader.ReadSingle();

                    if (i == 0)
                    {
                        sm.size = temp.radius;
                    }
                }

                //read comments
                stream.Seek(myHeader.ofs_comment, SeekOrigin.Begin);
                int charRead = 0;
                while (charRead < myHeader.num_comment)
                {
                    char   c = reader.ReadChar(); charRead++;
                    string s = "";
                    while (c != '\0')
                    {
                        s += c;
                        c  = reader.ReadChar(); charRead++;
                    }

                    myComments.Add(s);
                }

                //read extensions
                //TODO

                //setup the bone data
                Matrix4[] baseframe        = new Matrix4[myHeader.num_joints];
                Matrix4[] inversebaseframe = new Matrix4[myHeader.num_joints];
                for (int i = 0; i < (int)myHeader.num_joints; i++)
                {
                    iqmjoint joint = myJoints[i];
                    Matrix4  r, t, s;
                    r                   = Matrix4.CreateFromQuaternion(joint.rotate);
                    t                   = Matrix4.CreateTranslation(joint.translate);
                    s                   = Matrix4.CreateScale(joint.scale);
                    baseframe[i]        = s * r * t;
                    inversebaseframe[i] = baseframe[i].Inverted();
                    if (joint.parent >= 0)
                    {
                        baseframe[i]        = baseframe[i] * baseframe[joint.parent];
                        inversebaseframe[i] = inversebaseframe[joint.parent] * inversebaseframe[i];
                    }

                    Bone b = new Bone();
                    b.myName            = myJoints[i].name;
                    b.myParent          = myJoints[i].parent;
                    b.myWorldBindMatrix = baseframe[i];
                    sm.skeleton.myBones.Add(b);
                }

                Matrix4[] absMatrix = new Matrix4[myHeader.num_frames * myHeader.num_poses];
                int       count     = 0;
                for (int i = 0; i < myHeader.num_frames; i++)
                {
                    for (int j = 0; j < myHeader.num_poses; j++)
                    {
                        iqmpose    p         = myPoses[j];
                        Quaternion rotate    = new Quaternion();
                        Vector3    translate = new Vector3();
                        Vector3    scale     = new Vector3();
                        translate.X = p.channeloffset[0]; if ((p.channelmask & 0x01) != 0)
                        {
                            translate.X += myFrameData[count++] * p.channelscale[0];
                        }
                        translate.Y = p.channeloffset[1]; if ((p.channelmask & 0x02) != 0)
                        {
                            translate.Y += myFrameData[count++] * p.channelscale[1];
                        }
                        translate.Z = p.channeloffset[2]; if ((p.channelmask & 0x04) != 0)
                        {
                            translate.Z += myFrameData[count++] * p.channelscale[2];
                        }
                        rotate.X = p.channeloffset[3]; if ((p.channelmask & 0x08) != 0)
                        {
                            rotate.X += myFrameData[count++] * p.channelscale[3];
                        }
                        rotate.Y = p.channeloffset[4]; if ((p.channelmask & 0x10) != 0)
                        {
                            rotate.Y += myFrameData[count++] * p.channelscale[4];
                        }
                        rotate.Z = p.channeloffset[5]; if ((p.channelmask & 0x20) != 0)
                        {
                            rotate.Z += myFrameData[count++] * p.channelscale[5];
                        }
                        rotate.W = p.channeloffset[6]; if ((p.channelmask & 0x40) != 0)
                        {
                            rotate.W += myFrameData[count++] * p.channelscale[6];
                        }
                        scale.X = p.channeloffset[7]; if ((p.channelmask & 0x80) != 0)
                        {
                            scale.X += myFrameData[count++] * p.channelscale[7];
                        }
                        scale.Y = p.channeloffset[8]; if ((p.channelmask & 0x100) != 0)
                        {
                            scale.Y += myFrameData[count++] * p.channelscale[8];
                        }
                        scale.Z = p.channeloffset[9]; if ((p.channelmask & 0x200) != 0)
                        {
                            scale.Z += myFrameData[count++] * p.channelscale[9];
                        }
                        // Concatenate each pose with the inverse base pose to avoid doing this at animation time.
                        // If the joint has a parent, then it needs to be pre-concatenated with its parent's base pose.
                        // Thus it all negates at animation time like so:
                        //   (parentPose * parentInverseBasePose) * (parentBasePose * childPose * childInverseBasePose) =>
                        //   parentPose * (parentInverseBasePose * parentBasePose) * childPose * childInverseBasePose =>
                        //   parentPose * childPose * childInverseBasePose
                        rotate.Normalize();
                        Matrix4 r, t, s;
                        r = Matrix4.CreateFromQuaternion(rotate);
                        t = Matrix4.CreateTranslation(translate);
                        s = Matrix4.CreateScale(scale);
                        Matrix4 pose = s * r * t;
                        if (p.parent >= 0)
                        {
                            Matrix4 parent     = baseframe[p.parent];
                            Matrix4 inv        = inversebaseframe[j];
                            Matrix4 parentPose = absMatrix[i * myHeader.num_poses + p.parent];
                            absMatrix[i * myHeader.num_poses + j] = inv * pose * parent * parentPose;
                        }
                        else
                        {
                            Matrix4 inv = inversebaseframe[j];
                            absMatrix[i * myHeader.num_poses + j] = inv * pose;
                        }
                    }
                }

                Vector4[] boneData = new Vector4[myHeader.num_frames * myHeader.num_poses * 4];
                int       next     = 0;
                for (int i = 0; i < myHeader.num_frames * myHeader.num_poses; i++)
                {
                    boneData[next++] = absMatrix[i].Row0;
                    boneData[next++] = absMatrix[i].Row1;
                    boneData[next++] = absMatrix[i].Row2;
                    boneData[next++] = absMatrix[i].Row3;
                }

                //setup the buffers
                sm.myBindings = V3N3T2B4W4.bindings();
                VertexBufferObject vbo = new VertexBufferObject(BufferUsageHint.StaticDraw);
                vbo.setData(vertexData);
                sm.myVbos.Add(vbo);

                List <ushort> indexes    = new List <ushort>();
                int           indexCount = 0;
                for (int m = 0; m < sm.myMeshes.Count; m++)
                {
                    Mesh mesh = sm.myMeshes[m];
                    mesh.primativeType = PrimitiveType.Triangles;
                    mesh.indexBase     = indexCount;

                    for (int t = 0; t < meshData[m].num_triangles; t++)
                    {
                        //swap the order the indicies since we want counter clockwise triangles instead of clockwise
                        indexes.Add(triangleIndexes[meshData[m].first_triangle * 3 + (t * 3) + 0]);
                        indexes.Add(triangleIndexes[meshData[m].first_triangle * 3 + (t * 3) + 2]);
                        indexes.Add(triangleIndexes[meshData[m].first_triangle * 3 + (t * 3) + 1]);
                        indexCount += 3;
                    }

                    mesh.indexCount = indexCount - mesh.indexBase;
                }

                sm.myIbo.setData(indexes);

                //upload the frame data
                sm.myFrames.setData(boneData);

                return(sm);
            }
            catch (Exception ex)
            {
                throw new Exception("Error while loading IQM model from definition file ( " + filename + " ).", ex);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                }
            }
        }
Exemplo n.º 6
0
        SkinnedModel bufferData()
        {
            SkinnedModel sm = new SkinnedModel();

            //just the first group at this time
            int vertCount = 0;

            for (int g = 0; g < msGroups.Length; g++)
            {
                vertCount += msGroups[g].numTriangles * 3;
            }

            V3N3T2B4W4[] verts    = new V3N3T2B4W4[vertCount];
            ushort[]     indexes  = new ushort[vertCount];
            Vector4[]    boneData = new Vector4[msJointCount * msTotalFrames * 4]; //store an absolute matrix for each bone for each frame

            int next = 0;

            for (int g = 0; g < msGroups.Length; g++)
            {
                Mesh m = new Mesh();
                m.indexBase = next;
                for (int t = 0; t < msGroups[g].numTriangles; t++)
                {
                    MilkshapeTriangle tri = msTris[msGroups[g].triangleIndexs[t]];
                    for (int v = 0; v < 3; v++)
                    {
                        verts[next].Position = msVerts[tri.vertexIndex[v]].vertex;
                        verts[next].Normal   = tri.vertexNormals[v];
                        verts[next].TexCoord = tri.uvs[v];

                        //this format only uses 1 bone per vertex, but my vertex format allows for up to 4
                        verts[next].BoneId.X     = msVerts[tri.vertexIndex[v]].boneId;
                        verts[next].BoneId.Y     = -1;
                        verts[next].BoneId.Z     = -1;
                        verts[next].BoneId.W     = -1;
                        verts[next].BoneWeight.X = 1.0f; //only 1 bone influences the mesh
                        verts[next].BoneWeight.Y = 0.0f;
                        verts[next].BoneWeight.Z = 0.0f;
                        verts[next].BoneWeight.W = 0.0f;

                        indexes[next] = (ushort)next;
                        next++;
                    }
                }
                m.indexCount = msGroups[g].numTriangles * 3;
                m.material   = myMaterials[msGroups[g].materialIndex];
                sm.myMeshes.Add(m);
            }

            //prep the bone data
            next = 0;
            for (int f = 0; f < msTotalFrames; f++)
            {
                //get the joints as an absolute matrix
                Matrix4[] absMat = getJoints(f);

                for (int j = 0; j < msJointCount; j++)
                {
                    boneData[next++] = absMat[j].Row0;
                    boneData[next++] = absMat[j].Row1;
                    boneData[next++] = absMat[j].Row2;
                    boneData[next++] = absMat[j].Row3;
                }
            }

            sm.myVbo.setData(verts);
            sm.myIbo.setData(indexes);
            sm.myFrames.setData(boneData);
            sm.boneCount = boneCount;

            return(sm);
        }
Exemplo n.º 7
0
        public SkinnedModel loadFromFile(string path)
        {
            Info.print("Loading MS3D model {0}", path);

            if (File.Exists(path) == false)
            {
                Warn.print("Cannot find file {0}", path);
                return(null);
            }

            FileStream   stream = null;
            BinaryReader reader = null;

            try
            {
                myFilename = path;
                // Open the specified file as a stream.
                stream = new FileStream(path, FileMode.Open, FileAccess.Read);

                // Pipe the stream in to a binary reader so we can work at the byte-by-byte level.
                reader = new BinaryReader(stream);

                //load the header
                msHeader         = new MilkshapeHeader();
                msHeader.id      = reader.ReadChars(10);
                msHeader.version = reader.ReadInt32();

                //check if the header is ok
                //string magic = "MS3D000000".ToString();
                if (msHeader.id.ToString() == "MS3D000000")
                {
                    Warn.print("{0} is not a valid Milkshape file", path);
                    return(null);
                }
                if (msHeader.version != 4)
                {
                    Warn.print("{0} is not a valid Milkshape file", path);
                    return(null);
                }

                #region "read the verts"
                //read the verts
                msVertCount = reader.ReadUInt16();
                msVerts     = new MilkshapeVertex[msVertCount];
                for (int i = 0; i < msVertCount; i++)
                {
                    msVerts[i].flags          = reader.ReadByte();
                    msVerts[i].vertex.X       = reader.ReadSingle();
                    msVerts[i].vertex.Y       = reader.ReadSingle();
                    msVerts[i].vertex.Z       = reader.ReadSingle();
                    msVerts[i].boneId         = reader.ReadSByte();
                    msVerts[i].referenceCount = reader.ReadByte();
                }
                #endregion

                #region "read the tris"
                //read the tris
                msTriCount = reader.ReadUInt16();
                msTris     = new MilkshapeTriangle[msTriCount];
                for (int i = 0; i < msTriCount; i++)
                {
                    msTris[i].flags          = reader.ReadUInt16();
                    msTris[i].vertexIndex    = new int[3];
                    msTris[i].vertexIndex[0] = reader.ReadUInt16();
                    msTris[i].vertexIndex[1] = reader.ReadUInt16();
                    msTris[i].vertexIndex[2] = reader.ReadUInt16();

                    msTris[i].vertexNormals      = new Vector3[3];
                    msTris[i].vertexNormals[0].X = reader.ReadSingle();
                    msTris[i].vertexNormals[0].Y = reader.ReadSingle();
                    msTris[i].vertexNormals[0].Z = reader.ReadSingle();

                    msTris[i].vertexNormals[1].X = reader.ReadSingle();
                    msTris[i].vertexNormals[1].Y = reader.ReadSingle();
                    msTris[i].vertexNormals[1].Z = reader.ReadSingle();

                    msTris[i].vertexNormals[2].X = reader.ReadSingle();
                    msTris[i].vertexNormals[2].Y = reader.ReadSingle();
                    msTris[i].vertexNormals[2].Z = reader.ReadSingle();

                    //not sure why its stored this way, but it's their format
                    msTris[i].uvs            = new Vector2[3];
                    msTris[i].uvs[0].X       = reader.ReadSingle();
                    msTris[i].uvs[1].X       = reader.ReadSingle();
                    msTris[i].uvs[2].X       = reader.ReadSingle();
                    msTris[i].uvs[0].Y       = reader.ReadSingle();
                    msTris[i].uvs[1].Y       = reader.ReadSingle();
                    msTris[i].uvs[2].Y       = reader.ReadSingle();
                    msTris[i].smoothingGroup = reader.ReadByte();
                    msTris[i].groupIndex     = reader.ReadByte();
                }
                #endregion

                #region "read the groups"
                //read the meshes or groups
                msGroupCount = reader.ReadUInt16();
                msGroups     = new MilkshapeGroup[msGroupCount];
                for (int i = 0; i < msGroupCount; i++)
                {
                    msGroups[i].flags = reader.ReadByte();
                    byte[] n   = reader.ReadBytes(32);
                    int    idx = Array.FindIndex(n, 0, item => item == '\0');
                    msGroups[i].name           = System.Text.Encoding.ASCII.GetString(n, 0, idx);;
                    msGroups[i].numTriangles   = reader.ReadUInt16();
                    msGroups[i].triangleIndexs = new int[msGroups[i].numTriangles];
                    for (int j = 0; j < msGroups[i].numTriangles; j++)
                    {
                        msGroups[i].triangleIndexs[j] = reader.ReadUInt16();
                    }
                    msGroups[i].materialIndex = reader.ReadSByte();
                }
                #endregion

                #region "read the materials"
                //read the materials
                msMaterialCount = reader.ReadUInt16();
                msMaterials     = new MilkshapeMaterial[msMaterialCount];
                for (int i = 0; i < msMaterialCount; i++)
                {
                    byte[] n       = reader.ReadBytes(32);
                    int    idx     = Array.FindIndex(n, 0, item => item == '\0');
                    String matName = System.Text.Encoding.ASCII.GetString(n, 0, idx);
                    System.Console.WriteLine("Found Material: {0}", matName);
                    Material m   = new Material(myFilename + "/" + matName);
                    Color4   amb = new Color4();
                    amb.R     = reader.ReadSingle();
                    amb.G     = reader.ReadSingle();
                    amb.B     = reader.ReadSingle();
                    amb.A     = reader.ReadSingle();
                    m.ambient = amb;

                    Color4 dif = new Color4();
                    dif.R     = reader.ReadSingle();
                    dif.G     = reader.ReadSingle();
                    dif.B     = reader.ReadSingle();
                    dif.A     = reader.ReadSingle();
                    m.diffuse = dif;

                    Color4 spec = new Color4();
                    spec.R = reader.ReadSingle();
                    spec.G = reader.ReadSingle();
                    spec.B = reader.ReadSingle();
                    spec.A = reader.ReadSingle();
                    m.spec = spec;

                    Color4 emmit = new Color4();
                    emmit.R    = reader.ReadSingle();
                    emmit.G    = reader.ReadSingle();
                    emmit.B    = reader.ReadSingle();
                    emmit.A    = reader.ReadSingle();
                    m.emission = emmit;

                    m.shininess = reader.ReadSingle();
                    m.alpha     = reader.ReadSingle();

                    //if the alpha channel is used for something other than alpha
                    int mode = reader.ReadByte();

                    n   = reader.ReadBytes(128);
                    idx = Array.FindIndex(n, 0, item => item == '\0');
                    String diffuseMapName = System.Text.Encoding.ASCII.GetString(n, 0, idx);
                    if (diffuseMapName != "")
                    {
                        Texture diffText = findTexture(diffuseMapName);
                        if (diffText != null)
                        {
                            m.addAttribute(new TextureAttribute("diffuseMap", diffText));
                        }
                    }

                    n   = reader.ReadBytes(128);
                    idx = Array.FindIndex(n, 0, item => item == '\0');
                    String alphaMapName = System.Text.Encoding.ASCII.GetString(n, 0, idx);
                    if (alphaMapName != "")
                    {
                        Texture alphaText = findTexture(alphaMapName);
                        if (alphaText != null)
                        {
                            m.addAttribute(new TextureAttribute("alphaTexture", alphaText));
                        }
                    }

                    myMaterials.Add(m);
                }
                #endregion

                #region "read animation data"

                fps = reader.ReadSingle();
                float currentTime = reader.ReadSingle();
                msTotalFrames = reader.ReadInt32();


                #endregion

                #region "read the joints"
                //read the joints
                msJointCount = reader.ReadUInt16();
                boneCount    = msJointCount;
                msJoints     = new MilkshapeJoint[msJointCount];
                for (int i = 0; i < msJointCount; i++)
                {
                    msJoints[i].flags = reader.ReadByte();
                    byte[] n   = reader.ReadBytes(32);
                    int    idx = Array.FindIndex(n, 0, item => item == '\0');
                    msJoints[i].name = System.Text.Encoding.ASCII.GetString(n, 0, idx);;
                    n   = reader.ReadBytes(32);
                    idx = Array.FindIndex(n, 0, item => item == '\0');
                    msJoints[i].parentName           = System.Text.Encoding.ASCII.GetString(n, 0, idx);
                    msJoints[i].rotation.X           = reader.ReadSingle();
                    msJoints[i].rotation.Y           = reader.ReadSingle();
                    msJoints[i].rotation.Z           = reader.ReadSingle();
                    msJoints[i].position.X           = reader.ReadSingle();
                    msJoints[i].position.Y           = reader.ReadSingle();
                    msJoints[i].position.Z           = reader.ReadSingle();
                    msJoints[i].numRotationKeyframes = reader.ReadUInt16();
                    msJoints[i].numPositionKeyframes = reader.ReadUInt16();
                    msJoints[i].rotationKeyframes    = new MilkshapeKeyframe[msJoints[i].numRotationKeyframes];
                    msJoints[i].translationKeyframes = new MilkshapeKeyframe[msJoints[i].numPositionKeyframes];
                    for (int j = 0; j < msJoints[i].numRotationKeyframes; j++)
                    {
                        msJoints[i].rotationKeyframes[j].time    = reader.ReadSingle();
                        msJoints[i].rotationKeyframes[j].param.X = reader.ReadSingle();
                        msJoints[i].rotationKeyframes[j].param.Y = reader.ReadSingle();
                        msJoints[i].rotationKeyframes[j].param.Z = reader.ReadSingle();
                    }
                    for (int j = 0; j < msJoints[i].numPositionKeyframes; j++)
                    {
                        msJoints[i].translationKeyframes[j].time    = reader.ReadSingle();
                        msJoints[i].translationKeyframes[j].param.X = reader.ReadSingle();
                        msJoints[i].translationKeyframes[j].param.Y = reader.ReadSingle();
                        msJoints[i].translationKeyframes[j].param.Z = reader.ReadSingle();
                    }
                }

                //fixup parent indexes
                for (int i = 0; i < msJointCount; i++)
                {
                    if (msJoints[i].parentName != "")
                    {
                        //find the parent name
                        for (int j = 0; j < msJointCount; j++)
                        {
                            if (msJoints[j].name == msJoints[i].parentName)
                            {
                                msJoints[i].parentIndex = j;
                                break;
                            }
                        }
                    }
                    else
                    {
                        msJoints[i].parentIndex = -1;
                    }
                }

                #endregion

                #region "setup joints"

                for (int i = 0; i < msJoints.Length; i++)
                {
                    msJoints[i].local  = Matrix4.CreateRotationX(msJoints[i].rotation.X) * Matrix4.CreateRotationY(msJoints[i].rotation.Y) * Matrix4.CreateRotationZ(msJoints[i].rotation.Z);
                    msJoints[i].local *= Matrix4.CreateTranslation(msJoints[i].position);

                    if (msJoints[i].parentIndex == -1)
                    {
                        msJoints[i].absolute = msJoints[i].local;
                    }
                    else
                    {
                        msJoints[i].absolute = msJoints[msJoints[i].parentIndex].absolute * msJoints[i].local;
                    }


                    //initialize the final position of the joint to the default position
                    msJoints[i].final = msJoints[i].absolute;
                }

                #endregion

                #region "modifiy verticies"
                for (int i = 0; i < msVertCount; i++)
                {
                    if (msVerts[i].boneId != -1)
                    {
                        Matrix4 m   = msJoints[msVerts[i].boneId].absolute;
                        Matrix4 inv = Matrix4.Invert(m);
                        msVerts[i].vertex = Vector3.TransformPosition(msVerts[i].vertex, inv);
                    }
                }
                #endregion

                //push all the stuff onto the graphics card
                SkinnedModel sm = bufferData();
                sm.size = (findMax() - findMin()).Length / 2.0f;

                return(sm);
            }
            catch (Exception ex)
            {
                throw new Exception("Error while loading Milkshape model from definition file ( " + path + " ).", ex);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                }
            }
        }
Exemplo n.º 8
0
 public AnimationController(SkinnedModelRenderable renderable)
     : base(renderable, "animation")
 {
     myModel          = renderable.model as SkinnedModel;
     myAnimationState = myModel.createAnimationState("null");
 }