using System; using System.Collections.Generic; using System.Globalization; using System.IO; namespace Oni.Motoko { internal class GeometryImporter : Importer { private readonly bool generateNormals; private readonly bool flatNormals; private readonly float shellOffset; private readonly bool overrideTextureName; private string textureName; public GeometryImporter(string[] args) { foreach (string arg in args) { if (arg == "-normals") { generateNormals = true; } else if (arg == "-flat") { flatNormals = true; } else if (arg == "-cel" || arg.StartsWith("-cel:", StringComparison.Ordinal)) { int i = arg.IndexOf(':'); if (i != -1) shellOffset = float.Parse(arg.Substring(i + 1), CultureInfo.InvariantCulture); else shellOffset = 0.07f; } else if (arg.StartsWith("-tex:", StringComparison.Ordinal)) { textureName = arg.Substring(5); overrideTextureName = true; } } } public ImporterDescriptor Import(string filePath, ImporterFile importer) { var scene = Dae.Reader.ReadFile(filePath); Dae.FaceConverter.Triangulate(scene); var daeInstances = new List(); foreach (var node in scene.Nodes) { var daeInstance = node.GeometryInstances.FirstOrDefault(); if (daeInstance == null || daeInstance.Target == null) continue; daeInstances.Add(daeInstance); } foreach (var daeInstance in daeInstances) { var daeGeometry = daeInstance.Target; var geometry = GeometryDaeReader.Read(daeGeometry, generateNormals, flatNormals, shellOffset); string textureFilePath = null; if (!overrideTextureName && daeInstance.Materials.Count > 0) textureFilePath = ReadMaterial(daeInstance.Materials[0].Target); geometry.TextureName = Path.GetFileNameWithoutExtension(textureFilePath); return GeometryDatWriter.Write(geometry, importer); } return null; } public override void Import(string filePath, string outputDirPath) { var scene = Dae.Reader.ReadFile(filePath); Dae.FaceConverter.Triangulate(scene); var daeInstances = new List(); foreach (var node in scene.Nodes) { var daeInstance = node.GeometryInstances.FirstOrDefault(); if (daeInstance == null || daeInstance.Target == null) continue; daeInstances.Add(daeInstance); } foreach (var daeInstance in daeInstances) { var daeGeometry = daeInstance.Target; var geometry = GeometryDaeReader.Read(daeGeometry, generateNormals, flatNormals, shellOffset); geometry.Name = Path.GetFileNameWithoutExtension(filePath); if (daeInstances.Count > 1) geometry.Name += daeGeometry.Name; string textureFilePath = null; if (!overrideTextureName && daeInstance.Materials.Count > 0) textureFilePath = ReadMaterial(daeInstance.Materials[0].Target); WriteM3GM(geometry, textureFilePath, outputDirPath); } } private void WriteM3GM(Geometry geometry, string textureFilePath, string outputDirPath) { geometry.Name = MakeInstanceName(TemplateTag.M3GM, geometry.Name); if (string.IsNullOrEmpty(textureFilePath)) geometry.TextureName = textureName; else geometry.TextureName = Path.GetFileNameWithoutExtension(textureFilePath); BeginImport(); GeometryDatWriter.Write(geometry, ImporterFile); Write(outputDirPath); } private string ReadMaterial(Dae.Material material) { if (material == null || material.Effect == null) return null; var texture = material.Effect.Textures.FirstOrDefault(t => t.Channel == Dae.EffectTextureChannel.Diffuse); if (texture == null) return null; var sampler = texture.Sampler; if (sampler == null || sampler.Surface == null || sampler.Surface.InitFrom == null || string.IsNullOrEmpty(sampler.Surface.InitFrom.FilePath)) return null; return sampler.Surface.InitFrom.FilePath; } } }