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); }
public override IResource create(ResourceManager mgr) { BobSkinnedModelLoader loader = new BobSkinnedModelLoader(mgr); SkinnedModel m = loader.loadFromFile(name); return(m); }
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); }
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); }
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(); } } }
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); }
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(); } } }
public AnimationController(SkinnedModelRenderable renderable) : base(renderable, "animation") { myModel = renderable.model as SkinnedModel; myAnimationState = myModel.createAnimationState("null"); }