BabylonExporter.Texture.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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, intArray.Length * 4);
  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 currentSize = Math.Max(width, height);
  28. while (currentSize > 1)
  29. {
  30. currentSize = currentSize >> 1;
  31. expected++;
  32. }
  33. RaiseWarning(string.Format("Mipmaps chain is not complete: {0} maps instead of {1} (based on texture max size: {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, out BabylonFresnelParameters fresnelParameters, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
  46. {
  47. fresnelParameters = null;
  48. if (!stdMat.MapEnabled(index))
  49. {
  50. return null;
  51. }
  52. var babylonTexture = new BabylonTexture();
  53. var texMap = stdMat.GetSubTexmap(index);
  54. // Fallout
  55. if (texMap.ClassName == "Falloff") // This is the only way I found to detect it. This is crappy but it works
  56. {
  57. fresnelParameters = new BabylonFresnelParameters();
  58. var paramBlock = texMap.GetParamBlock(0);
  59. var color1 = paramBlock.GetColor(0, 0, 0);
  60. var color2 = paramBlock.GetColor(4, 0, 0);
  61. fresnelParameters.isEnabled = true;
  62. fresnelParameters.leftColor = color2.ToArray();
  63. fresnelParameters.rightColor = color1.ToArray();
  64. if (paramBlock.GetInt(8, 0, 0) == 2)
  65. {
  66. fresnelParameters.power = paramBlock.GetFloat(12, 0, 0);
  67. }
  68. else
  69. {
  70. fresnelParameters.power = 1;
  71. }
  72. var texMap1 = paramBlock.GetTexmap(2, 0, 0);
  73. var texMap1On = paramBlock.GetInt(3, 0, 0);
  74. var texMap2 = paramBlock.GetTexmap(6, 0, 0);
  75. var texMap2On = paramBlock.GetInt(7, 0, 0);
  76. if (texMap1 != null && texMap1On != 0)
  77. {
  78. texMap = texMap1;
  79. fresnelParameters.rightColor = new float[] { 1, 1, 1 };
  80. if (texMap2 != null && texMap2On != 0)
  81. {
  82. RaiseWarning(string.Format("You cannot specify two textures for falloff. Only one is supported"), 2);
  83. }
  84. }
  85. else if (texMap2 != null && texMap2On != 0)
  86. {
  87. fresnelParameters.leftColor = new float[] { 1, 1, 1 };
  88. texMap = texMap2;
  89. }
  90. else
  91. {
  92. return null;
  93. }
  94. }
  95. // Bitmap
  96. var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;
  97. if (texture == null)
  98. {
  99. return null;
  100. }
  101. if (forceAlpha)
  102. {
  103. babylonTexture.hasAlpha = true;
  104. babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3);
  105. }
  106. else
  107. {
  108. babylonTexture.hasAlpha = (texture.AlphaSource != 3);
  109. babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
  110. }
  111. babylonTexture.level = stdMat.GetTexmapAmt(index, 0);
  112. var uvGen = texture.UVGen;
  113. switch (uvGen.GetCoordMapping(0))
  114. {
  115. case 1: //MAP_SPHERICAL
  116. babylonTexture.coordinatesMode = 1;
  117. break;
  118. case 2: //MAP_PLANAR
  119. babylonTexture.coordinatesMode = 2;
  120. break;
  121. default:
  122. babylonTexture.coordinatesMode = 0;
  123. break;
  124. }
  125. babylonTexture.coordinatesIndex = uvGen.MapChannel - 1;
  126. if (uvGen.MapChannel > 2)
  127. {
  128. RaiseWarning(string.Format("Unsupported map channel, Only channel 1 and 2 are supported."), 2);
  129. }
  130. babylonTexture.uOffset = uvGen.GetUOffs(0);
  131. babylonTexture.vOffset = uvGen.GetVOffs(0);
  132. babylonTexture.uScale = uvGen.GetUScl(0);
  133. babylonTexture.vScale = uvGen.GetVScl(0);
  134. if (Path.GetExtension(texture.MapName).ToLower() == ".dds")
  135. {
  136. babylonTexture.vScale *= -1; // Need to invert Y-axis for DDS texture
  137. }
  138. babylonTexture.uAng = uvGen.GetUAng(0);
  139. babylonTexture.vAng = uvGen.GetVAng(0);
  140. babylonTexture.wAng = uvGen.GetWAng(0);
  141. babylonTexture.wrapU = 0; // CLAMP
  142. if ((uvGen.TextureTiling & 1) != 0) // WRAP
  143. {
  144. babylonTexture.wrapU = 1;
  145. }
  146. else if ((uvGen.TextureTiling & 4) != 0) // MIRROR
  147. {
  148. babylonTexture.wrapU = 2;
  149. }
  150. babylonTexture.wrapV = 0; // CLAMP
  151. if ((uvGen.TextureTiling & 2) != 0) // WRAP
  152. {
  153. babylonTexture.wrapV = 1;
  154. }
  155. else if ((uvGen.TextureTiling & 8) != 0) // MIRROR
  156. {
  157. babylonTexture.wrapV = 2;
  158. }
  159. babylonTexture.name = Path.GetFileName(texture.MapName);
  160. // Animations
  161. var animations = new List<BabylonAnimation>();
  162. ExportFloatAnimation("uOffset", animations, key => new[] { uvGen.GetUOffs(key) });
  163. ExportFloatAnimation("vOffset", animations, key => new[] { uvGen.GetVOffs(key) });
  164. ExportFloatAnimation("uScale", animations, key => new[] { uvGen.GetUScl(key) });
  165. ExportFloatAnimation("vScale", animations, key => new[] { uvGen.GetVScl(key) });
  166. ExportFloatAnimation("uAng", animations, key => new[] { uvGen.GetUAng(key) });
  167. ExportFloatAnimation("vAng", animations, key => new[] { uvGen.GetVAng(key) });
  168. ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });
  169. babylonTexture.animations = animations.ToArray();
  170. // Copy texture to output
  171. try
  172. {
  173. if (File.Exists(texture.MapName))
  174. {
  175. babylonTexture.isCube = IsTextureCube(texture.MapName);
  176. if (CopyTexturesToOutput)
  177. {
  178. File.Copy(texture.MapName, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
  179. }
  180. }
  181. else
  182. {
  183. var texturepath = Path.Combine(Path.GetDirectoryName(Loader.Core.CurFilePath), babylonTexture.name);
  184. if (File.Exists(texturepath))
  185. {
  186. babylonTexture.isCube = IsTextureCube(texturepath);
  187. if (CopyTexturesToOutput)
  188. {
  189. File.Copy(texturepath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
  190. }
  191. }
  192. else
  193. {
  194. RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
  195. }
  196. }
  197. }
  198. catch
  199. {
  200. // silently fails
  201. }
  202. if (babylonTexture.isCube && !allowCube)
  203. {
  204. RaiseWarning(string.Format("Cube texture are only supported for reflection channel"), 2);
  205. }
  206. return babylonTexture;
  207. }
  208. }
  209. }