Model I/O: 2. UV Set fuer MDLMesh

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • ja, sorry, wenn das etwas knapp war... daher hier etwas ausfuehrlicher - in der Hoffnung dass es ueberhaupt Leute gibt, die sich native 3D antun...

    Also ich suche einen Weg, wie ich ein 2. UV-Set implementieren kann. Das erste brauche ich fuer kachelbare diffuse Maps und das zweite fuer eine objekt-bezogene 'Ganzkoerper'-Normal Map.

    Zu diesem Zweck verwende ich das CTM-Format, das passt auch alles soweit. Siehe Code.

    Nun suche ich einen Weg, das 2. UV-Set so zu implementieren dass ich es zumindest erstmal bis in die SCNGeometry hinueberretten kann. Im gegensatz zu Unity-3D scheint es dafuer wohl keine dedizierte VertexAttribute-Semantik zu geben, so dass ich mich schweren Herzens mit dem gedanken trage ein anderes Attribute zu verwenden. Das waere meine erste Frage gewesen... ist unten auskommentiert.

    Der Spass geht dann natuerlich auf der SCN-Ebene weiter, wobei es wohl auf einen Custom-Shader hinauslaufen wird, was wohl auf SCN-Ebene (im Gegensatz zur Model IO-Ebene) kein Problem ist. Auch hier waere ich ueber Gedankenaustausch/Tipps dankbar.

    Mahlzeit,

    Ekki

    Quellcode

    1. using System;
    2. using System.IO;
    3. using OpenCTM;
    4. using ModelIO;
    5. // https://developer.apple.com/videos/play/wwdc2015/602/
    6. namespace IG.Mobile.Planning.iOS
    7. {
    8. public static class D3OpenCtm
    9. {
    10. /// <summary>
    11. /// Submeshes seem to need an initial non-null material otherwise staying white.
    12. /// </summary>
    13. static readonly MDLMaterial defaultMaterial = new MDLMaterial();
    14. public static MDLMesh FromCtm(FileStream stream)
    15. {
    16. var tReader = new CtmFileReader(stream);
    17. var tSourceMesh = tReader.decode();
    18. var tVertexCount = tSourceMesh.getVertexCount();
    19. var tAllocator = new MDLMeshBufferDataAllocator();
    20. #region Indices
    21. var tByteArray = new byte[tSourceMesh.indices.Length * sizeof(int)];
    22. Buffer.BlockCopy(tSourceMesh.indices, 0, tByteArray, 0, tByteArray.Length);
    23. var tIndexBuffer = tAllocator.CreateBuffer(Foundation.NSData.FromArray(tByteArray), MDLMeshBufferType.Index);
    24. #endregion
    25. #region Configuration
    26. var tHasNormals = tSourceMesh.hasNormals();
    27. float[] tUVCoordinates = null;
    28. float[] tUV2Coordinates = null;
    29. if (tSourceMesh.texCoordinates != null)
    30. {
    31. foreach (var tData in tSourceMesh.texCoordinates)
    32. {
    33. switch (tData.name)
    34. {
    35. case OpenCTM.Mesh.DiffuseColor:
    36. tUVCoordinates = tData.values;
    37. break;
    38. case OpenCTM.Mesh.Object:
    39. tUV2Coordinates = tData.values;
    40. break;
    41. }
    42. }
    43. }
    44. var tHasUVs = tUVCoordinates != null;
    45. var tHasUV2s = tUV2Coordinates != null;
    46. #endregion
    47. #region Vertices
    48. var tVertexSize = 3;
    49. if (tHasNormals)
    50. {
    51. tVertexSize += 3;
    52. }
    53. if (tHasUVs)
    54. {
    55. tVertexSize += 2;
    56. }
    57. if (tHasUV2s)
    58. {
    59. tVertexSize += 2;
    60. }
    61. var tVertices = new float[tVertexCount * tVertexSize];
    62. var tVCnt = 0;
    63. var tPCnt = 0;
    64. var tNCnt = 0;
    65. var tUVCnt = 0;
    66. var tUV2Cnt = 0;
    67. for (var tI = 0; tI < tVertexCount; tI++)
    68. {
    69. tVertices[tVCnt++] = tSourceMesh.vertices[tPCnt++];
    70. tVertices[tVCnt++] = tSourceMesh.vertices[tPCnt++];
    71. tVertices[tVCnt++] = tSourceMesh.vertices[tPCnt++];
    72. if (tHasNormals)
    73. {
    74. tVertices[tVCnt++] = tSourceMesh.normals[tNCnt++];
    75. tVertices[tVCnt++] = tSourceMesh.normals[tNCnt++];
    76. tVertices[tVCnt++] = tSourceMesh.normals[tNCnt++];
    77. }
    78. if (tHasUVs)
    79. {
    80. tVertices[tVCnt++] = tUVCoordinates[tUVCnt++];
    81. tVertices[tVCnt++] = tUVCoordinates[tUVCnt++];
    82. }
    83. if (tHasUV2s)
    84. {
    85. tVertices[tVCnt++] = tUV2Coordinates[tUV2Cnt++];
    86. tVertices[tVCnt++] = tUV2Coordinates[tUV2Cnt++];
    87. }
    88. }
    89. tByteArray = new byte[tVertices.Length * sizeof(float)];
    90. Buffer.BlockCopy(tVertices, 0, tByteArray, 0, tByteArray.Length);
    91. var tVertexBuffer = tAllocator.CreateBuffer(Foundation.NSData.FromArray(tByteArray), MDLMeshBufferType.Vertex);
    92. #endregion
    93. #region Creation
    94. var tVertexDescriptor = new MDLVertexDescriptor();
    95. var tVertexAttribute = new MDLVertexAttribute(MDLVertexAttributes.Position, MDLVertexFormat.Float3, 0, 0);
    96. tVertexDescriptor.AddOrReplaceAttribute(tVertexAttribute);
    97. var tOffset = (nuint)3;
    98. if (tHasNormals)
    99. {
    100. tVertexAttribute = new MDLVertexAttribute(MDLVertexAttributes.Normal, MDLVertexFormat.Float3, tOffset * sizeof(float), 0);
    101. tVertexDescriptor.AddOrReplaceAttribute(tVertexAttribute);
    102. tOffset += 3;
    103. }
    104. if (tHasUVs)
    105. {
    106. tVertexAttribute = new MDLVertexAttribute(MDLVertexAttributes.TextureCoordinate, MDLVertexFormat.Float2, tOffset * sizeof(float), 0);
    107. tVertexDescriptor.AddOrReplaceAttribute(tVertexAttribute);
    108. tOffset += 2;
    109. }
    110. if (tHasUV2s)
    111. {
    112. // tVertexAttribute = new MDLVertexAttribute(MDLVertexAttributes., MDLVertexFormat.Float2, tOffset * sizeof(float), 0);
    113. // tVertexDescriptor.AddOrReplaceAttribute(tVertexAttribute);
    114. tOffset += 2;
    115. }
    116. tVertexDescriptor.Layouts = new Foundation.NSMutableArray<MDLVertexBufferLayout>(new MDLVertexBufferLayout[]
    117. {
    118. new MDLVertexBufferLayout(tOffset * (sizeof(float)))
    119. });
    120. var tMesh = new MDLMesh(tVertexBuffer, (nuint)tVertexCount, tVertexDescriptor, new MDLSubmesh[]
    121. {
    122. new MDLSubmesh(tIndexBuffer, (nuint)tSourceMesh.indices.Length, MDLIndexBitDepth.UInt32, MDLGeometryType.Triangles, defaultMaterial)
    123. });
    124. /*
    125. if (!tHasNormals)
    126. {
    127. tMesh.AddNormals(MDLVertexAttributes.Normal, 0.2f);
    128. }
    129. */
    130. #endregion
    131. return tMesh;
    132. }
    133. }
    134. }
    Alles anzeigen
  • 1) man kann eine eigene MDL-Vertex-Attribute-Semantik definieren, z.B. MDLVertexAttributes.TextureCoordinate + "2"

    2) dann kommt das auf Ebene SCNGeometry sauber an und wird auch als Texturkoordinaten-GeometrySource erkannt (aufgrund welcher Heuristik auch immer)

    3) dann kann man den Index dieser GeometrySource innerhalb der TextureCoordinates-GeometrySources (wichtig!) der Normal-Map als mappingChannel mit geben.

    und alles laueft wie erwartet!