BabylonExporter.Texture.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using Autodesk.Max;
  5. using BabylonExport.Entities;
  6. namespace Max2Babylon
  7. {
  8. partial class BabylonExporter
  9. {
  10. bool IsTextureCube(string filepath)
  11. {
  12. try
  13. {
  14. if (Path.GetExtension(filepath).ToLower() != ".dds")
  15. {
  16. return false;
  17. }
  18. var data = File.ReadAllBytes(filepath);
  19. var intArray = new int[data.Length / 4];
  20. Buffer.BlockCopy(data, 0, intArray, 0, data.Length);
  21. int width = intArray[4];
  22. int height = intArray[3];
  23. int mipmapsCount = intArray[7];
  24. if ((width >> (mipmapsCount -1)) > 1)
  25. {
  26. var expected = 1;
  27. var currentWidth = width;
  28. while (currentWidth > 1)
  29. {
  30. currentWidth = currentWidth >> 1;
  31. expected++;
  32. }
  33. RaiseWarning(string.Format("Mipmaps chain is not complete: {0} maps instead of {1} (based on texture width: {2})", mipmapsCount, expected, width), 2);
  34. RaiseWarning(string.Format("You must generate a complete mipmaps chain for .dds)"), 2);
  35. RaiseWarning(string.Format("Mipmaps will be disabled for this texture. If you want automatic texture generation you cannot use a .dds)"), 2);
  36. }
  37. bool isCube = (intArray[28] & 0x200) == 0x200;
  38. return isCube;
  39. }
  40. catch
  41. {
  42. return false;
  43. }
  44. }
  45. private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, BabylonScene babylonScene, Boolean allowCube = false)
  46. {
  47. if (!stdMat.MapEnabled(index))
  48. {
  49. return null;
  50. }
  51. var babylonTexture = new BabylonTexture();
  52. var texMap = stdMat.GetSubTexmap(index);
  53. var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;
  54. if (texture == null)
  55. {
  56. return null;
  57. }
  58. babylonTexture.hasAlpha = (texture.AlphaSource != 3);
  59. babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
  60. babylonTexture.level = stdMat.GetTexmapAmt(index, 0);
  61. var uvGen = texture.UVGen;
  62. switch (uvGen.GetCoordMapping(0))
  63. {
  64. case 1: //MAP_SPHERICAL
  65. babylonTexture.coordinatesMode = 1;
  66. break;
  67. case 2: //MAP_PLANAR
  68. babylonTexture.coordinatesMode = 2;
  69. break;
  70. default:
  71. babylonTexture.coordinatesMode = 0;
  72. break;
  73. }
  74. babylonTexture.coordinatesIndex = uvGen.MapChannel - 1;
  75. if (uvGen.MapChannel > 2)
  76. {
  77. RaiseWarning(string.Format("Unsupported map channel, Only channel 1 and 2 are supported."), 2);
  78. }
  79. babylonTexture.uOffset = uvGen.GetUOffs(0);
  80. babylonTexture.vOffset = uvGen.GetVOffs(0);
  81. babylonTexture.uScale = uvGen.GetUScl(0);
  82. babylonTexture.vScale = uvGen.GetVScl(0);
  83. if (Path.GetExtension(texture.MapName).ToLower() == ".dds")
  84. {
  85. babylonTexture.vScale *= -1; // Need to invert Y-axis for DDS texture
  86. }
  87. babylonTexture.uAng = uvGen.GetUAng(0);
  88. babylonTexture.vAng = uvGen.GetVAng(0);
  89. babylonTexture.wAng = uvGen.GetWAng(0);
  90. babylonTexture.wrapU = 0; // CLAMP
  91. if ((uvGen.TextureTiling & 1) != 0) // WRAP
  92. {
  93. babylonTexture.wrapU = 1;
  94. }
  95. else if ((uvGen.TextureTiling & 4) != 0) // MIRROR
  96. {
  97. babylonTexture.wrapU = 2;
  98. }
  99. babylonTexture.wrapV = 0; // CLAMP
  100. if ((uvGen.TextureTiling & 2) != 0) // WRAP
  101. {
  102. babylonTexture.wrapV = 1;
  103. }
  104. else if ((uvGen.TextureTiling & 8) != 0) // MIRROR
  105. {
  106. babylonTexture.wrapV = 2;
  107. }
  108. babylonTexture.name = Path.GetFileName(texture.MapName);
  109. // Animations
  110. var animations = new List<BabylonAnimation>();
  111. ExportFloatAnimation("uOffset", animations, key => new[] { uvGen.GetUOffs(key) });
  112. ExportFloatAnimation("vOffset", animations, key => new[] { uvGen.GetVOffs(key) });
  113. ExportFloatAnimation("uScale", animations, key => new[] { uvGen.GetUScl(key) });
  114. ExportFloatAnimation("vScale", animations, key => new[] { uvGen.GetVScl(key) });
  115. ExportFloatAnimation("uAng", animations, key => new[] { uvGen.GetUAng(key) });
  116. ExportFloatAnimation("vAng", animations, key => new[] { uvGen.GetVAng(key) });
  117. ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });
  118. babylonTexture.animations = animations.ToArray();
  119. // Copy texture to output
  120. try
  121. {
  122. if (File.Exists(texture.MapName))
  123. {
  124. if (CopyTexturesToOutput)
  125. {
  126. File.Copy(texture.MapName, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
  127. }
  128. babylonTexture.isCube = IsTextureCube(texture.MapName);
  129. }
  130. else
  131. {
  132. var texturepath = Path.Combine(Path.GetDirectoryName(Loader.Core.CurFilePath), babylonTexture.name);
  133. if (File.Exists(texturepath))
  134. {
  135. if (CopyTexturesToOutput)
  136. {
  137. File.Copy(texturepath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
  138. }
  139. babylonTexture.isCube = IsTextureCube(texturepath);
  140. }
  141. else
  142. {
  143. RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
  144. }
  145. }
  146. }
  147. catch
  148. {
  149. // silently fails
  150. }
  151. if (babylonTexture.isCube && !allowCube)
  152. {
  153. RaiseWarning(string.Format("Cube texture are only supported for reflection channel"), 2);
  154. }
  155. return babylonTexture;
  156. }
  157. }
  158. }