MB3_MeshCombiner.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Specialized;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Text;
  7. using DigitalOpus.MB.Core;
  8. namespace DigitalOpus.MB.Core {
  9. //TODO bug with triangles if using showHide with AddDelete reproduce by using the AddDeleteParts script and changeing some of it to show hide
  10. [System.Serializable]
  11. public abstract class MB3_MeshCombiner : MB_IMeshBakerSettings
  12. {
  13. public delegate void GenerateUV2Delegate(Mesh m, float hardAngle, float packMargin);
  14. public class MBBlendShapeKey
  15. {
  16. public GameObject gameObject;
  17. public int blendShapeIndexInSrc;
  18. public MBBlendShapeKey(GameObject srcSkinnedMeshRenderGameObject, int blendShapeIndexInSource)
  19. {
  20. gameObject = srcSkinnedMeshRenderGameObject;
  21. blendShapeIndexInSrc = blendShapeIndexInSource;
  22. }
  23. public override bool Equals(object obj)
  24. {
  25. if (!(obj is MBBlendShapeKey) || obj == null)
  26. {
  27. return false;
  28. }
  29. MBBlendShapeKey other = (MBBlendShapeKey)obj;
  30. return (gameObject == other.gameObject && blendShapeIndexInSrc == other.blendShapeIndexInSrc);
  31. }
  32. public override int GetHashCode()
  33. {
  34. int hash = 23;
  35. unchecked
  36. {
  37. hash = hash * 31 + gameObject.GetInstanceID();
  38. hash = hash * 31 + blendShapeIndexInSrc;
  39. }
  40. return hash;
  41. }
  42. }
  43. public class MBBlendShapeValue
  44. {
  45. public GameObject combinedMeshGameObject;
  46. public int blendShapeIndex;
  47. }
  48. public static bool EVAL_VERSION {
  49. get { return false; }
  50. }
  51. [SerializeField] protected MB2_ValidationLevel _validationLevel = MB2_ValidationLevel.robust;
  52. public virtual MB2_ValidationLevel validationLevel
  53. {
  54. get { return _validationLevel; }
  55. set { _validationLevel = value; }
  56. }
  57. [SerializeField] protected string _name;
  58. public string name
  59. {
  60. get { return _name; }
  61. set { _name = value; }
  62. }
  63. [SerializeField] protected MB2_TextureBakeResults _textureBakeResults;
  64. public virtual MB2_TextureBakeResults textureBakeResults
  65. {
  66. get { return _textureBakeResults; }
  67. set { _textureBakeResults = value; }
  68. }
  69. [SerializeField] protected GameObject _resultSceneObject;
  70. public virtual GameObject resultSceneObject
  71. {
  72. get { return _resultSceneObject; }
  73. set { _resultSceneObject = value; }
  74. }
  75. [SerializeField] protected UnityEngine.Renderer _targetRenderer;
  76. public virtual Renderer targetRenderer
  77. {
  78. get { return _targetRenderer; }
  79. set
  80. {
  81. if (_targetRenderer != null && _targetRenderer != value)
  82. {
  83. Debug.LogWarning("Previous targetRenderer was not null. Combined mesh may be being used by more than one Renderer");
  84. }
  85. _targetRenderer = value;
  86. }
  87. }
  88. [SerializeField] protected MB2_LogLevel _LOG_LEVEL = MB2_LogLevel.info;
  89. public virtual MB2_LogLevel LOG_LEVEL
  90. {
  91. get { return _LOG_LEVEL; }
  92. set { _LOG_LEVEL = value; }
  93. }
  94. public MB_IMeshBakerSettings settings
  95. {
  96. get
  97. {
  98. if (_settingsHolder != null)
  99. {
  100. return settingsHolder.GetMeshBakerSettings();
  101. }
  102. else
  103. {
  104. return this;
  105. }
  106. }
  107. }
  108. /// <summary>
  109. /// This needs to be an Object so it gets serialized and works with SerializedProperty.
  110. /// Would like this to be of type MB_IMeshBakerSettingsHolder
  111. /// </summary>
  112. [SerializeField] protected UnityEngine.Object _settingsHolder;
  113. public virtual MB_IMeshBakerSettingsHolder settingsHolder
  114. {
  115. get {
  116. if (_settingsHolder != null)
  117. {
  118. if (_settingsHolder is MB_IMeshBakerSettingsHolder)
  119. {
  120. return (MB_IMeshBakerSettingsHolder)_settingsHolder;
  121. } else {
  122. _settingsHolder = null;
  123. }
  124. }
  125. return null;
  126. }
  127. set
  128. {
  129. if (value is UnityEngine.Object)
  130. {
  131. _settingsHolder = (UnityEngine.Object)value;
  132. } else
  133. {
  134. Debug.LogError("The settings holder must be a UnityEngine.Object");
  135. }
  136. }
  137. }
  138. //-----------------------
  139. [SerializeField] protected MB_RenderType _renderType;
  140. public virtual MB_RenderType renderType {
  141. get { return _renderType; }
  142. set { _renderType = value; }
  143. }
  144. [SerializeField] protected MB2_OutputOptions _outputOption;
  145. public virtual MB2_OutputOptions outputOption
  146. {
  147. get { return _outputOption; }
  148. set { _outputOption = value; }
  149. }
  150. [SerializeField] protected MB2_LightmapOptions _lightmapOption = MB2_LightmapOptions.ignore_UV2;
  151. public virtual MB2_LightmapOptions lightmapOption {
  152. get { return _lightmapOption; }
  153. set { _lightmapOption = value; }
  154. }
  155. [SerializeField] protected bool _doNorm = true;
  156. public virtual bool doNorm {
  157. get { return _doNorm; }
  158. set { _doNorm = value; }
  159. }
  160. [SerializeField] protected bool _doTan = true;
  161. public virtual bool doTan {
  162. get { return _doTan; }
  163. set { _doTan = value; }
  164. }
  165. [SerializeField] protected bool _doCol;
  166. public virtual bool doCol {
  167. get { return _doCol; }
  168. set { _doCol = value; }
  169. }
  170. [SerializeField] protected bool _doUV = true;
  171. public virtual bool doUV {
  172. get { return _doUV; }
  173. set { _doUV = value; }
  174. }
  175. /// <summary>
  176. /// only included for backward compatibility. Does nothing
  177. /// </summary>
  178. public virtual bool doUV1 {
  179. get { return false; }
  180. set { }
  181. }
  182. public virtual bool doUV2() {
  183. return _lightmapOption == MB2_LightmapOptions.copy_UV2_unchanged || _lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping || _lightmapOption == MB2_LightmapOptions.copy_UV2_unchanged_to_separate_rects;
  184. }
  185. [SerializeField] protected bool _doUV3;
  186. public virtual bool doUV3 {
  187. get { return _doUV3; }
  188. set { _doUV3 = value; }
  189. }
  190. [SerializeField] protected bool _doUV4;
  191. public virtual bool doUV4 {
  192. get { return _doUV4; }
  193. set { _doUV4 = value; }
  194. }
  195. [SerializeField] protected bool _doUV5;
  196. public virtual bool doUV5
  197. {
  198. get { return _doUV5; }
  199. set { _doUV5 = value; }
  200. }
  201. [SerializeField] protected bool _doUV6;
  202. public virtual bool doUV6
  203. {
  204. get { return _doUV6; }
  205. set { _doUV6 = value; }
  206. }
  207. [SerializeField] protected bool _doUV7;
  208. public virtual bool doUV7
  209. {
  210. get { return _doUV7; }
  211. set { _doUV7 = value; }
  212. }
  213. [SerializeField] protected bool _doUV8;
  214. public virtual bool doUV8
  215. {
  216. get { return _doUV8; }
  217. set { _doUV8 = value; }
  218. }
  219. [SerializeField]
  220. protected bool _doBlendShapes;
  221. public virtual bool doBlendShapes
  222. {
  223. get { return _doBlendShapes; }
  224. set { _doBlendShapes = value; }
  225. }
  226. [UnityEngine.Serialization.FormerlySerializedAs("_recenterVertsToBoundsCenter")]
  227. [SerializeField]
  228. protected MB_MeshPivotLocation _pivotLocationType;
  229. public virtual MB_MeshPivotLocation pivotLocationType
  230. {
  231. get { return _pivotLocationType; }
  232. set { _pivotLocationType = value; }
  233. }
  234. [SerializeField]
  235. protected Vector3 _pivotLocation;
  236. public virtual Vector3 pivotLocation
  237. {
  238. get { return _pivotLocation; }
  239. set { _pivotLocation = value; }
  240. }
  241. /*
  242. [SerializeField]
  243. protected bool _recenterVertsToBoundsCenter = false;
  244. public virtual bool recenterVertsToBoundsCenter
  245. {
  246. get { return _recenterVertsToBoundsCenter; }
  247. set { _recenterVertsToBoundsCenter = value; }
  248. }
  249. */
  250. [SerializeField]
  251. protected bool _clearBuffersAfterBake = false;
  252. public virtual bool clearBuffersAfterBake
  253. {
  254. get { return _clearBuffersAfterBake; }
  255. set {
  256. Debug.LogError("Not implemented.");
  257. _clearBuffersAfterBake = value;
  258. }
  259. }
  260. [SerializeField]
  261. public bool _optimizeAfterBake = true;
  262. public bool optimizeAfterBake
  263. {
  264. get { return _optimizeAfterBake; }
  265. set { _optimizeAfterBake = value; }
  266. }
  267. [SerializeField]
  268. [UnityEngine.Serialization.FormerlySerializedAs("uv2UnwrappingParamsHardAngle")]
  269. protected float _uv2UnwrappingParamsHardAngle = 60f;
  270. public float uv2UnwrappingParamsHardAngle
  271. {
  272. get { return _uv2UnwrappingParamsHardAngle; }
  273. set { _uv2UnwrappingParamsHardAngle = value; }
  274. }
  275. [SerializeField]
  276. [UnityEngine.Serialization.FormerlySerializedAs("uv2UnwrappingParamsPackMargin")]
  277. protected float _uv2UnwrappingParamsPackMargin = .005f;
  278. public float uv2UnwrappingParamsPackMargin
  279. {
  280. get { return _uv2UnwrappingParamsPackMargin; }
  281. set { _uv2UnwrappingParamsPackMargin = value; }
  282. }
  283. [SerializeField]
  284. protected UnityEngine.Object _assignToMeshCustomizer;
  285. public IAssignToMeshCustomizer assignToMeshCustomizer
  286. {
  287. get
  288. {
  289. if (_assignToMeshCustomizer is IAssignToMeshCustomizer)
  290. {
  291. return (IAssignToMeshCustomizer)_assignToMeshCustomizer;
  292. }
  293. else
  294. {
  295. _assignToMeshCustomizer = null;
  296. return null;
  297. }
  298. }
  299. set
  300. {
  301. _assignToMeshCustomizer = (UnityEngine.Object) value;
  302. }
  303. }
  304. protected bool _usingTemporaryTextureBakeResult;
  305. public abstract int GetLightmapIndex();
  306. public abstract void ClearBuffers();
  307. public abstract void ClearMesh();
  308. public abstract void DisposeRuntimeCreated();
  309. public abstract void DestroyMesh();
  310. public abstract void DestroyMeshEditor(MB2_EditorMethodsInterface editorMethods);
  311. public abstract List<GameObject> GetObjectsInCombined();
  312. public abstract int GetNumObjectsInCombined();
  313. public abstract int GetNumVerticesFor(GameObject go);
  314. public abstract int GetNumVerticesFor(int instanceID);
  315. /// <summary>
  316. /// Builds a map for mapping blend shapes in the source SkinnedMeshRenderers to blend shapes in the
  317. /// combined skinned meshes. If you need to serialize the map then use: BuildSourceBlendShapeToCombinedSerializableIndexMap.
  318. /// </summary>
  319. [System.Obsolete("BuildSourceBlendShapeToCombinedIndexMap is deprecated. The map will be attached to the combined SkinnedMeshRenderer object as the MB_BlendShape2CombinedMap Component.")]
  320. public abstract Dictionary<MBBlendShapeKey, MBBlendShapeValue> BuildSourceBlendShapeToCombinedIndexMap();
  321. /// <summary>
  322. /// Copies Mesh Baker internal data to the mesh.
  323. /// </summary>
  324. public virtual void Apply(){
  325. Apply(null);
  326. }
  327. /// <summary>
  328. /// Copies Mesh Baker internal data to the mesh.
  329. /// </summary>
  330. /// <param name='uv2GenerationMethod'>
  331. /// Uv2 generation method. This is normally editor class method Unwrapping.GenerateSecondaryUVSet
  332. /// </param>
  333. public abstract void Apply(GenerateUV2Delegate uv2GenerationMethod);
  334. /// <summary>
  335. /// Apply the specified triangles, vertices, normals, tangents, uvs, colors, uv1, uv2, bones and uv2GenerationMethod.
  336. /// </summary>
  337. /// <param name='triangles'>
  338. /// Triangles.
  339. /// </param>
  340. /// <param name='vertices'>
  341. /// Vertices.
  342. /// </param>
  343. /// <param name='normals'>
  344. /// Normals.
  345. /// </param>
  346. /// <param name='tangents'>
  347. /// Tangents.
  348. /// </param>
  349. /// <param name='uvs'>
  350. /// Uvs.
  351. /// </param>
  352. /// <param name='colors'>
  353. /// Colors.
  354. /// </param>
  355. /// <param name='uv3'>
  356. /// Uv3.
  357. /// </param>
  358. /// <param name='uv4'>
  359. /// Uv4.
  360. /// </param>
  361. /// <param name='uv2'>
  362. /// Uv2.
  363. /// </param>
  364. /// <param name='bones'>
  365. /// Bones.
  366. /// </param>
  367. /// <param name='uv2GenerationMethod'>
  368. /// Uv2 generation method. This is normally method Unwrapping.GenerateSecondaryUVSet. This should be null when calling Apply at runtime.
  369. /// </param>
  370. public abstract void Apply(bool triangles,
  371. bool vertices,
  372. bool normals,
  373. bool tangents,
  374. bool uvs,
  375. bool uv2,
  376. bool uv3,
  377. bool uv4,
  378. bool uv5,
  379. bool uv6,
  380. bool uv7,
  381. bool uv8,
  382. bool colors,
  383. bool bones = false,
  384. bool blendShapeFlag = false,
  385. GenerateUV2Delegate uv2GenerationMethod = null);
  386. /// <summary>
  387. /// Apply the specified triangles, vertices, normals, tangents, uvs, colors, uv1, uv2, bones and uv2GenerationMethod.
  388. /// This is the pre 2018.2 version that does not suport eight UV channels.
  389. /// </summary>
  390. /// <param name='triangles'>
  391. /// Triangles.
  392. /// </param>
  393. /// <param name='vertices'>
  394. /// Vertices.
  395. /// </param>
  396. /// <param name='normals'>
  397. /// Normals.
  398. /// </param>
  399. /// <param name='tangents'>
  400. /// Tangents.
  401. /// </param>
  402. /// <param name='uvs'>
  403. /// Uvs.
  404. /// </param>
  405. /// <param name='colors'>
  406. /// Colors.
  407. /// </param>
  408. /// <param name='uv3'>
  409. /// Uv3.
  410. /// </param>
  411. /// <param name='uv4'>
  412. /// Uv4.
  413. /// </param>
  414. /// <param name='uv2'>
  415. /// Uv2.
  416. /// </param>
  417. /// <param name='bones'>
  418. /// Bones.
  419. /// </param>
  420. /// <param name='uv2GenerationMethod'>
  421. /// Uv2 generation method. This is normally method Unwrapping.GenerateSecondaryUVSet. This should be null when calling Apply at runtime.
  422. /// </param>
  423. public abstract void Apply(bool triangles,
  424. bool vertices,
  425. bool normals,
  426. bool tangents,
  427. bool uvs,
  428. bool uv2,
  429. bool uv3,
  430. bool uv4,
  431. bool colors,
  432. bool bones=false,
  433. bool blendShapeFlag=false,
  434. GenerateUV2Delegate uv2GenerationMethod = null);
  435. public virtual bool UpdateGameObjects(GameObject[] gos)
  436. {
  437. return UpdateGameObjects(gos, true, true, true, true, true, false, false, false,
  438. false, false, false, false, false, false);
  439. }
  440. /// <summary>
  441. /// Updates the data in the combined mesh for meshes that are already in the combined mesh.
  442. /// This is faster than adding and removing a mesh and has a much lower memory footprint.
  443. /// This method can only be used if the meshes being updated have the same layout(number of
  444. /// vertices, triangles, submeshes).
  445. /// This is faster than removing and re-adding
  446. /// For efficiency update as few channels as possible.
  447. /// Apply must be called to apply the changes to the combined mesh
  448. /// </summary>
  449. public virtual bool UpdateGameObjects(GameObject[] gos, bool updateBounds)
  450. {
  451. return UpdateGameObjects(gos, updateBounds, true, true, true, true, false, false, false, false, false, false, false, false, false);
  452. }
  453. /// <summary>
  454. /// Updates the data in the combined mesh for meshes that are already in the combined mesh.
  455. /// This is faster than adding and removing a mesh and has a much lower memory footprint.
  456. /// This method can only be used if the meshes being updated have the same layout(number of
  457. /// vertices, triangles, submeshes).
  458. /// This is faster than removing and re-adding
  459. /// For efficiency update as few channels as possible.
  460. /// Apply must be called to apply the changes to the combined mesh
  461. /// </summary>
  462. public abstract bool UpdateGameObjects(GameObject[] gos, bool recalcBounds,
  463. bool updateVertices, bool updateNormals, bool updateTangents,
  464. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4,
  465. bool updateColors, bool updateSkinningInfo);
  466. /// <summary>
  467. /// Updates the data in the combined mesh for meshes that are already in the combined mesh.
  468. /// This is faster than adding and removing a mesh and has a much lower memory footprint.
  469. /// This method can only be used if the meshes being updated have the same layout(number of
  470. /// vertices, triangles, submeshes).
  471. /// This is faster than removing and re-adding
  472. /// For efficiency update as few channels as possible.
  473. /// Apply must be called to apply the changes to the combined mesh
  474. /// </summary>
  475. public abstract bool UpdateGameObjects(GameObject[] gos, bool recalcBounds,
  476. bool updateVertices, bool updateNormals, bool updateTangents,
  477. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4,
  478. bool updateUV5, bool updateUV6, bool updateUV7, bool updateUV8,
  479. bool updateColors, bool updateSkinningInfo);
  480. public abstract bool AddDeleteGameObjects(GameObject[] gos, GameObject[] deleteGOs, bool disableRendererInSource=true);
  481. public abstract bool AddDeleteGameObjectsByID(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource);
  482. public abstract bool CombinedMeshContains(GameObject go);
  483. public abstract void UpdateSkinnedMeshApproximateBounds();
  484. public abstract void UpdateSkinnedMeshApproximateBoundsFromBones();
  485. public abstract void CheckIntegrity();
  486. /// <summary>
  487. /// Updates the skinned mesh approximate bounds from the bounds of the source objects.
  488. /// </summary>
  489. public abstract void UpdateSkinnedMeshApproximateBoundsFromBounds();
  490. /// <summary>
  491. /// Updates the skinned mesh bounds by creating a bounding box that contains the bones (skeleton) of the source objects.
  492. /// </summary>
  493. public static void UpdateSkinnedMeshApproximateBoundsFromBonesStatic(Transform[] bs, SkinnedMeshRenderer smr){
  494. Vector3 max, min;
  495. max = bs[0].position;
  496. min = bs[0].position;
  497. for (int i = 1; i < bs.Length; i++){
  498. Vector3 v = bs[i].position;
  499. if (v.x < min.x) min.x = v.x;
  500. if (v.y < min.y) min.y = v.y;
  501. if (v.z < min.z) min.z = v.z;
  502. if (v.x > max.x) max.x = v.x;
  503. if (v.y > max.y) max.y = v.y;
  504. if (v.z > max.z) max.z = v.z;
  505. }
  506. Vector3 center = (max + min)/2f;
  507. Vector3 size = max - min;
  508. Matrix4x4 w2l = smr.worldToLocalMatrix;
  509. Bounds b = new Bounds(w2l * center, w2l * size);
  510. smr.localBounds = b;
  511. }
  512. public static void UpdateSkinnedMeshApproximateBoundsFromBoundsStatic(List<GameObject> objectsInCombined,SkinnedMeshRenderer smr){
  513. Bounds b = new Bounds();
  514. Bounds bigB = new Bounds();
  515. if (MB_Utility.GetBounds(objectsInCombined[0],out b)){
  516. bigB = b;
  517. } else {
  518. Debug.LogError("Could not get bounds. Not updating skinned mesh bounds");
  519. return;
  520. }
  521. for (int i = 1; i < objectsInCombined.Count; i++){
  522. if (MB_Utility.GetBounds(objectsInCombined[i],out b)){
  523. bigB.Encapsulate(b);
  524. } else {
  525. Debug.LogError("Could not get bounds. Not updating skinned mesh bounds");
  526. return;
  527. }
  528. }
  529. smr.localBounds = bigB;
  530. }
  531. protected virtual bool _CreateTemporaryTextrueBakeResult(GameObject[] gos, List<Material> matsOnTargetRenderer){
  532. if (GetNumObjectsInCombined() > 0)
  533. {
  534. Debug.LogError("Can't add objects if there are already objects in combined mesh when 'Texture Bake Result' is not set. Perhaps enable 'Clear Buffers After Bake'");
  535. return false;
  536. }
  537. _usingTemporaryTextureBakeResult = true;
  538. _textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(gos, matsOnTargetRenderer);
  539. return true;
  540. }
  541. public abstract List<Material> GetMaterialsOnTargetRenderer();
  542. }
  543. }