源战役客户端
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

284 lignes
9.8 KiB

  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using DigitalOpus.MB.Core;
  6. using LuaFramework;
  7. public class MB3_MeshBakerGrouper : MonoBehaviour {
  8. public MB3_MeshBakerGrouperCore grouper;
  9. //these are for getting a resonable bounds in which to draw gizmos.
  10. [HideInInspector] public Bounds sourceObjectBounds = new Bounds(Vector3.zero,Vector3.one);
  11. void OnDrawGizmosSelected(){
  12. if (grouper == null) return;
  13. if (grouper.clusterGrouper == null) return;
  14. if (grouper.clusterGrouper.clusterType == MB3_MeshBakerGrouperCore.ClusterType.grid){
  15. Vector3 cs = grouper.clusterGrouper.cellSize;
  16. if (cs.x <= .00001f || cs.y <= .00001f || cs.z <= .00001f) return;
  17. Vector3 p = sourceObjectBounds.center - sourceObjectBounds.extents;
  18. Vector3 offset = grouper.clusterGrouper.origin;
  19. offset.x = offset.x % cs.x;
  20. offset.y = offset.y % cs.y;
  21. offset.z = offset.z % cs.z;
  22. //snap p to closest cell center
  23. Vector3 start;
  24. p.x = Mathf.Round((p.x) / cs.x) * cs.x + offset.x;
  25. p.y = Mathf.Round((p.y) / cs.y) * cs.y + offset.y;
  26. p.z = Mathf.Round((p.z) / cs.z) * cs.z + offset.z;
  27. if (p.x > sourceObjectBounds.center.x - sourceObjectBounds.extents.x) p.x = p.x - cs.x;
  28. if (p.y > sourceObjectBounds.center.y - sourceObjectBounds.extents.y) p.y = p.y - cs.y;
  29. if (p.z > sourceObjectBounds.center.z - sourceObjectBounds.extents.z) p.z = p.z - cs.z;
  30. start = p;
  31. int numcells = Mathf.CeilToInt(sourceObjectBounds.size.x / cs.x + sourceObjectBounds.size.y / cs.y + sourceObjectBounds.size.z / cs.z);
  32. if (numcells > 200){
  33. Gizmos.DrawWireCube(grouper.clusterGrouper.origin + cs/2f,cs);
  34. } else {
  35. for (;p.x < sourceObjectBounds.center.x + sourceObjectBounds.extents.x; p.x += cs.x){
  36. p.y = start.y;
  37. for (;p.y < sourceObjectBounds.center.y + sourceObjectBounds.extents.y; p.y += cs.y){
  38. p.z = start.z;
  39. for (;p.z < sourceObjectBounds.center.z + sourceObjectBounds.extents.z; p.z += cs.z){
  40. Gizmos.DrawWireCube(p + cs/2f,cs);
  41. }
  42. }
  43. }
  44. }
  45. }
  46. if (grouper.clusterGrouper.clusterType == MB3_MeshBakerGrouperCore.ClusterType.pie){
  47. if (grouper.clusterGrouper.pieAxis.magnitude < .1f) return;
  48. if (grouper.clusterGrouper.pieNumSegments < 1) return;
  49. float rad = sourceObjectBounds.extents.magnitude;
  50. DrawCircle(grouper.clusterGrouper.pieAxis,grouper.clusterGrouper.origin,rad,24);
  51. Quaternion yIsUp2PieAxis = Quaternion.FromToRotation(Vector3.up,grouper.clusterGrouper.pieAxis);
  52. Quaternion rStep = Quaternion.AngleAxis(180f / grouper.clusterGrouper.pieNumSegments, Vector3.up);
  53. Vector3 r = rStep * Vector3.forward;
  54. for (int i = 0; i < grouper.clusterGrouper.pieNumSegments; i++){
  55. Vector3 rr = yIsUp2PieAxis * r;
  56. Gizmos.DrawLine(grouper.clusterGrouper.origin, grouper.clusterGrouper.origin + rr * rad);
  57. r = rStep * r;
  58. r = rStep * r;
  59. }
  60. }
  61. }
  62. public static void DrawCircle (Vector3 axis, Vector3 center, float radius, int subdiv) {
  63. Quaternion q = Quaternion.AngleAxis (360 / subdiv, axis);
  64. Vector3 r = new Vector3 (axis.y, -axis.x, axis.z); //should be perpendicular to axis
  65. r.Normalize ();
  66. r *= radius;
  67. for (int i = 0; i < subdiv+1; i ++) {
  68. Vector3 r2 = q * r;
  69. Gizmos.DrawLine (center + r, center + r2);
  70. r = r2;
  71. }
  72. }
  73. }
  74. [Serializable]
  75. public class MB3_MeshBakerGrouperCore{
  76. public enum ClusterType{
  77. none,
  78. grid,
  79. pie,
  80. //voroni,
  81. }
  82. [Serializable]
  83. public class ClusterGrouper{
  84. public ClusterType clusterType;
  85. public Vector3 origin;
  86. //for grid
  87. public Vector3 cellSize;
  88. //for pie
  89. public int pieNumSegments = 4;
  90. public Vector3 pieAxis = Vector3.up;
  91. public Dictionary<string,List<Renderer>> FilterIntoGroups(List<GameObject> selection){
  92. if (clusterType == ClusterType.none){
  93. return FilterIntoGroupsNone(selection);
  94. } else if (clusterType == ClusterType.grid) {
  95. return FilterIntoGroupsGrid(selection);
  96. } else if (clusterType == ClusterType.pie){
  97. return FilterIntoGroupsPie(selection);
  98. }
  99. return new Dictionary<string, List<Renderer>>();
  100. }
  101. public Dictionary<string,List<Renderer>> FilterIntoGroupsNone(List<GameObject> selection)
  102. {
  103. LogManager.Log ("Filtering into groups none");
  104. Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
  105. List<Renderer> rs = new List<Renderer>();
  106. for (int i = 0; i < selection.Count; i++)
  107. {
  108. rs.Add (selection[i].GetComponent<Renderer>());
  109. }
  110. cell2objs.Add ("MeshBaker",rs);
  111. return cell2objs;
  112. }
  113. public Dictionary<string,List<Renderer>> FilterIntoGroupsGrid(List<GameObject> selection){
  114. Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
  115. if (cellSize.x <= 0f || cellSize.y <= 0f || cellSize.z <= 0f ){
  116. LogManager.LogError ("cellSize x,y,z must all be greater than zero.");
  117. return cell2objs;
  118. }
  119. LogManager.Log("Collecting renderers in each cell");
  120. foreach (GameObject t in selection){
  121. GameObject go = t;
  122. Renderer[] mrs = go.GetComponentsInChildren<Renderer>();
  123. for (int j = 0; j < mrs.Length; j++){
  124. if (mrs[j] is MeshRenderer || mrs[j] is SkinnedMeshRenderer){
  125. //get the cell this gameObject is in
  126. Vector3 gridVector = mrs[j].transform.position;
  127. gridVector.x = Mathf.Floor((gridVector.x - origin.x) / cellSize.x) * cellSize.x;
  128. gridVector.y = Mathf.Floor((gridVector.y - origin.y) / cellSize.y) * cellSize.y;
  129. gridVector.z = Mathf.Floor((gridVector.z - origin.z) / cellSize.z) * cellSize.z;
  130. List<Renderer> objs = null;
  131. string gridVectorStr = gridVector.ToString();
  132. if (cell2objs.ContainsKey(gridVectorStr)){
  133. objs = cell2objs[gridVectorStr];
  134. } else {
  135. objs = new List<Renderer>();
  136. cell2objs.Add (gridVectorStr,objs);
  137. }
  138. if (!objs.Contains(mrs[j])){
  139. objs.Add (mrs[j]);
  140. }
  141. }
  142. }
  143. }
  144. return cell2objs;
  145. }
  146. public Dictionary<string,List<Renderer>> FilterIntoGroupsPie(List<GameObject> selection){
  147. Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
  148. if (pieNumSegments == 0 ){
  149. LogManager.LogError ("pieNumSegments must be greater than zero.");
  150. return cell2objs;
  151. }
  152. if (pieAxis.magnitude <= .000001f ){
  153. LogManager.LogError ("Pie axis must have length greater than zero.");
  154. return cell2objs;
  155. }
  156. pieAxis.Normalize();
  157. Quaternion pieAxis2yIsUp = Quaternion.FromToRotation(pieAxis,Vector3.up);
  158. LogManager.Log("Collecting renderers in each cell");
  159. foreach (GameObject t in selection){
  160. GameObject go = t;
  161. Renderer[] mrs = go.GetComponentsInChildren<Renderer>();
  162. for (int j = 0; j < mrs.Length; j++){
  163. if (mrs[j] is MeshRenderer || mrs[j] is SkinnedMeshRenderer){
  164. //get the cell this gameObject is in
  165. Vector3 origin2obj = mrs[j].transform.position - origin;
  166. origin2obj.Normalize();
  167. origin2obj = pieAxis2yIsUp * origin2obj;
  168. float d_aboutY = 0f;
  169. if (Mathf.Abs(origin2obj.x) < 10e-5f && Mathf.Abs(origin2obj.z) < 10e-5f){
  170. d_aboutY = 0f;
  171. } else {
  172. d_aboutY = Mathf.Atan2(origin2obj.z,origin2obj.x) * Mathf.Rad2Deg;
  173. if (d_aboutY < 0f) d_aboutY = 360f + d_aboutY;
  174. }
  175. int segment = Mathf.FloorToInt(d_aboutY / 360f * pieNumSegments);
  176. List<Renderer> objs = null;
  177. string segStr = "seg_" + segment;
  178. if (cell2objs.ContainsKey(segStr)){
  179. objs = cell2objs[segStr];
  180. } else {
  181. objs = new List<Renderer>();
  182. cell2objs.Add (segStr,objs);
  183. }
  184. if (!objs.Contains(mrs[j])){
  185. objs.Add (mrs[j]);
  186. }
  187. }
  188. }
  189. }
  190. return cell2objs;
  191. }
  192. }
  193. public ClusterGrouper clusterGrouper;
  194. public bool clusterOnLMIndex;
  195. public void DoClustering(MB3_TextureBaker tb){
  196. if (clusterGrouper == null){
  197. LogManager.LogError("Cluster Grouper was null.");
  198. return;
  199. }
  200. //todo warn for no objects and no material bake result
  201. Dictionary<string,List<Renderer>> cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine());
  202. LogManager.Log ("Found " + cell2objs.Count + " cells with Renderers. Creating bakers.");
  203. if (clusterOnLMIndex){
  204. Dictionary<string,List<Renderer>> cell2objsNew = new Dictionary<string, List<Renderer>>();
  205. foreach (string key in cell2objs.Keys){
  206. List<Renderer> gaws = cell2objs[key];
  207. Dictionary<int,List<Renderer>> idx2objs = GroupByLightmapIndex(gaws);
  208. foreach(int keyIdx in idx2objs.Keys){
  209. string keyNew = key + "-LM-" + keyIdx;
  210. cell2objsNew.Add (keyNew,idx2objs[keyIdx]);
  211. }
  212. }
  213. cell2objs = cell2objsNew;
  214. }
  215. foreach (string key in cell2objs.Keys){
  216. List<Renderer> gaws = cell2objs[key];
  217. AddMeshBaker (tb,key,gaws);
  218. }
  219. }
  220. Dictionary<int,List<Renderer>> GroupByLightmapIndex(List<Renderer> gaws){
  221. Dictionary<int,List<Renderer>> idx2objs = new Dictionary<int, List<Renderer>>();
  222. for (int i = 0; i < gaws.Count; i++){
  223. List<Renderer> objs = null;
  224. if (idx2objs.ContainsKey(gaws[i].lightmapIndex)){
  225. objs = idx2objs[gaws[i].lightmapIndex];
  226. } else {
  227. objs = new List<Renderer>();
  228. idx2objs.Add (gaws[i].lightmapIndex,objs);
  229. }
  230. objs.Add (gaws[i]);
  231. }
  232. return idx2objs;
  233. }
  234. void AddMeshBaker(MB3_TextureBaker tb, string key, List<Renderer> gaws){
  235. int numVerts = 0;
  236. for (int i = 0; i < gaws.Count; i++){
  237. Mesh m = MB_Utility.GetMesh(gaws[i].gameObject);
  238. if (m != null)
  239. numVerts += m.vertexCount;
  240. }
  241. GameObject nmb = new GameObject("MeshBaker-" + key);
  242. nmb.transform.position = Vector3.zero;
  243. MB3_MeshBakerCommon newMeshBaker;
  244. if (numVerts >= 65535){
  245. newMeshBaker = nmb.AddComponent<MB3_MultiMeshBaker>();
  246. newMeshBaker.useObjsToMeshFromTexBaker = false;
  247. } else {
  248. newMeshBaker = nmb.AddComponent<MB3_MeshBaker>();
  249. newMeshBaker.useObjsToMeshFromTexBaker = false;
  250. }
  251. newMeshBaker.textureBakeResults = tb.textureBakeResults;
  252. newMeshBaker.transform.parent = tb.transform;
  253. for (int i = 0; i < gaws.Count; i++){
  254. newMeshBaker.GetObjectsToCombine().Add (gaws[i].gameObject);
  255. }
  256. }
  257. }