MB3_MultiMeshCombiner.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. //----------------------------------------------
  2. // MeshBaker
  3. // Copyright © 2011-2012 Ian Deane
  4. //----------------------------------------------
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.Collections.Specialized;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Text;
  11. using DigitalOpus.MB.Core;
  12. namespace DigitalOpus.MB.Core
  13. {
  14. /// <summary>
  15. /// This class is an endless mesh. You don't need to worry about the 65k limit when adding meshes. It is like a List of combined meshes. Internally it manages
  16. /// a collection of MB2_MeshComber objects to which meshes added and deleted as necessary.
  17. ///
  18. /// Note that this implementation does
  19. /// not attempt to split meshes. Each mesh is added to one of the internal meshes as an atomic unit.
  20. ///
  21. /// This class is not a Component so it can be instantiated and used like a regular C Sharp class.
  22. /// </summary>
  23. [System.Serializable]
  24. public class MB3_MultiMeshCombiner : MB3_MeshCombiner
  25. {
  26. [System.Serializable]
  27. public class CombinedMesh
  28. {
  29. public MB3_MeshCombinerSingle combinedMesh;
  30. public int extraSpace = -1;
  31. public int numVertsInListToDelete = 0;
  32. public int numVertsInListToAdd = 0;
  33. public List<GameObject> gosToAdd;
  34. public List<int> gosToDelete;
  35. public List<GameObject> gosToUpdate;
  36. public bool isDirty = false; //needs apply
  37. public CombinedMesh(int maxNumVertsInMesh, GameObject resultSceneObject, MB2_LogLevel ll)
  38. {
  39. combinedMesh = new MB3_MeshCombinerSingle();
  40. combinedMesh.resultSceneObject = resultSceneObject;
  41. combinedMesh.LOG_LEVEL = ll;
  42. extraSpace = maxNumVertsInMesh;
  43. numVertsInListToDelete = 0;
  44. numVertsInListToAdd = 0;
  45. gosToAdd = new List<GameObject>();
  46. gosToDelete = new List<int>();
  47. gosToUpdate = new List<GameObject>();
  48. }
  49. public bool isEmpty()
  50. {
  51. List<GameObject> obsIn = new List<GameObject>();
  52. obsIn.AddRange(combinedMesh.GetObjectsInCombined());
  53. for (int i = 0; i < gosToDelete.Count; i++)
  54. {
  55. for (int j = 0; j < obsIn.Count; j++)
  56. {
  57. if (obsIn[j].GetInstanceID() == gosToDelete[i])
  58. {
  59. obsIn.RemoveAt(j);
  60. break;
  61. }
  62. }
  63. }
  64. if (obsIn.Count == 0) return true;
  65. return false;
  66. }
  67. }
  68. static GameObject[] empty = new GameObject[0];
  69. static int[] emptyIDs = new int[0];
  70. public override MB2_LogLevel LOG_LEVEL
  71. {
  72. get { return _LOG_LEVEL; }
  73. set
  74. {
  75. _LOG_LEVEL = value;
  76. for (int i = 0; i < meshCombiners.Count; i++)
  77. {
  78. meshCombiners[i].combinedMesh.LOG_LEVEL = value;
  79. }
  80. }
  81. }
  82. public override MB2_ValidationLevel validationLevel
  83. {
  84. set
  85. {
  86. _validationLevel = value;
  87. for (int i = 0; i < meshCombiners.Count; i++)
  88. {
  89. meshCombiners[i].combinedMesh.validationLevel = _validationLevel;
  90. }
  91. }
  92. get { return _validationLevel; }
  93. }
  94. public Dictionary<int, CombinedMesh> obj2MeshCombinerMap = new Dictionary<int, CombinedMesh>();
  95. [SerializeField]
  96. public List<CombinedMesh> meshCombiners = new List<CombinedMesh>();
  97. [SerializeField]
  98. int _maxVertsInMesh = 65535;
  99. public int maxVertsInMesh
  100. {
  101. get { return _maxVertsInMesh; }
  102. set
  103. {
  104. if (obj2MeshCombinerMap.Count > 0)
  105. {
  106. //todo how to warn with gui
  107. //Debug.LogError("Can't set the max verts in meshes once there are objects in the mesh.");
  108. return;
  109. }
  110. else if (value < 3)
  111. {
  112. Debug.LogError("Max verts in mesh must be greater than three.");
  113. }
  114. else if (value > MBVersion.MaxMeshVertexCount())
  115. {
  116. Debug.LogError("Meshes in unity cannot have more than " + MBVersion.MaxMeshVertexCount() + " vertices.");
  117. }
  118. else
  119. {
  120. _maxVertsInMesh = value;
  121. }
  122. }
  123. }
  124. public override int GetNumObjectsInCombined()
  125. {
  126. return obj2MeshCombinerMap.Count;
  127. }
  128. public override int GetNumVerticesFor(GameObject go)
  129. {
  130. CombinedMesh c = null;
  131. if (obj2MeshCombinerMap.TryGetValue(go.GetInstanceID(), out c))
  132. {
  133. return c.combinedMesh.GetNumVerticesFor(go);
  134. }
  135. else
  136. {
  137. return -1;
  138. }
  139. }
  140. public override int GetNumVerticesFor(int gameObjectID)
  141. {
  142. CombinedMesh c = null;
  143. if (obj2MeshCombinerMap.TryGetValue(gameObjectID, out c))
  144. {
  145. return c.combinedMesh.GetNumVerticesFor(gameObjectID);
  146. }
  147. else
  148. {
  149. return -1;
  150. }
  151. }
  152. public override List<GameObject> GetObjectsInCombined()
  153. { //todo look at getting from keys
  154. List<GameObject> allObjs = new List<GameObject>();
  155. for (int i = 0; i < meshCombiners.Count; i++)
  156. {
  157. allObjs.AddRange(meshCombiners[i].combinedMesh.GetObjectsInCombined());
  158. }
  159. return allObjs;
  160. }
  161. public override int GetLightmapIndex()
  162. { //todo check that all meshcombiners use same lightmap index
  163. if (meshCombiners.Count > 0) return meshCombiners[0].combinedMesh.GetLightmapIndex();
  164. return -1;
  165. }
  166. public override bool CombinedMeshContains(GameObject go)
  167. {
  168. return obj2MeshCombinerMap.ContainsKey(go.GetInstanceID());
  169. }
  170. bool _validateTextureBakeResults()
  171. {
  172. if (_textureBakeResults == null)
  173. {
  174. Debug.LogError("Texture Bake Results is null. Can't combine meshes.");
  175. return false;
  176. }
  177. if ((_textureBakeResults.materialsAndUVRects == null || _textureBakeResults.materialsAndUVRects.Length == 0))
  178. {
  179. Debug.LogError("Texture Bake Results has no materials in material to sourceUVRect map. Try baking materials. Can't combine meshes.");
  180. return false;
  181. }
  182. if (_textureBakeResults.resultMaterials == null || _textureBakeResults.resultMaterials.Length == 0)
  183. {
  184. Debug.LogError("Texture Bake Results has no result materials. Try baking materials. Can't combine meshes.");
  185. return false;
  186. }
  187. return true;
  188. }
  189. public override void Apply(MB3_MeshCombiner.GenerateUV2Delegate uv2GenerationMethod)
  190. {
  191. for (int i = 0; i < meshCombiners.Count; i++)
  192. {
  193. if (meshCombiners[i].isDirty)
  194. {
  195. meshCombiners[i].combinedMesh.Apply(uv2GenerationMethod);
  196. meshCombiners[i].isDirty = false;
  197. }
  198. }
  199. }
  200. public override void Apply(bool triangles,
  201. bool vertices,
  202. bool normals,
  203. bool tangents,
  204. bool uvs,
  205. bool uv2,
  206. bool uv3,
  207. bool uv4,
  208. bool colors,
  209. bool bones = false,
  210. bool blendShapesFlag = false,
  211. MB3_MeshCombiner.GenerateUV2Delegate uv2GenerationMethod = null)
  212. {
  213. for (int i = 0; i < meshCombiners.Count; i++)
  214. {
  215. if (meshCombiners[i].isDirty)
  216. {
  217. meshCombiners[i].combinedMesh.Apply(triangles, vertices, normals, tangents, uvs, uv2, uv3, uv4, colors, bones, blendShapesFlag, uv2GenerationMethod);
  218. meshCombiners[i].isDirty = false;
  219. }
  220. }
  221. }
  222. public override void UpdateSkinnedMeshApproximateBounds()
  223. {
  224. for (int i = 0; i < meshCombiners.Count; i++)
  225. {
  226. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBounds();
  227. }
  228. }
  229. public override void UpdateSkinnedMeshApproximateBoundsFromBones()
  230. {
  231. for (int i = 0; i < meshCombiners.Count; i++)
  232. {
  233. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBoundsFromBones();
  234. }
  235. }
  236. public override void UpdateSkinnedMeshApproximateBoundsFromBounds()
  237. {
  238. for (int i = 0; i < meshCombiners.Count; i++)
  239. {
  240. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBoundsFromBounds();
  241. }
  242. }
  243. public override void UpdateGameObjects(GameObject[] gos, bool recalcBounds = true,
  244. bool updateVertices = true, bool updateNormals = true, bool updateTangents = true,
  245. bool updateUV = false, bool updateUV2 = false, bool updateUV3 = false, bool updateUV4 = false,
  246. bool updateColors = false, bool updateSkinningInfo = false)
  247. {
  248. if (gos == null)
  249. {
  250. Debug.LogError("list of game objects cannot be null");
  251. return;
  252. }
  253. //build gos lists
  254. for (int i = 0; i < meshCombiners.Count; i++)
  255. {
  256. meshCombiners[i].gosToUpdate.Clear();
  257. }
  258. for (int i = 0; i < gos.Length; i++)
  259. {
  260. CombinedMesh cm = null;
  261. obj2MeshCombinerMap.TryGetValue(gos[i].GetInstanceID(), out cm);
  262. if (cm != null)
  263. {
  264. cm.gosToUpdate.Add(gos[i]);
  265. }
  266. else
  267. {
  268. Debug.LogWarning("Object " + gos[i] + " is not in the combined mesh.");
  269. }
  270. }
  271. for (int i = 0; i < meshCombiners.Count; i++)
  272. {
  273. if (meshCombiners[i].gosToUpdate.Count > 0)
  274. {
  275. meshCombiners[i].isDirty = true;
  276. GameObject[] gosToUpdate = meshCombiners[i].gosToUpdate.ToArray();
  277. meshCombiners[i].combinedMesh.UpdateGameObjects(gosToUpdate, recalcBounds, updateVertices, updateNormals, updateTangents, updateUV, updateUV2, updateUV3, updateUV4, updateColors, updateSkinningInfo);
  278. }
  279. }
  280. }
  281. public override bool AddDeleteGameObjects(GameObject[] gos, GameObject[] deleteGOs, bool disableRendererInSource = true)
  282. {
  283. int[] delInstanceIDs = null;
  284. if (deleteGOs != null)
  285. {
  286. delInstanceIDs = new int[deleteGOs.Length];
  287. for (int i = 0; i < deleteGOs.Length; i++)
  288. {
  289. if (deleteGOs[i] == null)
  290. {
  291. Debug.LogError("The " + i + "th object on the list of objects to delete is 'Null'");
  292. }
  293. else
  294. {
  295. delInstanceIDs[i] = deleteGOs[i].GetInstanceID();
  296. }
  297. }
  298. }
  299. return AddDeleteGameObjectsByID(gos, delInstanceIDs, disableRendererInSource);
  300. }
  301. public override bool AddDeleteGameObjectsByID(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource = true)
  302. {
  303. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects1");
  304. //PART 1 ==== Validate
  305. if (_usingTemporaryTextureBakeResult && gos != null && gos.Length > 0)
  306. {
  307. MB_Utility.Destroy(_textureBakeResults);
  308. _textureBakeResults = null;
  309. _usingTemporaryTextureBakeResult = false;
  310. }
  311. //if all objects use the same material we can create a temporary _textureBakeResults
  312. if (_textureBakeResults == null && gos != null && gos.Length > 0 && gos[0] != null)
  313. {
  314. if (!_CreateTemporaryTextrueBakeResult(gos, GetMaterialsOnTargetRenderer()))
  315. {
  316. return false;
  317. }
  318. }
  319. if (!_validate(gos, deleteGOinstanceIDs))
  320. {
  321. return false;
  322. }
  323. _distributeAmongBakers(gos, deleteGOinstanceIDs);
  324. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.AddDeleteGameObjects numCombinedMeshes: " + meshCombiners.Count + " added:" + gos + " deleted:" + deleteGOinstanceIDs + " disableRendererInSource:" + disableRendererInSource + " maxVertsPerCombined:" + _maxVertsInMesh);
  325. return _bakeStep1(gos, deleteGOinstanceIDs, disableRendererInSource);
  326. }
  327. bool _validate(GameObject[] gos, int[] deleteGOinstanceIDs)
  328. {
  329. if (_validationLevel == MB2_ValidationLevel.none) return true;
  330. if (_maxVertsInMesh < 3) Debug.LogError("Invalid value for maxVertsInMesh=" + _maxVertsInMesh);
  331. _validateTextureBakeResults();
  332. if (gos != null)
  333. {
  334. for (int i = 0; i < gos.Length; i++)
  335. {
  336. if (gos[i] == null)
  337. {
  338. Debug.LogError("The " + i + "th object on the list of objects to combine is 'None'. Use Command-Delete on Mac OS X; Delete or Shift-Delete on Windows to remove this one element.");
  339. return false;
  340. }
  341. if (_validationLevel >= MB2_ValidationLevel.robust)
  342. {
  343. for (int j = i + 1; j < gos.Length; j++)
  344. {
  345. if (gos[i] == gos[j])
  346. {
  347. Debug.LogError("GameObject " + gos[i] + "appears twice in list of game objects to add");
  348. return false;
  349. }
  350. }
  351. if (obj2MeshCombinerMap.ContainsKey(gos[i].GetInstanceID()))
  352. {
  353. bool isInDeleteList = false;
  354. if (deleteGOinstanceIDs != null)
  355. {
  356. for (int k = 0; k < deleteGOinstanceIDs.Length; k++)
  357. {
  358. if (deleteGOinstanceIDs[k] == gos[i].GetInstanceID()) isInDeleteList = true;
  359. }
  360. }
  361. if (!isInDeleteList)
  362. {
  363. Debug.LogError("GameObject " + gos[i] + " is already in the combined mesh " + gos[i].GetInstanceID());
  364. return false;
  365. }
  366. }
  367. }
  368. }
  369. }
  370. if (deleteGOinstanceIDs != null)
  371. {
  372. if (_validationLevel >= MB2_ValidationLevel.robust)
  373. {
  374. for (int i = 0; i < deleteGOinstanceIDs.Length; i++)
  375. {
  376. for (int j = i + 1; j < deleteGOinstanceIDs.Length; j++)
  377. {
  378. if (deleteGOinstanceIDs[i] == deleteGOinstanceIDs[j])
  379. {
  380. Debug.LogError("GameObject " + deleteGOinstanceIDs[i] + "appears twice in list of game objects to delete");
  381. return false;
  382. }
  383. }
  384. if (!obj2MeshCombinerMap.ContainsKey(deleteGOinstanceIDs[i]))
  385. {
  386. Debug.LogWarning("GameObject with instance ID " + deleteGOinstanceIDs[i] + " on the list of objects to delete is not in the combined mesh.");
  387. }
  388. }
  389. }
  390. }
  391. return true;
  392. }
  393. void _distributeAmongBakers(GameObject[] gos, int[] deleteGOinstanceIDs)
  394. {
  395. if (gos == null) gos = empty;
  396. if (deleteGOinstanceIDs == null) deleteGOinstanceIDs = emptyIDs;
  397. if (resultSceneObject == null) resultSceneObject = new GameObject("CombinedMesh-" + name);
  398. //PART 2 ==== calculate which bakers to add objects to
  399. for (int i = 0; i < meshCombiners.Count; i++)
  400. {
  401. meshCombiners[i].extraSpace = _maxVertsInMesh - meshCombiners[i].combinedMesh.GetMesh().vertexCount;
  402. }
  403. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects1");
  404. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects2.1");
  405. //first delete game objects from the existing combinedMeshes keep track of free space
  406. for (int i = 0; i < deleteGOinstanceIDs.Length; i++)
  407. {
  408. CombinedMesh c = null;
  409. if (obj2MeshCombinerMap.TryGetValue(deleteGOinstanceIDs[i], out c))
  410. {
  411. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Removing " + deleteGOinstanceIDs[i] + " from meshCombiner " + meshCombiners.IndexOf(c));
  412. c.numVertsInListToDelete += c.combinedMesh.GetNumVerticesFor(deleteGOinstanceIDs[i]); //m.vertexCount;
  413. c.gosToDelete.Add(deleteGOinstanceIDs[i]);
  414. }
  415. else
  416. {
  417. Debug.LogWarning("Object " + deleteGOinstanceIDs[i] + " in the list of objects to delete is not in the combined mesh.");
  418. }
  419. }
  420. for (int i = 0; i < gos.Length; i++)
  421. {
  422. GameObject go = gos[i];
  423. int numVerts = MB_Utility.GetMesh(go).vertexCount;
  424. CombinedMesh cm = null;
  425. for (int j = 0; j < meshCombiners.Count; j++)
  426. {
  427. if (meshCombiners[j].extraSpace + meshCombiners[j].numVertsInListToDelete - meshCombiners[j].numVertsInListToAdd > numVerts)
  428. {
  429. cm = meshCombiners[j];
  430. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Added " + gos[i] + " to combinedMesh " + j, LOG_LEVEL);
  431. break;
  432. }
  433. }
  434. if (cm == null)
  435. {
  436. cm = new CombinedMesh(maxVertsInMesh, _resultSceneObject, _LOG_LEVEL);
  437. _setMBValues(cm.combinedMesh);
  438. meshCombiners.Add(cm);
  439. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Created new combinedMesh");
  440. }
  441. cm.gosToAdd.Add(go);
  442. cm.numVertsInListToAdd += numVerts;
  443. // obj2MeshCombinerMap.Add(go,cm);
  444. }
  445. }
  446. bool _bakeStep1(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource)
  447. {
  448. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects2.2");
  449. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects3");
  450. //PART 3 ==== Add delete meshes from combined
  451. for (int i = 0; i < meshCombiners.Count; i++)
  452. {
  453. CombinedMesh cm = meshCombiners[i];
  454. if (cm.combinedMesh.targetRenderer == null)
  455. {
  456. cm.combinedMesh.resultSceneObject = _resultSceneObject;
  457. cm.combinedMesh.BuildSceneMeshObject(gos, true);
  458. if (_LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("BuildSO combiner {0} goID {1} targetRenID {2} meshID {3}", i, cm.combinedMesh.targetRenderer.gameObject.GetInstanceID(), cm.combinedMesh.targetRenderer.GetInstanceID(), cm.combinedMesh.GetMesh().GetInstanceID());
  459. }
  460. else
  461. {
  462. if (cm.combinedMesh.targetRenderer.transform.parent != resultSceneObject.transform)
  463. {
  464. Debug.LogError("targetRender objects must be children of resultSceneObject");
  465. return false;
  466. }
  467. }
  468. if (cm.gosToAdd.Count > 0 || cm.gosToDelete.Count > 0)
  469. {
  470. cm.combinedMesh.AddDeleteGameObjectsByID(cm.gosToAdd.ToArray(), cm.gosToDelete.ToArray(), disableRendererInSource);
  471. if (_LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Baked combiner {0} obsAdded {1} objsRemoved {2} goID {3} targetRenID {4} meshID {5}", i, cm.gosToAdd.Count, cm.gosToDelete.Count, cm.combinedMesh.targetRenderer.gameObject.GetInstanceID(), cm.combinedMesh.targetRenderer.GetInstanceID(), cm.combinedMesh.GetMesh().GetInstanceID());
  472. }
  473. Renderer r = cm.combinedMesh.targetRenderer;
  474. Mesh m = cm.combinedMesh.GetMesh();
  475. if (r is MeshRenderer)
  476. {
  477. MeshFilter mf = r.gameObject.GetComponent<MeshFilter>();
  478. mf.sharedMesh = m;
  479. }
  480. else
  481. {
  482. SkinnedMeshRenderer smr = (SkinnedMeshRenderer)r;
  483. smr.sharedMesh = m;
  484. }
  485. }
  486. for (int i = 0; i < meshCombiners.Count; i++)
  487. {
  488. CombinedMesh cm = meshCombiners[i];
  489. for (int j = 0; j < cm.gosToDelete.Count; j++)
  490. {
  491. obj2MeshCombinerMap.Remove(cm.gosToDelete[j]);
  492. }
  493. }
  494. for (int i = 0; i < meshCombiners.Count; i++)
  495. {
  496. CombinedMesh cm = meshCombiners[i];
  497. for (int j = 0; j < cm.gosToAdd.Count; j++)
  498. {
  499. obj2MeshCombinerMap.Add(cm.gosToAdd[j].GetInstanceID(), cm);
  500. }
  501. if (cm.gosToAdd.Count > 0 || cm.gosToDelete.Count > 0)
  502. {
  503. cm.gosToDelete.Clear();
  504. cm.gosToAdd.Clear();
  505. cm.numVertsInListToDelete = 0;
  506. cm.numVertsInListToAdd = 0;
  507. cm.isDirty = true;
  508. }
  509. }
  510. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects3");
  511. if (LOG_LEVEL >= MB2_LogLevel.debug)
  512. {
  513. string s = "Meshes in combined:";
  514. for (int i = 0; i < meshCombiners.Count; i++)
  515. {
  516. s += " mesh" + i + "(" + meshCombiners[i].combinedMesh.GetObjectsInCombined().Count + ")\n";
  517. }
  518. s += "children in result: " + resultSceneObject.transform.childCount;
  519. MB2_Log.LogDebug(s, LOG_LEVEL);
  520. }
  521. if (meshCombiners.Count > 0)
  522. {
  523. return true;
  524. }
  525. else
  526. {
  527. return false;
  528. }
  529. }
  530. public override Dictionary<MBBlendShapeKey, MBBlendShapeValue> BuildSourceBlendShapeToCombinedIndexMap()
  531. {
  532. Dictionary<MBBlendShapeKey, MBBlendShapeValue> map = new Dictionary<MBBlendShapeKey, MBBlendShapeValue>();
  533. for (int combinerIdx = 0; combinerIdx < meshCombiners.Count; combinerIdx++)
  534. {
  535. for (int i = 0; i < meshCombiners[combinerIdx].combinedMesh.blendShapes.Length; i++)
  536. {
  537. MB3_MeshCombinerSingle.MBBlendShape bs = meshCombiners[combinerIdx].combinedMesh.blendShapes[i];
  538. MBBlendShapeValue bsv = new MBBlendShapeValue();
  539. bsv.combinedMeshGameObject = meshCombiners[combinerIdx].combinedMesh.targetRenderer.gameObject;
  540. bsv.blendShapeIndex = i;
  541. map.Add(new MBBlendShapeKey(bs.gameObjectID, bs.indexInSource), bsv);
  542. }
  543. }
  544. return map;
  545. }
  546. public override void ClearBuffers()
  547. {
  548. for (int i = 0; i < meshCombiners.Count; i++)
  549. {
  550. meshCombiners[i].combinedMesh.ClearBuffers();
  551. }
  552. obj2MeshCombinerMap.Clear();
  553. }
  554. public override void ClearMesh()
  555. {
  556. DestroyMesh();
  557. }
  558. public override void DestroyMesh()
  559. {
  560. for (int i = 0; i < meshCombiners.Count; i++)
  561. {
  562. if (meshCombiners[i].combinedMesh.targetRenderer != null)
  563. {
  564. MB_Utility.Destroy(meshCombiners[i].combinedMesh.targetRenderer.gameObject);
  565. }
  566. meshCombiners[i].combinedMesh.ClearMesh();
  567. }
  568. obj2MeshCombinerMap.Clear();
  569. meshCombiners.Clear();
  570. }
  571. public override void DestroyMeshEditor(MB2_EditorMethodsInterface editorMethods)
  572. {
  573. for (int i = 0; i < meshCombiners.Count; i++)
  574. {
  575. if (meshCombiners[i].combinedMesh.targetRenderer != null)
  576. {
  577. editorMethods.Destroy(meshCombiners[i].combinedMesh.targetRenderer.gameObject);
  578. }
  579. meshCombiners[i].combinedMesh.ClearMesh();
  580. }
  581. obj2MeshCombinerMap.Clear();
  582. meshCombiners.Clear();
  583. }
  584. void _setMBValues(MB3_MeshCombinerSingle targ)
  585. {
  586. targ.validationLevel = _validationLevel;
  587. targ.renderType = renderType;
  588. targ.outputOption = MB2_OutputOptions.bakeIntoSceneObject;
  589. targ.lightmapOption = lightmapOption;
  590. targ.textureBakeResults = textureBakeResults;
  591. targ.doNorm = doNorm;
  592. targ.doTan = doTan;
  593. targ.doCol = doCol;
  594. targ.doUV = doUV;
  595. targ.doUV3 = doUV3;
  596. targ.doUV4 = doUV4;
  597. targ.doBlendShapes = doBlendShapes;
  598. targ.optimizeAfterBake = optimizeAfterBake;
  599. targ.recenterVertsToBoundsCenter = recenterVertsToBoundsCenter;
  600. targ.uv2UnwrappingParamsHardAngle = uv2UnwrappingParamsHardAngle;
  601. targ.uv2UnwrappingParamsPackMargin = uv2UnwrappingParamsPackMargin;
  602. }
  603. public override List<Material> GetMaterialsOnTargetRenderer()
  604. {
  605. HashSet<Material> hs = new HashSet<Material>();
  606. for (int i = 0; i < meshCombiners.Count; i++)
  607. {
  608. hs.UnionWith(meshCombiners[i].combinedMesh.GetMaterialsOnTargetRenderer());
  609. }
  610. List<Material> outMats = new List<Material>(hs);
  611. return outMats;
  612. }
  613. public override void CheckIntegrity()
  614. {
  615. if (!MB_Utility.DO_INTEGRITY_CHECKS) return;
  616. for (int i = 0; i < meshCombiners.Count; i++)
  617. {
  618. meshCombiners[i].combinedMesh.CheckIntegrity();
  619. }
  620. }
  621. }
  622. }