private void SaveDAE(Root root, ExporterOptions options) { var exporter = new ColladaExporter(); exporter.Options = options; exporter.Export(root, options.OutputPath); }
private void Save(Root root, ExporterOptions options) { switch (options.OutputFormat) { case ExportFormat.GR2: FileManager.TryToCreateDirectory(options.OutputPath); SaveGR2(options.OutputPath, root); break; case ExportFormat.DAE: SaveDAE(root, options); break; default: throw new NotImplementedException("Unsupported output format"); } }
public mesh ExportToCollada(ExporterOptions options) { // TODO: model transform/inverse transform? source vertexSource = null; var sources = new List <source>(); ulong inputOffset = 0; var inputs = new List <InputLocal>(); var inputOffsets = new List <InputLocalOffset>(); foreach (var component in PrimaryVertexData.VertexComponentNames) { var input = new InputLocal(); source source = null; switch (component.String) { case "Position": { source = PrimaryVertexData.MakeColladaPositions(Name); vertexSource = source; input.semantic = "POSITION"; var vertexInputOff = new InputLocalOffset(); vertexInputOff.semantic = "VERTEX"; vertexInputOff.source = "#" + source.id; vertexInputOff.offset = inputOffset++; inputOffsets.Add(vertexInputOff); break; } case "Normal": { if (options.ExportNormals) { source = PrimaryVertexData.MakeColladaNormals(Name); input.semantic = "NORMAL"; } break; } case "Tangent": { if (options.ExportTangents) { source = PrimaryVertexData.MakeColladaTangents(Name); input.semantic = "TANGENT"; } break; } case "Binormal": { if (options.ExportTangents) { source = PrimaryVertexData.MakeColladaBinormals(Name); input.semantic = "BINORMAL"; } break; } case "MaxChannel_1": case "MaxChannel_2": case "UVChannel_1": case "UVChannel_2": { if (options.ExportUVs) { int uvIndex = Int32.Parse(component.String.Substring(11)) - 1; source = PrimaryVertexData.MakeColladaUVs(Name, uvIndex); var texInputOff = new InputLocalOffset(); texInputOff.semantic = "TEXCOORD"; texInputOff.source = "#" + source.id; texInputOff.offset = inputOffset++; inputOffsets.Add(texInputOff); } break; } case "BoneWeights": case "BoneIndices": // These are handled in ExportSkin() break; case "DiffuseColor0": case "map1": // Possibly bogus D:OS name for DiffuseColor0 // TODO: This is not exported at the moment. break; default: throw new NotImplementedException("Vertex component not supported: " + component.String); } if (source != null) { sources.Add(source); } if (input.semantic != null) { input.source = "#" + source.id; inputs.Add(input); } } var triangles = PrimaryTopology.MakeColladaTriangles( inputOffsets.ToArray(), PrimaryVertexData.Deduplicator.VertexDeduplicationMap, PrimaryVertexData.Deduplicator.UVDeduplicationMaps ); var colladaMesh = new mesh(); colladaMesh.vertices = new vertices(); colladaMesh.vertices.id = Name + "-vertices"; colladaMesh.vertices.input = inputs.ToArray(); colladaMesh.source = sources.ToArray(); colladaMesh.Items = new object[] { triangles }; return(colladaMesh); }
public void ImportFromCollada(mesh mesh, VertexDescriptor vertexFormat, bool isSkinned, ExporterOptions options) { Options = options; Mesh = mesh; ImportSources(); ImportFaces(); if (vertexFormat == null) { vertexFormat = FindVertexFormat(isSkinned); } InputVertexType = vertexFormat; OutputVertexType = new VertexDescriptor { HasPosition = InputVertexType.HasPosition, HasBoneWeights = InputVertexType.HasBoneWeights, NumBoneInfluences = InputVertexType.NumBoneInfluences, NormalType = InputVertexType.NormalType, TangentType = InputVertexType.TangentType, BinormalType = InputVertexType.BinormalType, ColorMapType = InputVertexType.ColorMapType, ColorMaps = InputVertexType.ColorMaps, TextureCoordinateType = InputVertexType.TextureCoordinateType, TextureCoordinates = InputVertexType.TextureCoordinates }; ImportVertices(); // TODO: This should be done before deduplication! // TODO: Move this to somewhere else ... ? if (!HasNormals || Options.RecalculateNormals) { if (!HasNormals) { Utils.Info(String.Format("Channel 'NORMAL' not found, will rebuild vertex normals after import.")); } HasNormals = true; OutputVertexType.NormalType = NormalType.Float3; computeNormals(); } ImportColors(); ImportUVs(); if (UVInputIndices.Count() > 0 || ColorInputIndices.Count() > 0 || NormalsInputIndex != -1 || TangentsInputIndex != -1 || BinormalsInputIndex != -1) { var outVertexIndices = new Dictionary <int[], int>(new VertexIndexComparer()); ConsolidatedIndices = new List <int>(TriangleCount * 3); ConsolidatedVertices = new List <Vertex>(Vertices.Count); OriginalToConsolidatedVertexIndexMap = new Dictionary <int, List <int> >(); for (var vert = 0; vert < TriangleCount * 3; vert++) { var index = new int[InputOffsetCount]; for (var i = 0; i < InputOffsetCount; i++) { index[i] = Indices[vert * InputOffsetCount + i]; } int consolidatedIndex; if (!outVertexIndices.TryGetValue(index, out consolidatedIndex)) { var vertexIndex = index[VertexInputIndex]; consolidatedIndex = ConsolidatedVertices.Count; Vertex vertex = Vertices[vertexIndex].Clone(); if (NormalsInputIndex != -1) { vertex.Normal = Normals[index[NormalsInputIndex]]; } if (TangentsInputIndex != -1) { vertex.Tangent = Tangents[index[TangentsInputIndex]]; } if (BinormalsInputIndex != -1) { vertex.Binormal = Binormals[index[BinormalsInputIndex]]; } for (int uv = 0; uv < UVInputIndices.Count(); uv++) { vertex.SetUV(uv, UVs[uv][index[UVInputIndices[uv]]]); } for (int color = 0; color < ColorInputIndices.Count(); color++) { vertex.SetColor(color, Colors[color][index[ColorInputIndices[color]]]); } outVertexIndices.Add(index, consolidatedIndex); ConsolidatedVertices.Add(vertex); List <int> mappedIndices = null; if (!OriginalToConsolidatedVertexIndexMap.TryGetValue(vertexIndex, out mappedIndices)) { mappedIndices = new List <int>(); OriginalToConsolidatedVertexIndexMap.Add(vertexIndex, mappedIndices); } mappedIndices.Add(consolidatedIndex); } ConsolidatedIndices.Add(consolidatedIndex); } Utils.Info(String.Format("Merged {0} vertices into {1} output vertices", Vertices.Count, ConsolidatedVertices.Count)); } else { Utils.Info(String.Format("Mesh has no separate normals, colors or UV map, vertex consolidation step skipped.")); ConsolidatedVertices = Vertices; ConsolidatedIndices = new List <int>(TriangleCount * 3); for (var vert = 0; vert < TriangleCount * 3; vert++) { ConsolidatedIndices.Add(VertexIndex(vert)); } OriginalToConsolidatedVertexIndexMap = new Dictionary <int, List <int> >(); for (var i = 0; i < Vertices.Count; i++) { OriginalToConsolidatedVertexIndexMap.Add(i, new List <int> { i }); } } if ((InputVertexType.TangentType == NormalType.None || InputVertexType.BinormalType == NormalType.None) && ((!HasTangents && UVs.Count > 0) || Options.RecalculateTangents)) { if (!HasTangents) { Utils.Info(String.Format("Channel 'TANGENT'/'BINROMAL' not found, will rebuild vertex tangents after import.")); } OutputVertexType.TangentType = NormalType.Float3; OutputVertexType.BinormalType = NormalType.Float3; HasTangents = true; computeTangents(); } // Use optimized tangent, texture map and color map format when exporting for D:OS 2 if ((Options.ModelInfoFormat == DivinityModelInfoFormat.LSMv0 || Options.ModelInfoFormat == DivinityModelInfoFormat.LSMv1) && HasNormals && HasTangents) { OutputVertexType.NormalType = NormalType.QTangent; OutputVertexType.TangentType = NormalType.QTangent; OutputVertexType.BinormalType = NormalType.QTangent; if (OutputVertexType.TextureCoordinateType == TextureCoordinateType.Float2) { OutputVertexType.TextureCoordinateType = TextureCoordinateType.Half2; } if (OutputVertexType.ColorMapType == ColorMapType.Float4) { OutputVertexType.ColorMapType = ColorMapType.Byte4; } } }
public void ImportFromCollada(mesh mesh, string vertexFormat, bool isSkinned, ExporterOptions options) { Options = options; Mesh = mesh; ImportSources(); ImportFaces(); if (vertexFormat == null) { vertexFormat = FindVertexFormat(isSkinned); } VertexType = VertexFormatRegistry.Resolve(vertexFormat); ImportVertices(); // TODO: This should be done before deduplication! // TODO: Move this to somewhere else ... ? if (!HasNormals || Options.RecalculateNormals) { if (!HasNormals) { Utils.Info(String.Format("Channel 'NORMAL' not found, will rebuild vertex normals after import.")); } computeNormals(); } ImportColors(); ImportUVs(); if (UVInputIndices.Count() > 0 || ColorInputIndices.Count() > 0) { var outVertexIndices = new Dictionary <int[], int>(new VertexIndexComparer()); ConsolidatedIndices = new List <int>(TriangleCount * 3); ConsolidatedVertices = new List <Vertex>(Vertices.Count); OriginalToConsolidatedVertexIndexMap = new Dictionary <int, List <int> >(); for (var vert = 0; vert < TriangleCount * 3; vert++) { var index = new int[InputOffsetCount]; for (var i = 0; i < InputOffsetCount; i++) { index[i] = Indices[vert * InputOffsetCount + i]; } int consolidatedIndex; if (!outVertexIndices.TryGetValue(index, out consolidatedIndex)) { var vertexIndex = index[VertexInputIndex]; consolidatedIndex = ConsolidatedVertices.Count; Vertex vertex = Vertices[vertexIndex].Clone(); for (int uv = 0; uv < UVInputIndices.Count(); uv++) { vertex.SetUV(uv, UVs[uv][index[UVInputIndices[uv]]]); } for (int color = 0; color < ColorInputIndices.Count(); color++) { vertex.SetColor(color, Colors[color][index[ColorInputIndices[color]]]); } outVertexIndices.Add(index, consolidatedIndex); ConsolidatedVertices.Add(vertex); List <int> mappedIndices = null; if (!OriginalToConsolidatedVertexIndexMap.TryGetValue(vertexIndex, out mappedIndices)) { mappedIndices = new List <int>(); OriginalToConsolidatedVertexIndexMap.Add(vertexIndex, mappedIndices); } mappedIndices.Add(consolidatedIndex); } ConsolidatedIndices.Add(consolidatedIndex); } Utils.Info(String.Format("Merged {0} vertices into {1} output vertices", Vertices.Count, ConsolidatedVertices.Count)); } else { Utils.Info(String.Format("Mesh has no UV map, vertex consolidation step skipped.")); ConsolidatedVertices = Vertices; ConsolidatedIndices = new List <int>(TriangleCount * 3); for (var vert = 0; vert < TriangleCount * 3; vert++) { ConsolidatedIndices.Add(VertexIndex(vert)); } OriginalToConsolidatedVertexIndexMap = new Dictionary <int, List <int> >(); for (var i = 0; i < Vertices.Count; i++) { OriginalToConsolidatedVertexIndexMap.Add(i, new List <int> { i }); } } var description = Vertex.Description(VertexType); if ((description.Tangent && description.Binormal) && (!HasTangents || Options.RecalculateTangents)) { if (!HasTangents) { Utils.Info(String.Format("Channel 'TANGENT'/'BINROMAL' not found, will rebuild vertex tangents after import.")); } computeTangents(); } }
public ColladaMeshExporter(Mesh mesh, ExporterOptions options) { ExportedMesh = mesh; Options = options; }
private void UpdateCommonExporterSettings(ExporterOptions settings) { var game = GetGame(); if (game == DivGame.DOS) { settings.Is64Bit = false; settings.AlternateSignature = false; settings.VersionTag = Header.Tag_DOS; } else { settings.Is64Bit = true; settings.AlternateSignature = true; settings.VersionTag = Header.Tag_DOSEE; } settings.ExportNormals = exportNormals.Checked; settings.ExportTangents = exportTangents.Checked; settings.ExportUVs = exportUVs.Checked; settings.RecalculateNormals = recalculateNormals.Checked; settings.RecalculateTangents = recalculateTangents.Checked; settings.RecalculateIWT = recalculateJointIWT.Checked; settings.BuildDummySkeleton = buildDummySkeleton.Checked; settings.CompactIndices = use16bitIndex.Checked; settings.DeduplicateVertices = deduplicateVertices.Checked; settings.DeduplicateUVs = filterUVs.Checked; settings.ApplyBasisTransforms = applyBasisTransforms.Checked; settings.UseObsoleteVersionTag = forceLegacyVersion.Checked; if (conformToOriginal.Checked && conformantGR2Path.Text.Length > 0) { settings.ConformGR2Path = conformantGR2Path.Text; } else { settings.ConformGR2Path = null; } }
private void UpdateExporterSettings(ExporterOptions settings) { UpdateCommonExporterSettings(settings); settings.InputPath = inputPath.Text; if (settings.InputPath.Substring(settings.InputPath.Length - 4).ToLower() == ".gr2") { settings.InputFormat = ExportFormat.GR2; } else { settings.InputFormat = ExportFormat.DAE; } settings.OutputPath = outputPath.Text; if (settings.OutputPath.Substring(settings.OutputPath.Length - 4).ToLower() == ".gr2") { settings.OutputFormat = ExportFormat.GR2; } else { settings.OutputFormat = ExportFormat.DAE; } foreach (var item in resourceFormats.Items) { var setting = item as ListViewItem; var name = setting.SubItems[0].Text; var type = setting.SubItems[1].Text; var value = setting.SubItems[2].Text; if (type == "Mesh" && value != "Automatic") { settings.VertexFormats.Add(name, value); } } }