SceneBuilder.Meshes.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. using System;
  2. using BabylonExport.Entities;
  3. using UnityEngine;
  4. namespace Unity3D2Babylon
  5. {
  6. partial class SceneBuilder
  7. {
  8. private BabylonAbstractMesh ConvertUnityMeshToInstance(GameObject gameObject)
  9. {
  10. BabylonAbstractMesh babylonMesh = new BabylonAbstractMesh();
  11. Transform transform = gameObject.transform;
  12. babylonMesh.name = gameObject.name;
  13. babylonMesh.position = new float[3];
  14. babylonMesh.position[0] = transform.position.x;
  15. babylonMesh.position[1] = transform.position.y;
  16. babylonMesh.position[2] = transform.position.z;
  17. babylonMesh.rotation = new float[3];
  18. babylonMesh.rotation[0] = transform.rotation.eulerAngles.x * (float)Math.PI / 180;
  19. babylonMesh.rotation[1] = transform.rotation.eulerAngles.y * (float)Math.PI / 180;
  20. babylonMesh.rotation[2] = transform.rotation.eulerAngles.z * (float)Math.PI / 180;
  21. babylonMesh.scaling = new float[3];
  22. babylonMesh.scaling[0] = transform.localScale.x;
  23. babylonMesh.scaling[1] = transform.localScale.y;
  24. babylonMesh.scaling[2] = transform.localScale.z;
  25. return babylonMesh;
  26. }
  27. private void ConvertTransform(BabylonMesh babylonMesh, Transform transform, GameObject gameObject, BabylonAbstractMesh[] instances = null)
  28. {
  29. Action SetTransformFromGameobject = () =>
  30. {
  31. babylonMesh.position = transform.localPosition.ToFloat();
  32. babylonMesh.rotation = new float[3];
  33. babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
  34. babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
  35. babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
  36. babylonMesh.scaling = transform.localScale.ToFloat();
  37. };
  38. Action SetTransformFromFirstInstance = () =>
  39. {
  40. BabylonAbstractMesh first = instances[0];
  41. babylonMesh.position = new float[3];
  42. babylonMesh.position[0] = first.position[0];
  43. babylonMesh.position[1] = first.position[1];
  44. babylonMesh.position[2] = first.position[2];
  45. babylonMesh.rotation = new float[3];
  46. babylonMesh.rotation[0] = first.rotation[0];
  47. babylonMesh.rotation[1] = first.rotation[1];
  48. babylonMesh.rotation[2] = first.rotation[2];
  49. babylonMesh.scaling = new float[3];
  50. babylonMesh.scaling[0] = first.scaling[0];
  51. babylonMesh.scaling[1] = first.scaling[1];
  52. babylonMesh.scaling[2] = first.scaling[2];
  53. };
  54. //Check if this is a prefab
  55. if (instances != null)
  56. {
  57. /*
  58. Unity3D prefabs don't have transforms (position, rotation, scale) because they are just a template and are not drawn on screen
  59. but Babylon.js meshes must have a transform because they are drawn on the screen
  60. so what we do is take the first instance
  61. copy its transform (position, rotation, scale) into the prefab mesh
  62. then remove that first instance
  63. */
  64. BabylonAbstractMesh first = instances[0];
  65. babylonMesh.instances = new BabylonAbstractMesh[instances.Length - 1];
  66. //Effectively remove first instance from list of all instances
  67. for (int i = 0; i < instances.Length - 1; i++)
  68. {
  69. babylonMesh.instances[i] = instances[i + 1];
  70. }
  71. //If this is the root object then copy values directly from first instance
  72. if (GetParentID(transform) == null)
  73. {
  74. babylonMesh.position = new float[3];
  75. babylonMesh.position[0] = first.position[0];
  76. babylonMesh.position[1] = first.position[1];
  77. babylonMesh.position[2] = first.position[2];
  78. babylonMesh.rotation = new float[3];
  79. babylonMesh.rotation[0] = first.rotation[0];
  80. babylonMesh.rotation[1] = first.rotation[1];
  81. babylonMesh.rotation[2] = first.rotation[2];
  82. babylonMesh.scaling = new float[3];
  83. babylonMesh.scaling[0] = first.scaling[0];
  84. babylonMesh.scaling[1] = first.scaling[1];
  85. babylonMesh.scaling[2] = first.scaling[2];
  86. }
  87. else
  88. {
  89. SetTransformFromGameobject();
  90. }
  91. }
  92. else
  93. {
  94. SetTransformFromGameobject();
  95. }
  96. }
  97. private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject, BabylonAbstractMesh[] instances = null)
  98. {
  99. BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
  100. var transform = gameObject.transform;
  101. babylonMesh.parentId = GetParentID(transform);
  102. ConvertTransform(babylonMesh, transform, gameObject, instances);
  103. babylonScene.MeshesList.Add(babylonMesh);
  104. // Animations
  105. ExportAnimations(transform, babylonMesh);
  106. if (IsRotationQuaternionAnimated(babylonMesh))
  107. {
  108. babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
  109. }
  110. }
  111. private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress, BabylonAbstractMesh[] instances = null)
  112. {
  113. BabylonMesh babylonMesh = new BabylonMesh();
  114. var renderer = gameObject.GetComponent<Renderer>();
  115. ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name);
  116. babylonMesh.name = gameObject.name;
  117. babylonMesh.id = GetID(transform.gameObject);
  118. babylonMesh.receiveShadows = renderer.receiveShadows;
  119. babylonMesh.parentId = GetParentID(transform);
  120. ConvertTransform(babylonMesh, transform, gameObject, instances);
  121. babylonMesh.positions = new float[mesh.vertexCount * 3];
  122. for (int i = 0; i < mesh.vertices.Length; i++)
  123. {
  124. babylonMesh.positions[i * 3] = mesh.vertices[i].x;
  125. babylonMesh.positions[(i * 3) + 1] = mesh.vertices[i].y;
  126. babylonMesh.positions[(i * 3) + 2] = mesh.vertices[i].z;
  127. // Computing world extends
  128. var worldPosition = transform.TransformPoint(mesh.vertices[i]);
  129. if (worldPosition.x > babylonScene.MaxVector.X)
  130. {
  131. babylonScene.MaxVector.X = worldPosition.x;
  132. }
  133. if (worldPosition.y > babylonScene.MaxVector.Y)
  134. {
  135. babylonScene.MaxVector.Y = worldPosition.y;
  136. }
  137. if (worldPosition.z > babylonScene.MaxVector.Z)
  138. {
  139. babylonScene.MaxVector.Z = worldPosition.z;
  140. }
  141. if (worldPosition.x < babylonScene.MinVector.X)
  142. {
  143. babylonScene.MinVector.X = worldPosition.x;
  144. }
  145. if (worldPosition.y < babylonScene.MinVector.Y)
  146. {
  147. babylonScene.MinVector.Y = worldPosition.y;
  148. }
  149. if (worldPosition.z < babylonScene.MinVector.Z)
  150. {
  151. babylonScene.MinVector.Z = worldPosition.z;
  152. }
  153. }
  154. babylonMesh.normals = new float[mesh.vertexCount * 3];
  155. for (int i = 0; i < mesh.normals.Length; i++)
  156. {
  157. babylonMesh.normals[i * 3] = mesh.normals[i].x;
  158. babylonMesh.normals[(i * 3) + 1] = mesh.normals[i].y;
  159. babylonMesh.normals[(i * 3) + 2] = mesh.normals[i].z;
  160. }
  161. babylonMesh.uvs = new float[mesh.vertexCount * 2];
  162. for (int i = 0; i < mesh.uv.Length; i++)
  163. {
  164. babylonMesh.uvs[i * 2] = mesh.uv[i].x;
  165. babylonMesh.uvs[(i * 2) + 1] = mesh.uv[i].y;
  166. }
  167. if (mesh.uv2 != null)
  168. {
  169. babylonMesh.uvs2 = new float[mesh.vertexCount * 2];
  170. for (int i = 0; i < mesh.uv2.Length; i++)
  171. {
  172. babylonMesh.uvs2[i * 2] = mesh.uv2[i].x;
  173. babylonMesh.uvs2[(i * 2) + 1] = mesh.uv2[i].y;
  174. }
  175. }
  176. babylonMesh.indices = new int[mesh.triangles.Length];
  177. for (int i = 0; i < mesh.triangles.Length; i += 3)
  178. {
  179. babylonMesh.indices[i] = mesh.triangles[i + 2];
  180. babylonMesh.indices[i + 1] = mesh.triangles[i + 1];
  181. babylonMesh.indices[i + 2] = mesh.triangles[i];
  182. }
  183. if (mesh.subMeshCount > 1) // Multimaterials
  184. {
  185. BabylonMultiMaterial bMultiMat;
  186. if (!multiMatDictionary.ContainsKey(renderer.sharedMaterial.name))
  187. {
  188. bMultiMat = new BabylonMultiMaterial
  189. {
  190. materials = new string[mesh.subMeshCount],
  191. id = Guid.NewGuid().ToString(),
  192. name = renderer.sharedMaterial.name
  193. };
  194. for (int i = 0; i < renderer.sharedMaterials.Length; i++)
  195. {
  196. var bMat = DumpMaterial(renderer.sharedMaterials[i], renderer);
  197. bMultiMat.materials[i] = bMat.id;
  198. }
  199. if (mesh.subMeshCount > 1)
  200. {
  201. multiMatDictionary.Add(bMultiMat.name, bMultiMat);
  202. }
  203. }
  204. else
  205. {
  206. bMultiMat = multiMatDictionary[renderer.sharedMaterial.name];
  207. }
  208. babylonMesh.materialId = bMultiMat.id;
  209. babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount];
  210. var offset = 0;
  211. for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++)
  212. {
  213. var unityTriangles = mesh.GetTriangles(materialIndex);
  214. babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh
  215. {
  216. verticesStart = 0,
  217. verticesCount = mesh.vertexCount,
  218. materialIndex = materialIndex,
  219. indexStart = offset,
  220. indexCount = unityTriangles.Length
  221. };
  222. offset += unityTriangles.Length;
  223. }
  224. }
  225. else
  226. {
  227. babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer).id;
  228. }
  229. babylonScene.MeshesList.Add(babylonMesh);
  230. // Animations
  231. ExportAnimations(transform, babylonMesh);
  232. if (IsRotationQuaternionAnimated(babylonMesh))
  233. {
  234. babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
  235. }
  236. // Collisions
  237. if (exportationOptions.ExportCollisions)
  238. {
  239. var collider = gameObject.GetComponent<Collider>();
  240. if (collider != null)
  241. {
  242. babylonMesh.checkCollisions = true;
  243. }
  244. }
  245. }
  246. }
  247. }