SceneBuilder.Meshes.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using BabylonExport.Entities;
  5. using UnityEngine;
  6. namespace Unity3D2Babylon
  7. {
  8. partial class SceneBuilder
  9. {
  10. private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject)
  11. {
  12. BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) };
  13. var transform = gameObject.transform;
  14. babylonMesh.parentId = GetParentID(transform);
  15. babylonMesh.position = transform.localPosition.ToFloat();
  16. babylonMesh.rotation = new float[3];
  17. babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
  18. babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
  19. babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
  20. babylonMesh.scaling = transform.localScale.ToFloat();
  21. babylonScene.MeshesList.Add(babylonMesh);
  22. // Animations
  23. ExportAnimations(transform, babylonMesh);
  24. if (IsRotationQuaternionAnimated(babylonMesh))
  25. {
  26. babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
  27. }
  28. }
  29. private BabylonMesh ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress)
  30. {
  31. BabylonMesh babylonMesh = new BabylonMesh();
  32. var renderer = gameObject.GetComponent<Renderer>();
  33. ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name);
  34. babylonMesh.name = gameObject.name;
  35. babylonMesh.id = GetID(transform.gameObject);
  36. if (renderer != null)
  37. {
  38. babylonMesh.receiveShadows = renderer.receiveShadows;
  39. }
  40. babylonMesh.parentId = GetParentID(transform);
  41. babylonMesh.position = transform.localPosition.ToFloat();
  42. babylonMesh.rotation = new float[3];
  43. babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
  44. babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
  45. babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;
  46. babylonMesh.scaling = transform.localScale.ToFloat();
  47. if (mesh != null)
  48. {
  49. babylonMesh.positions = new float[mesh.vertexCount * 3];
  50. for (int i = 0; i < mesh.vertices.Length; i++)
  51. {
  52. babylonMesh.positions[i * 3] = mesh.vertices[i].x;
  53. babylonMesh.positions[(i * 3) + 1] = mesh.vertices[i].y;
  54. babylonMesh.positions[(i * 3) + 2] = mesh.vertices[i].z;
  55. // Computing world extends
  56. var worldPosition = transform.TransformPoint(mesh.vertices[i]);
  57. if (worldPosition.x > babylonScene.MaxVector.X)
  58. {
  59. babylonScene.MaxVector.X = worldPosition.x;
  60. }
  61. if (worldPosition.y > babylonScene.MaxVector.Y)
  62. {
  63. babylonScene.MaxVector.Y = worldPosition.y;
  64. }
  65. if (worldPosition.z > babylonScene.MaxVector.Z)
  66. {
  67. babylonScene.MaxVector.Z = worldPosition.z;
  68. }
  69. if (worldPosition.x < babylonScene.MinVector.X)
  70. {
  71. babylonScene.MinVector.X = worldPosition.x;
  72. }
  73. if (worldPosition.y < babylonScene.MinVector.Y)
  74. {
  75. babylonScene.MinVector.Y = worldPosition.y;
  76. }
  77. if (worldPosition.z < babylonScene.MinVector.Z)
  78. {
  79. babylonScene.MinVector.Z = worldPosition.z;
  80. }
  81. }
  82. babylonMesh.normals = new float[mesh.vertexCount * 3];
  83. for (int i = 0; i < mesh.normals.Length; i++)
  84. {
  85. babylonMesh.normals[i * 3] = mesh.normals[i].x;
  86. babylonMesh.normals[(i * 3) + 1] = mesh.normals[i].y;
  87. babylonMesh.normals[(i * 3) + 2] = mesh.normals[i].z;
  88. }
  89. babylonMesh.uvs = new float[mesh.vertexCount * 2];
  90. for (int i = 0; i < mesh.uv.Length; i++)
  91. {
  92. babylonMesh.uvs[i * 2] = mesh.uv[i].x;
  93. babylonMesh.uvs[(i * 2) + 1] = mesh.uv[i].y;
  94. }
  95. babylonMesh.uvs2 = new float[mesh.vertexCount * 2];
  96. if (mesh.uv2 != null && mesh.uv2.Length > 0)
  97. {
  98. for (int i = 0; i < mesh.uv2.Length; i++)
  99. {
  100. babylonMesh.uvs2[i * 2] = mesh.uv2[i].x;
  101. babylonMesh.uvs2[(i * 2) + 1] = mesh.uv2[i].y;
  102. }
  103. }
  104. else
  105. {
  106. for (int i = 0; i < mesh.uv.Length; i++)
  107. {
  108. babylonMesh.uvs2[i * 2] = mesh.uv[i].x;
  109. babylonMesh.uvs2[(i * 2) + 1] = mesh.uv[i].y;
  110. }
  111. }
  112. babylonMesh.indices = new int[mesh.triangles.Length];
  113. for (int i = 0; i < mesh.triangles.Length; i += 3)
  114. {
  115. babylonMesh.indices[i] = mesh.triangles[i + 2];
  116. babylonMesh.indices[i + 1] = mesh.triangles[i + 1];
  117. babylonMesh.indices[i + 2] = mesh.triangles[i];
  118. }
  119. if (mesh.boneWeights.Length == mesh.vertexCount)
  120. {
  121. babylonMesh.matricesIndices = new int[mesh.vertexCount];
  122. babylonMesh.matricesWeights = new float[mesh.vertexCount * 4];
  123. for (int i = 0; i < mesh.vertexCount; i++)
  124. {
  125. // Weight Packing.
  126. babylonMesh.matricesIndices[i] = (mesh.boneWeights[i].boneIndex3 << 24) | (mesh.boneWeights[i].boneIndex2 << 16) | (mesh.boneWeights[i].boneIndex1 << 8) | mesh.boneWeights[i].boneIndex0;
  127. babylonMesh.matricesWeights[i * 4 + 0] = mesh.boneWeights[i].weight0;
  128. babylonMesh.matricesWeights[i * 4 + 1] = mesh.boneWeights[i].weight1;
  129. babylonMesh.matricesWeights[i * 4 + 2] = mesh.boneWeights[i].weight2;
  130. babylonMesh.matricesWeights[i * 4 + 3] = mesh.boneWeights[i].weight3;
  131. var totalWeight = mesh.boneWeights[i].weight0 + mesh.boneWeights[i].weight1 + mesh.boneWeights[i].weight2 + mesh.boneWeights[i].weight3;
  132. if (Mathf.Abs(totalWeight - 1.0f) > 0.01f)
  133. {
  134. throw new Exception("Total bone weights is not normalized for: " + mesh);
  135. }
  136. }
  137. }
  138. if (renderer != null && renderer.sharedMaterial != null)
  139. {
  140. if (mesh.subMeshCount > 1) // Multimaterials
  141. {
  142. BabylonMultiMaterial bMultiMat;
  143. if (!multiMatDictionary.ContainsKey(renderer.sharedMaterial.name))
  144. {
  145. bMultiMat = new BabylonMultiMaterial
  146. {
  147. materials = new string[mesh.subMeshCount],
  148. id = Guid.NewGuid().ToString(),
  149. name = renderer.sharedMaterial.name
  150. };
  151. for (int i = 0; i < renderer.sharedMaterials.Length; i++)
  152. {
  153. var sharedMaterial = renderer.sharedMaterials[i];
  154. BabylonMaterial babylonMaterial;
  155. babylonMaterial = DumpMaterial(sharedMaterial, renderer);
  156. bMultiMat.materials[i] = babylonMaterial.id;
  157. }
  158. if (mesh.subMeshCount > 1)
  159. {
  160. multiMatDictionary.Add(bMultiMat.name, bMultiMat);
  161. }
  162. }
  163. else
  164. {
  165. bMultiMat = multiMatDictionary[renderer.sharedMaterial.name];
  166. }
  167. babylonMesh.materialId = bMultiMat.id;
  168. babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount];
  169. var offset = 0;
  170. for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++)
  171. {
  172. var unityTriangles = mesh.GetTriangles(materialIndex);
  173. babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh
  174. {
  175. verticesStart = 0,
  176. verticesCount = mesh.vertexCount,
  177. materialIndex = materialIndex,
  178. indexStart = offset,
  179. indexCount = unityTriangles.Length
  180. };
  181. offset += unityTriangles.Length;
  182. }
  183. }
  184. else
  185. {
  186. babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer).id;
  187. }
  188. }
  189. babylonScene.MeshesList.Add(babylonMesh);
  190. // Animations
  191. ExportAnimations(transform, babylonMesh);
  192. if (IsRotationQuaternionAnimated(babylonMesh))
  193. {
  194. babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
  195. }
  196. // Collisions
  197. if (exportationOptions.ExportCollisions)
  198. {
  199. var collider = gameObject.GetComponent<Collider>();
  200. if (collider != null)
  201. {
  202. babylonMesh.checkCollisions = true;
  203. }
  204. }
  205. }
  206. return babylonMesh;
  207. }
  208. private BabylonSkeleton ConvertUnitySkeletonToBabylon(Transform[] bones, Matrix4x4[] bindPoses, Transform transform, GameObject gameObject, float progress)
  209. {
  210. ExporterWindow.ReportProgress(progress, "Exporting Skeleton: " + gameObject.name);
  211. BabylonSkeleton babylonSkeleton = new BabylonSkeleton();
  212. babylonSkeleton.name = gameObject.name;
  213. babylonSkeleton.id = Math.Abs(GetID(transform.gameObject).GetHashCode());
  214. babylonSkeleton.needInitialSkinMatrix = false;
  215. // Prefilled to keep order and track parents.
  216. var transformToBoneMap = new Dictionary<Transform, BabylonBone>();
  217. for (var i = 0; i < bones.Length; i++)
  218. {
  219. var unityBone = bones[i];
  220. ExporterWindow.ReportProgress(progress, "Exporting bone: " + unityBone.name + " at index " + i);
  221. var babylonBone = new BabylonBone();
  222. babylonBone.name = unityBone.name;
  223. babylonBone.index = i;
  224. transformToBoneMap.Add(unityBone, babylonBone);
  225. }
  226. // Attaches Matrix and parent.
  227. for (var i = 0; i < bones.Length; i++)
  228. {
  229. var unityBone = bones[i];
  230. var babylonBone = transformToBoneMap[unityBone];
  231. Matrix4x4 localTransform;
  232. // Unity BindPose is already inverse so take the inverse again :-)
  233. if (transformToBoneMap.ContainsKey(unityBone.parent))
  234. {
  235. var babylonParentBone = transformToBoneMap[unityBone.parent];
  236. babylonBone.parentBoneIndex = babylonParentBone.index;
  237. localTransform = bindPoses[babylonBone.parentBoneIndex] * bindPoses[i].inverse;
  238. }
  239. else
  240. {
  241. babylonBone.parentBoneIndex = -1;
  242. localTransform = bindPoses[i].inverse;
  243. }
  244. transformToBoneMap[unityBone].matrix = new[] {
  245. localTransform[0, 0], localTransform[1, 0], localTransform[2, 0], localTransform[3, 0],
  246. localTransform[0, 1], localTransform[1, 1], localTransform[2, 1], localTransform[3, 1],
  247. localTransform[0, 2], localTransform[1, 2], localTransform[2, 2], localTransform[3, 2],
  248. localTransform[0, 3], localTransform[1, 3], localTransform[2, 3], localTransform[3, 3]
  249. };
  250. }
  251. // Reorder and attach the skeleton.
  252. babylonSkeleton.bones = transformToBoneMap.Values.OrderBy(b => b.index).ToArray();
  253. babylonScene.SkeletonsList.Add(babylonSkeleton);
  254. return babylonSkeleton;
  255. }
  256. }
  257. }