MB3_MultiMeshCombiner.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  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("MultiMeshCombiner error in maxVertsInMesh. Meshes in unity cannot have more than " + MBVersion.MaxMeshVertexCount() + " vertices. " + value);
  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. "If you are trying to combine meshes without combining materials, try removing the Texture Bake Result.");
  181. return false;
  182. }
  183. if (_textureBakeResults.NumResultMaterials() == 0)
  184. {
  185. Debug.LogError("Texture Bake Results has no result materials. Try baking materials. Can't combine meshes.");
  186. return false;
  187. }
  188. return true;
  189. }
  190. public override void Apply(MB3_MeshCombiner.GenerateUV2Delegate uv2GenerationMethod)
  191. {
  192. for (int i = 0; i < meshCombiners.Count; i++)
  193. {
  194. if (meshCombiners[i].isDirty)
  195. {
  196. meshCombiners[i].combinedMesh.Apply(uv2GenerationMethod);
  197. meshCombiners[i].isDirty = false;
  198. }
  199. }
  200. }
  201. public override void Apply(bool triangles, bool vertices, bool normals, bool tangents, bool uvs, bool uv2, bool uv3, bool uv4, bool colors, bool bones = false, bool blendShapeFlag = false, GenerateUV2Delegate uv2GenerationMethod = null)
  202. {
  203. Apply(triangles, vertices, normals, tangents,
  204. uvs, uv2, uv3, uv4,
  205. false, false, false, false,
  206. colors, bones, blendShapeFlag, uv2GenerationMethod);
  207. }
  208. public override void Apply(bool triangles,
  209. bool vertices,
  210. bool normals,
  211. bool tangents,
  212. bool uvs,
  213. bool uv2,
  214. bool uv3,
  215. bool uv4,
  216. bool uv5,
  217. bool uv6,
  218. bool uv7,
  219. bool uv8,
  220. bool colors,
  221. bool bones = false,
  222. bool blendShapesFlag = false,
  223. MB3_MeshCombiner.GenerateUV2Delegate uv2GenerationMethod = null)
  224. {
  225. for (int i = 0; i < meshCombiners.Count; i++)
  226. {
  227. if (meshCombiners[i].isDirty)
  228. {
  229. meshCombiners[i].combinedMesh.Apply(triangles, vertices, normals, tangents, uvs, uv2, uv3, uv4, colors, bones, blendShapesFlag, uv2GenerationMethod);
  230. meshCombiners[i].isDirty = false;
  231. }
  232. }
  233. }
  234. public override void UpdateSkinnedMeshApproximateBounds()
  235. {
  236. for (int i = 0; i < meshCombiners.Count; i++)
  237. {
  238. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBounds();
  239. }
  240. }
  241. public override void UpdateSkinnedMeshApproximateBoundsFromBones()
  242. {
  243. for (int i = 0; i < meshCombiners.Count; i++)
  244. {
  245. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBoundsFromBones();
  246. }
  247. }
  248. public override void UpdateSkinnedMeshApproximateBoundsFromBounds()
  249. {
  250. for (int i = 0; i < meshCombiners.Count; i++)
  251. {
  252. meshCombiners[i].combinedMesh.UpdateSkinnedMeshApproximateBoundsFromBounds();
  253. }
  254. }
  255. public override bool UpdateGameObjects(GameObject[] gos, bool recalcBounds,
  256. bool updateVertices, bool updateNormals, bool updateTangents,
  257. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4,
  258. bool updateColors, bool updateSkinningInfo)
  259. {
  260. return UpdateGameObjects(gos, recalcBounds, updateVertices, updateNormals, updateTangents,
  261. updateUV, updateUV2, updateUV3, updateUV4, false, false, false, false,
  262. updateColors, updateSkinningInfo);
  263. }
  264. public override bool UpdateGameObjects(GameObject[] gos, bool recalcBounds,
  265. bool updateVertices, bool updateNormals, bool updateTangents,
  266. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4,
  267. bool updateUV5, bool updateUV6, bool updateUV7, bool updateUV8,
  268. bool updateColors, bool updateSkinningInfo)
  269. {
  270. if (gos == null)
  271. {
  272. Debug.LogError("list of game objects cannot be null");
  273. return false;
  274. }
  275. //build gos lists
  276. for (int i = 0; i < meshCombiners.Count; i++)
  277. {
  278. meshCombiners[i].gosToUpdate.Clear();
  279. }
  280. for (int i = 0; i < gos.Length; i++)
  281. {
  282. CombinedMesh cm = null;
  283. obj2MeshCombinerMap.TryGetValue(gos[i].GetInstanceID(), out cm);
  284. if (cm != null)
  285. {
  286. cm.gosToUpdate.Add(gos[i]);
  287. }
  288. else
  289. {
  290. Debug.LogWarning("Object " + gos[i] + " is not in the combined mesh.");
  291. }
  292. }
  293. bool success = true;
  294. for (int i = 0; i < meshCombiners.Count; i++)
  295. {
  296. if (meshCombiners[i].gosToUpdate.Count > 0)
  297. {
  298. meshCombiners[i].isDirty = true;
  299. GameObject[] gosToUpdate = meshCombiners[i].gosToUpdate.ToArray();
  300. success = success && meshCombiners[i].combinedMesh.UpdateGameObjects(gosToUpdate, recalcBounds, updateVertices, updateNormals, updateTangents,
  301. updateUV, updateUV2, updateUV3, updateUV4, updateUV5, updateUV6, updateUV7, updateUV8,
  302. updateColors, updateSkinningInfo);
  303. }
  304. }
  305. return success;
  306. }
  307. public override bool AddDeleteGameObjects(GameObject[] gos, GameObject[] deleteGOs, bool disableRendererInSource = true)
  308. {
  309. int[] delInstanceIDs = null;
  310. if (deleteGOs != null)
  311. {
  312. delInstanceIDs = new int[deleteGOs.Length];
  313. for (int i = 0; i < deleteGOs.Length; i++)
  314. {
  315. if (deleteGOs[i] == null)
  316. {
  317. Debug.LogError("The " + i + "th object on the list of objects to delete is 'Null'");
  318. }
  319. else
  320. {
  321. delInstanceIDs[i] = deleteGOs[i].GetInstanceID();
  322. }
  323. }
  324. }
  325. return AddDeleteGameObjectsByID(gos, delInstanceIDs, disableRendererInSource);
  326. }
  327. public override bool AddDeleteGameObjectsByID(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource = true)
  328. {
  329. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects1");
  330. //PART 1 ==== Validate
  331. if (_usingTemporaryTextureBakeResult && gos != null && gos.Length > 0)
  332. {
  333. MB_Utility.Destroy(_textureBakeResults);
  334. _textureBakeResults = null;
  335. _usingTemporaryTextureBakeResult = false;
  336. }
  337. //if all objects use the same material we can create a temporary _textureBakeResults
  338. if (_textureBakeResults == null && gos != null && gos.Length > 0 && gos[0] != null)
  339. {
  340. if (!_CreateTemporaryTextrueBakeResult(gos, GetMaterialsOnTargetRenderer()))
  341. {
  342. return false;
  343. }
  344. }
  345. if (!_validate(gos, deleteGOinstanceIDs))
  346. {
  347. return false;
  348. }
  349. _distributeAmongBakers(gos, deleteGOinstanceIDs);
  350. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.AddDeleteGameObjects numCombinedMeshes: " + meshCombiners.Count + " added:" + gos + " deleted:" + deleteGOinstanceIDs + " disableRendererInSource:" + disableRendererInSource + " maxVertsPerCombined:" + _maxVertsInMesh);
  351. return _bakeStep1(gos, deleteGOinstanceIDs, disableRendererInSource);
  352. }
  353. bool _validate(GameObject[] gos, int[] deleteGOinstanceIDs)
  354. {
  355. if (_validationLevel == MB2_ValidationLevel.none) return true;
  356. if (_maxVertsInMesh < 3) Debug.LogError("Invalid value for maxVertsInMesh=" + _maxVertsInMesh);
  357. _validateTextureBakeResults();
  358. if (gos != null)
  359. {
  360. for (int i = 0; i < gos.Length; i++)
  361. {
  362. if (gos[i] == null)
  363. {
  364. 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.");
  365. return false;
  366. }
  367. if (_validationLevel >= MB2_ValidationLevel.robust)
  368. {
  369. for (int j = i + 1; j < gos.Length; j++)
  370. {
  371. if (gos[i] == gos[j])
  372. {
  373. Debug.LogError("GameObject " + gos[i] + "appears twice in list of game objects to add");
  374. return false;
  375. }
  376. }
  377. if (obj2MeshCombinerMap.ContainsKey(gos[i].GetInstanceID()))
  378. {
  379. bool isInDeleteList = false;
  380. if (deleteGOinstanceIDs != null)
  381. {
  382. for (int k = 0; k < deleteGOinstanceIDs.Length; k++)
  383. {
  384. if (deleteGOinstanceIDs[k] == gos[i].GetInstanceID()) isInDeleteList = true;
  385. }
  386. }
  387. if (!isInDeleteList)
  388. {
  389. Debug.LogError("GameObject " + gos[i] + " is already in the combined mesh " + gos[i].GetInstanceID());
  390. return false;
  391. }
  392. }
  393. }
  394. }
  395. }
  396. if (deleteGOinstanceIDs != null)
  397. {
  398. if (_validationLevel >= MB2_ValidationLevel.robust)
  399. {
  400. for (int i = 0; i < deleteGOinstanceIDs.Length; i++)
  401. {
  402. for (int j = i + 1; j < deleteGOinstanceIDs.Length; j++)
  403. {
  404. if (deleteGOinstanceIDs[i] == deleteGOinstanceIDs[j])
  405. {
  406. Debug.LogError("GameObject " + deleteGOinstanceIDs[i] + "appears twice in list of game objects to delete");
  407. return false;
  408. }
  409. }
  410. if (!obj2MeshCombinerMap.ContainsKey(deleteGOinstanceIDs[i]))
  411. {
  412. Debug.LogWarning("GameObject with instance ID " + deleteGOinstanceIDs[i] + " on the list of objects to delete is not in the combined mesh.");
  413. }
  414. }
  415. }
  416. }
  417. return true;
  418. }
  419. void _distributeAmongBakers(GameObject[] gos, int[] deleteGOinstanceIDs)
  420. {
  421. if (gos == null) gos = empty;
  422. if (deleteGOinstanceIDs == null) deleteGOinstanceIDs = emptyIDs;
  423. if (resultSceneObject == null) resultSceneObject = new GameObject("CombinedMesh-" + name);
  424. //PART 2 ==== calculate which bakers to add objects to
  425. for (int i = 0; i < meshCombiners.Count; i++)
  426. {
  427. meshCombiners[i].extraSpace = _maxVertsInMesh - meshCombiners[i].combinedMesh.GetMesh().vertexCount;
  428. }
  429. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects1");
  430. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects2.1");
  431. //first delete game objects from the existing combinedMeshes keep track of free space
  432. for (int i = 0; i < deleteGOinstanceIDs.Length; i++)
  433. {
  434. CombinedMesh c = null;
  435. if (obj2MeshCombinerMap.TryGetValue(deleteGOinstanceIDs[i], out c))
  436. {
  437. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Removing " + deleteGOinstanceIDs[i] + " from meshCombiner " + meshCombiners.IndexOf(c));
  438. c.numVertsInListToDelete += c.combinedMesh.GetNumVerticesFor(deleteGOinstanceIDs[i]); //m.vertexCount;
  439. c.gosToDelete.Add(deleteGOinstanceIDs[i]);
  440. }
  441. else
  442. {
  443. Debug.LogWarning("Object " + deleteGOinstanceIDs[i] + " in the list of objects to delete is not in the combined mesh.");
  444. }
  445. }
  446. for (int i = 0; i < gos.Length; i++)
  447. {
  448. GameObject go = gos[i];
  449. int numVerts = MB_Utility.GetMesh(go).vertexCount;
  450. CombinedMesh cm = null;
  451. for (int j = 0; j < meshCombiners.Count; j++)
  452. {
  453. if (meshCombiners[j].extraSpace + meshCombiners[j].numVertsInListToDelete - meshCombiners[j].numVertsInListToAdd > numVerts)
  454. {
  455. cm = meshCombiners[j];
  456. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Added " + gos[i] + " to combinedMesh " + j, LOG_LEVEL);
  457. break;
  458. }
  459. }
  460. if (cm == null)
  461. {
  462. cm = new CombinedMesh(maxVertsInMesh, _resultSceneObject, _LOG_LEVEL);
  463. _setMBValues(cm.combinedMesh);
  464. meshCombiners.Add(cm);
  465. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("MB2_MultiMeshCombiner.Created new combinedMesh");
  466. }
  467. cm.gosToAdd.Add(go);
  468. cm.numVertsInListToAdd += numVerts;
  469. // obj2MeshCombinerMap.Add(go,cm);
  470. }
  471. }
  472. bool _bakeStep1(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource)
  473. {
  474. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects2.2");
  475. //Profile.Start//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects3");
  476. //PART 3 ==== Add delete meshes from combined
  477. for (int i = 0; i < meshCombiners.Count; i++)
  478. {
  479. CombinedMesh cm = meshCombiners[i];
  480. if (cm.combinedMesh.targetRenderer == null)
  481. {
  482. cm.combinedMesh.resultSceneObject = _resultSceneObject;
  483. cm.combinedMesh.BuildSceneMeshObject(gos, true);
  484. 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());
  485. }
  486. else
  487. {
  488. if (cm.combinedMesh.targetRenderer.transform.parent != resultSceneObject.transform)
  489. {
  490. Debug.LogError("targetRender objects must be children of resultSceneObject");
  491. return false;
  492. }
  493. }
  494. if (cm.gosToAdd.Count > 0 || cm.gosToDelete.Count > 0)
  495. {
  496. cm.combinedMesh.AddDeleteGameObjectsByID(cm.gosToAdd.ToArray(), cm.gosToDelete.ToArray(), disableRendererInSource);
  497. 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());
  498. }
  499. Renderer r = cm.combinedMesh.targetRenderer;
  500. Mesh m = cm.combinedMesh.GetMesh();
  501. if (r is MeshRenderer)
  502. {
  503. MeshFilter mf = r.gameObject.GetComponent<MeshFilter>();
  504. mf.sharedMesh = m;
  505. }
  506. else
  507. {
  508. SkinnedMeshRenderer smr = (SkinnedMeshRenderer)r;
  509. smr.sharedMesh = m;
  510. }
  511. }
  512. for (int i = 0; i < meshCombiners.Count; i++)
  513. {
  514. CombinedMesh cm = meshCombiners[i];
  515. for (int j = 0; j < cm.gosToDelete.Count; j++)
  516. {
  517. obj2MeshCombinerMap.Remove(cm.gosToDelete[j]);
  518. }
  519. }
  520. for (int i = 0; i < meshCombiners.Count; i++)
  521. {
  522. CombinedMesh cm = meshCombiners[i];
  523. for (int j = 0; j < cm.gosToAdd.Count; j++)
  524. {
  525. obj2MeshCombinerMap.Add(cm.gosToAdd[j].GetInstanceID(), cm);
  526. }
  527. if (cm.gosToAdd.Count > 0 || cm.gosToDelete.Count > 0)
  528. {
  529. cm.gosToDelete.Clear();
  530. cm.gosToAdd.Clear();
  531. cm.numVertsInListToDelete = 0;
  532. cm.numVertsInListToAdd = 0;
  533. cm.isDirty = true;
  534. }
  535. }
  536. //Profile.End//Profile("MB2_MultiMeshCombiner.AddDeleteGameObjects3");
  537. if (LOG_LEVEL >= MB2_LogLevel.debug)
  538. {
  539. string s = "Meshes in combined:";
  540. for (int i = 0; i < meshCombiners.Count; i++)
  541. {
  542. s += " mesh" + i + "(" + meshCombiners[i].combinedMesh.GetObjectsInCombined().Count + ")\n";
  543. }
  544. s += "children in result: " + resultSceneObject.transform.childCount;
  545. MB2_Log.LogDebug(s, LOG_LEVEL);
  546. }
  547. if (meshCombiners.Count > 0)
  548. {
  549. return true;
  550. }
  551. else
  552. {
  553. return false;
  554. }
  555. }
  556. [System.Obsolete("BuildSourceBlendShapeToCombinedIndexMap is deprecated. The map will be attached to the combined SkinnedMeshRenderer objects as the MB_BlendShape2CombinedMap Component.")]
  557. public override Dictionary<MBBlendShapeKey, MBBlendShapeValue> BuildSourceBlendShapeToCombinedIndexMap()
  558. {
  559. Dictionary<MBBlendShapeKey, MBBlendShapeValue> map = new Dictionary<MBBlendShapeKey, MBBlendShapeValue>();
  560. for (int combinerIdx = 0; combinerIdx < meshCombiners.Count; combinerIdx++)
  561. {
  562. if (meshCombiners[combinerIdx].combinedMesh.targetRenderer == null) continue;
  563. MB_BlendShape2CombinedMap mapComponent = meshCombiners[combinerIdx].combinedMesh.targetRenderer.GetComponent<MB_BlendShape2CombinedMap>();
  564. if (mapComponent == null) continue;
  565. foreach (KeyValuePair<MBBlendShapeKey, MBBlendShapeValue> entry in mapComponent.srcToCombinedMap.GenerateMapFromSerializedData())
  566. {
  567. map.Add(entry.Key, entry.Value);
  568. }
  569. }
  570. return map;
  571. }
  572. public override void ClearBuffers()
  573. {
  574. for (int i = 0; i < meshCombiners.Count; i++)
  575. {
  576. meshCombiners[i].combinedMesh.ClearBuffers();
  577. }
  578. obj2MeshCombinerMap.Clear();
  579. }
  580. public override void ClearMesh()
  581. {
  582. DestroyMesh();
  583. /*
  584. for (int i = 0; i < meshCombiners.Count; i++)
  585. {
  586. meshCombiners[i].combinedMesh.ClearMesh();
  587. }
  588. */
  589. }
  590. public override void DisposeRuntimeCreated()
  591. {
  592. for (int i = 0; i < meshCombiners.Count; i++)
  593. {
  594. meshCombiners[i].combinedMesh.DisposeRuntimeCreated();
  595. }
  596. }
  597. public override void DestroyMesh()
  598. {
  599. for (int i = 0; i < meshCombiners.Count; i++)
  600. {
  601. if (meshCombiners[i].combinedMesh.targetRenderer != null)
  602. {
  603. MB_Utility.Destroy(meshCombiners[i].combinedMesh.targetRenderer.gameObject);
  604. }
  605. meshCombiners[i].combinedMesh.DestroyMesh();
  606. }
  607. obj2MeshCombinerMap.Clear();
  608. meshCombiners.Clear();
  609. }
  610. public override void DestroyMeshEditor(MB2_EditorMethodsInterface editorMethods)
  611. {
  612. for (int i = 0; i < meshCombiners.Count; i++)
  613. {
  614. if (meshCombiners[i].combinedMesh.targetRenderer != null)
  615. {
  616. editorMethods.Destroy(meshCombiners[i].combinedMesh.targetRenderer.gameObject);
  617. }
  618. meshCombiners[i].combinedMesh.ClearMesh();
  619. }
  620. obj2MeshCombinerMap.Clear();
  621. meshCombiners.Clear();
  622. }
  623. void _setMBValues(MB3_MeshCombinerSingle targ)
  624. {
  625. targ.validationLevel = _validationLevel;
  626. targ.textureBakeResults = textureBakeResults;
  627. // Even though the MultiMeshBaker supports baking into prefabs, the sub-combiners don't do bake into prefab when
  628. // this is happening. They do bake into sceneObject, then the MultiMeshBaker takes their output and combines it
  629. // into a prefab.
  630. targ.outputOption = MB2_OutputOptions.bakeIntoSceneObject;
  631. if (settingsHolder != null)
  632. {
  633. targ.settingsHolder = settingsHolder;
  634. } else
  635. {
  636. targ.renderType = renderType;
  637. targ.lightmapOption = lightmapOption;
  638. targ.doNorm = doNorm;
  639. targ.doTan = doTan;
  640. targ.doCol = doCol;
  641. targ.doUV = doUV;
  642. targ.doUV3 = doUV3;
  643. targ.doUV4 = doUV4;
  644. targ.doUV5 = doUV5;
  645. targ.doUV6 = doUV6;
  646. targ.doUV7 = doUV7;
  647. targ.doUV8 = doUV8;
  648. targ.doBlendShapes = doBlendShapes;
  649. targ.optimizeAfterBake = optimizeAfterBake;
  650. targ.pivotLocationType = pivotLocationType;
  651. targ.uv2UnwrappingParamsHardAngle = uv2UnwrappingParamsHardAngle;
  652. targ.uv2UnwrappingParamsPackMargin = uv2UnwrappingParamsPackMargin;
  653. targ.assignToMeshCustomizer = assignToMeshCustomizer;
  654. }
  655. }
  656. public override List<Material> GetMaterialsOnTargetRenderer()
  657. {
  658. HashSet<Material> hs = new HashSet<Material>();
  659. for (int i = 0; i < meshCombiners.Count; i++)
  660. {
  661. hs.UnionWith(meshCombiners[i].combinedMesh.GetMaterialsOnTargetRenderer());
  662. }
  663. List<Material> outMats = new List<Material>(hs);
  664. return outMats;
  665. }
  666. public override void CheckIntegrity()
  667. {
  668. if (!MB_Utility.DO_INTEGRITY_CHECKS) return;
  669. for (int i = 0; i < meshCombiners.Count; i++)
  670. {
  671. meshCombiners[i].combinedMesh.CheckIntegrity();
  672. }
  673. }
  674. }
  675. }