private static Mesh LoadXbfObject(XbfObject xbfObject, XbfShader shader, IReadOnlyList <int> textures) { var allVertices = new Dictionary <int, List <VertexPositionNormalUv> >(); var allIndices = new Dictionary <int, List <ShaderIndex> >(); foreach (var triangle in xbfObject.Triangles) { if (triangle.Texture == -1) { continue; } if (!allVertices.ContainsKey(triangle.Texture)) { allVertices.Add(triangle.Texture, new List <VertexPositionNormalUv>()); allIndices.Add(triangle.Texture, new List <ShaderIndex>()); } var vertices = allVertices[triangle.Texture]; var indices = allIndices[triangle.Texture]; for (var i = 0; i < 3; i++) { vertices.Add( new VertexPositionNormalUv( XbfMesh.Convert(xbfObject.Vertices[triangle.Vertices[i]].Position), XbfMesh.Convert(xbfObject.Vertices[triangle.Vertices[i]].Normal), XbfMesh.Convert(triangle.Uv[i]) * new Vector2(1, -1) ) ); } indices.Add(new ShaderIndex(vertices.Count - 3, vertices.Count - 2, vertices.Count - 1)); } return(new Mesh(null, null, null) { Name = xbfObject.Name, Transform = XbfMesh.Convert(xbfObject.Transform), TransformAnimation = xbfObject.ObjectAnimation != null && xbfObject.ObjectAnimation.Frames.Count > 0 ? XbfMesh.BuildAnimation(xbfObject.ObjectAnimation) : null, Children = allVertices.Keys .Select( texture => new Mesh( new XbfShader.XbfShaderParameters(shader) { Texture = textures[texture] }, allVertices[texture].Select(vertex => vertex.Pack()).SelectMany(v => v).ToArray(), allIndices[texture].Select(index => index.Pack()).SelectMany(i => i).ToArray() ) ) .Concat(xbfObject.Children.Select(childXbfObject => XbfMesh.LoadXbfObject(childXbfObject, shader, textures))) .ToArray(), }); }
private static Matrix4[] BuildAnimation(XbfObjectAnimation xbfObjectAnimation) { var frames = new Matrix4[xbfObjectAnimation.Length]; var first = xbfObjectAnimation.Frames.Keys.Min(); var last = xbfObjectAnimation.Frames.Keys.Max(); var lastFrame = 0; for (var i = 0; i < xbfObjectAnimation.Length; i++) { if (!xbfObjectAnimation.Frames.ContainsKey(i)) { continue; } frames[i] = XbfMesh.Convert(xbfObjectAnimation.Frames[i]); if (i == first) { for (var j = 0; j < i; j++) { frames[j] = frames[i]; } } else if (i > last) { frames[i] = frames[last]; } else { for (; lastFrame + 1 < i; lastFrame++) { frames[lastFrame + 1] = frames[lastFrame] + (frames[i] - frames[lastFrame]) * (1f / (i - lastFrame)); } } lastFrame = i; } return(frames); }