private void BuildTextures(OptFile opt) { this.nullTexture = null; this.textures = null; if (opt == null) { return; } this.nullTexture = new DiffuseMaterial(Brushes.White); this.textures = new Dictionary <string, Material>(); foreach (var texture in opt.Textures.Values) { var image = CreateTexture(opt, texture.Name); image.Freeze(); var brush = new ImageBrush(image) { ViewportUnits = BrushMappingMode.Absolute, Stretch = Stretch.Fill, TileMode = TileMode.Tile, Opacity = texture.HasAlpha ? 0.999 : 1.0 }; brush.Freeze(); var material = new DiffuseMaterial(brush); material.Freeze(); this.textures.Add(texture.Name, material); } }
private void ExecuteNewCommand() { BusyIndicatorService.Run(dispatcher => { bool isEmpty = this.OptModel.File == null || (string.IsNullOrEmpty(this.OptModel.File.FileName) && this.OptModel.File.Meshes.Count == 0 && this.OptModel.File.Textures.Count == 0); if (!isEmpty) { var message = Messenger.Instance.Notify(new MessageBoxMessage("Creating a new opt will erase the existing one.\nDo you want to continue?", "New opt", MessageBoxButton.YesNo, MessageBoxImage.Warning)); if (message.Result != MessageBoxResult.Yes) { return; } } dispatcher(() => this.OptModel.File = null); var opt = new OptFile(); dispatcher(() => this.OptModel.File = opt); dispatcher(() => this.OptModel.UndoStackPush("new")); }); }
private List <ModelVisual3D> CreateMeshModelWireframe(OptFile opt, int meshIndex, int lodIndex) { if (opt == null || opt.Meshes.ElementAtOrDefault(meshIndex) == null || opt.Meshes[meshIndex].Lods.ElementAtOrDefault(lodIndex) == null) { return(new List <ModelVisual3D>()); } var cache = this.Cache; if (meshIndex >= cache.meshesWireframes.Length || lodIndex >= cache.meshesWireframes[meshIndex].Length) { return(new List <ModelVisual3D>()); } return(new List <ModelVisual3D> { new LinesVisual3D { Points = new Point3DCollection(cache.meshesWireframes[meshIndex][lodIndex]), DepthOffset = 0.0001, Color = Colors.White } }); }
private static ICollection <string> GetTexturesExist(string optName, OptFile opt, List <string> distinctSkins) { var texturesExist = new SortedSet <string>(); string directory = Path.GetDirectoryName(opt.FileName); foreach (string skin in distinctSkins) { string skinDirectory = $"{directory}\\Skins\\{optName}\\{skin}"; if (!Directory.Exists(skinDirectory)) { continue; } var filesEnum = Directory.EnumerateFiles(skinDirectory) .Select(t => Path.GetFileName(t)); var filesSet = new SortedSet <string>(filesEnum, StringComparer.OrdinalIgnoreCase); foreach (string textureName in opt.Textures.Keys) { if (TextureExists(filesSet, textureName, skin) != null) { texturesExist.Add(textureName); } } } return(texturesExist); }
private void ExecuteOpenCommand() { BusyIndicatorService.Run(dispatcher => { string fileName = FileDialogService.GetOpenOptFileName(); if (fileName == null) { return; } BusyIndicatorService.Notify(string.Concat("Opening ", System.IO.Path.GetFileName(fileName), "...")); try { dispatcher(() => this.OptModel.File = null); var opt = OptFile.FromFile(fileName); dispatcher(() => this.OptModel.File = opt); dispatcher(() => this.OptModel.UndoStackPush("open " + System.IO.Path.GetFileNameWithoutExtension(fileName))); if (!this.OptModel.IsPlayable) { Messenger.Instance.Notify(new MainViewSelectorMessage("PlayabilityMessages")); Messenger.Instance.Notify(new MessageBoxMessage(fileName + "\n\n" + "This opt will not be fully playable.", "Check Opt Playability", MessageBoxButton.OK, MessageBoxImage.Warning)); } } catch (Exception ex) { Messenger.Instance.Notify(new MessageBoxMessage(fileName, ex)); } }); }
private Tuple <OptFile, OptCache> GetOptModel(string name) { OptFile file; if (!this.optFiles.TryGetValue(name, out file)) { string fileName = AppSettings.WorkingDirectory + "FLIGHTMODELS\\" + name + ".opt"; if (!System.IO.File.Exists(fileName)) { return(null); } file = OptFile.FromFile(fileName); this.optFiles.Add(name, file); } OptCache cache; if (!this.optCaches.TryGetValue(name, out cache)) { cache = new OptCache(file); this.optCaches.Add(name, cache); } return(new Tuple <OptFile, OptCache>(file, cache)); }
public static int ReadOptFunction([MarshalAs(UnmanagedType.LPStr)] string optFilename) { if (!File.Exists(optFilename)) { return(0); } string optName = Path.GetFileNameWithoutExtension(optFilename); IList <string> objectLines = GetCustomFileLines("Skins"); IList <string> baseSkins = XwaHooksConfig.Tokennize(XwaHooksConfig.GetFileKeyValue(objectLines, optName)); var baseDefaultSkinDirectory = new DirectoryInfo($"FlightModels\\Skins\\{optName}\\Default"); bool baseDefaultSkinExists = baseDefaultSkinDirectory.Exists && baseDefaultSkinDirectory.EnumerateFiles().Any(); int fgCount = GetFlightgroupsCount(objectLines, optName); bool hasSkins = baseDefaultSkinExists || baseSkins.Count != 0 || fgCount != 0; if (hasSkins) { var opt = OptFile.FromFile(optFilename); fgCount = Math.Max(fgCount, opt.MaxTextureVersion); UpdateOptFile(optName, opt, objectLines, baseSkins, fgCount); opt.Save("temp.opt"); } return(hasSkins ? 1 : 0); }
public TextureBrowserWindow(Window owner, OptFile optFile) { InitializeComponent(); this.Owner = owner; this.DataContext = optFile; }
public static int ReadOptFunction([MarshalAs(UnmanagedType.LPStr)] string optFilename) { _tempOptFile = null; _tempOptFileSize = 0; if (!File.Exists(optFilename)) { return(0); } string optName = Path.GetFileNameWithoutExtension(optFilename); IList <string> objectLines = GetCustomFileLines("Skins"); IList <string> baseSkins = XwaHooksConfig.Tokennize(XwaHooksConfig.GetFileKeyValue(objectLines, optName)); bool hasDefaultSkin = GetSkinDirectoryLocatorPath(optName, "Default") != null; int fgCount = GetFlightgroupsCount(objectLines, optName); bool hasSkins = hasDefaultSkin || baseSkins.Count != 0 || fgCount != 0; if (hasSkins) { var opt = OptFile.FromFile(optFilename); fgCount = Math.Max(fgCount, opt.MaxTextureVersion); UpdateOptFile(optName, opt, objectLines, baseSkins, fgCount, hasDefaultSkin); //opt.Save("temp.opt", false); _tempOptFile = opt; _tempOptFileSize = opt.GetSaveRequiredFileSize(false); } return(hasSkins ? _tempOptFileSize : 0); }
public OptCache(OptFile opt) { this.file = opt; this.BuildTextures(opt); this.BuildMeshes(opt); this.BuildMeshesWireframes(opt); }
public OptModel() { this.PlayabilityMessages = new ObservableCollection <PlayabilityMessage>(); this.UndoStack = new ObservableCollection <Tuple <string, OptFile> >(); this.file = new OptFile(); this.UndoStackPush("new"); }
private void ExecuteImportOptCommand() { BusyIndicatorService.Run(dispatcher => { string fileName = FileDialogService.GetOpenOptFileName(); if (fileName == null) { return; } BusyIndicatorService.Notify(string.Concat("Importing ", System.IO.Path.GetFileName(fileName), "...")); var opt = this.OptModel.File; try { dispatcher(() => this.OptModel.File = null); var import = OptFile.FromFile(fileName); string importName = System.IO.Path.GetFileNameWithoutExtension(fileName) + "_"; foreach (var faceGroup in import.Meshes.SelectMany(t => t.Lods).SelectMany(t => t.FaceGroups)) { var textures = faceGroup.Textures.ToList(); faceGroup.Textures.Clear(); foreach (var texture in textures) { faceGroup.Textures.Add(texture.StartsWith(importName, StringComparison.Ordinal) ? texture : (importName + texture)); } } foreach (var texture in import.Textures.Values) { texture.Name = texture.Name.StartsWith(importName, StringComparison.Ordinal) ? texture.Name : (importName + texture.Name); } foreach (var texture in import.Textures.Values) { opt.Textures[texture.Name] = texture; } foreach (var mesh in import.Meshes) { opt.Meshes.Add(mesh); } } catch (Exception ex) { Messenger.Instance.Notify(new MessageBoxMessage(fileName, ex)); } dispatcher(() => this.OptModel.File = opt); dispatcher(() => this.OptModel.UndoStackPush("import " + System.IO.Path.GetFileName(fileName))); }); }
private static void UpdateOptFile(string optName, OptFile opt, IList <string> objectLines, IList <string> baseSkins, int fgCount) { List <List <string> > fgSkins = ReadFgSkins(optName, objectLines, baseSkins, fgCount); List <string> distinctSkins = fgSkins.SelectMany(t => t).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); ICollection <string> texturesExist = GetTexturesExist(optName, opt, distinctSkins); CreateSwitchTextures(opt, texturesExist, fgSkins); UpdateSkins(optName, opt, fgSkins); }
private void ExecuteConvertAllTexturesTo8BppCommand() { BusyIndicatorService.Run(dispatcher => { string fileName = FileDialogService.GetOpenOptFileName(); if (fileName == null) { return; } string directory = System.IO.Path.GetDirectoryName(fileName); BusyIndicatorService.Notify("Converting all textures to 8 bpp..."); var message = Messenger.Instance.Notify(new MessageBoxMessage(string.Concat("The textures of all OPTs in \"", directory, "\" will be converted to 8 bpp.\nDo you want to continue?"), "Converting textures", MessageBoxButton.YesNo, MessageBoxImage.Warning)); if (message.Result != MessageBoxResult.Yes) { return; } foreach (string file in System.IO.Directory.GetFiles(directory, "*.opt")) { BusyIndicatorService.Notify(string.Concat("Converting ", System.IO.Path.GetFileName(file), " to 8 bpp...")); OptFile opt = null; try { opt = OptFile.FromFile(file); } catch (System.IO.InvalidDataException) { continue; } if (opt.TexturesBitsPerPixel == 8) { continue; } opt.ConvertTextures32To8(); opt.Save(opt.FileName); } BusyIndicatorService.Notify("Converting all textures to 8 bpp completed."); Messenger.Instance.Notify(new MessageBoxMessage("Converting all textures to 8 bpp completed.", "Converting textures")); }); }
private void Execute_Open(object sender, ExecutedRoutedEventArgs e) { Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.Filter = "Xwa OPT files|*.opt"; if (dlg.ShowDialog() == true) { try { this.OptFile = OptFile.FromFile(dlg.FileName); } catch (Exception ex) { MessageBox.Show(ex.Message, ex.Source, MessageBoxButton.OK, MessageBoxImage.Error); } } }
public static unsafe void WriteOptFunction(IntPtr ptr) { if (ptr == IntPtr.Zero || _tempOptFile == null || _tempOptFileSize == 0) { _tempOptFile = null; _tempOptFileSize = 0; return; } using (var stream = new UnmanagedMemoryStream((byte *)ptr, _tempOptFileSize, _tempOptFileSize, FileAccess.Write)) { _tempOptFile.Save(stream, false, false); } _tempOptFile = null; _tempOptFileSize = 0; }
private static void UpdateSkins(string optName, OptFile opt, List <List <string> > fgSkins) { opt.Textures.AsParallel().ForAll(texture => { int position = texture.Key.IndexOf("_fg_"); if (position == -1) { return; } string textureName = texture.Key.Substring(0, position); int fgIndex = int.Parse(texture.Key.Substring(position + 4, texture.Key.IndexOf('_', position + 4) - position - 4), CultureInfo.InvariantCulture); string directory = Path.GetDirectoryName(opt.FileName); foreach (string skin in fgSkins[fgIndex]) { string skinDirectory = $"{directory}\\Skins\\{optName}\\{skin}"; if (!Directory.Exists(skinDirectory)) { continue; } var filesEnum = Directory.EnumerateFiles(skinDirectory) .Select(t => Path.GetFileName(t)); var filesSet = new SortedSet <string>(filesEnum, StringComparer.InvariantCultureIgnoreCase); string filename = TextureExists(filesSet, textureName, skin); if (filename == null) { continue; } CombineTextures(texture.Value, Path.Combine(skinDirectory, filename)); } texture.Value.GenerateMipmaps(); }); }
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values.Length < 2 || values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue) { return(null); } OptFile optFile = values[1] as OptFile; if (optFile == null) { return(null); } Texture texture = optFile.Textures.ContainsKey((string)values[0]) ? optFile.Textures[(string)values[0]] : null; return(TextureUtils.BuildOptTexture(texture)); }
private static ICollection <string> GetTexturesExist(string optName, OptFile opt, List <string> distinctSkins) { var texturesExist = new SortedSet <string>(); foreach (string skin in distinctSkins) { string path = GetSkinDirectoryLocatorPath(optName, skin); if (path == null) { continue; } SortedSet <string> filesSet; using (IFileLocator locator = FileLocatorFactory.Create(path)) { if (locator == null) { continue; } var filesEnum = locator.EnumerateFiles() .Select(t => Path.GetFileName(t)); filesSet = new SortedSet <string>(filesEnum, StringComparer.OrdinalIgnoreCase); } foreach (string textureName in opt.Textures.Keys) { if (TextureExists(filesSet, textureName, skin) != null) { texturesExist.Add(textureName); } } } return(texturesExist); }
public void XWOpt_Read_TieFighter() { opt.Read(TieFighter); Hardpoint <Vector3> hardpoint = opt.OfType <Hardpoint <Vector3> >().First(); Assert.That(hardpoint, Is.InstanceOf(typeof(Hardpoint <Vector3>))); Assert.That(hardpoint.Location, Is.EqualTo(new Vector3(-17f, -70f, -32f))); Assert.That(opt.OfType <Hardpoint <Vector3> >().Count(), Is.EqualTo(2)); var convertedOpt = new OptFile <Vector2, Vector3>() { RotateFromOptSpace = new CoordinateSystemConverter <Vector3>(RotateIntoUnitySpace), Logger = msg => TestContext.Out.WriteLine(msg), }; convertedOpt.Read(TieFighter); var rotatedHardpoint = convertedOpt.OfType <Hardpoint <Vector3> >().First(); Assert.That(rotatedHardpoint, Is.InstanceOf(typeof(Hardpoint <Vector3>))); Assert.That(rotatedHardpoint.Location, Is.EqualTo(new Vector3(-17f, -32f, 70f))); }
private static void CreateSwitchTextures(OptFile opt, ICollection <string> texturesExist, List <List <string> > fgSkins, List <int> fgColors) { int fgCount = fgSkins.Count; if (fgCount == 0) { return; } var newTextures = new List <Texture>(); foreach (var texture in opt.Textures) { if (!texturesExist.Contains(texture.Key)) { continue; } foreach (int i in fgColors) { texture.Value.Convert8To32(); Texture newTexture = texture.Value.Clone(); newTexture.Name += "_fg_" + i.ToString(CultureInfo.InvariantCulture) + "_" + string.Join(",", fgSkins[i]); newTextures.Add(newTexture); } } foreach (var newTexture in newTextures) { opt.Textures.Add(newTexture.Name, newTexture); } foreach (var mesh in opt.Meshes) { foreach (var lod in mesh.Lods) { foreach (var faceGroup in lod.FaceGroups) { if (faceGroup.Textures.Count == 0) { continue; } string name = faceGroup.Textures[0]; if (!texturesExist.Contains(name)) { continue; } faceGroup.Textures.Clear(); for (int i = 0; i < fgCount; i++) { if (fgColors.Contains(i)) { faceGroup.Textures.Add(name + "_fg_" + i.ToString(CultureInfo.InvariantCulture) + "_" + string.Join(",", fgSkins[i])); } else { faceGroup.Textures.Add(name); } } } } } }
private static void UpdateSkins(string optName, OptFile opt, List <string> distinctSkins, List <List <string> > fgSkins) { var locatorsPath = new Dictionary <string, string>(distinctSkins.Count, StringComparer.OrdinalIgnoreCase); var filesSets = new Dictionary <string, SortedSet <string> >(distinctSkins.Count, StringComparer.OrdinalIgnoreCase); foreach (string skin in distinctSkins) { string path = GetSkinDirectoryLocatorPath(optName, skin); locatorsPath.Add(skin, path); SortedSet <string> filesSet = null; if (path != null) { using (IFileLocator locator = FileLocatorFactory.Create(path)) { if (locator != null) { var filesEnum = locator.EnumerateFiles() .Select(t => Path.GetFileName(t)); filesSet = new SortedSet <string>(filesEnum, StringComparer.OrdinalIgnoreCase); } } } filesSets.Add(skin, filesSet ?? new SortedSet <string>()); } opt.Textures.AsParallel().ForAll(texture => { int position = texture.Key.IndexOf("_fg_"); if (position == -1) { return; } string textureName = texture.Key.Substring(0, position); int fgIndex = int.Parse(texture.Key.Substring(position + 4, texture.Key.IndexOf('_', position + 4) - position - 4), CultureInfo.InvariantCulture); foreach (string skin in fgSkins[fgIndex]) { string path = locatorsPath[skin]; if (path == null) { continue; } string filename = TextureExists(filesSets[skin], textureName, skin); if (filename == null) { continue; } using (IFileLocator locator = FileLocatorFactory.Create(path)) { if (locator == null) { continue; } CombineTextures(texture.Value, locator, filename); } } texture.Value.GenerateMipmaps(); }); }
public static void OptToObj(OptFile opt, string objPath, bool scale) { if (opt == null) { throw new ArgumentNullException("opt"); } string objDirectory = Path.GetDirectoryName(objPath); string objName = Path.GetFileNameWithoutExtension(objPath); var objMaterials = new ObjMaterialDictionary(); foreach (var texture in opt.Textures.Values) { var material = new ObjMaterial { Name = texture.Name, DiffuseMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}.png", texture.Name) }; texture.Save(Path.Combine(objDirectory, material.DiffuseMapFileName)); if (texture.HasAlpha) { material.AlphaMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}_alpha.png", texture.Name); texture.SaveAlphaMap(Path.Combine(objDirectory, material.AlphaMapFileName)); } objMaterials.Add(texture.Name, material); } objMaterials.Save(Path.ChangeExtension(objPath, "mtl")); var distances = opt.Meshes .SelectMany(t => t.Lods) .Select(t => t.Distance) .Distinct() .OrderByDescending(t => t) .ToArray(); for (int distance = 0; distance < distances.Length; distance++) { var obj = new ObjFile(); int objectsIndex = 0; int verticesIndex = 0; int verticesTexIndex = 0; int verticesNormalIndex = 0; foreach (var mesh in opt.Meshes) { var lod = mesh.Lods.FirstOrDefault(t => t.Distance <= distances[distance]); if (lod == null) { continue; } var objMesh = new ObjMesh(string.Format(CultureInfo.InvariantCulture, "{0}.{1:D3}", mesh.Descriptor.MeshType, objectsIndex)); obj.Meshes.Add(objMesh); objectsIndex++; if (scale) { foreach (var v in mesh.Vertices) { obj.Vertices.Add(new ObjVector3(v.X * OptFile.ScaleFactor, v.Z * OptFile.ScaleFactor, v.Y * OptFile.ScaleFactor)); } } else { foreach (var v in mesh.Vertices) { obj.Vertices.Add(new ObjVector3(v.X, v.Z, v.Y)); } } foreach (var v in mesh.TextureCoordinates) { obj.VertexTexCoords.Add(new ObjVector2(v.U, -v.V)); } foreach (var v in mesh.VertexNormals) { obj.VertexNormals.Add(new ObjVector3(v.X, v.Z, v.Y)); } foreach (var faceGroup in lod.FaceGroups) { var objFaceGroup = new ObjFaceGroup(); if (faceGroup.Textures.Count > 0) { objFaceGroup.MaterialName = faceGroup.Textures[0]; } objMesh.FaceGroups.Add(objFaceGroup); foreach (var face in faceGroup.Faces) { if (face.VerticesIndex.D < 0) { objFaceGroup.Faces.Add(new ObjFace() { VerticesIndex = new ObjIndex( verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C ), VertexTexCoordsIndex = new ObjIndex( verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C), VertexNormalsIndex = new ObjIndex( verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C) }); } else { objFaceGroup.Faces.Add(new ObjFace() { VerticesIndex = new ObjIndex( verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C, verticesIndex + face.VerticesIndex.D ), VertexTexCoordsIndex = new ObjIndex( verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C, verticesTexIndex + face.TextureCoordinatesIndex.D), VertexNormalsIndex = new ObjIndex( verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C, verticesNormalIndex + face.VertexNormalsIndex.D) }); } } } verticesIndex += mesh.Vertices.Count; verticesTexIndex += mesh.TextureCoordinates.Count; verticesNormalIndex += mesh.VertexNormals.Count; } obj.Save(Path.Combine(objDirectory, string.Format(CultureInfo.InvariantCulture, "{0}_{1}.obj", objName, distance)), objName); } }
public static OptFile An8ToOpt(string an8Path, bool scale) { string an8Directory = Path.GetDirectoryName(an8Path); var an8 = An8File.FromFile(an8Path); var opt = new OptFile(); foreach (var mesh in an8.Objects .SelectMany(t => t.Components) .SelectMany(t => Converter.EnumMeshes(t))) { var optMesh = new Mesh(); opt.Meshes.Add(optMesh); if (scale) { foreach (var v in mesh.Points) { optMesh.Vertices.Add(new Vector(v.X / OptFile.ScaleFactor, v.Z / OptFile.ScaleFactor, v.Y / OptFile.ScaleFactor)); } } else { foreach (var v in mesh.Points) { optMesh.Vertices.Add(new Vector(v.X, v.Z, v.Y)); } } foreach (var v in mesh.TexCoords) { optMesh.TextureCoordinates.Add(new TextureCoordinates(v.U, -v.V)); } foreach (var v in mesh.Normals) { optMesh.VertexNormals.Add(new Vector(v.X, v.Z, v.Y)); } optMesh.TextureCoordinates.Add(new TextureCoordinates(0, 0)); optMesh.TextureCoordinates.Add(new TextureCoordinates(1, 0)); optMesh.TextureCoordinates.Add(new TextureCoordinates(1, 1)); optMesh.TextureCoordinates.Add(new TextureCoordinates(0, 1)); var optLod = new MeshLod(); optMesh.Lods.Add(optLod); foreach (var face in mesh.Faces) { if (face.PointIndexes.Length < 3) { continue; } bool isQuad = face.PointIndexes.Length > 3; var optFaceGroup = new FaceGroup(); optLod.FaceGroups.Add(optFaceGroup); var materialName = mesh.MaterialList.ElementAtOrDefault(face.MaterialIndex); if (!string.IsNullOrEmpty(materialName)) { optFaceGroup.Textures.Add(materialName); } Index verticesIndex = new Index( face.PointIndexes[0], face.PointIndexes[1], face.PointIndexes[2], isQuad ? face.PointIndexes[3] : -1); if (verticesIndex.A >= optMesh.Vertices.Count) { verticesIndex.A = 0; } if (verticesIndex.B >= optMesh.Vertices.Count) { verticesIndex.B = 0; } if (verticesIndex.C >= optMesh.Vertices.Count) { verticesIndex.C = 0; } if (verticesIndex.D >= optMesh.Vertices.Count) { verticesIndex.D = 0; } Index textureCoordinatesIndex = new Index( face.TexCoordIndexes[0], face.TexCoordIndexes[1], face.TexCoordIndexes[2], isQuad ? face.TexCoordIndexes[3] : -1); if (textureCoordinatesIndex.A >= optMesh.TextureCoordinates.Count) { textureCoordinatesIndex.A = 0; } if (textureCoordinatesIndex.B >= optMesh.TextureCoordinates.Count) { textureCoordinatesIndex.B = 0; } if (textureCoordinatesIndex.C >= optMesh.TextureCoordinates.Count) { textureCoordinatesIndex.C = 0; } if (textureCoordinatesIndex.D >= optMesh.TextureCoordinates.Count) { textureCoordinatesIndex.D = 0; } Index vertexNormalsIndex = new Index( face.NormalIndexes[0], face.NormalIndexes[1], face.NormalIndexes[2], isQuad ? face.NormalIndexes[3] : -1); if (vertexNormalsIndex.A >= optMesh.VertexNormals.Count) { vertexNormalsIndex.A = 0; } if (vertexNormalsIndex.B >= optMesh.VertexNormals.Count) { vertexNormalsIndex.B = 0; } if (vertexNormalsIndex.C >= optMesh.VertexNormals.Count) { vertexNormalsIndex.C = 0; } if (vertexNormalsIndex.D >= optMesh.VertexNormals.Count) { vertexNormalsIndex.D = 0; } if (textureCoordinatesIndex.A < 0 || textureCoordinatesIndex.B < 0 || textureCoordinatesIndex.C < 0 || (verticesIndex.D >= 0 && textureCoordinatesIndex.D < 0)) { textureCoordinatesIndex.A = optMesh.TextureCoordinates.Count - 4; textureCoordinatesIndex.B = optMesh.TextureCoordinates.Count - 3; textureCoordinatesIndex.C = optMesh.TextureCoordinates.Count - 2; textureCoordinatesIndex.D = verticesIndex.D < 0 ? -1 : optMesh.TextureCoordinates.Count - 1; } Vector normal = Vector.Normal( optMesh.Vertices.ElementAtOrDefault(verticesIndex.A), optMesh.Vertices.ElementAtOrDefault(verticesIndex.B), optMesh.Vertices.ElementAtOrDefault(verticesIndex.C)); if (vertexNormalsIndex.A < 0 || vertexNormalsIndex.B < 0 || vertexNormalsIndex.C < 0 || (verticesIndex.D >= 0 && vertexNormalsIndex.D < 0)) { optMesh.VertexNormals.Add(normal); vertexNormalsIndex.A = optMesh.VertexNormals.Count - 1; vertexNormalsIndex.B = optMesh.VertexNormals.Count - 1; vertexNormalsIndex.C = optMesh.VertexNormals.Count - 1; vertexNormalsIndex.D = verticesIndex.D < 0 ? -1 : optMesh.VertexNormals.Count - 1; } var optFace = new Face() { VerticesIndex = verticesIndex, TextureCoordinatesIndex = textureCoordinatesIndex, VertexNormalsIndex = vertexNormalsIndex, Normal = normal }; optFaceGroup.Faces.Add(optFace); } } opt.CompactBuffers(); opt.ComputeHitzones(); foreach (var material in an8.Materials .Concat(an8.Objects.SelectMany(t => t.Materials)) .Where(t => t.FrontSurface != null) .Select(t => new { Name = t.Name, Diffuse = t.FrontSurface.Diffuse, Alpha = t.FrontSurface.Alpha })) { Texture texture; var an8Texture = material.Diffuse.TextureName != null? an8.Textures.FirstOrDefault(t => string.Equals(t.Name, material.Diffuse.TextureName, StringComparison.Ordinal)) : null; if (an8Texture == null) { byte r = material.Diffuse.Red; byte g = material.Diffuse.Green; byte b = material.Diffuse.Blue; int width = 8; int height = 8; int length = width * height; byte[] data = new byte[length * 4]; for (int i = 0; i < length; i++) { data[i * 4 + 0] = b; data[i * 4 + 1] = g; data[i * 4 + 2] = r; data[i * 4 + 3] = 255; } texture = new Texture(); texture.Name = material.Name; texture.Width = width; texture.Height = height; texture.ImageData = data; } else { string colorFileName = Path.Combine(an8Directory, Path.GetFileName(an8Texture.Files[0])); texture = Texture.FromFile(colorFileName); texture.Name = material.Name; } if (material.Alpha > 0 && material.Alpha < 255) { byte alpha = (byte)material.Alpha; int length = texture.Width * texture.Height; byte[] alphaData = new byte[length]; var data = texture.ImageData; for (int i = 0; i < length; i++) { alphaData[i] = alpha; data[i * 4 + 3] = alpha; } texture.AlphaData = alphaData; } opt.Textures.Add(texture.Name, texture); } opt.GenerateTexturesMipmaps(); return(opt); }
public OptModel(string fileName) { this.File = OptFile.FromFile(fileName); this.Cache = new OptCache(this.File); this.SpanSize = this.File.SpanSize; }
public static void OptToAn8(OptFile opt, string an8Path, bool scale) { if (opt == null) { throw new ArgumentNullException("opt"); } string an8Directory = Path.GetDirectoryName(an8Path); string an8Name = Path.GetFileNameWithoutExtension(an8Path); foreach (var texture in opt.Textures.Values) { texture.Save(Path.Combine(an8Directory, string.Concat(texture.Name, ".png"))); } var distances = opt.Meshes .SelectMany(t => t.Lods) .Select(t => t.Distance) .Distinct() .OrderByDescending(t => t) .ToArray(); for (int distance = 0; distance < distances.Length; distance++) { var an8 = new An8File(); foreach (var texture in opt.Textures.Values) { var an8Texture = new An8Texture(); an8Texture.Name = texture.Name; an8Texture.Files.Add(string.Concat(texture.Name, ".png")); an8.Textures.Add(an8Texture); var an8Material = new An8Material(); an8Material.Name = texture.Name; an8Material.FrontSurface = new An8Surface(); an8Material.FrontSurface.Diffuse = new An8MaterialColor { TextureName = texture.Name, TextureParams = new An8TextureParams { AlphaMode = texture.HasAlpha ? An8AlphaMode.Final : An8AlphaMode.None, BlendMode = An8BlendMode.Darken } }; an8.Materials.Add(an8Material); } var an8Object = new An8Object(); an8Object.Name = Path.GetFileNameWithoutExtension(opt.FileName); an8.Objects.Add(an8Object); int objectsIndex = 0; foreach (var mesh in opt.Meshes) { var lod = mesh.Lods.FirstOrDefault(t => t.Distance <= distances[distance]); if (lod == null) { continue; } var an8Mesh = new An8Mesh(); an8Mesh.Name = string.Format(CultureInfo.InvariantCulture, "{0}.{1:D3}", mesh.Descriptor.MeshType, objectsIndex); an8Object.Components.Add(an8Mesh); objectsIndex++; foreach (var texture in mesh.Lods .SelectMany(t => t.FaceGroups) .SelectMany(t => t.Textures) .Distinct()) { an8Mesh.MaterialList.Add(texture); } if (scale) { foreach (var v in mesh.Vertices) { an8Mesh.Points.Add(new An8Point { X = v.X * OptFile.ScaleFactor, Y = v.Z * OptFile.ScaleFactor, Z = v.Y * OptFile.ScaleFactor }); } } else { foreach (var v in mesh.Vertices) { an8Mesh.Points.Add(new An8Point { X = v.X, Y = v.Z, Z = v.Y }); } } foreach (var v in mesh.TextureCoordinates) { an8Mesh.TexCoords.Add(new An8TexCoord { U = v.U, V = -v.V }); } foreach (var v in mesh.VertexNormals) { an8Mesh.Normals.Add(new An8Point { X = v.X, Y = v.Z, Z = v.Y }); } int verticesIndex = 0; int verticesTexIndex = 0; int verticesNormalIndex = 0; foreach (var faceGroup in lod.FaceGroups) { int materialIndex = 0; if (faceGroup.Textures.Count > 0) { materialIndex = an8Mesh.MaterialList.IndexOf(faceGroup.Textures[0]); } foreach (var face in faceGroup.Faces) { if (face.VerticesIndex.D < 0) { var an8Face = new An8Face { MaterialIndex = materialIndex, FlatNormalIndex = -1 }; an8Face.PointIndexes = new int[] { verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C }; an8Face.TexCoordIndexes = new int[] { verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C }; an8Face.NormalIndexes = new int[] { verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C }; an8Mesh.Faces.Add(an8Face); } else { var an8Face = new An8Face { MaterialIndex = materialIndex, FlatNormalIndex = -1 }; an8Face.PointIndexes = new int[] { verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C, verticesIndex + face.VerticesIndex.D }; an8Face.TexCoordIndexes = new int[] { verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C, verticesTexIndex + face.TextureCoordinatesIndex.D }; an8Face.NormalIndexes = new int[] { verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C, verticesNormalIndex + face.VertexNormalsIndex.D }; an8Mesh.Faces.Add(an8Face); } } } verticesIndex += mesh.Vertices.Count; verticesTexIndex += mesh.TextureCoordinates.Count; verticesNormalIndex += mesh.VertexNormals.Count; } an8.Save(Path.Combine(an8Directory, string.Format(CultureInfo.InvariantCulture, "{0}_{1}.an8", an8Name, distance))); } }
public static void OptToAn8(OptFile opt, string an8Path) { Converter.OptToAn8(opt, an8Path, true); }
public TextureBrowserMessage(OptFile optFile) { this.OptFile = optFile; }
private List <ModelVisual3D> CreateMeshModel(OptFile opt, int meshIndex, int lodIndex, int version) { if (opt == null || opt.Meshes.ElementAtOrDefault(meshIndex) == null || opt.Meshes[meshIndex].Lods.ElementAtOrDefault(lodIndex) == null) { return(new List <ModelVisual3D>()); } var cache = this.Cache; var mesh = opt.Meshes[meshIndex]; var lod = mesh.Lods[lodIndex]; if (meshIndex >= cache.meshes.Length || lodIndex >= cache.meshes[meshIndex].Length || lod.FaceGroups.Count > cache.meshes[meshIndex][lodIndex].Length) { return(new List <ModelVisual3D>()); } List <ModelVisual3D> group = new List <ModelVisual3D>(); for (int faceGroupIndex = 0; faceGroupIndex < lod.FaceGroups.Count; faceGroupIndex++) { var faceGroup = lod.FaceGroups[faceGroupIndex]; Material texture = null; bool alpha = false; if (faceGroup.Textures.Count != 0) { int currentVersion = version; if (version < 0 || version >= faceGroup.Textures.Count) { currentVersion = faceGroup.Textures.Count - 1; } string textureName = faceGroup.Textures[currentVersion]; if (cache.textures.ContainsKey(textureName)) { texture = cache.textures[textureName]; alpha = opt.Textures[textureName].HasAlpha; } } var geometries = cache.meshes[meshIndex][lodIndex][faceGroupIndex]; if (alpha) { for (int i = 1; i < geometries.Length; i++) { GeometryModel3D model = new GeometryModel3D { Geometry = geometries[i], Material = texture ?? cache.nullTexture, BackMaterial = texture ?? cache.nullTexture }; model.Freeze(); group.Add(new ModelVisual3D() { Content = model }); this.ModelToMeshLodFace.Add(model, new MeshLodFace(opt.Meshes[meshIndex], opt.Meshes[meshIndex].Lods[lodIndex], faceGroup)); } } else { GeometryModel3D model = new GeometryModel3D { Geometry = geometries[0], Material = texture ?? cache.nullTexture }; model.Freeze(); group.Add(new ModelVisual3D() { Content = model }); this.ModelToMeshLodFace.Add(model, new MeshLodFace(opt.Meshes[meshIndex], opt.Meshes[meshIndex].Lods[lodIndex], faceGroup)); } } return(group); }
private static void ContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { var opt = (OptVisual3D)obj; switch (args.Property.Name) { case "FileName": opt.File = null; if (!string.IsNullOrEmpty(opt.FileName)) { try { opt.File = OptFile.FromFile(opt.FileName); } catch (InvalidDataException) { } } break; case "File": opt.Cache = null; if (opt.File != null) { opt.Cache = new OptCache(opt.File); } break; case "Cache": case "Mesh": case "Lod": case "Distance": case "Version": case "IsSolid": case "IsWireframe": if (opt.Distance == null) { opt.LoadOpt(opt.Mesh, opt.Lod, opt.Version); } else { opt.LoadOpt(opt.Mesh, opt.Distance.Value, opt.Version); } break; } opt.Changed?.Invoke(opt, EventArgs.Empty); switch (args.Property.Name) { case "Cache": case "Mesh": case "Lod": case "Distance": opt.ModelChanged?.Invoke(opt, EventArgs.Empty); break; case "Version": case "IsSolid": case "IsWireframe": opt.AppearanceChanged?.Invoke(opt, EventArgs.Empty); break; } }