Beispiel #1
0
        void getVertexBoneData(Assimp.Mesh mesh)
        {
            int weightsPerVertex = 4;

            //we should set this once
            if (myModel.boneCount == 0)
            {
                myModel.boneCount = mesh.BoneCount;
                foreach (Bone b in mesh.Bones)
                {
                    if (boneNames.Contains(b.Name) == false)
                    {
                        boneNames.Add(b.Name);
                        bones.Add(toMatrix(b.OffsetMatrix));
                    }
                }
            }
            else
            {
                if (myModel.boneCount != mesh.BoneCount)
                {
                    Warn.print("Weird model.  Meshes have different bones");
                    throw new Exception("Weird Model");
                }
            }

            for (int i = 0; i < mesh.BoneCount; i++)
            {
                Bone b = mesh.Bones[i];

                if (b.HasVertexWeights == false)
                {
                    continue;
                }

                foreach (VertexWeight weight in b.VertexWeights)
                {
                    V3N3T2B4W4 vert = myVerts[weight.VertexID + currVertOffset];

                    //find the next available weight (if there is space)
                    for (int k = 0; k < weightsPerVertex; k++)
                    {
                        if (vert.BoneWeight[k] == 0.0f)
                        {
                            vert.BoneId[k]     = (float)i;
                            vert.BoneWeight[k] = weight.Weight;
                            break;
                        }
                    }

                    myVerts[weight.VertexID + currVertOffset] = vert;
                }
            }
        }
Beispiel #2
0
        public void loadVerts(BobModelChunk bmc)
        {
            for (int i = 0; i < bmc.vertexCount; i++)
            {
                V3N3T2B4W4 v = new V3N3T2B4W4();
                v.Position   = bmc.verts[i];
                v.Normal     = bmc.normals[i];
                v.TexCoord   = bmc.uvs[i];
                v.BoneId     = bmc.boneIdx[i];
                v.BoneWeight = bmc.boneWeights[i];
                myVerts.Add(v);
            }

            myModel.myVbo.setData(myVerts);
        }
Beispiel #3
0
        void loadVerts(Model m, Bob.ModelChunk bmc)
        {
            VertexBufferObject vbo = new VertexBufferObject(BufferUsageHint.StaticDraw);

            if (bmc.animated == false)
            {
                List <V3N3T2> verts = new List <V3N3T2>();
                for (int i = 0; i < bmc.vertexCount; i++)
                {
                    V3N3T2 v = new V3N3T2();
                    v.Position = bmc.verts[i];
                    v.Normal   = bmc.normals[i];
                    v.TexCoord = bmc.uvs[i];
                    verts.Add(v);
                }

                m.myBindings = V3N3T2.bindings();
                vbo.setData(verts);
            }
            else
            {
                List <V3N3T2B4W4> verts = new List <V3N3T2B4W4>();
                for (int i = 0; i < bmc.vertexCount; i++)
                {
                    V3N3T2B4W4 v = new V3N3T2B4W4();
                    v.Position   = bmc.verts[i];
                    v.Normal     = bmc.normals[i];
                    v.TexCoord   = bmc.uvs[i];
                    v.BoneId     = bmc.boneIdx[i];
                    v.BoneWeight = bmc.boneWeights[i];
                    verts.Add(v);
                }

                m.myBindings = V3N3T2B4W4.bindings();
                vbo.setData(verts);
            }

            m.myVbos.Add(vbo);
        }
        public SkinnedModel loadFromFile(string filename)
        {
            Info.print("Loading Assimp model {0}", filename);

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

            myRootPath = Path.GetDirectoryName(filename);
            try
            {
                myScene = theAssimpContext.ImportFile(filename, PostProcessSteps.Triangulate | PostProcessSteps.GenerateNormals);
                Node rootNode = myScene.RootNode;

                //load static meshes
                createMeshes(rootNode);
                loadBoneData();
                loadAnimationData();
            }
            catch
            {
                Warn.print("Failed to load model {0}", filename);
                return(null);
            }

            myModel.myBindings = V3N3T2B4W4.bindings();
            VertexBufferObject vbo = new VertexBufferObject(BufferUsageHint.StaticDraw);

            vbo.setData(myVerts);
            myModel.myVbos.Add(vbo);
            myModel.myIbo.setData(index);

            //should probably build a bounding box
            myModel.size = (findMax() - findMin()).Length / 2.0f;

            return(myModel);
        }
Beispiel #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();
                }
            }
        }
Beispiel #6
0
        void createMeshes(Node node)
        {
            if (node.HasMeshes)
            {
                foreach (int meshIndex in node.MeshIndices)
                {
                    Assimp.Mesh amesh = myScene.Meshes[meshIndex];

                    //create the material
                    Graphics.Material mat = createMaterial(myScene.Materials[amesh.MaterialIndex]);

                    //create the geometry
                    Graphics.Mesh mesh = new Graphics.Mesh();
                    mesh.primativeType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles;
                    mesh.indexBase     = currIndexOffset;
                    mesh.indexCount    = amesh.FaceCount * 3;
                    mesh.material      = mat;

                    //get the indices
                    foreach (Face face in amesh.Faces)
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            index.Add((UInt16)(face.Indices[i] + currVertOffset));
                            currIndexOffset++;
                        }
                    }

                    //get the verts
                    for (int i = 0; i < amesh.VertexCount; i++)
                    {
                        V3N3T2B4W4 v = new V3N3T2B4W4();
                        v.Position = toVector(amesh.Vertices[i]);

                        if (amesh.HasNormals == true)
                        {
                            v.Normal = toVector(amesh.Normals[i]);
                        }

                        if (amesh.HasTextureCoords(0) == true)
                        {
                            v.TexCoord = toVector2D(amesh.TextureCoordinateChannels[0][i]);
                        }

                        myVerts.Add(v);
                    }

                    //get the bone data
                    if (amesh.HasBones)
                    {
                        getVertexBoneData(amesh);
                    }

                    currVertOffset += amesh.VertexCount;

                    myModel.myMeshes.Add(mesh);
                }
            }

            if (node.HasChildren)
            {
                foreach (Node child in node.Children)
                {
                    createMeshes(child);
                }
            }
        }
Beispiel #7
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);
        }
Beispiel #8
0
        //public override void preparePerViewBegin(View v) { }
        //public override void preparePerView(Renderable r, View v) { }
        //public override void preparePerViewFinalize(View v) { }
        //public override void preparePerPassBegin(Pass p) { }
        //public override void preparePerPass(Renderable r, Pass p) { }

        public override void preparePerPass(Renderable r, Pass p)
        {
            SkinnedModelRenderable smr = r as SkinnedModelRenderable;


            SkinnedModelUniformData modelData = new SkinnedModelUniformData();

            modelData.modelMatrix  = smr.model.myInitialTransform * smr.modelMatrix;
            modelData.normalMatrix = (smr.model.myInitialTransform * smr.modelMatrix).ClearTranslation();
            //modelData.inverseNormalMatrix = modelData.normalMatrix.Inverted();
            modelData.activeLights = new Vector4(0, 1, 2, 3);
            modelData.boneCount    = smr.model.skeleton.boneCount;
            myModelData.Add(modelData);

            //save the index for this model
            int modelDataIndex = myModelData.Count - 1;

            foreach (Mesh mesh in smr.model.myMeshes)
            {
                MaterialEffect effect             = getEffect(p.technique, (UInt32)mesh.material.myFeatures);
                PipelineState  pipeline           = effect.createPipeline(mesh.material);
                RenderQueue <SkinnedModelInfo> rq = p.findRenderQueue(pipeline.id) as RenderQueue <SkinnedModelInfo>;
                if (rq == null)
                {
                    rq      = Renderer.device.createRenderQueue <SkinnedModelInfo>(effect.createPipeline(mesh.material));
                    rq.name = rq.myPipeline.shaderState.shaderProgram.name + "-" + (mesh.material.hasTransparency == true ? "transparent" : "opaque");
                    rq.myPipeline.vaoState.vao = new VertexArrayObject();
                    rq.myPipeline.vaoState.vao.bindVertexFormat(rq.myPipeline.shaderState.shaderProgram, V3N3T2B4W4.bindings());
                    rq.visualizer = this;
                    p.registerQueue(rq);
                }

                SkinnedModelInfo info = rq.nextInfo();

                effect.updateRenderState(mesh.material, info.renderState);

                float dist = (p.view.camera.position - r.position).Length;
                info.distToCamera = dist;

                info.indexCount  = mesh.indexCount;
                info.indexOffset = mesh.indexBase;

                info.renderState.setUniform(new UniformData(0, Uniform.UniformType.Int, modelDataIndex));
                info.renderState.setStorageBuffer(myModelBuffer.id, 0);
                info.renderState.setUniformBuffer(smr.mySkinningBuffer.id, 3);
                info.renderState.setVertexBuffer(smr.model.myVbos[0].id, 0, 0, V3N3T2B4W4.stride);
                info.renderState.setIndexBuffer(smr.model.myIbo.id);

                info.sortId = getSortId(info);
            }
        }