MB3_MeshCombinerSimple.cs 138 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116
  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. {
  10. /// <summary>
  11. /// Manages a single combined mesh.This class is the core of the mesh combining API.
  12. ///
  13. /// It is not a component so it can be can be instantiated and used like a normal c sharp class.
  14. /// </summary>
  15. [System.Serializable]
  16. public class MB3_MeshCombinerSingle : MB3_MeshCombiner
  17. {
  18. //2D arrays are not serializable but arrays of arrays are.
  19. [System.Serializable]
  20. public class SerializableIntArray
  21. {
  22. public int[] data;
  23. public SerializableIntArray() { }
  24. public SerializableIntArray(int len)
  25. {
  26. data = new int[len];
  27. }
  28. }
  29. /*
  30. Stores information about one source game object that has been added to
  31. the combined mesh.
  32. */
  33. [System.Serializable]
  34. public class MB_DynamicGameObject : IComparable<MB_DynamicGameObject>
  35. {
  36. public int instanceID;
  37. public string name;
  38. public int vertIdx;
  39. public int blendShapeIdx;
  40. public int numVerts;
  41. public int numBlendShapes;
  42. //distinct list of bones in the bones array
  43. public int[] indexesOfBonesUsed = new int[0];
  44. //public Transform[] _originalBones; //used only for integrity checking
  45. //public Matrix4x4[] _originalBindPoses; //used only for integrity checking
  46. public int lightmapIndex = -1;
  47. public Vector4 lightmapTilingOffset = new Vector4(1f, 1f, 0f, 0f);
  48. public Vector3 meshSize = Vector3.one; // in world coordinates
  49. public bool show = true;
  50. public bool invertTriangles = false;
  51. /// <summary>
  52. /// combined mesh will have one submesh per result material
  53. /// source meshes can have any number of submeshes.They are mapped to a result submesh based on their material
  54. /// if two different submeshes have the same material they are merged in the same result submesh
  55. /// </summary>
  56. // These are result mesh submeshCount comine these into a class.
  57. public int[] submeshTriIdxs;
  58. public int[] submeshNumTris;
  59. /// <summary>
  60. /// These are source go mesh submeshCount todo combined these into a class.
  61. /// Maps each submesh in source mesh to a submesh in combined mesh.
  62. /// </summary>
  63. public int[] targetSubmeshIdxs;
  64. /// <summary>
  65. /// The UVRects in the combinedMaterial atlas.
  66. /// </summary>
  67. public Rect[] uvRects;
  68. /// <summary>
  69. /// If AllPropsUseSameMatTiling is the rect that was used for sampling the atlas texture from the source texture including both mesh uvTiling and material tiling.
  70. /// else is the source mesh obUVrect. We don't need to care which.
  71. /// </summary>
  72. public Rect[] encapsulatingRect;
  73. /// <summary>
  74. /// If AllPropsUseSameMatTiling is the source texture material tiling.
  75. /// else is 0,0,1,1. We don't need to care which.
  76. /// </summary>
  77. public Rect[] sourceMaterialTiling;
  78. /// <summary>
  79. /// The obUVRect for each submesh;
  80. /// </summary>
  81. public Rect[] obUVRects;
  82. public bool _beingDeleted = false;
  83. public int _triangleIdxAdjustment = 0;
  84. //used so we don't have to call GetBones and GetBindposes twice
  85. [NonSerialized]
  86. public SerializableIntArray[] _tmpSubmeshTris;
  87. [NonSerialized]
  88. public Transform[] _tmpCachedBones;
  89. [NonSerialized]
  90. public Matrix4x4[] _tmpCachedBindposes;
  91. [NonSerialized]
  92. public BoneWeight[] _tmpCachedBoneWeights;
  93. [NonSerialized]
  94. public int[] _tmpIndexesOfSourceBonesUsed;
  95. public int CompareTo(MB_DynamicGameObject b)
  96. {
  97. return this.vertIdx - b.vertIdx;
  98. }
  99. }
  100. //if baking many instances of the same sharedMesh, want to cache these results rather than grab them multiple times from the mesh
  101. public class MeshChannels
  102. {
  103. public Vector3[] vertices;
  104. public Vector3[] normals;
  105. public Vector4[] tangents;
  106. public Vector2[] uv0raw;
  107. public Vector2[] uv0modified;
  108. public Vector2[] uv2;
  109. public Vector2[] uv3;
  110. public Vector2[] uv4;
  111. public Color[] colors;
  112. public BoneWeight[] boneWeights;
  113. public Matrix4x4[] bindPoses;
  114. public int[] triangles;
  115. public MBBlendShape[] blendShapes;
  116. }
  117. [Serializable]
  118. public class MBBlendShapeFrame
  119. {
  120. public float frameWeight;
  121. public Vector3[] vertices;
  122. public Vector3[] normals;
  123. public Vector3[] tangents;
  124. }
  125. [Serializable]
  126. public class MBBlendShape
  127. {
  128. public int gameObjectID;
  129. public string name;
  130. public int indexInSource;
  131. public MBBlendShapeFrame[] frames;
  132. }
  133. public class MeshChannelsCache
  134. {
  135. MB3_MeshCombinerSingle mc;
  136. protected Dictionary<int, MeshChannels> meshID2MeshChannels = new Dictionary<int, MeshChannels>();
  137. public MeshChannelsCache(MB3_MeshCombinerSingle mcs)
  138. {
  139. mc = mcs;
  140. }
  141. internal Vector3[] GetVertices(Mesh m)
  142. {
  143. MeshChannels mc;
  144. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  145. {
  146. mc = new MeshChannels();
  147. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  148. }
  149. if (mc.vertices == null)
  150. {
  151. mc.vertices = m.vertices;
  152. }
  153. return mc.vertices;
  154. }
  155. internal Vector3[] GetNormals(Mesh m)
  156. {
  157. MeshChannels mc;
  158. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  159. {
  160. mc = new MeshChannels();
  161. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  162. }
  163. if (mc.normals == null)
  164. {
  165. mc.normals = _getMeshNormals(m);
  166. }
  167. return mc.normals;
  168. }
  169. internal Vector4[] GetTangents(Mesh m)
  170. {
  171. MeshChannels mc;
  172. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  173. {
  174. mc = new MeshChannels();
  175. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  176. }
  177. if (mc.tangents == null)
  178. {
  179. mc.tangents = _getMeshTangents(m);
  180. }
  181. return mc.tangents;
  182. }
  183. internal Vector2[] GetUv0Raw(Mesh m)
  184. {
  185. MeshChannels mc;
  186. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  187. {
  188. mc = new MeshChannels();
  189. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  190. }
  191. if (mc.uv0raw == null)
  192. {
  193. mc.uv0raw = _getMeshUVs(m);
  194. }
  195. return mc.uv0raw;
  196. }
  197. internal Vector2[] GetUv0Modified(Mesh m)
  198. {
  199. MeshChannels mc;
  200. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  201. {
  202. mc = new MeshChannels();
  203. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  204. }
  205. if (mc.uv0modified == null)
  206. {
  207. //todo
  208. mc.uv0modified = null;
  209. }
  210. return mc.uv0modified;
  211. }
  212. internal Vector2[] GetUv2(Mesh m)
  213. {
  214. MeshChannels mc;
  215. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  216. {
  217. mc = new MeshChannels();
  218. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  219. }
  220. if (mc.uv2 == null)
  221. {
  222. mc.uv2 = _getMeshUV2s(m);
  223. }
  224. return mc.uv2;
  225. }
  226. internal Vector2[] GetUv3(Mesh m)
  227. {
  228. MeshChannels mc;
  229. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  230. {
  231. mc = new MeshChannels();
  232. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  233. }
  234. if (mc.uv3 == null)
  235. {
  236. mc.uv3 = MBVersion.GetMeshUV3orUV4(m, true, this.mc.LOG_LEVEL);
  237. }
  238. return mc.uv3;
  239. }
  240. internal Vector2[] GetUv4(Mesh m)
  241. {
  242. MeshChannels mc;
  243. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  244. {
  245. mc = new MeshChannels();
  246. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  247. }
  248. if (mc.uv4 == null)
  249. {
  250. mc.uv4 = MBVersion.GetMeshUV3orUV4(m, false, this.mc.LOG_LEVEL);
  251. }
  252. return mc.uv4;
  253. }
  254. internal Color[] GetColors(Mesh m)
  255. {
  256. MeshChannels mc;
  257. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  258. {
  259. mc = new MeshChannels();
  260. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  261. }
  262. if (mc.colors == null)
  263. {
  264. mc.colors = _getMeshColors(m);
  265. }
  266. return mc.colors;
  267. }
  268. internal Matrix4x4[] GetBindposes(Renderer r)
  269. {
  270. MeshChannels mc;
  271. Mesh m = MB_Utility.GetMesh(r.gameObject);
  272. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  273. {
  274. mc = new MeshChannels();
  275. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  276. }
  277. if (mc.bindPoses == null)
  278. {
  279. mc.bindPoses = _getBindPoses(r);
  280. }
  281. return mc.bindPoses;
  282. }
  283. internal BoneWeight[] GetBoneWeights(Renderer r, int numVertsInMeshBeingAdded)
  284. {
  285. MeshChannels mc;
  286. Mesh m = MB_Utility.GetMesh(r.gameObject);
  287. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  288. {
  289. mc = new MeshChannels();
  290. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  291. }
  292. if (mc.boneWeights == null)
  293. {
  294. mc.boneWeights = _getBoneWeights(r, numVertsInMeshBeingAdded);
  295. }
  296. return mc.boneWeights;
  297. }
  298. internal int[] GetTriangles(Mesh m)
  299. {
  300. MeshChannels mc;
  301. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  302. {
  303. mc = new MeshChannels();
  304. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  305. }
  306. if (mc.triangles == null)
  307. {
  308. mc.triangles = m.triangles;
  309. }
  310. return mc.triangles;
  311. }
  312. internal MBBlendShape[] GetBlendShapes(Mesh m, int gameObjectID)
  313. {
  314. if (MBVersion.GetMajorVersion() > 5 ||
  315. ( MBVersion.GetMajorVersion() == 5 && MBVersion.GetMinorVersion() >= 3))
  316. {
  317. MeshChannels mc;
  318. if (!meshID2MeshChannels.TryGetValue(m.GetInstanceID(), out mc))
  319. {
  320. mc = new MeshChannels();
  321. meshID2MeshChannels.Add(m.GetInstanceID(), mc);
  322. }
  323. if (mc.blendShapes == null)
  324. {
  325. MBBlendShape[] shapes = new MBBlendShape[m.blendShapeCount];
  326. int arrayLen = m.vertexCount;
  327. for (int i = 0; i < shapes.Length; i++)
  328. {
  329. MBBlendShape shape = shapes[i] = new MBBlendShape();
  330. shape.frames = new MBBlendShapeFrame[MBVersion.GetBlendShapeFrameCount(m, i)];
  331. shape.name = m.GetBlendShapeName(i);
  332. shape.indexInSource = i;
  333. shape.gameObjectID = gameObjectID;
  334. for (int j = 0; j < shape.frames.Length; j++)
  335. {
  336. MBBlendShapeFrame frame = shape.frames[j] = new MBBlendShapeFrame();
  337. frame.frameWeight = MBVersion.GetBlendShapeFrameWeight(m, i, j);
  338. frame.vertices = new Vector3[arrayLen];
  339. frame.normals = new Vector3[arrayLen];
  340. frame.tangents = new Vector3[arrayLen];
  341. MBVersion.GetBlendShapeFrameVertices(m, i, j, frame.vertices, frame.normals, frame.tangents);
  342. }
  343. }
  344. mc.blendShapes = shapes;
  345. return mc.blendShapes;
  346. }
  347. else
  348. { //copy cached blend shapes assigning a different gameObjectID
  349. MBBlendShape[] shapes = new MBBlendShape[mc.blendShapes.Length];
  350. for (int i = 0; i < shapes.Length; i++)
  351. {
  352. shapes[i] = new MBBlendShape();
  353. shapes[i].name = mc.blendShapes[i].name;
  354. shapes[i].indexInSource = mc.blendShapes[i].indexInSource;
  355. shapes[i].frames = mc.blendShapes[i].frames;
  356. shapes[i].gameObjectID = gameObjectID;
  357. }
  358. return shapes;
  359. }
  360. } else {
  361. return new MBBlendShape[0];
  362. }
  363. }
  364. Color[] _getMeshColors(Mesh m)
  365. {
  366. Color[] cs = m.colors;
  367. if (cs.Length == 0)
  368. {
  369. if (this.mc.LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no colors. Generating");
  370. if (this.mc.LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have colors. Generating an array of white colors");
  371. cs = new Color[m.vertexCount];
  372. for (int i = 0; i < cs.Length; i++) { cs[i] = Color.white; }
  373. }
  374. return cs;
  375. }
  376. Vector3[] _getMeshNormals(Mesh m)
  377. {
  378. Vector3[] ns = m.normals;
  379. if (ns.Length == 0)
  380. {
  381. if (this.mc.LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no normals. Generating");
  382. if (this.mc.LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have normals. Generating normals.");
  383. Mesh tempMesh = (Mesh)GameObject.Instantiate(m);
  384. tempMesh.RecalculateNormals();
  385. ns = tempMesh.normals;
  386. MB_Utility.Destroy(tempMesh);
  387. }
  388. return ns;
  389. }
  390. Vector4[] _getMeshTangents(Mesh m)
  391. {
  392. Vector4[] ts = m.tangents;
  393. if (ts.Length == 0)
  394. {
  395. if (this.mc.LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no tangents. Generating");
  396. if (this.mc.LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have tangents. Generating tangents.");
  397. Vector3[] verts = m.vertices;
  398. Vector2[] uvs = GetUv0Raw(m);
  399. Vector3[] norms = _getMeshNormals(m);
  400. ts = new Vector4[m.vertexCount];
  401. for (int i = 0; i < m.subMeshCount; i++)
  402. {
  403. int[] tris = m.GetTriangles(i);
  404. _generateTangents(tris, verts, uvs, norms, ts);
  405. }
  406. }
  407. return ts;
  408. }
  409. Vector2 _HALF_UV = new Vector2(.5f, .5f);
  410. Vector2[] _getMeshUVs(Mesh m)
  411. {
  412. Vector2[] uv = m.uv;
  413. if (uv.Length == 0)
  414. {
  415. if (this.mc.LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no uvs. Generating");
  416. if (this.mc.LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have uvs. Generating uvs.");
  417. uv = new Vector2[m.vertexCount];
  418. for (int i = 0; i < uv.Length; i++) { uv[i] = _HALF_UV; }
  419. }
  420. return uv;
  421. }
  422. Vector2[] _getMeshUV2s(Mesh m)
  423. {
  424. Vector2[] uv = m.uv2;
  425. if (uv.Length == 0)
  426. {
  427. if (this.mc.LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no uv2s. Generating");
  428. if (this.mc.LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have uv2s. Generating uv2s.");
  429. if (this.mc._lightmapOption == MB2_LightmapOptions.copy_UV2_unchanged_to_separate_rects) Debug.LogError("Mesh " + m + " did not have a UV2 channel. Nothing to copy when trying to copy UV2 to separate rects. The combined mesh will not lightmap properly. Try using generate new uv2 layout.");
  430. uv = new Vector2[m.vertexCount];
  431. for (int i = 0; i < uv.Length; i++) { uv[i] = _HALF_UV; }
  432. }
  433. return uv;
  434. }
  435. public static Matrix4x4[] _getBindPoses(Renderer r)
  436. {
  437. if (r is SkinnedMeshRenderer)
  438. {
  439. return ((SkinnedMeshRenderer)r).sharedMesh.bindposes;
  440. }
  441. else if (r is MeshRenderer)
  442. {
  443. Matrix4x4 bindPose = Matrix4x4.identity;
  444. Matrix4x4[] poses = new Matrix4x4[1];
  445. poses[0] = bindPose;
  446. return poses;
  447. }
  448. else {
  449. Debug.LogError("Could not _getBindPoses. Object does not have a renderer");
  450. return null;
  451. }
  452. }
  453. public static BoneWeight[] _getBoneWeights(Renderer r, int numVertsInMeshBeingAdded)
  454. {
  455. if (r is SkinnedMeshRenderer)
  456. {
  457. return ((SkinnedMeshRenderer)r).sharedMesh.boneWeights;
  458. }
  459. else if (r is MeshRenderer)
  460. {
  461. BoneWeight bw = new BoneWeight();
  462. bw.boneIndex0 = bw.boneIndex1 = bw.boneIndex2 = bw.boneIndex3 = 0;
  463. bw.weight0 = 1f;
  464. bw.weight1 = bw.weight2 = bw.weight3 = 0f;
  465. BoneWeight[] bws = new BoneWeight[numVertsInMeshBeingAdded];
  466. for (int i = 0; i < bws.Length; i++) bws[i] = bw;
  467. return bws;
  468. }
  469. else {
  470. Debug.LogError("Could not _getBoneWeights. Object does not have a renderer");
  471. return null;
  472. }
  473. }
  474. void _generateTangents(int[] triangles, Vector3[] verts, Vector2[] uvs, Vector3[] normals, Vector4[] outTangents)
  475. {
  476. int triangleCount = triangles.Length;
  477. int vertexCount = verts.Length;
  478. Vector3[] tan1 = new Vector3[vertexCount];
  479. Vector3[] tan2 = new Vector3[vertexCount];
  480. for (int a = 0; a < triangleCount; a += 3)
  481. {
  482. int i1 = triangles[a + 0];
  483. int i2 = triangles[a + 1];
  484. int i3 = triangles[a + 2];
  485. Vector3 v1 = verts[i1];
  486. Vector3 v2 = verts[i2];
  487. Vector3 v3 = verts[i3];
  488. Vector2 w1 = uvs[i1];
  489. Vector2 w2 = uvs[i2];
  490. Vector2 w3 = uvs[i3];
  491. float x1 = v2.x - v1.x;
  492. float x2 = v3.x - v1.x;
  493. float y1 = v2.y - v1.y;
  494. float y2 = v3.y - v1.y;
  495. float z1 = v2.z - v1.z;
  496. float z2 = v3.z - v1.z;
  497. float s1 = w2.x - w1.x;
  498. float s2 = w3.x - w1.x;
  499. float t1 = w2.y - w1.y;
  500. float t2 = w3.y - w1.y;
  501. float rBot = (s1 * t2 - s2 * t1);
  502. if (rBot == 0f)
  503. {
  504. Debug.LogError("Could not compute tangents. All UVs need to form a valid triangles in UV space. If any UV triangles are collapsed, tangents cannot be generated.");
  505. return;
  506. }
  507. float r = 1.0f / rBot;
  508. Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
  509. Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
  510. tan1[i1] += sdir;
  511. tan1[i2] += sdir;
  512. tan1[i3] += sdir;
  513. tan2[i1] += tdir;
  514. tan2[i2] += tdir;
  515. tan2[i3] += tdir;
  516. }
  517. for (int a = 0; a < vertexCount; ++a)
  518. {
  519. Vector3 n = normals[a];
  520. Vector3 t = tan1[a];
  521. Vector3 tmp = (t - n * Vector3.Dot(n, t)).normalized;
  522. outTangents[a] = new Vector4(tmp.x, tmp.y, tmp.z);
  523. outTangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
  524. }
  525. }
  526. }
  527. //Used for comparing if skinned meshes use the same bone and bindpose.
  528. //Skinned meshes must be bound with the same TRS to share a bone.
  529. public struct BoneAndBindpose
  530. {
  531. public Transform bone;
  532. public Matrix4x4 bindPose;
  533. public BoneAndBindpose(Transform t, Matrix4x4 bp)
  534. {
  535. bone = t;
  536. bindPose = bp;
  537. }
  538. public override bool Equals(object obj)
  539. {
  540. if (obj is BoneAndBindpose)
  541. {
  542. if (bone == ((BoneAndBindpose)obj).bone && bindPose == ((BoneAndBindpose)obj).bindPose)
  543. {
  544. return true;
  545. }
  546. }
  547. return false;
  548. }
  549. public override int GetHashCode()
  550. {
  551. //OK if don't check bindPose well because bp should be the same
  552. return (bone.GetInstanceID() % 2147483647) ^ (int)bindPose[0, 0];
  553. }
  554. }
  555. public override MB2_TextureBakeResults textureBakeResults
  556. {
  557. set
  558. {
  559. if (mbDynamicObjectsInCombinedMesh.Count > 0 && _textureBakeResults != value && _textureBakeResults != null)
  560. {
  561. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("If Texture Bake Result is changed then objects currently in combined mesh may be invalid.");
  562. }
  563. _textureBakeResults = value;
  564. }
  565. }
  566. public override MB_RenderType renderType
  567. {
  568. set
  569. {
  570. if (value == MB_RenderType.skinnedMeshRenderer && _renderType == MB_RenderType.meshRenderer)
  571. {
  572. if (boneWeights.Length != verts.Length) Debug.LogError("Can't set the render type to SkinnedMeshRenderer without clearing the mesh first. Try deleteing the CombinedMesh scene object.");
  573. }
  574. _renderType = value;
  575. }
  576. }
  577. public override GameObject resultSceneObject
  578. {
  579. set
  580. {
  581. if (_resultSceneObject != value)
  582. {
  583. _targetRenderer = null;
  584. if (_mesh != null && _LOG_LEVEL >= MB2_LogLevel.warn)
  585. {
  586. Debug.LogWarning("Result Scene Object was changed when this mesh baker component had a reference to a mesh. If mesh is being used by another object make sure to reset the mesh to none before baking to avoid overwriting the other mesh.");
  587. }
  588. }
  589. _resultSceneObject = value;
  590. }
  591. }
  592. //this contains object instances that have been added to the combined mesh through AddDelete
  593. [SerializeField]
  594. protected List<GameObject> objectsInCombinedMesh = new List<GameObject>();
  595. [SerializeField]
  596. int lightmapIndex = -1;
  597. [SerializeField]
  598. List<MB_DynamicGameObject> mbDynamicObjectsInCombinedMesh = new List<MB_DynamicGameObject>();
  599. Dictionary<int, MB_DynamicGameObject> _instance2combined_map = new Dictionary<int, MB_DynamicGameObject>();
  600. [SerializeField]
  601. Vector3[] verts = new Vector3[0];
  602. [SerializeField]
  603. Vector3[] normals = new Vector3[0];
  604. [SerializeField]
  605. Vector4[] tangents = new Vector4[0];
  606. [SerializeField]
  607. Vector2[] uvs = new Vector2[0];
  608. [SerializeField]
  609. Vector2[] uv2s = new Vector2[0];
  610. [SerializeField]
  611. Vector2[] uv3s = new Vector2[0];
  612. [SerializeField]
  613. Vector2[] uv4s = new Vector2[0];
  614. [SerializeField]
  615. Color[] colors = new Color[0];
  616. [SerializeField]
  617. Matrix4x4[] bindPoses = new Matrix4x4[0];
  618. [SerializeField]
  619. Transform[] bones = new Transform[0];
  620. [SerializeField]
  621. internal MBBlendShape[] blendShapes = new MBBlendShape[0];
  622. [SerializeField]
  623. //these blend shapes are not cleared they are used to build the src to combined blend shape map
  624. internal MBBlendShape[] blendShapesInCombined = new MBBlendShape[0];
  625. [SerializeField]
  626. SerializableIntArray[] submeshTris = new SerializableIntArray[0];
  627. [SerializeField]
  628. Mesh _mesh;
  629. //unity won't serialize these
  630. BoneWeight[] boneWeights = new BoneWeight[0];
  631. //used if user passes null in as parameter to AddOrDelete
  632. GameObject[] empty = new GameObject[0];
  633. int[] emptyIDs = new int[0];
  634. MB_DynamicGameObject instance2Combined_MapGet(int gameObjectID)
  635. {
  636. return _instance2combined_map[gameObjectID];
  637. }
  638. void instance2Combined_MapAdd(int gameObjectID, MB_DynamicGameObject dgo)
  639. {
  640. _instance2combined_map.Add(gameObjectID, dgo);
  641. }
  642. void instance2Combined_MapRemove(int gameObjectID)
  643. {
  644. _instance2combined_map.Remove(gameObjectID);
  645. }
  646. bool instance2Combined_MapTryGetValue(int gameObjectID, out MB_DynamicGameObject dgo)
  647. {
  648. return _instance2combined_map.TryGetValue(gameObjectID, out dgo);
  649. }
  650. int instance2Combined_MapCount()
  651. {
  652. return _instance2combined_map.Count;
  653. }
  654. void instance2Combined_MapClear()
  655. {
  656. _instance2combined_map.Clear();
  657. }
  658. bool instance2Combined_MapContainsKey(int gameObjectID)
  659. {
  660. return _instance2combined_map.ContainsKey(gameObjectID);
  661. }
  662. public override int GetNumObjectsInCombined()
  663. {
  664. return mbDynamicObjectsInCombinedMesh.Count;
  665. }
  666. public override List<GameObject> GetObjectsInCombined()
  667. {
  668. List<GameObject> outObs = new List<GameObject>();
  669. outObs.AddRange(objectsInCombinedMesh);
  670. return outObs;
  671. }
  672. public Mesh GetMesh()
  673. {
  674. if (_mesh == null)
  675. {
  676. _mesh = new Mesh();
  677. // _mesh.MarkDynamic();
  678. }
  679. return _mesh;
  680. }
  681. public void SetMesh(Mesh m)
  682. {
  683. _mesh = m;
  684. }
  685. public Transform[] GetBones()
  686. {
  687. return bones;
  688. }
  689. public override int GetLightmapIndex()
  690. {
  691. if (lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout || lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping)
  692. {
  693. return lightmapIndex;
  694. }
  695. else {
  696. return -1;
  697. }
  698. }
  699. public override int GetNumVerticesFor(GameObject go)
  700. {
  701. return GetNumVerticesFor(go.GetInstanceID());
  702. }
  703. public override int GetNumVerticesFor(int instanceID)
  704. {
  705. MB_DynamicGameObject dgo;
  706. if (instance2Combined_MapTryGetValue(instanceID, out dgo))
  707. {
  708. return dgo.numVerts;
  709. }
  710. else {
  711. return -1;
  712. }
  713. }
  714. public override Dictionary<MBBlendShapeKey, MBBlendShapeValue> BuildSourceBlendShapeToCombinedIndexMap()
  715. {
  716. Dictionary<MBBlendShapeKey, MBBlendShapeValue> map = new Dictionary<MBBlendShapeKey, MBBlendShapeValue>();
  717. for (int i = 0; i < blendShapesInCombined.Length; i++)
  718. {
  719. MBBlendShapeValue bsv = new MBBlendShapeValue();
  720. bsv.combinedMeshGameObject = _targetRenderer.gameObject;
  721. bsv.blendShapeIndex = i;
  722. map.Add(new MBBlendShapeKey(blendShapesInCombined[i].gameObjectID, blendShapesInCombined[i].indexInSource), bsv);
  723. }
  724. return map;
  725. }
  726. void _initialize(int numResultMats)
  727. {
  728. if (mbDynamicObjectsInCombinedMesh.Count == 0)
  729. {
  730. lightmapIndex = -1;
  731. }
  732. if (_mesh == null)
  733. {
  734. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("_initialize Creating new Mesh");
  735. _mesh = GetMesh();
  736. }
  737. if (instance2Combined_MapCount() != mbDynamicObjectsInCombinedMesh.Count)
  738. {
  739. //build the instance2Combined map
  740. instance2Combined_MapClear();
  741. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  742. {
  743. if (mbDynamicObjectsInCombinedMesh[i] != null)
  744. {
  745. instance2Combined_MapAdd(mbDynamicObjectsInCombinedMesh[i].instanceID, mbDynamicObjectsInCombinedMesh[i]);
  746. }
  747. }
  748. //BoneWeights are not serialized get from combined mesh
  749. boneWeights = _mesh.boneWeights;
  750. }
  751. if (objectsInCombinedMesh.Count == 0)
  752. {
  753. if (submeshTris.Length != numResultMats)
  754. {
  755. submeshTris = new SerializableIntArray[numResultMats];
  756. for (int i = 0; i < submeshTris.Length; i++) submeshTris[i] = new SerializableIntArray(0);
  757. }
  758. }
  759. //MeshBaker was baked using old system that had duplicated bones. Upgrade to new system
  760. //need to build indexesOfBonesUsed maps for dgos
  761. if (mbDynamicObjectsInCombinedMesh.Count > 0 &&
  762. mbDynamicObjectsInCombinedMesh[0].indexesOfBonesUsed.Length == 0 &&
  763. renderType == MB_RenderType.skinnedMeshRenderer &&
  764. boneWeights.Length > 0)
  765. {
  766. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  767. {
  768. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  769. HashSet<int> idxsOfBonesUsed = new HashSet<int>();
  770. for (int j = dgo.vertIdx; j < dgo.vertIdx + dgo.numVerts; j++)
  771. {
  772. if (boneWeights[j].weight0 > 0f) idxsOfBonesUsed.Add(boneWeights[j].boneIndex0);
  773. if (boneWeights[j].weight1 > 0f) idxsOfBonesUsed.Add(boneWeights[j].boneIndex1);
  774. if (boneWeights[j].weight2 > 0f) idxsOfBonesUsed.Add(boneWeights[j].boneIndex2);
  775. if (boneWeights[j].weight3 > 0f) idxsOfBonesUsed.Add(boneWeights[j].boneIndex3);
  776. }
  777. dgo.indexesOfBonesUsed = new int[idxsOfBonesUsed.Count];
  778. idxsOfBonesUsed.CopyTo(dgo.indexesOfBonesUsed);
  779. }
  780. if (LOG_LEVEL >= MB2_LogLevel.debug)
  781. Debug.Log("Baker used old systems that duplicated bones. Upgrading to new system by building indexesOfBonesUsed");
  782. }
  783. if (LOG_LEVEL >= MB2_LogLevel.trace) {
  784. Debug.Log (String.Format ("_initialize numObjsInCombined={0}", mbDynamicObjectsInCombinedMesh.Count));
  785. }
  786. }
  787. bool _collectMaterialTriangles(Mesh m, MB_DynamicGameObject dgo, Material[] sharedMaterials, OrderedDictionary sourceMats2submeshIdx_map)
  788. {
  789. //everything here applies to the source object being added
  790. int numTriMeshes = m.subMeshCount;
  791. if (sharedMaterials.Length < numTriMeshes) numTriMeshes = sharedMaterials.Length;
  792. dgo._tmpSubmeshTris = new SerializableIntArray[numTriMeshes];
  793. dgo.targetSubmeshIdxs = new int[numTriMeshes];
  794. for (int i = 0; i < numTriMeshes; i++)
  795. {
  796. if (_textureBakeResults.doMultiMaterial)
  797. {
  798. if (!sourceMats2submeshIdx_map.Contains(sharedMaterials[i]))
  799. {
  800. Debug.LogError("Object " + dgo.name + " has a material that was not found in the result materials maping. " + sharedMaterials[i]);
  801. return false;
  802. }
  803. dgo.targetSubmeshIdxs[i] = (int)sourceMats2submeshIdx_map[sharedMaterials[i]];
  804. }
  805. else {
  806. dgo.targetSubmeshIdxs[i] = 0;
  807. }
  808. dgo._tmpSubmeshTris[i] = new SerializableIntArray();
  809. dgo._tmpSubmeshTris[i].data = m.GetTriangles(i);
  810. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Collecting triangles for: " + dgo.name + " submesh:" + i + " maps to submesh:" + dgo.targetSubmeshIdxs[i] + " added:" + dgo._tmpSubmeshTris[i].data.Length, LOG_LEVEL);
  811. }
  812. return true;
  813. }
  814. // if adding many copies of the same mesh want to cache obUVsResults
  815. bool _collectOutOfBoundsUVRects2(Mesh m, MB_DynamicGameObject dgo, Material[] sharedMaterials, OrderedDictionary sourceMats2submeshIdx_map, Dictionary<int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResults, MeshChannelsCache meshChannelCache)
  816. {
  817. if (_textureBakeResults == null)
  818. {
  819. Debug.LogError("Need to bake textures into combined material");
  820. return false;
  821. }
  822. MB_Utility.MeshAnalysisResult[] res;
  823. if (meshAnalysisResults.TryGetValue(m.GetInstanceID(), out res))
  824. {
  825. dgo.obUVRects = new Rect[sharedMaterials.Length];
  826. for (int i = 0; i < dgo.obUVRects.Length; i++)
  827. {
  828. dgo.obUVRects[i] = res[i].uvRect;
  829. }
  830. }
  831. else {
  832. int numTriMeshes = m.subMeshCount;
  833. int numUsedTriMeshes = numTriMeshes;
  834. if (sharedMaterials.Length < numTriMeshes) numUsedTriMeshes = sharedMaterials.Length;
  835. dgo.obUVRects = new Rect[numUsedTriMeshes];
  836. //the mesh analysis result might be longer because we are caching and sharing the result with other
  837. //renderers which may use more materials
  838. res = new MB_Utility.MeshAnalysisResult[numTriMeshes];
  839. for (int i = 0; i < numTriMeshes; i++)
  840. {
  841. int idxInResultMats = dgo.targetSubmeshIdxs[i];
  842. if (_textureBakeResults.resultMaterials[idxInResultMats].considerMeshUVs)
  843. {
  844. Vector2[] uvs = meshChannelCache.GetUv0Raw(m);
  845. MB_Utility.hasOutOfBoundsUVs(uvs, m, ref res[i], i);
  846. Rect r = res[i].uvRect;
  847. if (i < numUsedTriMeshes) dgo.obUVRects[i] = r;
  848. }
  849. }
  850. meshAnalysisResults.Add(m.GetInstanceID(), res);
  851. }
  852. return true;
  853. }
  854. bool _validateTextureBakeResults()
  855. {
  856. if (_textureBakeResults == null)
  857. {
  858. Debug.LogError("Texture Bake Results is null. Can't combine meshes.");
  859. return false;
  860. }
  861. if (_textureBakeResults.materialsAndUVRects == null || _textureBakeResults.materialsAndUVRects.Length == 0)
  862. {
  863. Debug.LogError("Texture Bake Results has no materials in material to sourceUVRect map. Try baking materials. Can't combine meshes.");
  864. return false;
  865. }
  866. if (_textureBakeResults.resultMaterials == null || _textureBakeResults.resultMaterials.Length == 0)
  867. {
  868. Debug.LogError("Texture Bake Results has no result materials. Try baking materials. Can't combine meshes.");
  869. return false;
  870. }
  871. return true;
  872. }
  873. bool _validateMeshFlags()
  874. {
  875. if (mbDynamicObjectsInCombinedMesh.Count > 0)
  876. {
  877. if (_doNorm == false && doNorm == true ||
  878. _doTan == false && doTan == true ||
  879. _doCol == false && doCol == true ||
  880. _doUV == false && doUV == true ||
  881. _doUV3 == false && doUV3 == true ||
  882. _doUV4 == false && doUV4 == true)
  883. {
  884. Debug.LogError("The channels have changed. There are already objects in the combined mesh that were added with a different set of channels.");
  885. return false;
  886. }
  887. }
  888. _doNorm = doNorm;
  889. _doTan = doTan;
  890. _doCol = doCol;
  891. _doUV = doUV;
  892. _doUV3 = doUV3;
  893. _doUV4 = doUV4;
  894. return true;
  895. }
  896. bool _showHide(GameObject[] goToShow, GameObject[] goToHide)
  897. {
  898. if (goToShow == null) goToShow = empty;
  899. if (goToHide == null) goToHide = empty;
  900. //calculate amount to hide
  901. int numResultMats = _textureBakeResults.resultMaterials.Length;
  902. _initialize(numResultMats);
  903. for (int i = 0; i < goToHide.Length; i++)
  904. {
  905. if (!instance2Combined_MapContainsKey(goToHide[i].GetInstanceID()))
  906. {
  907. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Trying to hide an object " + goToHide[i] + " that is not in combined mesh. Did you initially bake with 'clear buffers after bake' enabled?");
  908. return false;
  909. }
  910. }
  911. //now to show
  912. for (int i = 0; i < goToShow.Length; i++)
  913. {
  914. if (!instance2Combined_MapContainsKey(goToShow[i].GetInstanceID()))
  915. {
  916. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Trying to show an object " + goToShow[i] + " that is not in combined mesh. Did you initially bake with 'clear buffers after bake' enabled?");
  917. return false;
  918. }
  919. }
  920. //set flags
  921. for (int i = 0; i < goToHide.Length; i++) _instance2combined_map[goToHide[i].GetInstanceID()].show = false;
  922. for (int i = 0; i < goToShow.Length; i++) _instance2combined_map[goToShow[i].GetInstanceID()].show = true;
  923. return true;
  924. }
  925. bool _addToCombined(GameObject[] goToAdd, int[] goToDelete, bool disableRendererInSource)
  926. {
  927. System.Diagnostics.Stopwatch sw = null;
  928. if (LOG_LEVEL >= MB2_LogLevel.debug)
  929. {
  930. sw = new System.Diagnostics.Stopwatch();
  931. sw.Start();
  932. }
  933. GameObject[] _goToAdd;
  934. int[] _goToDelete;
  935. if (!_validateTextureBakeResults()) return false;
  936. if (!_validateMeshFlags()) return false;
  937. if (!ValidateTargRendererAndMeshAndResultSceneObj()) return false;
  938. if (outputOption != MB2_OutputOptions.bakeMeshAssetsInPlace &&
  939. renderType == MB_RenderType.skinnedMeshRenderer)
  940. {
  941. if (_targetRenderer == null || !(_targetRenderer is SkinnedMeshRenderer))
  942. {
  943. Debug.LogError("Target renderer must be set and must be a SkinnedMeshRenderer");
  944. return false;
  945. }
  946. }
  947. if (_doBlendShapes && renderType != MB_RenderType.skinnedMeshRenderer)
  948. {
  949. Debug.LogError("If doBlendShapes is set then RenderType must be skinnedMeshRenderer.");
  950. return false;
  951. }
  952. if (goToAdd == null) _goToAdd = empty;
  953. else _goToAdd = (GameObject[])goToAdd.Clone();
  954. if (goToDelete == null) _goToDelete = emptyIDs;
  955. else _goToDelete = (int[])goToDelete.Clone();
  956. if (_mesh == null) DestroyMesh(); //cleanup maps and arrays
  957. MB2_TextureBakeResults.Material2AtlasRectangleMapper mat2rect_map = new MB2_TextureBakeResults.Material2AtlasRectangleMapper(textureBakeResults);
  958. int numResultMats = _textureBakeResults.resultMaterials.Length;
  959. _initialize(numResultMats);
  960. if (submeshTris.Length != numResultMats)
  961. {
  962. Debug.LogError("The number of submeshes " + submeshTris.Length + " in the combined mesh was not equal to the number of result materials " + numResultMats + " in the Texture Bake Result");
  963. return false;
  964. }
  965. if (_mesh.vertexCount > 0 && _instance2combined_map.Count == 0)
  966. {
  967. Debug.LogWarning("There were vertices in the combined mesh but nothing in the MeshBaker buffers. If you are trying to bake in the editor and modify at runtime, make sure 'Clear Buffers After Bake' is unchecked.");
  968. }
  969. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("==== Calling _addToCombined objs adding:" + _goToAdd.Length + " objs deleting:" + _goToDelete.Length + " fixOutOfBounds:" + textureBakeResults.DoAnyResultMatsUseConsiderMeshUVs() + " doMultiMaterial:" + textureBakeResults.doMultiMaterial + " disableRenderersInSource:" + disableRendererInSource, LOG_LEVEL);
  970. //backward compatibility set up resultMaterials if it is blank
  971. if (_textureBakeResults.resultMaterials == null || _textureBakeResults.resultMaterials.Length == 0)
  972. {
  973. Debug.LogError("No resultMaterials in this TextureBakeResults. Try baking textures.");
  974. return false;
  975. }
  976. OrderedDictionary sourceMats2submeshIdx_map = new OrderedDictionary();
  977. //build the sourceMats to submesh index map
  978. for (int i = 0; i < numResultMats; i++)
  979. {
  980. MB_MultiMaterial mm = _textureBakeResults.resultMaterials[i];
  981. for (int j = 0; j < mm.sourceMaterials.Count; j++)
  982. {
  983. if (mm.sourceMaterials[j] == null)
  984. {
  985. Debug.LogError("Found null material in source materials for combined mesh materials " + i);
  986. return false;
  987. }
  988. if (!sourceMats2submeshIdx_map.Contains(mm.sourceMaterials[j]))
  989. {
  990. sourceMats2submeshIdx_map.Add(mm.sourceMaterials[j], i);
  991. }
  992. }
  993. }
  994. //STEP 1 update our internal description of objects being added and deleted keep track of changes to buffer sizes as we do.
  995. //calculate amount to delete
  996. int totalDeleteVerts = 0;
  997. int[] totalDeleteSubmeshTris = new int[numResultMats];
  998. int totalDeleteBlendShapes = 0;
  999. //in order to decide if a bone can be deleted need to know which dgos use it so build a map
  1000. List<MB_DynamicGameObject>[] boneIdx2dgoMap = null;
  1001. HashSet<int> boneIdxsToDelete = new HashSet<int>();
  1002. HashSet<BoneAndBindpose> bonesToAdd = new HashSet<BoneAndBindpose>();
  1003. if (renderType == MB_RenderType.skinnedMeshRenderer && _goToDelete.Length > 0)
  1004. {
  1005. boneIdx2dgoMap = _buildBoneIdx2dgoMap();
  1006. }
  1007. for (int i = 0; i < _goToDelete.Length; i++)
  1008. {
  1009. MB_DynamicGameObject dgo;
  1010. if (instance2Combined_MapTryGetValue(_goToDelete[i], out dgo))
  1011. {
  1012. totalDeleteVerts += dgo.numVerts;
  1013. totalDeleteBlendShapes += dgo.numBlendShapes;
  1014. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1015. {
  1016. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
  1017. {
  1018. if (boneIdx2dgoMap[dgo.indexesOfBonesUsed[j]].Contains(dgo))
  1019. {
  1020. boneIdx2dgoMap[dgo.indexesOfBonesUsed[j]].Remove(dgo);
  1021. if (boneIdx2dgoMap[dgo.indexesOfBonesUsed[j]].Count == 0)
  1022. {
  1023. boneIdxsToDelete.Add(dgo.indexesOfBonesUsed[j]);
  1024. }
  1025. }
  1026. }
  1027. }
  1028. for (int j = 0; j < dgo.submeshNumTris.Length; j++)
  1029. {
  1030. totalDeleteSubmeshTris[j] += dgo.submeshNumTris[j];
  1031. }
  1032. }
  1033. else {
  1034. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Trying to delete an object that is not in combined mesh");
  1035. }
  1036. }
  1037. //now add
  1038. List<MB_DynamicGameObject> toAddDGOs = new List<MB_DynamicGameObject>();
  1039. Dictionary<int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary<int, MB_Utility.MeshAnalysisResult[]>(); //cache results
  1040. //we are often adding the same sharedMesh many times. Only want to grab the results once and cache them
  1041. MeshChannelsCache meshChannelCache = new MeshChannelsCache(this);
  1042. int totalAddVerts = 0;
  1043. int[] totalAddSubmeshTris = new int[numResultMats];
  1044. int totalAddBlendShapes = 0;
  1045. Dictionary<Transform, int> bone2idx = new Dictionary<Transform, int>();
  1046. for (int i = 0; i < bones.Length; i++)
  1047. {
  1048. bone2idx.Add(bones[i], i);
  1049. }
  1050. for (int i = 0; i < _goToAdd.Length; i++)
  1051. {
  1052. // if not already in mesh or we are deleting and re-adding in same operation
  1053. if (!instance2Combined_MapContainsKey(_goToAdd[i].GetInstanceID()) || Array.FindIndex<int>(_goToDelete, o => o == _goToAdd[i].GetInstanceID()) != -1)
  1054. {
  1055. MB_DynamicGameObject dgo = new MB_DynamicGameObject();
  1056. GameObject go = _goToAdd[i];
  1057. Material[] sharedMaterials = MB_Utility.GetGOMaterials(go);
  1058. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(String.Format("Getting {0} shared materials for {1}",sharedMaterials.Length, go));
  1059. if (sharedMaterials == null)
  1060. {
  1061. Debug.LogError("Object " + go.name + " does not have a Renderer");
  1062. _goToAdd[i] = null;
  1063. return false;
  1064. }
  1065. Mesh m = MB_Utility.GetMesh(go);
  1066. if (m == null)
  1067. {
  1068. Debug.LogError("Object " + go.name + " MeshFilter or SkinedMeshRenderer had no mesh");
  1069. _goToAdd[i] = null;
  1070. return false;
  1071. }
  1072. else if (MBVersion.IsRunningAndMeshNotReadWriteable(m))
  1073. {
  1074. Debug.LogError("Object " + go.name + " Mesh Importer has read/write flag set to 'false'. This needs to be set to 'true' in order to read data from this mesh.");
  1075. _goToAdd[i] = null;
  1076. return false;
  1077. }
  1078. MB_TextureTilingTreatment[] tilingTreatment = new MB_TextureTilingTreatment[sharedMaterials.Length];
  1079. Rect[] uvRectsInAtlas = new Rect[sharedMaterials.Length];
  1080. Rect[] encapsulatingRect = new Rect[sharedMaterials.Length];
  1081. Rect[] sourceMaterialTiling = new Rect[sharedMaterials.Length];
  1082. String errorMsg = "";
  1083. for (int j = 0; j < sharedMaterials.Length; j++)
  1084. {
  1085. System.Object subIdx = sourceMats2submeshIdx_map[sharedMaterials[j]];
  1086. int resMatIdx;
  1087. if (subIdx == null)
  1088. {
  1089. Debug.LogError("Source object " + go.name + " used a material " + sharedMaterials[j] + " that was not in the baked materials.");
  1090. return false;
  1091. } else
  1092. {
  1093. resMatIdx = (int)subIdx;
  1094. }
  1095. if (!mat2rect_map.TryMapMaterialToUVRect(sharedMaterials[j], m, j, resMatIdx, meshChannelCache, meshAnalysisResultsCache,
  1096. out tilingTreatment[j],
  1097. out uvRectsInAtlas[j],
  1098. out encapsulatingRect[j],
  1099. out sourceMaterialTiling[j],
  1100. ref errorMsg, LOG_LEVEL))
  1101. {
  1102. Debug.LogError(errorMsg);
  1103. _goToAdd[i] = null;
  1104. return false;
  1105. }
  1106. }
  1107. if (_goToAdd[i] != null)
  1108. {
  1109. toAddDGOs.Add(dgo);
  1110. dgo.name = String.Format("{0} {1}", _goToAdd[i].ToString(), _goToAdd[i].GetInstanceID());
  1111. dgo.instanceID = _goToAdd[i].GetInstanceID();
  1112. dgo.uvRects = uvRectsInAtlas;
  1113. dgo.encapsulatingRect = encapsulatingRect;
  1114. dgo.sourceMaterialTiling = sourceMaterialTiling;
  1115. dgo.numVerts = m.vertexCount;
  1116. if (_doBlendShapes)
  1117. {
  1118. dgo.numBlendShapes = m.blendShapeCount;
  1119. }
  1120. Renderer r = MB_Utility.GetRenderer(go);
  1121. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1122. {
  1123. _CollectBonesToAddForDGO(dgo, bone2idx, boneIdxsToDelete, bonesToAdd, r, meshChannelCache);
  1124. }
  1125. if (lightmapIndex == -1)
  1126. {
  1127. lightmapIndex = r.lightmapIndex; //initialize
  1128. }
  1129. if (lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping)
  1130. {
  1131. if (lightmapIndex != r.lightmapIndex)
  1132. {
  1133. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Object " + go.name + " has a different lightmap index. Lightmapping will not work.");
  1134. }
  1135. if (!MBVersion.GetActive(go))
  1136. {
  1137. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Object " + go.name + " is inactive. Can only get lightmap index of active objects.");
  1138. }
  1139. if (r.lightmapIndex == -1)
  1140. {
  1141. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Object " + go.name + " does not have an index to a lightmap.");
  1142. }
  1143. }
  1144. dgo.lightmapIndex = r.lightmapIndex;
  1145. dgo.lightmapTilingOffset = MBVersion.GetLightmapTilingOffset(r);
  1146. if (!_collectMaterialTriangles(m, dgo, sharedMaterials, sourceMats2submeshIdx_map))
  1147. {
  1148. return false;
  1149. }
  1150. dgo.meshSize = r.bounds.size;
  1151. dgo.submeshNumTris = new int[numResultMats];
  1152. dgo.submeshTriIdxs = new int[numResultMats];
  1153. if (textureBakeResults.DoAnyResultMatsUseConsiderMeshUVs())
  1154. {
  1155. if (!_collectOutOfBoundsUVRects2(m, dgo, sharedMaterials, sourceMats2submeshIdx_map, meshAnalysisResultsCache, meshChannelCache))
  1156. {
  1157. return false;
  1158. }
  1159. }
  1160. totalAddVerts += dgo.numVerts;
  1161. totalAddBlendShapes += dgo.numBlendShapes;
  1162. for (int j = 0; j < dgo._tmpSubmeshTris.Length; j++)
  1163. {
  1164. totalAddSubmeshTris[dgo.targetSubmeshIdxs[j]] += dgo._tmpSubmeshTris[j].data.Length;
  1165. }
  1166. dgo.invertTriangles = IsMirrored(go.transform.localToWorldMatrix);
  1167. }
  1168. }
  1169. else {
  1170. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Object " + _goToAdd[i].name + " has already been added");
  1171. _goToAdd[i] = null;
  1172. }
  1173. }
  1174. for (int i = 0; i < _goToAdd.Length; i++)
  1175. {
  1176. if (_goToAdd[i] != null && disableRendererInSource)
  1177. {
  1178. MB_Utility.DisableRendererInSource(_goToAdd[i]);
  1179. if (LOG_LEVEL == MB2_LogLevel.trace) Debug.Log("Disabling renderer on " + _goToAdd[i].name + " id=" + _goToAdd[i].GetInstanceID());
  1180. }
  1181. }
  1182. //STEP 2 to allocate new buffers and copy everything over
  1183. int newVertSize = verts.Length + totalAddVerts - totalDeleteVerts;
  1184. int newBonesSize = bindPoses.Length + bonesToAdd.Count - boneIdxsToDelete.Count;
  1185. int[] newSubmeshTrisSize = new int[numResultMats];
  1186. int newBlendShapeSize = blendShapes.Length + totalAddBlendShapes - totalDeleteBlendShapes;
  1187. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Verts adding:" + totalAddVerts + " deleting:" + totalDeleteVerts + " submeshes:" + newSubmeshTrisSize.Length + " bones:" + newBonesSize + " blendShapes:" + newBlendShapeSize);
  1188. for (int i = 0; i < newSubmeshTrisSize.Length; i++)
  1189. {
  1190. newSubmeshTrisSize[i] = submeshTris[i].data.Length + totalAddSubmeshTris[i] - totalDeleteSubmeshTris[i];
  1191. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug(" submesh :" + i + " already contains:" + submeshTris[i].data.Length + " tris to be Added:" + totalAddSubmeshTris[i] + " tris to be Deleted:" + totalDeleteSubmeshTris[i]);
  1192. }
  1193. if (newVertSize >= MBVersion.MaxMeshVertexCount())
  1194. {
  1195. Debug.LogError("Cannot add objects. Resulting mesh will have more than " + MBVersion.MaxMeshVertexCount() + " vertices. Try using a Multi-MeshBaker component. This will split the combined mesh into several meshes. You don't have to re-configure the MB2_TextureBaker. Just remove the MB2_MeshBaker component and add a MB2_MultiMeshBaker component.");
  1196. return false;
  1197. }
  1198. Vector3[] nnormals = null;
  1199. Vector4[] ntangents = null;
  1200. Vector2[] nuvs = null, nuv2s = null, nuv3s = null, nuv4s = null;
  1201. Color[] ncolors = null;
  1202. MBBlendShape[] nblendShapes = null;
  1203. Vector3[] nverts = new Vector3[newVertSize];
  1204. if (_doNorm) nnormals = new Vector3[newVertSize];
  1205. if (_doTan) ntangents = new Vector4[newVertSize];
  1206. if (_doUV) nuvs = new Vector2[newVertSize];
  1207. if (_doUV3) nuv3s = new Vector2[newVertSize];
  1208. if (_doUV4) nuv4s = new Vector2[newVertSize];
  1209. if (doUV2())
  1210. {
  1211. nuv2s = new Vector2[newVertSize];
  1212. }
  1213. if (_doCol) ncolors = new Color[newVertSize];
  1214. if (_doBlendShapes) nblendShapes = new MBBlendShape[newBlendShapeSize];
  1215. BoneWeight[] nboneWeights = new BoneWeight[newVertSize];
  1216. Matrix4x4[] nbindPoses = new Matrix4x4[newBonesSize];
  1217. Transform[] nbones = new Transform[newBonesSize];
  1218. SerializableIntArray[] nsubmeshTris = new SerializableIntArray[numResultMats];
  1219. for (int i = 0; i < nsubmeshTris.Length; i++)
  1220. {
  1221. nsubmeshTris[i] = new SerializableIntArray(newSubmeshTrisSize[i]);
  1222. }
  1223. for (int i = 0; i < _goToDelete.Length; i++)
  1224. {
  1225. MB_DynamicGameObject dgo = null;
  1226. if (instance2Combined_MapTryGetValue(_goToDelete[i], out dgo))
  1227. {
  1228. dgo._beingDeleted = true;
  1229. }
  1230. }
  1231. mbDynamicObjectsInCombinedMesh.Sort();
  1232. //copy existing arrays to narrays gameobj by gameobj omitting deleted ones
  1233. int targVidx = 0;
  1234. int targBlendShapeIdx = 0;
  1235. int[] targSubmeshTidx = new int[numResultMats];
  1236. int triangleIdxAdjustment = 0;
  1237. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  1238. {
  1239. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  1240. if (!dgo._beingDeleted)
  1241. {
  1242. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Copying obj in combined arrays idx:" + i, LOG_LEVEL);
  1243. Array.Copy(verts, dgo.vertIdx, nverts, targVidx, dgo.numVerts);
  1244. if (_doNorm) { Array.Copy(normals, dgo.vertIdx, nnormals, targVidx, dgo.numVerts); }
  1245. if (_doTan) { Array.Copy(tangents, dgo.vertIdx, ntangents, targVidx, dgo.numVerts); }
  1246. if (_doUV) { Array.Copy(uvs, dgo.vertIdx, nuvs, targVidx, dgo.numVerts); }
  1247. if (_doUV3) { Array.Copy(uv3s, dgo.vertIdx, nuv3s, targVidx, dgo.numVerts); }
  1248. if (_doUV4) { Array.Copy(uv4s, dgo.vertIdx, nuv4s, targVidx, dgo.numVerts); }
  1249. if (doUV2()) { Array.Copy(uv2s, dgo.vertIdx, nuv2s, targVidx, dgo.numVerts); }
  1250. if (_doCol) { Array.Copy(colors, dgo.vertIdx, ncolors, targVidx, dgo.numVerts); }
  1251. if (_doBlendShapes) { Array.Copy(blendShapes, dgo.blendShapeIdx, nblendShapes, targBlendShapeIdx, dgo.numBlendShapes); }
  1252. if (renderType == MB_RenderType.skinnedMeshRenderer) { Array.Copy(boneWeights, dgo.vertIdx, nboneWeights, targVidx, dgo.numVerts); }
  1253. //adjust triangles, then copy them over
  1254. for (int subIdx = 0; subIdx < numResultMats; subIdx++)
  1255. {
  1256. int[] sTris = submeshTris[subIdx].data;
  1257. int sTriIdx = dgo.submeshTriIdxs[subIdx];
  1258. int sNumTris = dgo.submeshNumTris[subIdx];
  1259. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug(" Adjusting submesh triangles submesh:" + subIdx + " startIdx:" + sTriIdx + " num:" + sNumTris + " nsubmeshTris:" + nsubmeshTris.Length + " targSubmeshTidx:" + targSubmeshTidx.Length, LOG_LEVEL);
  1260. for (int j = sTriIdx; j < sTriIdx + sNumTris; j++)
  1261. {
  1262. sTris[j] = sTris[j] - triangleIdxAdjustment;
  1263. }
  1264. Array.Copy(sTris, sTriIdx, nsubmeshTris[subIdx].data, targSubmeshTidx[subIdx], sNumTris);
  1265. }
  1266. dgo.vertIdx = targVidx;
  1267. dgo.blendShapeIdx = targBlendShapeIdx;
  1268. for (int j = 0; j < targSubmeshTidx.Length; j++)
  1269. {
  1270. dgo.submeshTriIdxs[j] = targSubmeshTidx[j];
  1271. targSubmeshTidx[j] += dgo.submeshNumTris[j];
  1272. }
  1273. targBlendShapeIdx += dgo.numBlendShapes;
  1274. targVidx += dgo.numVerts;
  1275. }
  1276. else {
  1277. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Not copying obj: " + i, LOG_LEVEL);
  1278. triangleIdxAdjustment += dgo.numVerts;
  1279. }
  1280. }
  1281. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1282. {
  1283. _CopyBonesWeAreKeepingToNewBonesArrayAndAdjustBWIndexes(boneIdxsToDelete, bonesToAdd, nbones, nbindPoses, nboneWeights, totalDeleteVerts);
  1284. }
  1285. //remove objects we are deleting
  1286. for (int i = mbDynamicObjectsInCombinedMesh.Count - 1; i >= 0; i--)
  1287. {
  1288. if (mbDynamicObjectsInCombinedMesh[i]._beingDeleted)
  1289. {
  1290. instance2Combined_MapRemove(mbDynamicObjectsInCombinedMesh[i].instanceID);
  1291. objectsInCombinedMesh.RemoveAt(i);
  1292. mbDynamicObjectsInCombinedMesh.RemoveAt(i);
  1293. }
  1294. }
  1295. verts = nverts;
  1296. if (_doNorm) normals = nnormals;
  1297. if (_doTan) tangents = ntangents;
  1298. if (_doUV) uvs = nuvs;
  1299. if (_doUV3) uv3s = nuv3s;
  1300. if (_doUV4) uv4s = nuv4s;
  1301. if (doUV2()) uv2s = nuv2s;
  1302. if (_doCol) colors = ncolors;
  1303. if (_doBlendShapes) blendShapes = nblendShapes;
  1304. if (renderType == MB_RenderType.skinnedMeshRenderer) boneWeights = nboneWeights;
  1305. int newBonesStartAtIdx = bones.Length - boneIdxsToDelete.Count;
  1306. bindPoses = nbindPoses;
  1307. bones = nbones;
  1308. submeshTris = nsubmeshTris;
  1309. //insert the new bones into the bones array
  1310. int bidx = 0;
  1311. foreach (BoneAndBindpose t in bonesToAdd)
  1312. {
  1313. nbones[newBonesStartAtIdx + bidx] = t.bone;
  1314. nbindPoses[newBonesStartAtIdx + bidx] = t.bindPose;
  1315. bidx++;
  1316. }
  1317. //add new
  1318. for (int i = 0; i < toAddDGOs.Count; i++)
  1319. {
  1320. MB_DynamicGameObject dgo = toAddDGOs[i];
  1321. GameObject go = _goToAdd[i];
  1322. int vertsIdx = targVidx;
  1323. int blendShapeIdx = targBlendShapeIdx;
  1324. // Profile.StartProfile("TestNewNorm");
  1325. Mesh mesh = MB_Utility.GetMesh(go);
  1326. Matrix4x4 l2wMat = go.transform.localToWorldMatrix;
  1327. //same as l2w with translation removed
  1328. Matrix4x4 l2wRotScale = l2wMat;
  1329. l2wRotScale[0, 3] = l2wRotScale[1, 3] = l2wRotScale[2, 3] = 0f;
  1330. //can't modify the arrays we get from the cache because they will be modified again
  1331. nverts = meshChannelCache.GetVertices(mesh);
  1332. Vector3[] nnorms = null;
  1333. Vector4[] ntangs = null;
  1334. if (_doNorm) nnorms = meshChannelCache.GetNormals(mesh);
  1335. if (_doTan) ntangs = meshChannelCache.GetTangents(mesh);
  1336. if (renderType != MB_RenderType.skinnedMeshRenderer)
  1337. { //for skinned meshes leave in bind pose
  1338. for (int j = 0; j < nverts.Length; j++)
  1339. {
  1340. int vIdx = vertsIdx + j;
  1341. verts[vertsIdx + j] = l2wMat.MultiplyPoint3x4(nverts[j]);
  1342. if (_doNorm)
  1343. {
  1344. normals[vIdx] = l2wRotScale.MultiplyPoint3x4(nnorms[j]);
  1345. normals[vIdx] = normals[vIdx].normalized;
  1346. }
  1347. if (_doTan)
  1348. {
  1349. float w = ntangs[j].w; //need to preserve the w value
  1350. Vector3 tn = l2wRotScale.MultiplyPoint3x4(ntangs[j]);
  1351. tn.Normalize();
  1352. tangents[vIdx] = tn;
  1353. tangents[vIdx].w = w;
  1354. }
  1355. }
  1356. }
  1357. else {
  1358. if (_doNorm) nnorms.CopyTo(normals, vertsIdx);
  1359. if (_doTan) ntangs.CopyTo(tangents, vertsIdx);
  1360. nverts.CopyTo(verts, vertsIdx);
  1361. }
  1362. // Profile.EndProfile("TestNewNorm");
  1363. int numTriSets = mesh.subMeshCount;
  1364. if (dgo.uvRects.Length < numTriSets)
  1365. {
  1366. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + dgo.name + " has more submeshes than materials");
  1367. numTriSets = dgo.uvRects.Length;
  1368. }
  1369. else if (dgo.uvRects.Length > numTriSets)
  1370. {
  1371. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + dgo.name + " has fewer submeshes than materials");
  1372. }
  1373. if (_doUV)
  1374. {
  1375. _copyAndAdjustUVsFromMesh(dgo, mesh, vertsIdx, meshChannelCache);
  1376. }
  1377. if (doUV2())
  1378. {
  1379. _copyAndAdjustUV2FromMesh(dgo, mesh, vertsIdx, meshChannelCache);
  1380. }
  1381. if (_doUV3)
  1382. {
  1383. nuv3s = meshChannelCache.GetUv3(mesh);
  1384. nuv3s.CopyTo(uv3s, vertsIdx);
  1385. }
  1386. if (_doUV4)
  1387. {
  1388. nuv4s = meshChannelCache.GetUv4(mesh);
  1389. nuv4s.CopyTo(uv4s, vertsIdx);
  1390. }
  1391. if (_doCol)
  1392. {
  1393. ncolors = meshChannelCache.GetColors(mesh);
  1394. ncolors.CopyTo(colors, vertsIdx);
  1395. }
  1396. if (_doBlendShapes)
  1397. {
  1398. nblendShapes = meshChannelCache.GetBlendShapes(mesh, dgo.instanceID);
  1399. nblendShapes.CopyTo(blendShapes, blendShapeIdx);
  1400. }
  1401. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1402. {
  1403. Renderer r = MB_Utility.GetRenderer(go);
  1404. _AddBonesToNewBonesArrayAndAdjustBWIndexes(dgo, r, vertsIdx, nbones, nboneWeights, meshChannelCache);
  1405. }
  1406. for (int combinedMeshIdx = 0; combinedMeshIdx < targSubmeshTidx.Length; combinedMeshIdx++)
  1407. {
  1408. dgo.submeshTriIdxs[combinedMeshIdx] = targSubmeshTidx[combinedMeshIdx];
  1409. }
  1410. for (int j = 0; j < dgo._tmpSubmeshTris.Length; j++)
  1411. {
  1412. int[] sts = dgo._tmpSubmeshTris[j].data;
  1413. for (int k = 0; k < sts.Length; k++)
  1414. {
  1415. sts[k] = sts[k] + vertsIdx;
  1416. }
  1417. if (dgo.invertTriangles)
  1418. {
  1419. //need to reverse winding order
  1420. for (int k = 0; k < sts.Length; k += 3)
  1421. {
  1422. int tmp = sts[k];
  1423. sts[k] = sts[k + 1];
  1424. sts[k + 1] = tmp;
  1425. }
  1426. }
  1427. int combinedMeshIdx = dgo.targetSubmeshIdxs[j];
  1428. sts.CopyTo(submeshTris[combinedMeshIdx].data, targSubmeshTidx[combinedMeshIdx]);
  1429. dgo.submeshNumTris[combinedMeshIdx] += sts.Length;
  1430. targSubmeshTidx[combinedMeshIdx] += sts.Length;
  1431. }
  1432. dgo.vertIdx = targVidx;
  1433. dgo.blendShapeIdx = targBlendShapeIdx;
  1434. instance2Combined_MapAdd(go.GetInstanceID(), dgo);
  1435. objectsInCombinedMesh.Add(go);
  1436. mbDynamicObjectsInCombinedMesh.Add(dgo);
  1437. targVidx += nverts.Length;
  1438. if (_doBlendShapes)
  1439. {
  1440. targBlendShapeIdx += nblendShapes.Length;
  1441. }
  1442. for (int j = 0; j < dgo._tmpSubmeshTris.Length; j++) dgo._tmpSubmeshTris[j] = null;
  1443. dgo._tmpSubmeshTris = null;
  1444. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Added to combined:" + dgo.name + " verts:" + nverts.Length + " bindPoses:" + nbindPoses.Length, LOG_LEVEL);
  1445. }
  1446. if (lightmapOption == MB2_LightmapOptions.copy_UV2_unchanged_to_separate_rects)
  1447. {
  1448. _copyUV2unchangedToSeparateRects();
  1449. }
  1450. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("===== _addToCombined completed. Verts in buffer: " + verts.Length + " time(ms): " + sw.ElapsedMilliseconds, LOG_LEVEL);
  1451. return true;
  1452. }
  1453. void _copyAndAdjustUVsFromMesh(MB_DynamicGameObject dgo, Mesh mesh, int vertsIdx, MeshChannelsCache meshChannelsCache)
  1454. {
  1455. Vector2[] nuvs = meshChannelsCache.GetUv0Raw(mesh);
  1456. int[] done = new int[nuvs.Length]; //use this to track uvs that have already been adjusted don't adjust twice
  1457. for (int l = 0; l < done.Length; l++)
  1458. done[l] = -1;
  1459. bool triangleArraysOverlap = false;
  1460. //Rect uvRectInSrc = new Rect (0f,0f,1f,1f);
  1461. //need to address the UVs through the submesh indexes because
  1462. //each submesh has a different UV index
  1463. for (int submeshIdx = 0; submeshIdx < dgo.targetSubmeshIdxs.Length; submeshIdx++)
  1464. {
  1465. int[] subTris;
  1466. if (dgo._tmpSubmeshTris != null)
  1467. {
  1468. subTris = dgo._tmpSubmeshTris[submeshIdx].data;
  1469. }
  1470. else
  1471. {
  1472. subTris = mesh.GetTriangles(submeshIdx);
  1473. }
  1474. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(String.Format("Build UV transform for mesh {0} submesh {1} encapsulatingRect {2}",
  1475. dgo.name,submeshIdx, dgo.encapsulatingRect[submeshIdx]));
  1476. Rect rr = MB3_TextureCombinerMerging.BuildTransformMeshUV2AtlasRect(
  1477. textureBakeResults.resultMaterials[dgo.targetSubmeshIdxs[submeshIdx]].considerMeshUVs,
  1478. dgo.uvRects[submeshIdx],
  1479. dgo.obUVRects == null ? new Rect(0,0,1,1) : dgo.obUVRects[submeshIdx],
  1480. dgo.sourceMaterialTiling[submeshIdx],
  1481. dgo.encapsulatingRect[submeshIdx]);
  1482. for (int l = 0; l < subTris.Length; l++)
  1483. {
  1484. int vidx = subTris[l];
  1485. if (done[vidx] == -1)
  1486. {
  1487. done[vidx] = submeshIdx; //prevents a uv from being adjusted twice. Same vert can be on more than one submesh.
  1488. Vector2 nuv = nuvs[vidx]; //don't modify nuvs directly because it is cached and we might be re-using
  1489. //if (textureBakeResults.fixOutOfBoundsUVs) {
  1490. //uvRectInSrc can be larger than (out of bounds uvs) or smaller than 0..1
  1491. //this transforms the uvs so they fit inside the uvRectInSrc sample box
  1492. // scale, shift to fit in atlas rect
  1493. nuv.x = rr.x + nuv.x * rr.width;
  1494. nuv.y = rr.y + nuv.y * rr.height;
  1495. uvs[vertsIdx + vidx] = nuv;
  1496. }
  1497. if (done[vidx] != submeshIdx)
  1498. {
  1499. triangleArraysOverlap = true;
  1500. }
  1501. }
  1502. }
  1503. if (triangleArraysOverlap)
  1504. {
  1505. if (LOG_LEVEL >= MB2_LogLevel.warn)
  1506. Debug.LogWarning(dgo.name + "has submeshes which share verticies. Adjusted uvs may not map correctly in combined atlas.");
  1507. }
  1508. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("_copyAndAdjustUVsFromMesh copied {0} verts", nuvs.Length));
  1509. }
  1510. void _copyAndAdjustUV2FromMesh(MB_DynamicGameObject dgo, Mesh mesh, int vertsIdx, MeshChannelsCache meshChannelsCache)
  1511. {
  1512. Vector2[] nuv2s = meshChannelsCache.GetUv2(mesh);
  1513. if (lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping)
  1514. { //has a lightmap
  1515. //this does not work in Unity 5. the lightmapTilingOffset is always 1,1,0,0 for all objects
  1516. //lightMap index is always 1
  1517. Vector2 uvscale2;
  1518. Vector4 lightmapTilingOffset = dgo.lightmapTilingOffset;
  1519. Vector2 uvscale = new Vector2(lightmapTilingOffset.x, lightmapTilingOffset.y);
  1520. Vector2 uvoffset = new Vector2(lightmapTilingOffset.z, lightmapTilingOffset.w);
  1521. for (int j = 0; j < nuv2s.Length; j++)
  1522. {
  1523. uvscale2.x = uvscale.x * nuv2s[j].x;
  1524. uvscale2.y = uvscale.y * nuv2s[j].y;
  1525. uv2s[vertsIdx + j] = uvoffset + uvscale2;
  1526. }
  1527. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("_copyAndAdjustUV2FromMesh copied and modify for preserve current lightmapping " + nuv2s.Length);
  1528. }
  1529. else
  1530. {
  1531. nuv2s.CopyTo(uv2s, vertsIdx);
  1532. if (LOG_LEVEL >= MB2_LogLevel.trace)
  1533. {
  1534. Debug.Log("_copyAndAdjustUV2FromMesh copied without modifying " + nuv2s.Length);
  1535. }
  1536. }
  1537. }
  1538. public override void UpdateSkinnedMeshApproximateBounds()
  1539. {
  1540. UpdateSkinnedMeshApproximateBoundsFromBounds();
  1541. }
  1542. public override void UpdateSkinnedMeshApproximateBoundsFromBones()
  1543. {
  1544. if (outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
  1545. {
  1546. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Can't UpdateSkinnedMeshApproximateBounds when output type is bakeMeshAssetsInPlace");
  1547. return;
  1548. }
  1549. if (bones.Length == 0)
  1550. {
  1551. if (verts.Length > 0) if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("No bones in SkinnedMeshRenderer. Could not UpdateSkinnedMeshApproximateBounds.");
  1552. return;
  1553. }
  1554. if (_targetRenderer == null)
  1555. {
  1556. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not set. No point in calling UpdateSkinnedMeshApproximateBounds.");
  1557. return;
  1558. }
  1559. if (!_targetRenderer.GetType().Equals(typeof(SkinnedMeshRenderer)))
  1560. {
  1561. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not a SkinnedMeshRenderer. No point in calling UpdateSkinnedMeshApproximateBounds.");
  1562. return;
  1563. }
  1564. UpdateSkinnedMeshApproximateBoundsFromBonesStatic(bones, (SkinnedMeshRenderer)targetRenderer);
  1565. }
  1566. public override void UpdateSkinnedMeshApproximateBoundsFromBounds()
  1567. {
  1568. if (outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
  1569. {
  1570. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Can't UpdateSkinnedMeshApproximateBoundsFromBounds when output type is bakeMeshAssetsInPlace");
  1571. return;
  1572. }
  1573. if (verts.Length == 0 || mbDynamicObjectsInCombinedMesh.Count == 0)
  1574. {
  1575. if (verts.Length > 0) if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Nothing in SkinnedMeshRenderer. Could not UpdateSkinnedMeshApproximateBoundsFromBounds.");
  1576. return;
  1577. }
  1578. if (_targetRenderer == null)
  1579. {
  1580. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not set. No point in calling UpdateSkinnedMeshApproximateBoundsFromBounds.");
  1581. return;
  1582. }
  1583. if (!_targetRenderer.GetType().Equals(typeof(SkinnedMeshRenderer)))
  1584. {
  1585. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Target Renderer is not a SkinnedMeshRenderer. No point in calling UpdateSkinnedMeshApproximateBoundsFromBounds.");
  1586. return;
  1587. }
  1588. UpdateSkinnedMeshApproximateBoundsFromBoundsStatic(objectsInCombinedMesh, (SkinnedMeshRenderer)targetRenderer);
  1589. }
  1590. int _getNumBones(Renderer r)
  1591. {
  1592. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1593. {
  1594. if (r is SkinnedMeshRenderer)
  1595. {
  1596. return ((SkinnedMeshRenderer)r).bones.Length;
  1597. }
  1598. else if (r is MeshRenderer)
  1599. {
  1600. return 1;
  1601. }
  1602. else {
  1603. Debug.LogError("Could not _getNumBones. Object does not have a renderer");
  1604. return 0;
  1605. }
  1606. }
  1607. else {
  1608. return 0;
  1609. }
  1610. }
  1611. Transform[] _getBones(Renderer r)
  1612. {
  1613. return MBVersion.GetBones(r);
  1614. }
  1615. public override void Apply(GenerateUV2Delegate uv2GenerationMethod)
  1616. {
  1617. bool doBones = false;
  1618. if (renderType == MB_RenderType.skinnedMeshRenderer) doBones = true;
  1619. Apply(true, true, _doNorm, _doTan, _doUV, doUV2(), _doUV3, _doUV4, doCol, doBones, doBlendShapes, uv2GenerationMethod);
  1620. }
  1621. public virtual void ApplyShowHide()
  1622. {
  1623. if (_validationLevel >= MB2_ValidationLevel.quick && !ValidateTargRendererAndMeshAndResultSceneObj()) return;
  1624. if (_mesh != null)
  1625. {
  1626. if (renderType == MB_RenderType.meshRenderer)
  1627. {
  1628. //for MeshRenderer meshes this is needed for adding. It breaks skinnedMeshRenderers
  1629. MBVersion.MeshClear(_mesh, true);
  1630. _mesh.vertices = verts;
  1631. }
  1632. SerializableIntArray[] submeshTrisToUse = GetSubmeshTrisWithShowHideApplied();
  1633. if (textureBakeResults.doMultiMaterial)
  1634. {
  1635. //submeshes with zero length tris cause error messages. must exclude these
  1636. int numNonZero = _mesh.subMeshCount = _numNonZeroLengthSubmeshTris(submeshTrisToUse);// submeshTrisToUse.Length;
  1637. int submeshIdx = 0;
  1638. for (int i = 0; i < submeshTrisToUse.Length; i++)
  1639. {
  1640. if (submeshTrisToUse[i].data.Length != 0)
  1641. {
  1642. _mesh.SetTriangles(submeshTrisToUse[i].data, submeshIdx);
  1643. submeshIdx++;
  1644. }
  1645. }
  1646. _updateMaterialsOnTargetRenderer(submeshTrisToUse, numNonZero);
  1647. }
  1648. else {
  1649. _mesh.triangles = submeshTrisToUse[0].data;
  1650. }
  1651. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1652. {
  1653. if (verts.Length == 0)
  1654. {
  1655. //disable mesh renderer to avoid skinning warning
  1656. targetRenderer.enabled = false;
  1657. }
  1658. else
  1659. {
  1660. targetRenderer.enabled = true;
  1661. }
  1662. //needed so that updating local bounds will take affect
  1663. bool uwos = ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen;
  1664. ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen = true;
  1665. ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen = uwos;
  1666. }
  1667. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("ApplyShowHide");
  1668. }
  1669. else {
  1670. Debug.LogError("Need to add objects to this meshbaker before calling ApplyShowHide");
  1671. }
  1672. }
  1673. public override void Apply(bool triangles,
  1674. bool vertices,
  1675. bool normals,
  1676. bool tangents,
  1677. bool uvs,
  1678. bool uv2,
  1679. bool uv3,
  1680. bool uv4,
  1681. bool colors,
  1682. bool bones = false,
  1683. bool blendShapesFlag = false,
  1684. GenerateUV2Delegate uv2GenerationMethod = null)
  1685. {
  1686. System.Diagnostics.Stopwatch sw = null;
  1687. if (LOG_LEVEL >= MB2_LogLevel.debug)
  1688. {
  1689. sw = new System.Diagnostics.Stopwatch();
  1690. sw.Start();
  1691. }
  1692. if (_validationLevel >= MB2_ValidationLevel.quick && !ValidateTargRendererAndMeshAndResultSceneObj()) return;
  1693. if (_mesh != null)
  1694. {
  1695. if (LOG_LEVEL >= MB2_LogLevel.trace)
  1696. {
  1697. Debug.Log(String.Format("Apply called tri={0} vert={1} norm={2} tan={3} uv={4} col={5} uv3={6} uv4={7} uv2={8} bone={9} blendShape{10} meshID={11}",
  1698. triangles, vertices, normals, tangents, uvs, colors, uv3, uv4, uv2, bones, blendShapes, _mesh.GetInstanceID()));
  1699. }
  1700. if (triangles || _mesh.vertexCount != verts.Length)
  1701. {
  1702. bool justClearTriangles = triangles && !vertices && !normals && !tangents && !uvs && !colors && !uv3 && !uv4 && !uv2 && !bones;
  1703. MBVersion.SetMeshIndexFormatAndClearMesh(_mesh, verts.Length, vertices, justClearTriangles);
  1704. }
  1705. if (vertices)
  1706. {
  1707. Vector3[] verts2Write = verts;
  1708. if (verts.Length > 0) {
  1709. if (_recenterVertsToBoundsCenter && _renderType == MB_RenderType.meshRenderer)
  1710. {
  1711. verts2Write = new Vector3[verts.Length];
  1712. Vector3 max = verts[0], min = verts[0];
  1713. for (int i = 1; i < verts.Length; i++)
  1714. {
  1715. Vector3 v = verts[i];
  1716. if (max.x < v.x) max.x = v.x;
  1717. if (max.y < v.y) max.y = v.y;
  1718. if (max.z < v.z) max.z = v.z;
  1719. if (min.x > v.x) min.x = v.x;
  1720. if (min.y > v.y) min.y = v.y;
  1721. if (min.z > v.z) min.z = v.z;
  1722. }
  1723. Vector3 center = (max + min) / 2f;
  1724. for (int i = 0; i < verts.Length; i++)
  1725. {
  1726. verts2Write[i] = verts[i] - center;
  1727. }
  1728. targetRenderer.transform.position = center;
  1729. } else
  1730. {
  1731. targetRenderer.transform.position = Vector3.zero;
  1732. }
  1733. }
  1734. _mesh.vertices = verts2Write;
  1735. }
  1736. if (triangles && _textureBakeResults)
  1737. {
  1738. if (_textureBakeResults == null)
  1739. {
  1740. Debug.LogError("Texture Bake Result was not set.");
  1741. }
  1742. else {
  1743. SerializableIntArray[] submeshTrisToUse = GetSubmeshTrisWithShowHideApplied();
  1744. //if (_textureBakeResults.doMultiMaterial)
  1745. //{
  1746. //submeshes with zero length tris cause error messages. must exclude these
  1747. int numNonZero = _mesh.subMeshCount = _numNonZeroLengthSubmeshTris(submeshTrisToUse);// submeshTrisToUse.Length;
  1748. int submeshIdx = 0;
  1749. for (int i = 0; i < submeshTrisToUse.Length; i++)
  1750. {
  1751. if (submeshTrisToUse[i].data.Length != 0)
  1752. {
  1753. _mesh.SetTriangles(submeshTrisToUse[i].data, submeshIdx);
  1754. submeshIdx++;
  1755. }
  1756. }
  1757. _updateMaterialsOnTargetRenderer(submeshTrisToUse, numNonZero);
  1758. //}
  1759. //else {
  1760. // _mesh.triangles = submeshTrisToUse[0].data;
  1761. //}
  1762. }
  1763. }
  1764. if (normals)
  1765. {
  1766. if (_doNorm) { _mesh.normals = this.normals; }
  1767. else { Debug.LogError("normal flag was set in Apply but MeshBaker didn't generate normals"); }
  1768. }
  1769. if (tangents)
  1770. {
  1771. if (_doTan) { _mesh.tangents = this.tangents; }
  1772. else { Debug.LogError("tangent flag was set in Apply but MeshBaker didn't generate tangents"); }
  1773. }
  1774. if (uvs)
  1775. {
  1776. if (_doUV) { _mesh.uv = this.uvs; }
  1777. else { Debug.LogError("uv flag was set in Apply but MeshBaker didn't generate uvs"); }
  1778. }
  1779. if (colors)
  1780. {
  1781. if (_doCol) { _mesh.colors = this.colors; }
  1782. else { Debug.LogError("color flag was set in Apply but MeshBaker didn't generate colors"); }
  1783. }
  1784. if (uv3)
  1785. {
  1786. if (_doUV3)
  1787. {
  1788. MBVersion.MeshAssignUV3(_mesh, this.uv3s);
  1789. }
  1790. else { Debug.LogError("uv3 flag was set in Apply but MeshBaker didn't generate uv3s"); }
  1791. }
  1792. if (uv4)
  1793. {
  1794. if (_doUV4)
  1795. {
  1796. MBVersion.MeshAssignUV4(_mesh, this.uv4s);
  1797. }
  1798. else { Debug.LogError("uv4 flag was set in Apply but MeshBaker didn't generate uv4s"); }
  1799. }
  1800. if (uv2)
  1801. {
  1802. if (doUV2()) { _mesh.uv2 = this.uv2s; }
  1803. else { Debug.LogError("uv2 flag was set in Apply but lightmapping option was set to " + lightmapOption); }
  1804. }
  1805. bool do_generate_new_UV2_layout = false;
  1806. if (renderType != MB_RenderType.skinnedMeshRenderer && lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
  1807. {
  1808. if (uv2GenerationMethod != null)
  1809. {
  1810. uv2GenerationMethod(_mesh, uv2UnwrappingParamsHardAngle, uv2UnwrappingParamsPackMargin);
  1811. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("generating new UV2 layout for the combined mesh ");
  1812. }
  1813. else {
  1814. Debug.LogError("No GenerateUV2Delegate method was supplied. UV2 cannot be generated.");
  1815. }
  1816. do_generate_new_UV2_layout = true;
  1817. }
  1818. else if (renderType == MB_RenderType.skinnedMeshRenderer && lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
  1819. {
  1820. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("UV2 cannot be generated for SkinnedMeshRenderer objects.");
  1821. }
  1822. if (renderType != MB_RenderType.skinnedMeshRenderer && lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout && do_generate_new_UV2_layout == false)
  1823. {
  1824. Debug.LogError("Failed to generate new UV2 layout. Only works in editor.");
  1825. }
  1826. if (renderType == MB_RenderType.skinnedMeshRenderer)
  1827. {
  1828. if (verts.Length == 0)
  1829. {
  1830. //disable mesh renderer to avoid skinning warning
  1831. targetRenderer.enabled = false;
  1832. }
  1833. else {
  1834. targetRenderer.enabled = true;
  1835. }
  1836. //needed so that updating local bounds will take affect
  1837. bool uwos = ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen;
  1838. ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen = true;
  1839. ((SkinnedMeshRenderer)targetRenderer).updateWhenOffscreen = uwos;
  1840. }
  1841. if (bones)
  1842. {
  1843. _mesh.bindposes = this.bindPoses;
  1844. _mesh.boneWeights = this.boneWeights;
  1845. }
  1846. if (blendShapesFlag)
  1847. {
  1848. if (MBVersion.GetMajorVersion() > 5 ||
  1849. (MBVersion.GetMajorVersion() == 5 && MBVersion.GetMinorVersion() >= 3))
  1850. {
  1851. if (blendShapesInCombined.Length != blendShapes.Length) blendShapesInCombined = new MBBlendShape[blendShapes.Length];
  1852. Vector3[] vs = new UnityEngine.Vector3[verts.Length];
  1853. Vector3[] ns = new UnityEngine.Vector3[verts.Length];
  1854. Vector3[] ts = new UnityEngine.Vector3[verts.Length];
  1855. MBVersion.ClearBlendShapes(_mesh);
  1856. for (int i = 0; i < blendShapes.Length; i++)
  1857. {
  1858. MB_DynamicGameObject dgo = instance2Combined_MapGet(blendShapes[i].gameObjectID);
  1859. if (dgo != null)
  1860. {
  1861. for (int j = 0; j < blendShapes[i].frames.Length; j++)
  1862. {
  1863. MBBlendShapeFrame frame = blendShapes[i].frames[j];
  1864. int destIdx = dgo.vertIdx;
  1865. Array.Copy(frame.vertices, 0, vs, destIdx, blendShapes[i].frames[j].vertices.Length);
  1866. Array.Copy(frame.normals, 0, ns, destIdx, blendShapes[i].frames[j].normals.Length);
  1867. Array.Copy(frame.tangents, 0, ts, destIdx, blendShapes[i].frames[j].tangents.Length);
  1868. MBVersion.AddBlendShapeFrame(_mesh,blendShapes[i].name + blendShapes[i].gameObjectID, frame.frameWeight, vs, ns, ts);
  1869. _ZeroArray(vs, destIdx, blendShapes[i].frames[j].vertices.Length);
  1870. _ZeroArray(ns, destIdx, blendShapes[i].frames[j].normals.Length);
  1871. _ZeroArray(ts, destIdx, blendShapes[i].frames[j].tangents.Length);
  1872. }
  1873. }
  1874. else
  1875. {
  1876. Debug.LogError("InstanceID in blend shape that was not in instance2combinedMap");
  1877. }
  1878. blendShapesInCombined[i] = blendShapes[i];
  1879. }
  1880. //this is necessary to get the renderer to refresh its data about the blendshapes.
  1881. ((SkinnedMeshRenderer)_targetRenderer).sharedMesh = null;
  1882. ((SkinnedMeshRenderer)_targetRenderer).sharedMesh = _mesh;
  1883. }
  1884. }
  1885. if (triangles || vertices)
  1886. {
  1887. if (LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("recalculating bounds on mesh.");
  1888. _mesh.RecalculateBounds();
  1889. } if (_optimizeAfterBake && !Application.isPlaying)
  1890. {
  1891. MBVersion.OptimizeMesh(_mesh);
  1892. }
  1893. }
  1894. else {
  1895. Debug.LogError("Need to add objects to this meshbaker before calling Apply or ApplyAll");
  1896. }
  1897. if (LOG_LEVEL >= MB2_LogLevel.debug)
  1898. {
  1899. Debug.Log("Apply Complete time: " + sw.ElapsedMilliseconds + " vertices: " + _mesh.vertexCount);
  1900. }
  1901. }
  1902. int _numNonZeroLengthSubmeshTris(SerializableIntArray[] subTris)
  1903. {
  1904. int num = 0;
  1905. for (int i = 0; i < subTris.Length; i++) { if (subTris[i].data.Length > 0) num++;}
  1906. return num;
  1907. }
  1908. private void _updateMaterialsOnTargetRenderer(SerializableIntArray[] subTris, int numNonZeroLengthSubmeshTris)
  1909. {
  1910. //zero length triangle arrays in mesh cause errors. have excluded these sumbeshes so must exclude these materials
  1911. if (subTris.Length != textureBakeResults.resultMaterials.Length) Debug.LogError("Mismatch between number of submeshes and number of result materials");
  1912. Material[] resMats = new Material[numNonZeroLengthSubmeshTris];
  1913. int submeshIdx = 0;
  1914. for (int i = 0; i < subTris.Length; i++)
  1915. {
  1916. if (subTris[i].data.Length > 0) {
  1917. resMats[submeshIdx] = _textureBakeResults.resultMaterials[i].combinedMaterial;
  1918. submeshIdx++;
  1919. }
  1920. }
  1921. targetRenderer.materials = resMats;
  1922. }
  1923. public SerializableIntArray[] GetSubmeshTrisWithShowHideApplied()
  1924. {
  1925. bool containsHiddenObjects = false;
  1926. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  1927. {
  1928. if (mbDynamicObjectsInCombinedMesh[i].show == false)
  1929. {
  1930. containsHiddenObjects = true;
  1931. break;
  1932. }
  1933. }
  1934. if (containsHiddenObjects)
  1935. {
  1936. int[] newLengths = new int[submeshTris.Length];
  1937. SerializableIntArray[] newSubmeshTris = new SerializableIntArray[submeshTris.Length];
  1938. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  1939. {
  1940. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  1941. if (dgo.show)
  1942. {
  1943. for (int j = 0; j < dgo.submeshNumTris.Length; j++)
  1944. {
  1945. newLengths[j] += dgo.submeshNumTris[j];
  1946. }
  1947. }
  1948. }
  1949. for (int i = 0; i < newSubmeshTris.Length; i++)
  1950. {
  1951. newSubmeshTris[i] = new SerializableIntArray(newLengths[i]);
  1952. }
  1953. int[] idx = new int[newSubmeshTris.Length];
  1954. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  1955. {
  1956. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  1957. if (dgo.show)
  1958. {
  1959. for (int j = 0; j < submeshTris.Length; j++)
  1960. { //for each submesh
  1961. int[] triIdxs = submeshTris[j].data;
  1962. int startIdx = dgo.submeshTriIdxs[j];
  1963. int endIdx = startIdx + dgo.submeshNumTris[j];
  1964. for (int k = startIdx; k < endIdx; k++)
  1965. {
  1966. newSubmeshTris[j].data[idx[j]] = triIdxs[k];
  1967. idx[j] = idx[j] + 1;
  1968. }
  1969. }
  1970. }
  1971. }
  1972. return newSubmeshTris;
  1973. }
  1974. else {
  1975. return submeshTris;
  1976. }
  1977. }
  1978. public override void UpdateGameObjects(GameObject[] gos, bool recalcBounds = true,
  1979. bool updateVertices = true, bool updateNormals = true, bool updateTangents = true,
  1980. bool updateUV = false, bool updateUV2 = false, bool updateUV3 = false, bool updateUV4 = false,
  1981. bool updateColors = false, bool updateSkinningInfo = false)
  1982. {
  1983. _updateGameObjects(gos, recalcBounds, updateVertices, updateNormals, updateTangents, updateUV, updateUV2, updateUV3, updateUV4, updateColors, updateSkinningInfo);
  1984. }
  1985. void _updateGameObjects(GameObject[] gos, bool recalcBounds,
  1986. bool updateVertices, bool updateNormals, bool updateTangents,
  1987. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4, bool updateColors, bool updateSkinningInfo)
  1988. {
  1989. if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("UpdateGameObjects called on " + gos.Length + " objects.");
  1990. int numResultMats = 1;
  1991. if (textureBakeResults.doMultiMaterial) numResultMats = textureBakeResults.resultMaterials.Length;
  1992. _initialize(numResultMats);
  1993. if (_mesh.vertexCount > 0 && _instance2combined_map.Count == 0)
  1994. {
  1995. Debug.LogWarning("There were vertices in the combined mesh but nothing in the MeshBaker buffers. If you are trying to bake in the editor and modify at runtime, make sure 'Clear Buffers After Bake' is unchecked.");
  1996. }
  1997. MeshChannelsCache meshChannelCache = new MeshChannelsCache(this);
  1998. for (int i = 0; i < gos.Length; i++)
  1999. {
  2000. _updateGameObject(gos[i], updateVertices, updateNormals, updateTangents, updateUV, updateUV2, updateUV3, updateUV4, updateColors, updateSkinningInfo, meshChannelCache);
  2001. }
  2002. if (recalcBounds)
  2003. _mesh.RecalculateBounds();
  2004. }
  2005. void _updateGameObject(GameObject go, bool updateVertices, bool updateNormals, bool updateTangents,
  2006. bool updateUV, bool updateUV2, bool updateUV3, bool updateUV4, bool updateColors, bool updateSkinningInfo, MeshChannelsCache meshChannelCache)
  2007. {
  2008. MB_DynamicGameObject dgo = null;
  2009. if (!instance2Combined_MapTryGetValue(go.GetInstanceID(), out dgo))
  2010. {
  2011. Debug.LogError("Object " + go.name + " has not been added");
  2012. return;
  2013. }
  2014. Mesh mesh = MB_Utility.GetMesh(go);
  2015. if (dgo.numVerts != mesh.vertexCount)
  2016. {
  2017. Debug.LogError("Object " + go.name + " source mesh has been modified since being added. To update it must have the same number of verts");
  2018. return;
  2019. }
  2020. if (_doUV && updateUV) _copyAndAdjustUVsFromMesh(dgo, mesh, dgo.vertIdx, meshChannelCache);
  2021. if (doUV2() && updateUV2) _copyAndAdjustUV2FromMesh(dgo, mesh, dgo.vertIdx, meshChannelCache);
  2022. if (renderType == MB_RenderType.skinnedMeshRenderer && updateSkinningInfo)
  2023. {
  2024. //only does BoneWeights. Used to do Bones and BindPoses but it doesn't make sence.
  2025. //if updating Bones and Bindposes should remove and re-add
  2026. Renderer r = MB_Utility.GetRenderer(go);
  2027. BoneWeight[] bws = meshChannelCache.GetBoneWeights(r, dgo.numVerts);
  2028. Transform[] bs = _getBones(r);
  2029. //assumes that the bones and boneweights have not been reeordered
  2030. int bwIdx = dgo.vertIdx; //the index in the verts array
  2031. bool switchedBonesDetected = false;
  2032. for (int i = 0; i < bws.Length; i++)
  2033. {
  2034. if (bs[bws[i].boneIndex0] != bones[boneWeights[bwIdx].boneIndex0])
  2035. {
  2036. switchedBonesDetected = true;
  2037. break;
  2038. }
  2039. boneWeights[bwIdx].weight0 = bws[i].weight0;
  2040. boneWeights[bwIdx].weight1 = bws[i].weight1;
  2041. boneWeights[bwIdx].weight2 = bws[i].weight2;
  2042. boneWeights[bwIdx].weight3 = bws[i].weight3;
  2043. bwIdx++;
  2044. }
  2045. if (switchedBonesDetected)
  2046. {
  2047. Debug.LogError("Detected that some of the boneweights reference different bones than when initial added. Boneweights must reference the same bones " + dgo.name);
  2048. }
  2049. }
  2050. //now do verts, norms, tangents, colors and uv1
  2051. Matrix4x4 l2wMat = go.transform.localToWorldMatrix;
  2052. if (updateVertices)
  2053. {
  2054. Vector3[] nverts = meshChannelCache.GetVertices(mesh);
  2055. for (int j = 0; j < nverts.Length; j++)
  2056. {
  2057. verts[dgo.vertIdx + j] = l2wMat.MultiplyPoint3x4(nverts[j]);
  2058. }
  2059. }
  2060. l2wMat[0, 3] = l2wMat[1, 3] = l2wMat[2, 3] = 0f;
  2061. if (_doNorm && updateNormals)
  2062. {
  2063. Vector3[] nnorms = meshChannelCache.GetNormals(mesh);
  2064. for (int j = 0; j < nnorms.Length; j++)
  2065. {
  2066. int vIdx = dgo.vertIdx + j;
  2067. normals[vIdx] = l2wMat.MultiplyPoint3x4(nnorms[j]);
  2068. normals[vIdx] = normals[vIdx].normalized;
  2069. }
  2070. }
  2071. if (_doTan && updateTangents)
  2072. {
  2073. Vector4[] ntangs = meshChannelCache.GetTangents(mesh);
  2074. for (int j = 0; j < ntangs.Length; j++)
  2075. {
  2076. int midx = dgo.vertIdx + j;
  2077. float w = ntangs[j].w; //need to preserve the w value
  2078. Vector3 tn = l2wMat.MultiplyPoint3x4(ntangs[j]);
  2079. tn.Normalize();
  2080. tangents[midx] = tn;
  2081. tangents[midx].w = w;
  2082. }
  2083. }
  2084. if (_doCol && updateColors)
  2085. {
  2086. Color[] ncolors = meshChannelCache.GetColors(mesh);
  2087. for (int j = 0; j < ncolors.Length; j++) colors[dgo.vertIdx + j] = ncolors[j];
  2088. }
  2089. if (_doUV3 && updateUV3)
  2090. {
  2091. Vector2[] nuv3 = meshChannelCache.GetUv3(mesh);
  2092. for (int j = 0; j < nuv3.Length; j++) uv3s[dgo.vertIdx + j] = nuv3[j];
  2093. }
  2094. if (_doUV4 && updateUV4)
  2095. {
  2096. Vector2[] nuv4 = meshChannelCache.GetUv4(mesh);
  2097. for (int j = 0; j < nuv4.Length; j++) uv4s[dgo.vertIdx + j] = nuv4[j];
  2098. }
  2099. }
  2100. public bool ShowHideGameObjects(GameObject[] toShow, GameObject[] toHide)
  2101. {
  2102. if (textureBakeResults == null)
  2103. {
  2104. Debug.LogError("TextureBakeResults must be set.");
  2105. return false;
  2106. }
  2107. return _showHide(toShow, toHide);
  2108. }
  2109. public override bool AddDeleteGameObjects(GameObject[] gos, GameObject[] deleteGOs, bool disableRendererInSource = true)
  2110. {
  2111. int[] delInstanceIDs = null;
  2112. if (deleteGOs != null)
  2113. {
  2114. delInstanceIDs = new int[deleteGOs.Length];
  2115. for (int i = 0; i < deleteGOs.Length; i++)
  2116. {
  2117. if (deleteGOs[i] == null)
  2118. {
  2119. Debug.LogError("The " + i + "th object on the list of objects to delete is 'Null'");
  2120. }
  2121. else {
  2122. delInstanceIDs[i] = deleteGOs[i].GetInstanceID();
  2123. }
  2124. }
  2125. }
  2126. return AddDeleteGameObjectsByID(gos, delInstanceIDs, disableRendererInSource);
  2127. }
  2128. public override bool AddDeleteGameObjectsByID(GameObject[] gos, int[] deleteGOinstanceIDs, bool disableRendererInSource)
  2129. {
  2130. // Profile.StartProfile("AddDeleteGameObjectsByID");
  2131. if (validationLevel > MB2_ValidationLevel.none)
  2132. {
  2133. //check for duplicates
  2134. if (gos != null)
  2135. {
  2136. for (int i = 0; i < gos.Length; i++)
  2137. {
  2138. if (gos[i] == null)
  2139. {
  2140. 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.");
  2141. return false;
  2142. }
  2143. if (validationLevel >= MB2_ValidationLevel.robust)
  2144. {
  2145. for (int j = i + 1; j < gos.Length; j++)
  2146. {
  2147. if (gos[i] == gos[j])
  2148. {
  2149. Debug.LogError("GameObject " + gos[i] + " appears twice in list of game objects to add");
  2150. return false;
  2151. }
  2152. }
  2153. }
  2154. }
  2155. }
  2156. if (deleteGOinstanceIDs != null && validationLevel >= MB2_ValidationLevel.robust)
  2157. {
  2158. for (int i = 0; i < deleteGOinstanceIDs.Length; i++)
  2159. {
  2160. for (int j = i + 1; j < deleteGOinstanceIDs.Length; j++)
  2161. {
  2162. if (deleteGOinstanceIDs[i] == deleteGOinstanceIDs[j])
  2163. {
  2164. Debug.LogError("GameObject " + deleteGOinstanceIDs[i] + "appears twice in list of game objects to delete");
  2165. return false;
  2166. }
  2167. }
  2168. }
  2169. }
  2170. }
  2171. if (_usingTemporaryTextureBakeResult && gos != null && gos.Length > 0)
  2172. {
  2173. MB_Utility.Destroy(_textureBakeResults);
  2174. _textureBakeResults = null;
  2175. _usingTemporaryTextureBakeResult = false;
  2176. }
  2177. //create a temporary _textureBakeResults if needed
  2178. if (_textureBakeResults == null && gos != null && gos.Length > 0 && gos[0] != null)
  2179. {
  2180. if (!_CreateTemporaryTextrueBakeResult(gos, GetMaterialsOnTargetRenderer()))
  2181. {
  2182. return false;
  2183. }
  2184. }
  2185. BuildSceneMeshObject(gos);
  2186. if (!_addToCombined(gos, deleteGOinstanceIDs, disableRendererInSource))
  2187. {
  2188. Debug.LogError("Failed to add/delete objects to combined mesh");
  2189. return false;
  2190. }
  2191. if (targetRenderer != null)
  2192. {
  2193. if (renderType == MB_RenderType.skinnedMeshRenderer)
  2194. {
  2195. SkinnedMeshRenderer smr = (SkinnedMeshRenderer)targetRenderer;
  2196. smr.sharedMesh = _mesh;
  2197. smr.bones = bones;
  2198. UpdateSkinnedMeshApproximateBoundsFromBounds();
  2199. }
  2200. targetRenderer.lightmapIndex = GetLightmapIndex();
  2201. }
  2202. // Profile.EndProfile("AddDeleteGameObjectsByID");
  2203. // Profile.PrintResults();
  2204. return true;
  2205. }
  2206. public override bool CombinedMeshContains(GameObject go)
  2207. {
  2208. return objectsInCombinedMesh.Contains(go);
  2209. }
  2210. public override void ClearBuffers()
  2211. {
  2212. verts = new Vector3[0];
  2213. normals = new Vector3[0];
  2214. tangents = new Vector4[0];
  2215. uvs = new Vector2[0];
  2216. uv2s = new Vector2[0];
  2217. uv3s = new Vector2[0];
  2218. uv4s = new Vector2[0];
  2219. colors = new Color[0];
  2220. bones = new Transform[0];
  2221. bindPoses = new Matrix4x4[0];
  2222. boneWeights = new BoneWeight[0];
  2223. submeshTris = new SerializableIntArray[0];
  2224. blendShapes = new MBBlendShape[0];
  2225. //We need to be able to build the blend shapes src2combined we keep although we clear the frames
  2226. if (blendShapesInCombined == null)
  2227. {
  2228. blendShapesInCombined = new MBBlendShape[0];
  2229. }
  2230. else
  2231. {
  2232. for (int i = 0; i < blendShapesInCombined.Length; i++)
  2233. {
  2234. blendShapesInCombined[i].frames = new MBBlendShapeFrame[0];
  2235. }
  2236. }
  2237. mbDynamicObjectsInCombinedMesh.Clear();
  2238. objectsInCombinedMesh.Clear();
  2239. instance2Combined_MapClear();
  2240. if (_usingTemporaryTextureBakeResult)
  2241. {
  2242. MB_Utility.Destroy(_textureBakeResults);
  2243. _textureBakeResults = null;
  2244. _usingTemporaryTextureBakeResult = false;
  2245. }
  2246. if (LOG_LEVEL >= MB2_LogLevel.trace) MB2_Log.LogDebug("ClearBuffers called");
  2247. }
  2248. /*
  2249. * Empties all channels and clears the mesh
  2250. */
  2251. public override void ClearMesh()
  2252. {
  2253. if (_mesh != null)
  2254. {
  2255. MBVersion.MeshClear(_mesh, false);
  2256. }
  2257. else {
  2258. _mesh = new Mesh();
  2259. }
  2260. ClearBuffers();
  2261. }
  2262. /*
  2263. * Empties all channels, destroys the mesh and replaces it with a new mesh
  2264. */
  2265. public override void DestroyMesh()
  2266. {
  2267. if (_mesh != null)
  2268. {
  2269. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Destroying Mesh");
  2270. MB_Utility.Destroy(_mesh);
  2271. }
  2272. _mesh = new Mesh();
  2273. ClearBuffers();
  2274. }
  2275. public override void DestroyMeshEditor(MB2_EditorMethodsInterface editorMethods)
  2276. {
  2277. if (_mesh != null)
  2278. {
  2279. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Destroying Mesh");
  2280. editorMethods.Destroy(_mesh);
  2281. }
  2282. _mesh = new Mesh();
  2283. ClearBuffers();
  2284. }
  2285. public bool ValidateTargRendererAndMeshAndResultSceneObj()
  2286. {
  2287. if (_resultSceneObject == null)
  2288. {
  2289. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Result Scene Object was not set.");
  2290. return false;
  2291. }
  2292. else {
  2293. if (_targetRenderer == null)
  2294. {
  2295. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Target Renderer was not set.");
  2296. return false;
  2297. }
  2298. else {
  2299. if (_targetRenderer.transform.parent != _resultSceneObject.transform)
  2300. {
  2301. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Target Renderer game object is not a child of Result Scene Object was not set.");
  2302. return false;
  2303. }
  2304. if (_renderType == MB_RenderType.skinnedMeshRenderer)
  2305. {
  2306. if (!(_targetRenderer is SkinnedMeshRenderer))
  2307. {
  2308. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Render Type is skinned mesh renderer but Target Renderer is not.");
  2309. return false;
  2310. }
  2311. /*
  2312. if (((SkinnedMeshRenderer)_targetRenderer).sharedMesh != _mesh)
  2313. {
  2314. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Target renderer mesh is not equal to mesh.");
  2315. return false;
  2316. }
  2317. */
  2318. }
  2319. if (_renderType == MB_RenderType.meshRenderer)
  2320. {
  2321. if (!(_targetRenderer is MeshRenderer))
  2322. {
  2323. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Render Type is mesh renderer but Target Renderer is not.");
  2324. return false;
  2325. }
  2326. MeshFilter mf = _targetRenderer.GetComponent<MeshFilter>();
  2327. if (_mesh != mf.sharedMesh)
  2328. {
  2329. if (_LOG_LEVEL >= MB2_LogLevel.error) Debug.LogError("Target renderer mesh is not equal to mesh.");
  2330. return false;
  2331. }
  2332. }
  2333. }
  2334. }
  2335. return true;
  2336. }
  2337. /*
  2338. should try to reverse engineer root. could be that user fed combiner a prefab or scene object
  2339. is called before bake so that targetRenderer and resultScene object exist in scene
  2340. is called after bake to build a prefab
  2341. for multimeshbaker each combiner should be a distinct child of result sceneobject
  2342. TODO split into three
  2343. before bake only needed to ensure valid resultSceneObject and targetRenderer
  2344. targetRenderer should be child of resultSceneObject (may or may not be distinct)
  2345. resultMats not important (shouldn't touch if targ is between bake and apply)
  2346. must handle mangled multiMeshBaker
  2347. rebuild prefab
  2348. multibaker should remove all meshrenderer children
  2349. must do materials which must be on targetRenderer
  2350. common code
  2351. */
  2352. internal static Renderer BuildSceneHierarchPreBake(MB3_MeshCombinerSingle mom, GameObject root, Mesh m, bool createNewChild = false, GameObject[] objsToBeAdded = null)
  2353. {
  2354. if (mom._LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("Building Scene Hierarchy createNewChild=" + createNewChild);
  2355. GameObject meshGO;
  2356. MeshFilter mf = null;
  2357. MeshRenderer mr = null;
  2358. SkinnedMeshRenderer smr = null;
  2359. Transform mt = null;
  2360. if (root == null)
  2361. {
  2362. Debug.LogError("root was null.");
  2363. return null;
  2364. }
  2365. if (mom.textureBakeResults == null)
  2366. {
  2367. Debug.LogError("textureBakeResults must be set.");
  2368. return null;
  2369. }
  2370. if (root.GetComponent<Renderer>() != null)
  2371. {
  2372. Debug.LogError("root game object cannot have a renderer component");
  2373. return null;
  2374. }
  2375. if (!createNewChild)
  2376. {
  2377. //try to find an existing child
  2378. if (mom.targetRenderer != null && mom.targetRenderer.transform.parent == root.transform)
  2379. {
  2380. mt = mom.targetRenderer.transform; //good setup
  2381. }
  2382. else
  2383. {
  2384. Renderer[] rs = (Renderer[])root.GetComponentsInChildren<Renderer>();
  2385. if (rs.Length == 1)
  2386. {
  2387. if (rs[0].transform.parent != root.transform)
  2388. {
  2389. Debug.LogError("Target Renderer is not an immediate child of Result Scene Object. Try using a game object with no children as the Result Scene Object..");
  2390. }
  2391. mt = rs[0].transform;
  2392. }
  2393. }
  2394. }
  2395. if (mt != null && mt.parent != root.transform)
  2396. { //target renderer must be a child of root
  2397. mt = null;
  2398. }
  2399. if (mt == null)
  2400. {
  2401. meshGO = new GameObject(mom.name + "-mesh");
  2402. meshGO.transform.parent = root.transform;
  2403. mt = meshGO.transform;
  2404. }
  2405. mt.parent = root.transform;
  2406. meshGO = mt.gameObject;
  2407. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2408. {
  2409. MeshRenderer r = meshGO.GetComponent<MeshRenderer>();
  2410. if (r != null) MB_Utility.Destroy(r);
  2411. MeshFilter f = meshGO.GetComponent<MeshFilter>();
  2412. if (f != null) MB_Utility.Destroy(f);
  2413. smr = meshGO.GetComponent<SkinnedMeshRenderer>();
  2414. if (smr == null) smr = meshGO.AddComponent<SkinnedMeshRenderer>();
  2415. }
  2416. else
  2417. {
  2418. SkinnedMeshRenderer r = meshGO.GetComponent<SkinnedMeshRenderer>();
  2419. if (r != null) MB_Utility.Destroy(r);
  2420. mf = meshGO.GetComponent<MeshFilter>();
  2421. if (mf == null) mf = meshGO.AddComponent<MeshFilter>();
  2422. mr = meshGO.GetComponent<MeshRenderer>();
  2423. if (mr == null) mr = meshGO.AddComponent<MeshRenderer>();
  2424. }
  2425. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2426. {
  2427. smr.bones = mom.GetBones();
  2428. bool origVal = smr.updateWhenOffscreen;
  2429. smr.updateWhenOffscreen = true;
  2430. smr.updateWhenOffscreen = origVal;
  2431. }
  2432. _ConfigureSceneHierarch(mom, root, mr, mf, smr, m, objsToBeAdded);
  2433. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2434. {
  2435. return smr;
  2436. }
  2437. else
  2438. {
  2439. return mr;
  2440. }
  2441. }
  2442. /*
  2443. could be building for a multiMeshBaker or a singleMeshBaker, targetRenderer will be a scene object.
  2444. */
  2445. public static void BuildPrefabHierarchy(MB3_MeshCombinerSingle mom, GameObject instantiatedPrefabRoot, Mesh m, bool createNewChild = false, GameObject[] objsToBeAdded = null)
  2446. {
  2447. SkinnedMeshRenderer smr = null;
  2448. MeshRenderer mr = null;
  2449. MeshFilter mf = null;
  2450. GameObject meshGO = new GameObject(mom.name + "-mesh");
  2451. meshGO.transform.parent = instantiatedPrefabRoot.transform;
  2452. Transform mt = meshGO.transform;
  2453. mt.parent = instantiatedPrefabRoot.transform;
  2454. meshGO = mt.gameObject;
  2455. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2456. {
  2457. MeshRenderer r = meshGO.GetComponent<MeshRenderer>();
  2458. if (r != null) MB_Utility.Destroy(r);
  2459. MeshFilter f = meshGO.GetComponent<MeshFilter>();
  2460. if (f != null) MB_Utility.Destroy(f);
  2461. smr = meshGO.GetComponent<SkinnedMeshRenderer>();
  2462. if (smr == null) smr = meshGO.AddComponent<SkinnedMeshRenderer>();
  2463. }
  2464. else
  2465. {
  2466. SkinnedMeshRenderer r = meshGO.GetComponent<SkinnedMeshRenderer>();
  2467. if (r != null) MB_Utility.Destroy(r);
  2468. mf = meshGO.GetComponent<MeshFilter>();
  2469. if (mf == null) mf = meshGO.AddComponent<MeshFilter>();
  2470. mr = meshGO.GetComponent<MeshRenderer>();
  2471. if (mr == null) mr = meshGO.AddComponent<MeshRenderer>();
  2472. }
  2473. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2474. {
  2475. smr.bones = mom.GetBones();
  2476. bool origVal = smr.updateWhenOffscreen;
  2477. smr.updateWhenOffscreen = true;
  2478. smr.updateWhenOffscreen = origVal;
  2479. smr.sharedMesh = m;
  2480. }
  2481. _ConfigureSceneHierarch(mom, instantiatedPrefabRoot, mr, mf, smr, m, objsToBeAdded);
  2482. //First try to get the materials from the target renderer. This is because the mesh may have fewer submeshes than number of result materials if some of the submeshes had zero length tris.
  2483. //If we have just baked then materials on the target renderer will be correct wheras materials on the textureBakeResult may not be correct.
  2484. if (mom.targetRenderer != null)
  2485. {
  2486. Material[] sharedMats = new Material[mom.targetRenderer.sharedMaterials.Length];
  2487. for (int i = 0; i < sharedMats.Length; i++)
  2488. {
  2489. sharedMats[i] = mom.targetRenderer.sharedMaterials[i];
  2490. }
  2491. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2492. {
  2493. smr.sharedMaterial = null;
  2494. smr.sharedMaterials = sharedMats;
  2495. }
  2496. else
  2497. {
  2498. mr.sharedMaterial = null;
  2499. mr.sharedMaterials = sharedMats;
  2500. }
  2501. }
  2502. }
  2503. private static void _ConfigureSceneHierarch(MB3_MeshCombinerSingle mom, GameObject root, MeshRenderer mr, MeshFilter mf, SkinnedMeshRenderer smr, Mesh m, GameObject[] objsToBeAdded = null)
  2504. {
  2505. //assumes everything is set up correctly
  2506. GameObject meshGO;
  2507. if (mom.renderType == MB_RenderType.skinnedMeshRenderer)
  2508. {
  2509. meshGO = smr.gameObject;
  2510. //smr.sharedMesh = m; can't assign mesh for skinned mesh until it has skinning information
  2511. smr.lightmapIndex = mom.GetLightmapIndex();
  2512. }
  2513. else {
  2514. meshGO = mr.gameObject;
  2515. mf.sharedMesh = m;
  2516. mr.lightmapIndex = mom.GetLightmapIndex();
  2517. }
  2518. if (mom.lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping || mom.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
  2519. {
  2520. meshGO.isStatic = true;
  2521. }
  2522. //set layer and tag of combined object if all source objs have same layer
  2523. if (objsToBeAdded != null && objsToBeAdded.Length > 0 && objsToBeAdded[0] != null)
  2524. {
  2525. bool tagsAreSame = true;
  2526. bool layersAreSame = true;
  2527. string tag = objsToBeAdded[0].tag;
  2528. int layer = objsToBeAdded[0].layer;
  2529. for (int i = 0; i < objsToBeAdded.Length; i++)
  2530. {
  2531. if (objsToBeAdded[i] != null)
  2532. {
  2533. if (!objsToBeAdded[i].tag.Equals(tag)) tagsAreSame = false;
  2534. if (objsToBeAdded[i].layer != layer) layersAreSame = false;
  2535. }
  2536. }
  2537. if (tagsAreSame)
  2538. {
  2539. root.tag = tag;
  2540. meshGO.tag = tag;
  2541. }
  2542. if (layersAreSame)
  2543. {
  2544. root.layer = layer;
  2545. meshGO.layer = layer;
  2546. }
  2547. }
  2548. }
  2549. public void BuildSceneMeshObject(GameObject[] gos = null, bool createNewChild = false)
  2550. {
  2551. if (_resultSceneObject == null)
  2552. {
  2553. _resultSceneObject = new GameObject("CombinedMesh-" + name);
  2554. }
  2555. _targetRenderer = BuildSceneHierarchPreBake(this, _resultSceneObject, GetMesh(), createNewChild, gos);
  2556. }
  2557. //tests if a matrix has been mirrored
  2558. bool IsMirrored(Matrix4x4 tm)
  2559. {
  2560. Vector3 x = tm.GetRow(0);
  2561. Vector3 y = tm.GetRow(1);
  2562. Vector3 z = tm.GetRow(2);
  2563. x.Normalize(); y.Normalize(); z.Normalize();
  2564. float an = Vector3.Dot(Vector3.Cross(x, y), z);
  2565. return an >= 0 ? false : true;
  2566. }
  2567. public override void CheckIntegrity()
  2568. {
  2569. if (!MB_Utility.DO_INTEGRITY_CHECKS) return;
  2570. //check bones.
  2571. if (renderType == MB_RenderType.skinnedMeshRenderer)
  2572. {
  2573. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2574. {
  2575. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  2576. HashSet<int> usedBonesWeights = new HashSet<int>();
  2577. HashSet<int> usedBonesIndexes = new HashSet<int>();
  2578. for (int j = dgo.vertIdx; j < dgo.vertIdx + dgo.numVerts; j++)
  2579. {
  2580. usedBonesWeights.Add(boneWeights[j].boneIndex0);
  2581. usedBonesWeights.Add(boneWeights[j].boneIndex1);
  2582. usedBonesWeights.Add(boneWeights[j].boneIndex2);
  2583. usedBonesWeights.Add(boneWeights[j].boneIndex3);
  2584. }
  2585. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
  2586. {
  2587. usedBonesIndexes.Add(dgo.indexesOfBonesUsed[j]);
  2588. }
  2589. usedBonesIndexes.ExceptWith(usedBonesWeights);
  2590. if (usedBonesIndexes.Count > 0)
  2591. {
  2592. Debug.LogError("The bone indexes were not the same. " + usedBonesWeights.Count + " " + usedBonesIndexes.Count);
  2593. }
  2594. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
  2595. {
  2596. if (j < 0 || j > bones.Length)
  2597. Debug.LogError("Bone index was out of bounds.");
  2598. }
  2599. if (renderType == MB_RenderType.skinnedMeshRenderer && dgo.indexesOfBonesUsed.Length < 1)
  2600. Debug.Log("DGO had no bones");
  2601. }
  2602. }
  2603. //check blend shapes
  2604. if (doBlendShapes)
  2605. {
  2606. if (renderType != MB_RenderType.skinnedMeshRenderer)
  2607. {
  2608. Debug.LogError("Blend shapes can only be used with skinned meshes.");
  2609. }
  2610. }
  2611. }
  2612. void _ZeroArray(Vector3[] arr, int idx, int length)
  2613. {
  2614. int bound = idx + length;
  2615. for (int i = idx; i < bound; i++)
  2616. {
  2617. arr[i] = Vector3.zero;
  2618. }
  2619. }
  2620. List<MB_DynamicGameObject>[] _buildBoneIdx2dgoMap()
  2621. {
  2622. List<MB_DynamicGameObject>[] boneIdx2dgoMap = new List<MB_DynamicGameObject>[bones.Length];
  2623. for (int i = 0; i < boneIdx2dgoMap.Length; i++) boneIdx2dgoMap[i] = new List<MB_DynamicGameObject>();
  2624. // build the map of bone indexes to objects that use them
  2625. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2626. {
  2627. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  2628. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
  2629. {
  2630. boneIdx2dgoMap[dgo.indexesOfBonesUsed[j]].Add(dgo);
  2631. }
  2632. }
  2633. return boneIdx2dgoMap;
  2634. }
  2635. void _CollectBonesToAddForDGO(MB_DynamicGameObject dgo, Dictionary<Transform,int> bone2idx, HashSet<int> boneIdxsToDelete, HashSet<BoneAndBindpose> bonesToAdd, Renderer r, MeshChannelsCache meshChannelCache)
  2636. {
  2637. //compile a list of bone transforms to add
  2638. Matrix4x4[] dgoBindPoses = dgo._tmpCachedBindposes = meshChannelCache.GetBindposes(r);
  2639. BoneWeight[] dgoBoneWeights = dgo._tmpCachedBoneWeights = meshChannelCache.GetBoneWeights(r,dgo.numVerts);
  2640. Transform[] dgoBones = dgo._tmpCachedBones = _getBones(r);
  2641. //find bones that are actually by the vertices in the skinned mesh
  2642. HashSet<int> usedBones = new HashSet<int>();
  2643. for (int j = 0; j < dgoBoneWeights.Length; j++)
  2644. {
  2645. usedBones.Add(dgoBoneWeights[j].boneIndex0);
  2646. usedBones.Add(dgoBoneWeights[j].boneIndex1);
  2647. usedBones.Add(dgoBoneWeights[j].boneIndex2);
  2648. usedBones.Add(dgoBoneWeights[j].boneIndex3);
  2649. }
  2650. int[] usedBoneIdx2srcMeshBoneIdx = new int[usedBones.Count];
  2651. usedBones.CopyTo(usedBoneIdx2srcMeshBoneIdx);
  2652. //for each bone see if it exists in the bones array
  2653. for (int i = 0; i < usedBoneIdx2srcMeshBoneIdx.Length; i++)
  2654. {
  2655. bool foundInBonesList = false;
  2656. int bidx;
  2657. int dgoBoneIdx = usedBoneIdx2srcMeshBoneIdx[i];
  2658. if (bone2idx.TryGetValue(dgoBones[dgoBoneIdx], out bidx))
  2659. {
  2660. if (dgoBones[dgoBoneIdx] == bones[bidx] && !boneIdxsToDelete.Contains(bidx))
  2661. {
  2662. if (dgoBindPoses[dgoBoneIdx] == bindPoses[bidx])
  2663. {
  2664. foundInBonesList = true;
  2665. }
  2666. }
  2667. }
  2668. if (!foundInBonesList)
  2669. {
  2670. BoneAndBindpose bb = new BoneAndBindpose(dgoBones[dgoBoneIdx], dgoBindPoses[dgoBoneIdx]);
  2671. if (!bonesToAdd.Contains(bb))
  2672. {
  2673. bonesToAdd.Add(bb);
  2674. }
  2675. }
  2676. }
  2677. dgo._tmpIndexesOfSourceBonesUsed = usedBoneIdx2srcMeshBoneIdx;
  2678. }
  2679. void _CopyBonesWeAreKeepingToNewBonesArrayAndAdjustBWIndexes(HashSet<int> boneIdxsToDeleteHS, HashSet<BoneAndBindpose> bonesToAdd, Transform[] nbones, Matrix4x4[] nbindPoses, BoneWeight[] nboneWeights, int totalDeleteVerts)
  2680. {
  2681. //bones are copied separately because some dgos share bones
  2682. if (boneIdxsToDeleteHS.Count > 0)
  2683. {
  2684. int[] boneIdxsToDelete = new int[boneIdxsToDeleteHS.Count];
  2685. boneIdxsToDeleteHS.CopyTo(boneIdxsToDelete);
  2686. Array.Sort(boneIdxsToDelete);
  2687. //bones are being moved in bones array so need to do some remapping
  2688. int[] oldBonesIndex2newBonesIndexMap = new int[bones.Length];
  2689. int newIdx = 0;
  2690. int indexInDeleteList = 0;
  2691. //bones were deleted so we need to rebuild bones and bind poses
  2692. //and build a map of old bone indexes to new bone indexes
  2693. //do this by copying old to new skipping ones we are deleting
  2694. for (int i = 0; i < bones.Length; i++)
  2695. {
  2696. if (indexInDeleteList < boneIdxsToDelete.Length &&
  2697. boneIdxsToDelete[indexInDeleteList] == i)
  2698. {
  2699. //we are deleting this bone so skip its index
  2700. indexInDeleteList++;
  2701. oldBonesIndex2newBonesIndexMap[i] = -1;
  2702. }
  2703. else {
  2704. oldBonesIndex2newBonesIndexMap[i] = newIdx;
  2705. nbones[newIdx] = bones[i];
  2706. nbindPoses[newIdx] = bindPoses[i];
  2707. newIdx++;
  2708. }
  2709. }
  2710. //adjust the indexes on the boneWeights
  2711. int numVertKeeping = boneWeights.Length - totalDeleteVerts;
  2712. for (int i = 0; i < numVertKeeping; i++)
  2713. {
  2714. nboneWeights[i].boneIndex0 = oldBonesIndex2newBonesIndexMap[nboneWeights[i].boneIndex0];
  2715. nboneWeights[i].boneIndex1 = oldBonesIndex2newBonesIndexMap[nboneWeights[i].boneIndex1];
  2716. nboneWeights[i].boneIndex2 = oldBonesIndex2newBonesIndexMap[nboneWeights[i].boneIndex2];
  2717. nboneWeights[i].boneIndex3 = oldBonesIndex2newBonesIndexMap[nboneWeights[i].boneIndex3];
  2718. }
  2719. //adjust the bone indexes on the dgos from old to new
  2720. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2721. {
  2722. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  2723. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++)
  2724. {
  2725. dgo.indexesOfBonesUsed[j] = oldBonesIndex2newBonesIndexMap[dgo.indexesOfBonesUsed[j]];
  2726. }
  2727. }
  2728. }
  2729. else { //no bones are moving so can simply copy bones from old to new
  2730. Array.Copy(bones, nbones, bones.Length);
  2731. Array.Copy(bindPoses, nbindPoses, bindPoses.Length);
  2732. }
  2733. }
  2734. void _AddBonesToNewBonesArrayAndAdjustBWIndexes(MB_DynamicGameObject dgo, Renderer r, int vertsIdx,
  2735. Transform[] nbones, BoneWeight[] nboneWeights, MeshChannelsCache meshChannelCache)
  2736. {
  2737. //Renderer r = MB_Utility.GetRenderer(go);
  2738. Transform[] dgoBones = dgo._tmpCachedBones;
  2739. Matrix4x4[] dgoBindPoses = dgo._tmpCachedBindposes;
  2740. BoneWeight[] dgoBoneWeights = dgo._tmpCachedBoneWeights;
  2741. int[] srcIndex2combinedIndexMap = new int[dgoBones.Length];
  2742. for (int j = 0; j < dgo._tmpIndexesOfSourceBonesUsed.Length; j++)
  2743. {
  2744. int dgoBoneIdx = dgo._tmpIndexesOfSourceBonesUsed[j];
  2745. for (int k = 0; k < nbones.Length; k++)
  2746. {
  2747. if (dgoBones[dgoBoneIdx] == nbones[k])
  2748. {
  2749. if (dgoBindPoses[dgoBoneIdx] == bindPoses[k])
  2750. {
  2751. srcIndex2combinedIndexMap[dgoBoneIdx] = k;
  2752. break;
  2753. }
  2754. }
  2755. }
  2756. }
  2757. //remap the bone weights for this dgo
  2758. //build a list of usedBones, can't trust dgoBones because it contains all bones in the rig
  2759. for (int j = 0; j < dgoBoneWeights.Length; j++)
  2760. {
  2761. int newVertIdx = vertsIdx + j;
  2762. nboneWeights[newVertIdx].boneIndex0 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex0];
  2763. nboneWeights[newVertIdx].boneIndex1 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex1];
  2764. nboneWeights[newVertIdx].boneIndex2 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex2];
  2765. nboneWeights[newVertIdx].boneIndex3 = srcIndex2combinedIndexMap[dgoBoneWeights[j].boneIndex3];
  2766. nboneWeights[newVertIdx].weight0 = dgoBoneWeights[j].weight0;
  2767. nboneWeights[newVertIdx].weight1 = dgoBoneWeights[j].weight1;
  2768. nboneWeights[newVertIdx].weight2 = dgoBoneWeights[j].weight2;
  2769. nboneWeights[newVertIdx].weight3 = dgoBoneWeights[j].weight3;
  2770. }
  2771. // repurposing the _tmpIndexesOfSourceBonesUsed since
  2772. //we don't need it anymore and this saves a memory allocation . remap the indexes that point to source bones to combined bones.
  2773. for (int j = 0; j < dgo._tmpIndexesOfSourceBonesUsed.Length; j++)
  2774. {
  2775. dgo._tmpIndexesOfSourceBonesUsed[j] = srcIndex2combinedIndexMap[dgo._tmpIndexesOfSourceBonesUsed[j]];
  2776. }
  2777. dgo.indexesOfBonesUsed = dgo._tmpIndexesOfSourceBonesUsed;
  2778. dgo._tmpIndexesOfSourceBonesUsed = null;
  2779. dgo._tmpCachedBones = null;
  2780. dgo._tmpCachedBindposes = null;
  2781. dgo._tmpCachedBoneWeights = null;
  2782. //check original bones and bindPoses
  2783. /*
  2784. for (int j = 0; j < dgo.indexesOfBonesUsed.Length; j++) {
  2785. Transform bone = bones[dgo.indexesOfBonesUsed[j]];
  2786. Matrix4x4 bindpose = bindPoses[dgo.indexesOfBonesUsed[j]];
  2787. bool found = false;
  2788. for (int k = 0; k < dgo._originalBones.Length; k++) {
  2789. if (dgo._originalBones[k] == bone && dgo._originalBindPoses[k] == bindpose) {
  2790. found = true;
  2791. }
  2792. }
  2793. if (!found) Debug.LogError("A Mismatch between original bones and bones array. " + dgo.name);
  2794. }
  2795. */
  2796. }
  2797. //-------- End Skinned Mesh Bone Routines -----------------
  2798. void _copyUV2unchangedToSeparateRects()
  2799. {
  2800. int uv2Padding = 16; //todo
  2801. //todo meshSize
  2802. List<Vector2> uv2AtlasSizes = new List<Vector2>();
  2803. float minSize = 10e10f;
  2804. float maxSize = 0f;
  2805. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2806. {
  2807. float zz = mbDynamicObjectsInCombinedMesh[i].meshSize.magnitude;
  2808. if (zz > maxSize) maxSize = zz;
  2809. if (zz < minSize) minSize = zz;
  2810. }
  2811. //normalize size so all values lie between these two values
  2812. float MAX_UV_VAL = 1000f;
  2813. float MIN_UV_VAL = 10f;
  2814. float offset = 0;
  2815. float scale = 1;
  2816. if (maxSize - minSize > MAX_UV_VAL - MIN_UV_VAL)
  2817. {
  2818. //need to compress the range. Scale until is MAX_UV_VAL - MIN_UV_VAL in size and shift
  2819. scale = (MAX_UV_VAL - MIN_UV_VAL) / (maxSize - minSize);
  2820. offset = MIN_UV_VAL - minSize * scale;
  2821. } else
  2822. {
  2823. scale = MAX_UV_VAL / maxSize;
  2824. }
  2825. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2826. {
  2827. float zz = mbDynamicObjectsInCombinedMesh[i].meshSize.magnitude;
  2828. zz = zz * scale + offset;
  2829. Vector2 sz = Vector2.one * zz;
  2830. uv2AtlasSizes.Add(sz);
  2831. }
  2832. //run texture packer on these rects
  2833. MB2_TexturePacker tp = new MB2_TexturePackerRegular();
  2834. tp.atlasMustBePowerOfTwo = false;
  2835. AtlasPackingResult[] uv2Rects = tp.GetRects(uv2AtlasSizes, 8192, 8192, uv2Padding);
  2836. //Debug.Assert(uv2Rects.Length == 1);
  2837. //adjust UV2s
  2838. for (int i = 0; i < mbDynamicObjectsInCombinedMesh.Count; i++)
  2839. {
  2840. MB_DynamicGameObject dgo = mbDynamicObjectsInCombinedMesh[i];
  2841. float minx, maxx, miny, maxy;
  2842. minx = maxx = uv2s[dgo.vertIdx].x;
  2843. miny = maxy = uv2s[dgo.vertIdx].y;
  2844. int endIdx = dgo.vertIdx + dgo.numVerts;
  2845. for (int j = dgo.vertIdx; j < endIdx; j++)
  2846. {
  2847. if (uv2s[j].x < minx) minx = uv2s[j].x;
  2848. if (uv2s[j].x > maxx) maxx = uv2s[j].x;
  2849. if (uv2s[j].y < miny) miny = uv2s[j].y;
  2850. if (uv2s[j].y > maxy) maxy = uv2s[j].y;
  2851. }
  2852. // scale it to fit the rect
  2853. Rect r = uv2Rects[0].rects[i];
  2854. for (int j = dgo.vertIdx; j < endIdx; j++)
  2855. {
  2856. float width = maxx - minx;
  2857. float height = maxy - miny;
  2858. if (width == 0f) width = 1f;
  2859. if (height == 0f) height = 1f;
  2860. uv2s[j].x = ((uv2s[j].x - minx) / width) * r.width + r.x;
  2861. uv2s[j].y = ((uv2s[j].y - miny) / height) * r.height + r.y;
  2862. }
  2863. }
  2864. }
  2865. public override List<Material> GetMaterialsOnTargetRenderer()
  2866. {
  2867. List<Material> outMats = new List<Material>();
  2868. if (_targetRenderer != null)
  2869. {
  2870. outMats.AddRange(_targetRenderer.sharedMaterials);
  2871. }
  2872. return outMats;
  2873. }
  2874. }
  2875. }