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 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 static void Unserialize(GR2Reader reader, Vertex v) { var d = v.Format; if (d.HasPosition) { v.Position = ReadVector3(reader); } if (d.HasBoneWeights) { if (d.NumBoneInfluences == 2) { v.BoneWeights = ReadInfluences2(reader); v.BoneIndices = ReadInfluences2(reader); } else { v.BoneWeights = ReadInfluences(reader); v.BoneIndices = ReadInfluences(reader); } } switch (d.NormalType) { case NormalType.None: break; case NormalType.Float3: v.Normal = ReadVector3(reader); break; case NormalType.Half4: v.Normal = ReadHalfVector4As3(reader); break; case NormalType.QTangent: { var qTangent = ReadQTangent(reader); v.Normal = qTangent.Row2; v.Tangent = qTangent.Row1; v.Binormal = qTangent.Row0; break; } } switch (d.TangentType) { case NormalType.None: break; case NormalType.Float3: v.Tangent = ReadVector3(reader); break; case NormalType.Half4: v.Tangent = ReadHalfVector4As3(reader); break; case NormalType.QTangent: break; // Tangent read from QTangent } switch (d.BinormalType) { case NormalType.None: break; case NormalType.Float3: v.Binormal = ReadVector3(reader); break; case NormalType.Half4: v.Binormal = ReadHalfVector4As3(reader); break; case NormalType.QTangent: break; // Binormal read from QTangent } if (d.ColorMaps > 0) { for (var i = 0; i < d.ColorMaps; i++) { Vector4 color; switch (d.ColorMapType) { case ColorMapType.Float4: color = ReadVector4(reader); break; case ColorMapType.Byte4: color = ReadNormalByteVector4(reader); break; default: throw new Exception($"Cannot unserialize color map: Unsupported format {d.ColorMapType}"); } v.SetColor(i, color); } } if (d.TextureCoordinates > 0) { for (var i = 0; i < d.TextureCoordinates; i++) { Vector2 uv; switch (d.TextureCoordinateType) { case TextureCoordinateType.Float2: uv = ReadVector2(reader); break; case TextureCoordinateType.Half2: uv = ReadHalfVector2(reader); break; default: throw new Exception($"Cannot unserialize UV map: Unsupported format {d.TextureCoordinateType}"); } v.SetUV(i, uv); } } }