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(), }); }
public XbfMesh(AssetManager assetManager, IReadableFileSystem fileSystem, string path) { this.assetManager = assetManager; var xbf = new Xbf(fileSystem.Read(path) !); this.Name = Path.GetFileNameWithoutExtension(path); // TODO: Some textures are using additional flags by prefixing their filenames: // TODO: = => apply player color to 0000?? pixels // TODO: ! => render additive // TODO: % might be "" // TODO: @ might be "" this.Children = xbf.Objects.Select( xbfObject => XbfMesh.LoadXbfObject( xbfObject, this.assetManager.Load <XbfShader>(this), xbf.Textures.Select( name => { try { return(this.assetManager.Load <Texture>(this, $"Textures/{name}").Id); } catch (Exception) { return(this.assetManager.Load <Texture>(this, "Textures/white.tga").Id); } } ) .ToArray() ) ) .ToArray(); }