public void Convert(ModelRoot gltf, PssgFile pssg) { // Get a list of nodes in the default scene as a flat list Dictionary <int, int> nodeBoneIndexMap = new Dictionary <int, int>(); var rootNode = gltf.DefaultScene.FindNode(n => n.Name.StartsWith("Scene Root")); if (rootNode is null) { throw new InvalidDataException("The default scene must have node name starting with `Scene Root`."); } // Determine libraries in which to store data var nodeLib = pssg.FindNodes("LIBRARY", "type", "NODE").First(); var rdsLib = pssg.FindNodes("LIBRARY", "type", "RENDERDATASOURCE").First(); var ribLib = pssg.FindNodes("LIBRARY", "type", "RENDERINTERFACEBOUND").First(); var state = new ImportState(ShaderInputInfo.CreateFromPssg(pssg).ToDictionary(si => si.ShaderGroupId)); // Clear out the libraries nodeLib.RemoveChildNodes(nodeLib.ChildNodes.Where(n => n.Name == "ROOTNODE")); rdsLib.RemoveChildNodes(rdsLib.ChildNodes.Where(n => n.Name == "RENDERDATASOURCE")); ribLib.RemoveChildNodes(ribLib.ChildNodes.Where(n => n.Name == "DATABLOCK")); // Write the scene graph, and collect mesh data ConvertSceneNodes(pssg, nodeLib, rootNode, state); }
public ModelRoot Convert(PssgFile pssg) { var sceneBuilder = new SceneBuilder(); var state = new ExportState(); // F1 games use lib YYY var parent = pssg.FindNodes("LIBRARY", "type", "NODE").FirstOrDefault(); if (parent is null) { parent = pssg.FindNodes("LIBRARY", "type", "YYY").FirstOrDefault(); state.IsF1 = true; } if (parent is null) { throw new InvalidDataException("Could not find library with scene nodes."); } foreach (var child in parent.ChildNodes) { CreateNode(sceneBuilder, child, null, state); } return(sceneBuilder.ToGltf2()); }
public void Convert(ModelRoot gltf, PssgFile pssg) { // Get a list of nodes in the default scene as a flat list Dictionary <int, int> nodeBoneIndexMap = new Dictionary <int, int>(); var rootNode = gltf.DefaultScene.FindNode(n => n.Name.StartsWith("Scene Root")); if (rootNode is null) { throw new InvalidDataException("The default scene must have node name starting with `Scene Root`."); } // Determine libraries in which to store data var nodeLib = pssg.FindNodes("LIBRARY", "type", "NODE").FirstOrDefault(); PssgNode rdsLib; PssgNode ribLib; if (nodeLib is not null) { rdsLib = pssg.FindNodes("LIBRARY", "type", "RENDERDATASOURCE").First(); ribLib = pssg.FindNodes("LIBRARY", "type", "RENDERINTERFACEBOUND").First(); } else { // F1 games use YYY, and put almost everything in this lib nodeLib = pssg.FindNodes("LIBRARY", "type", "YYY").FirstOrDefault(); if (nodeLib is null) { throw new InvalidDataException("Could not find library with scene nodes."); } rdsLib = nodeLib; ribLib = nodeLib; } var state = new ImportState(rdsLib, ribLib, ShaderInputInfo.CreateFromPssg(pssg).ToDictionary(si => si.ShaderGroupId)); // Clear out the libraries nodeLib.RemoveChildNodes(nodeLib.ChildNodes.Where(n => n.Name == "ROOTNODE")); rdsLib.RemoveChildNodes(rdsLib.ChildNodes.Where(n => n.Name == "RENDERDATASOURCE")); ribLib.RemoveChildNodes(ribLib.ChildNodes.Where(n => n.Name == "DATABLOCK")); // Write the scene graph, and collect mesh data ConvertSceneNodes(pssg, nodeLib, rootNode, state); // Seems in Dirt Rally 2.0 there is a bunch of useless data in lib SEGMENTSET // lets get rid of it var ssLibNode = pssg.FindNodes("LIBRARY", "type", "SEGMENTSET").FirstOrDefault(); if (ssLibNode is not null) { ssLibNode.ParentNode?.RemoveChild(ssLibNode); } }
private static void ConvertMaterial(PssgFile pssg, MaterialBuilder mat, int texCoordSets) { var shader = pssg.FindNodes("SHADERINSTANCE", "id", mat.Name).FirstOrDefault(); if (shader is null) { throw new InvalidDataException($"Could not find shader instance {mat.Name} referenced by the model."); } var shaderGroupId = shader.Attributes["shaderGroup"].GetValue <string>().Substring(1); var sgNode = shader.File.FindNodes("SHADERGROUP", "id", shaderGroupId).FirstOrDefault(); var textureInputs = shader.FindNodes("SHADERINPUT", "type", "texture"); mat.WithMetallicRoughnessShader() .WithMetallicRoughness(0.1f, 0.5f) .WithBaseColor(new Vector4(1, 1, 1, 1)); if (texCoordSets > 0) { mat.UseChannel(KnownChannel.BaseColor).UseTexture() .WithPrimaryImage(new MemoryImage(GetDiffuseTexture(sgNode, textureInputs))) .WithCoordinateSet(0); } if (texCoordSets > 1) { mat.UseChannel(KnownChannel.Occlusion).UseTexture() .WithPrimaryImage(new MemoryImage(GetOcclusionTexture(sgNode, textureInputs))) .WithCoordinateSet(1); } if (texCoordSets > 2) { mat.UseChannel(KnownChannel.Emissive).UseTexture() .WithPrimaryImage(new MemoryImage(GetEmissiveTexture(sgNode, textureInputs))) .WithCoordinateSet(2); } if (texCoordSets > 3) { mat.UseChannel(KnownChannel.Normal).UseTexture() .WithPrimaryImage(new MemoryImage(GetNormalTexture(sgNode, textureInputs))) .WithCoordinateSet(3); } }
public static List <ShaderInputInfo> CreateFromPssg(PssgFile pssg) { var visitedShaders = new HashSet <string>(); var inputInfos = new List <ShaderInputInfo>(); // Figure out the layout of the vertex data for each shader group by going through rds nodes var rdsNodes = pssg.FindNodes("RENDERDATASOURCE"); foreach (var rdsNode in rdsNodes) { var info = GetShaderInfo(rdsNode, visitedShaders); if (info is not null) { inputInfos.Add(info); } } return(inputInfos);
private static void ConvertMaterial(PssgFile pssg, MaterialBuilder mat, int texCoordSets) { var shader = pssg.FindNodes("SHADERINSTANCE", "id", mat.Name).FirstOrDefault(); if (shader is null) { throw new InvalidDataException($"Could not find shader instance {mat.Name} referenced by the model."); } mat.WithMetallicRoughnessShader() .WithMetallicRoughness(0.1f, 0.5f) .WithBaseColor(new Vector4(1, 1, 1, 1)); if (texCoordSets > 0) { mat.UseChannel(KnownChannel.BaseColor).UseTexture() .WithPrimaryImage(new MemoryImage(grayImageBytes)) .WithCoordinateSet(0); } if (texCoordSets > 1) { mat.UseChannel(KnownChannel.Occlusion).UseTexture() .WithPrimaryImage(new MemoryImage(whiteImageBytes)) .WithCoordinateSet(1); } if (texCoordSets > 2) { mat.UseChannel(KnownChannel.Emissive).UseTexture() .WithPrimaryImage(new MemoryImage(blackImageBytes)) .WithCoordinateSet(2); } if (texCoordSets > 3) { mat.UseChannel(KnownChannel.Normal).UseTexture() .WithPrimaryImage(new MemoryImage(blackImageBytes)) .WithCoordinateSet(3); } }
public static bool SupportsPssg(PssgFile pssg) { return(pssg.FindNodes("MATRIXPALETTERENDERINSTANCE").Any() || pssg.FindNodes("MATRIXPALETTEJOINTRENDERINSTANCE").Any()); }
public new static bool SupportsPssg(PssgFile pssg) { return(pssg.FindNodes("VISIBLERENDERNODE").Any()); }
public static bool SupportsPssg(PssgFile pssg) { var rsiNodes = pssg.FindNodes("RENDERSTREAMINSTANCE"); return(rsiNodes.Any() && rsiNodes.First().ParentNode?.Name == "MATRIXPALETTENODE"); }