public void Save(string path) { this.CompactBuffers(); OptFileNodes optNodes = new OptFileNodes(); Dictionary <string, bool> texturesWriten = this.Textures.Keys.ToDictionary(t => t, t => false); foreach (Mesh mesh in this.Meshes) { mesh.SortLods(); NodeGroupNode meshNode = new NodeGroupNode(); RotationScaleNode rotationScaleNode = new RotationScaleNode(); MeshDescriptorNode descriptorNode = new MeshDescriptorNode(); MeshVerticesNode verticesNode = new MeshVerticesNode(); TextureCoordinatesNode textureVerticesNode = new TextureCoordinatesNode(); VertexNormalsNode vertexNormalsNode = new VertexNormalsNode(); rotationScaleNode.Pivot = mesh.RotationScale.Pivot; rotationScaleNode.Look = mesh.RotationScale.Look; rotationScaleNode.Up = mesh.RotationScale.Up; rotationScaleNode.Right = mesh.RotationScale.Right; descriptorNode.MeshType = mesh.Descriptor.MeshType; descriptorNode.ExplosionType = mesh.Descriptor.ExplosionType; descriptorNode.Span = mesh.Descriptor.Span; descriptorNode.Center = mesh.Descriptor.Center; descriptorNode.Min = mesh.Descriptor.Min; descriptorNode.Max = mesh.Descriptor.Max; descriptorNode.TargetId = mesh.Descriptor.TargetId; descriptorNode.Target = mesh.Descriptor.Target; foreach (Vector vertex in mesh.Vertices) { verticesNode.Vertices.Add(vertex); } foreach (TextureCoordinates textureVertex in mesh.TextureCoordinates) { textureVerticesNode.TextureVertices.Add(textureVertex); } foreach (Vector vertexNormal in mesh.VertexNormals) { vertexNormalsNode.Normals.Add(vertexNormal); } meshNode.Nodes.Add(verticesNode); meshNode.Nodes.Add(textureVerticesNode); meshNode.Nodes.Add(vertexNormalsNode); meshNode.Nodes.Add(descriptorNode); meshNode.Nodes.Add(rotationScaleNode); FaceGroupingNode faceGroupingNode = new FaceGroupingNode(); foreach (var lod in mesh.Lods) { NodeGroupNode lodNode = new NodeGroupNode(); foreach (var faceGroup in lod.FaceGroups) { if (faceGroup.Textures.Count != 0) { List <Node> texturesNodes = new List <Node>(); foreach (var textureName in faceGroup.Textures) { if (!texturesWriten.ContainsKey(textureName) || texturesWriten[textureName]) { NodeReferenceNode textureNode = new NodeReferenceNode() { Reference = textureName }; texturesNodes.Add(textureNode); } else { var texture = this.Textures[textureName]; TextureNode textureNode = new TextureNode(); textureNode.Name = texture.Name; textureNode.UniqueId = 0; // texture.Id textureNode.Width = texture.Width; textureNode.Height = texture.Height; textureNode.Palettes = texture.Palette; textureNode.Bytes = texture.ImageData; if (texture.AlphaData != null) { TextureAlphaNode alphaNode = new TextureAlphaNode(); alphaNode.Bytes = texture.AlphaData; textureNode.Nodes.Add(alphaNode); } texturesNodes.Add(textureNode); texturesWriten[textureName] = true; } } if (texturesNodes.Count == 1) { lodNode.Nodes.Add(texturesNodes[0]); } else { NodeSwitchNode switchNode = new NodeSwitchNode(); foreach (var textureNode in texturesNodes) { switchNode.Nodes.Add(textureNode); } lodNode.Nodes.Add(switchNode); } } FaceDataNode faceDataNode = new FaceDataNode(); faceDataNode.EdgesCount = faceGroup.EdgesCount; foreach (var face in faceGroup.Faces) { FaceDataNodeData faceData = new FaceDataNodeData { VerticesIndex = face.VerticesIndex, EdgesIndex = face.EdgesIndex, TextureCoordinatesIndex = face.TextureCoordinatesIndex, VertexNormalsIndex = face.VertexNormalsIndex, Normal = face.Normal, TexturingDirection = face.TexturingDirection, TexturingMagniture = face.TexturingMagniture }; faceDataNode.Faces.Add(faceData); } lodNode.Nodes.Add(faceDataNode); } faceGroupingNode.Distances.Add(lod.Distance); faceGroupingNode.Nodes.Add(lodNode); } NodeGroupNode faceGroupingNodeGroup = new NodeGroupNode(); faceGroupingNodeGroup.Nodes.Add(Node.Null); faceGroupingNodeGroup.Nodes.Add(Node.Null); faceGroupingNodeGroup.Nodes.Add(Node.Null); faceGroupingNodeGroup.Nodes.Add(faceGroupingNode); meshNode.Nodes.Add(faceGroupingNodeGroup); foreach (var hardpoint in mesh.Hardpoints) { meshNode.Nodes.Add(new HardpointNode() { HardpointType = hardpoint.HardpointType, Position = hardpoint.Position }); } foreach (var engineGlow in mesh.EngineGlows) { meshNode.Nodes.Add(new EngineGlowNode() { IsDisabled = engineGlow.IsDisabled, CoreColor = engineGlow.CoreColor, OuterColor = engineGlow.OuterColor, Position = engineGlow.Position, Format = engineGlow.Format, Look = engineGlow.Look, Up = engineGlow.Up, Right = engineGlow.Right }); } optNodes.Nodes.Add(meshNode); } foreach (var texture in texturesWriten.Where(t => !t.Value)) { this.Textures.Remove(texture.Key); } optNodes.Save(path); this.FileName = path; }
public static OptFile FromFile(string path) { OptFile opt = new OptFile(); opt.FileName = path; OptFileNodes optNodes = OptFileNodes.FromFile(path); List <string> globalTexture = null; for (int meshId = 0; meshId < optNodes.Nodes.Count; meshId++) { if (meshId == 0 && optNodes.Nodes[meshId].NodeType == NodeType.Texture) { TextureNode textureNode = (TextureNode)optNodes.Nodes[meshId]; opt.CreateTexture(textureNode); globalTexture = new List <string>() { textureNode.Name }; continue; } if (optNodes.Nodes[meshId].NodeType != NodeType.NodeGroup) { throw new InvalidDataException("invalid mesh"); } NodeGroupNode meshNode = (NodeGroupNode)optNodes.Nodes[meshId]; var meshNodes = meshNode.Nodes.Union((meshNode.Nodes.Where(t => t.NodeType == NodeType.NodeGroup).FirstOrDefault() ?? new NodeGroupNode()).Nodes).ToList(); RotationScaleNode rotationScaleNode = (RotationScaleNode)meshNodes.FirstOrDefault(t => t.NodeType == NodeType.RotationScale); MeshDescriptorNode descriptorNode = (MeshDescriptorNode)meshNodes.FirstOrDefault(t => t.NodeType == NodeType.MeshDescriptor); MeshVerticesNode verticesNode = (MeshVerticesNode)meshNodes.First(t => t.NodeType == NodeType.MeshVertices); TextureCoordinatesNode textureVerticesNode = (TextureCoordinatesNode)meshNodes.First(t => t.NodeType == NodeType.TextureCoordinates); VertexNormalsNode vertexNormalsNode = (VertexNormalsNode)meshNodes.First(t => t.NodeType == NodeType.VertexNormals); var hardpointsNodes = meshNodes.Where(t => t.NodeType == NodeType.Hardpoint).Select(t => (HardpointNode)t).ToList(); var engineGlowsNodes = meshNodes.Where(t => t.NodeType == NodeType.EngineGlow).Select(t => (EngineGlowNode)t).ToList(); FaceGroupingNode faceGroupingNode = (FaceGroupingNode)meshNodes.First(t => t.NodeType == NodeType.FaceGrouping); Mesh mesh = new Mesh(); if (rotationScaleNode != null) { mesh.RotationScale.Pivot = rotationScaleNode.Pivot; mesh.RotationScale.Look = rotationScaleNode.Look; mesh.RotationScale.Up = rotationScaleNode.Up; mesh.RotationScale.Right = rotationScaleNode.Right; } if (descriptorNode != null) { mesh.Descriptor.MeshType = descriptorNode.MeshType; mesh.Descriptor.ExplosionType = descriptorNode.ExplosionType; mesh.Descriptor.Span = descriptorNode.Span; mesh.Descriptor.Center = descriptorNode.Center; mesh.Descriptor.Min = descriptorNode.Min; mesh.Descriptor.Max = descriptorNode.Max; mesh.Descriptor.TargetId = descriptorNode.TargetId; mesh.Descriptor.Target = descriptorNode.Target; } foreach (Vector vertex in verticesNode.Vertices) { mesh.Vertices.Add(vertex); } foreach (TextureCoordinates textureVertex in textureVerticesNode.TextureVertices) { mesh.TextureCoordinates.Add(textureVertex); } foreach (Vector normal in vertexNormalsNode.Normals) { mesh.VertexNormals.Add(normal); } foreach (var hardpoint in hardpointsNodes) { mesh.Hardpoints.Add(new Hardpoint() { HardpointType = hardpoint.HardpointType, Position = hardpoint.Position }); } foreach (var engineGlow in engineGlowsNodes) { mesh.EngineGlows.Add(new EngineGlow() { IsDisabled = engineGlow.IsDisabled, CoreColor = engineGlow.CoreColor, OuterColor = engineGlow.OuterColor, Position = engineGlow.Position, Format = engineGlow.Format, Look = engineGlow.Look, Up = engineGlow.Up, Right = engineGlow.Right }); } if (faceGroupingNode.Distances.Count != faceGroupingNode.Nodes.Count) { throw new InvalidDataException("invalid face groups count in face grouping"); } for (int lodId = 0; lodId < faceGroupingNode.Distances.Count; lodId++) { List <string> texture = globalTexture; MeshLod lod = new MeshLod(); lod.Distance = faceGroupingNode.Distances[lodId]; foreach (Node node in faceGroupingNode.Nodes[lodId].Nodes) { switch (node.NodeType) { case NodeType.Texture: { TextureNode textureNode = (TextureNode)node; opt.CreateTexture(textureNode); texture = new List <string>() { textureNode.Name }; break; } case NodeType.NodeReference: texture = new List <string>() { ((NodeReferenceNode)node).Reference }; break; case NodeType.NodeSwitch: { NodeSwitchNode switchNode = (NodeSwitchNode)node; texture = new List <string>(); foreach (Node nodeSwitch in switchNode.Nodes) { switch (nodeSwitch.NodeType) { case NodeType.Texture: { TextureNode textureNode = (TextureNode)nodeSwitch; opt.CreateTexture(textureNode); texture.Add(textureNode.Name); break; } case NodeType.NodeReference: texture.Add(((NodeReferenceNode)nodeSwitch).Reference); break; } } break; } case NodeType.FaceData: { FaceDataNode faceDataNode = (FaceDataNode)node; FaceGroup faceGroup = new FaceGroup(); if (texture != null) { foreach (var name in texture) { faceGroup.Textures.Add(name); } } foreach (var face in faceDataNode.Faces) { faceGroup.Faces.Add(new Face() { VerticesIndex = face.VerticesIndex, EdgesIndex = face.EdgesIndex, TextureCoordinatesIndex = face.TextureCoordinatesIndex, VertexNormalsIndex = face.VertexNormalsIndex, Normal = face.Normal, TexturingDirection = face.TexturingDirection, TexturingMagniture = face.TexturingMagniture }); } foreach (var face in faceGroup.Faces) { if (face.VertexNormalsIndex.A >= mesh.VertexNormals.Count) { face.VertexNormalsIndex = face.VertexNormalsIndex.SetA(0); } if (face.VertexNormalsIndex.B >= mesh.VertexNormals.Count) { face.VertexNormalsIndex = face.VertexNormalsIndex.SetB(0); } if (face.VertexNormalsIndex.C >= mesh.VertexNormals.Count) { face.VertexNormalsIndex = face.VertexNormalsIndex.SetC(0); } if (face.VertexNormalsIndex.D >= mesh.VertexNormals.Count) { face.VertexNormalsIndex = face.VertexNormalsIndex.SetD(0); } if (face.TextureCoordinatesIndex.A >= mesh.TextureCoordinates.Count) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetA(0); } if (face.TextureCoordinatesIndex.B >= mesh.TextureCoordinates.Count) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetB(0); } if (face.TextureCoordinatesIndex.C >= mesh.TextureCoordinates.Count) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetC(0); } if (face.TextureCoordinatesIndex.D >= mesh.TextureCoordinates.Count) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetD(0); } if (face.VerticesIndex.A >= 0 && face.TextureCoordinatesIndex.A < 0) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetA(0); } if (face.VerticesIndex.B >= 0 && face.TextureCoordinatesIndex.B < 0) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetB(0); } if (face.VerticesIndex.C >= 0 && face.TextureCoordinatesIndex.C < 0) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetC(0); } if (face.VerticesIndex.D >= 0 && face.TextureCoordinatesIndex.D < 0) { face.TextureCoordinatesIndex = face.TextureCoordinatesIndex.SetD(0); } } lod.FaceGroups.Add(faceGroup); texture = null; break; } } } mesh.Lods.Add(lod); } opt.Meshes.Add(mesh); } opt.SetFaceGroupTextureWhenEmpty(); return(opt); }