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 void Write(ShaderInputInfo shaderInput, PssgNode rdsLib, PssgNode ribLib, PssgModelWriterState state) { var streamCount = (uint)shaderInput.BlockInputs.Sum(bi => bi.VertexInputs.Count); var rdsNode = new PssgNode("RENDERDATASOURCE", rdsLib.File, rdsLib); rdsNode.AddAttribute("streamCount", streamCount); rdsNode.AddAttribute("id", Name); rdsLib.ChildNodes.Add(rdsNode); WriteIndices(rdsNode); // Write the data foreach (var bi in shaderInput.BlockInputs) { for (int i = 0; i < bi.VertexInputs.Count; ++i) { var vi = bi.VertexInputs[i]; WriteRenderStream(rdsNode, state.DataBlockCount, state.RenderStreamCount, (uint)i); state.RenderStreamCount++; } WriteDataBlock(bi, ribLib, state.DataBlockCount); state.DataBlockCount++; }
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); } }