private IList <Object3D> Load(BinaryReader reader) { var name = reader.ReadCMO_wchar(); int numMaterials = (int)reader.ReadUInt32(); var materials = new List <Tuple <PhongMaterial, IList <string> > >(numMaterials); for (int i = 0; i < numMaterials; ++i) { var material = new PhongMaterial { Name = reader.ReadCMO_wchar(), AmbientColor = reader.ReadStructure <Color4>(), DiffuseColor = reader.ReadStructure <Color4>(), SpecularColor = reader.ReadStructure <Color4>(), SpecularShininess = reader.ReadSingle(), EmissiveColor = reader.ReadStructure <Color4>() }; var uvTransform = reader.ReadStructure <Matrix>(); if (uvTransform == Matrix.Zero) { uvTransform = Matrix.Identity; } uvTransform.Decompose(out var s, out var r, out var tra); material.UVTransform = new UVTransform(r.Angle, new Vector2(s.X, s.Y), new Vector2(tra.X, tra.Y)); var pixelShaderName = reader.ReadCMO_wchar();//Not used var textures = new List <string>(); for (int t = 0; t < MaxTextures; ++t) { textures.Add(reader.ReadCMO_wchar()); } materials.Add(new Tuple <PhongMaterial, IList <string> >(material, textures)); } // BYTE - 1 if there is skeletal animation data present // is there skeletal animation data present? bool isAnimationData = reader.ReadByte() == 1; // UINT - SubMesh count // { [SubMesh count] // SubMesh structure // } // load sub meshes if any var mesh = new MeshGeometry3D(); int subMeshCount = (int)reader.ReadUInt32(); var subMesh = new List <SubMesh>(subMeshCount); for (int i = 0; i < subMeshCount; i++) { subMesh.Add(reader.ReadStructure <SubMesh>()); } // UINT - IB Count // { [IB Count] // UINT - Number of USHORTs in IB // USHORT[] - Array of indices // } // load triangle indices int indexBufferCount = (int)reader.ReadUInt32(); var indices = new List <ushort[]>(indexBufferCount); for (var i = 0; i < indexBufferCount; i++) { indices.Add(reader.ReadUInt16((int)reader.ReadUInt32())); } // UINT - VB Count // { [VB Count] // UINT - Number of verts in VB // Vertex[] - Array of vertices // } // load vertex positions int vertexBufferCount = (int)reader.ReadUInt32(); var vertexBuffers = new List <Vertex[]>(vertexBufferCount); for (var i = 0; i < vertexBufferCount; i++) { vertexBuffers.Add(reader.ReadStructure <Vertex>((int)reader.ReadUInt32())); } // UINT - Skinning VB Count // { [Skinning VB Count] // UINT - Number of verts in Skinning VB // SkinningVertex[] - Array of skinning verts // } // load vertex skinning parameters int skinningVertexBufferCount = (int)reader.ReadUInt32(); var skinningVertexBuffers = new List <SkinningVertex[]>(skinningVertexBufferCount); for (var i = 0; i < skinningVertexBufferCount; i++) { skinningVertexBuffers.Add(reader.ReadStructure <SkinningVertex>((int)reader.ReadUInt32())); } // load mesh extent var extent = reader.ReadStructure <MeshExtent>(); var animationHierarchy = new AnimationHierarchy(); IList <string> boneNames = null; if (isAnimationData) { // UINT - Bone count // { [Bone count] // UINT - Length of bone name // wchar_t[] - Bone name (if length > 0) // Bone structure // } int boneCount = (int)reader.ReadUInt32(); boneNames = new string[boneCount]; for (var i = 0; i < boneCount; i++) { boneNames[i] = reader.ReadCMO_wchar(); animationHierarchy.Bones.Add(reader.ReadStructure <BoneStruct>()); } // UINT - Animation clip count // { [Animation clip count] // UINT - Length of clip name // wchar_t[] - Clip name (if length > 0) // float - Start time // float - End time // UINT - Keyframe count // { [Keyframe count] // Keyframe structure // } // } int animationCount = (int)reader.ReadUInt32(); for (var i = 0; i < animationCount; i++) { Animation animation = new Animation(AnimationType.Keyframe); string animationName = reader.ReadCMO_wchar(); animation.StartTime = reader.ReadSingle(); animation.EndTime = reader.ReadSingle(); animation.Name = animationName; int keyframeCount = (int)reader.ReadUInt32(); for (var j = 0; j < keyframeCount; j++) { var keyframe = reader.ReadStructure <KeyframeCMO>(); keyframe.Transform.Decompose(out var s, out var q, out var t); animation.Keyframes.Add(new Keyframe() { Translation = t, Rotation = q, Scale = s, Time = keyframe.Time }); } animationHierarchy.Animations.Add(animation.Name, animation); if (!UniqueAnimations.ContainsKey(animation.Name)) { UniqueAnimations.Add(animation.Name, new List <Guid>()); } UniqueAnimations[animation.Name].Add(animation.GUID); } } var obj3Ds = new List <Object3D>(subMeshCount); for (int i = 0; i < subMesh.Count; ++i) { var sub = subMesh[i]; var material = materials.Count == 0 ? new PhongMaterial() : materials[(int)sub.MaterialIndex].Item1; var vertexCollection = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Position)); var normal = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Normal)); var tex = new Vector2Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.UV)); var tangent = new Vector3Collection(vertexBuffers[(int)sub.VertexDataIndex].Select(x => x.Tangent.ToVector3())); var biTangent = new Vector3Collection(normal.Zip(tangent, (x, y) => { return(Vector3.Cross(x, y)); })); var indexCollection = new IntCollection(indices[(int)sub.IndexDataIndex].Select(x => (int)x)); var meshGeo = new MeshGeometry3D() { Positions = vertexCollection, Indices = indexCollection, Normals = normal, Tangents = tangent, BiTangents = biTangent, TextureCoordinates = tex }; if (isAnimationData) { var boneskinmesh = new BoneSkinnedMeshGeometry3D(meshGeo); boneskinmesh.VertexBoneIds = new List <BoneIds>(skinningVertexBuffers[(int)sub.VertexDataIndex] .Select(x => new BoneIds() { Bone1 = (int)x.BoneIndex0, Bone2 = (int)x.BoneIndex1, Bone3 = (int)x.BoneIndex2, Bone4 = (int)x.BoneIndex3, Weights = new Vector4(x.BoneWeight0, x.BoneWeight1, x.BoneWeight2, x.BoneWeight3), })); meshGeo = boneskinmesh; } //Todo Load textures obj3Ds.Add(new Object3D() { Geometry = meshGeo, Material = material, Name = name }); animationHierarchy.Meshes.Add(obj3Ds.Last()); } AnimationHierarchy.Add(animationHierarchy); return(obj3Ds); }