|
|
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using DigitalOpus.MB.Core;
- using LuaFramework;
- public class MB3_MeshBakerGrouper : MonoBehaviour {
- public MB3_MeshBakerGrouperCore grouper;
-
- //these are for getting a resonable bounds in which to draw gizmos.
- [HideInInspector] public Bounds sourceObjectBounds = new Bounds(Vector3.zero,Vector3.one);
-
- void OnDrawGizmosSelected(){
- if (grouper == null) return;
- if (grouper.clusterGrouper == null) return;
- if (grouper.clusterGrouper.clusterType == MB3_MeshBakerGrouperCore.ClusterType.grid){
- Vector3 cs = grouper.clusterGrouper.cellSize;
- if (cs.x <= .00001f || cs.y <= .00001f || cs.z <= .00001f) return;
- Vector3 p = sourceObjectBounds.center - sourceObjectBounds.extents;
- Vector3 offset = grouper.clusterGrouper.origin;
- offset.x = offset.x % cs.x;
- offset.y = offset.y % cs.y;
- offset.z = offset.z % cs.z;
- //snap p to closest cell center
- Vector3 start;
- p.x = Mathf.Round((p.x) / cs.x) * cs.x + offset.x;
- p.y = Mathf.Round((p.y) / cs.y) * cs.y + offset.y;
- p.z = Mathf.Round((p.z) / cs.z) * cs.z + offset.z;
- if (p.x > sourceObjectBounds.center.x - sourceObjectBounds.extents.x) p.x = p.x - cs.x;
- if (p.y > sourceObjectBounds.center.y - sourceObjectBounds.extents.y) p.y = p.y - cs.y;
- if (p.z > sourceObjectBounds.center.z - sourceObjectBounds.extents.z) p.z = p.z - cs.z;
- start = p;
- int numcells = Mathf.CeilToInt(sourceObjectBounds.size.x / cs.x + sourceObjectBounds.size.y / cs.y + sourceObjectBounds.size.z / cs.z);
- if (numcells > 200){
- Gizmos.DrawWireCube(grouper.clusterGrouper.origin + cs/2f,cs);
- } else {
- for (;p.x < sourceObjectBounds.center.x + sourceObjectBounds.extents.x; p.x += cs.x){
- p.y = start.y;
- for (;p.y < sourceObjectBounds.center.y + sourceObjectBounds.extents.y; p.y += cs.y){
- p.z = start.z;
- for (;p.z < sourceObjectBounds.center.z + sourceObjectBounds.extents.z; p.z += cs.z){
- Gizmos.DrawWireCube(p + cs/2f,cs);
- }
- }
- }
- }
- }
- if (grouper.clusterGrouper.clusterType == MB3_MeshBakerGrouperCore.ClusterType.pie){
- if (grouper.clusterGrouper.pieAxis.magnitude < .1f) return;
- if (grouper.clusterGrouper.pieNumSegments < 1) return;
- float rad = sourceObjectBounds.extents.magnitude;
- DrawCircle(grouper.clusterGrouper.pieAxis,grouper.clusterGrouper.origin,rad,24);
- Quaternion yIsUp2PieAxis = Quaternion.FromToRotation(Vector3.up,grouper.clusterGrouper.pieAxis);
- Quaternion rStep = Quaternion.AngleAxis(180f / grouper.clusterGrouper.pieNumSegments, Vector3.up);
- Vector3 r = rStep * Vector3.forward;
- for (int i = 0; i < grouper.clusterGrouper.pieNumSegments; i++){
- Vector3 rr = yIsUp2PieAxis * r;
- Gizmos.DrawLine(grouper.clusterGrouper.origin, grouper.clusterGrouper.origin + rr * rad);
- r = rStep * r;
- r = rStep * r;
- }
- }
- }
-
- public static void DrawCircle (Vector3 axis, Vector3 center, float radius, int subdiv) {
- Quaternion q = Quaternion.AngleAxis (360 / subdiv, axis);
- Vector3 r = new Vector3 (axis.y, -axis.x, axis.z); //should be perpendicular to axis
- r.Normalize ();
- r *= radius;
- for (int i = 0; i < subdiv+1; i ++) {
- Vector3 r2 = q * r;
- Gizmos.DrawLine (center + r, center + r2);
- r = r2;
- }
- }
- }
-
- [Serializable]
- public class MB3_MeshBakerGrouperCore{
- public enum ClusterType{
- none,
- grid,
- pie,
- //voroni,
- }
-
- [Serializable]
- public class ClusterGrouper{
-
- public ClusterType clusterType;
- public Vector3 origin;
- //for grid
- public Vector3 cellSize;
- //for pie
- public int pieNumSegments = 4;
- public Vector3 pieAxis = Vector3.up;
-
- public Dictionary<string,List<Renderer>> FilterIntoGroups(List<GameObject> selection){
- if (clusterType == ClusterType.none){
- return FilterIntoGroupsNone(selection);
- } else if (clusterType == ClusterType.grid) {
- return FilterIntoGroupsGrid(selection);
- } else if (clusterType == ClusterType.pie){
- return FilterIntoGroupsPie(selection);
- }
- return new Dictionary<string, List<Renderer>>();
- }
-
- public Dictionary<string,List<Renderer>> FilterIntoGroupsNone(List<GameObject> selection)
- {
- LogManager.Log ("Filtering into groups none");
-
- Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
-
- List<Renderer> rs = new List<Renderer>();
- for (int i = 0; i < selection.Count; i++)
- {
- rs.Add (selection[i].GetComponent<Renderer>());
- }
-
- cell2objs.Add ("MeshBaker",rs);
- return cell2objs;
- }
-
- public Dictionary<string,List<Renderer>> FilterIntoGroupsGrid(List<GameObject> selection){
- Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
- if (cellSize.x <= 0f || cellSize.y <= 0f || cellSize.z <= 0f ){
- LogManager.LogError ("cellSize x,y,z must all be greater than zero.");
- return cell2objs;
- }
-
- LogManager.Log("Collecting renderers in each cell");
- foreach (GameObject t in selection){
- GameObject go = t;
- Renderer[] mrs = go.GetComponentsInChildren<Renderer>();
- for (int j = 0; j < mrs.Length; j++){
- if (mrs[j] is MeshRenderer || mrs[j] is SkinnedMeshRenderer){
- //get the cell this gameObject is in
- Vector3 gridVector = mrs[j].transform.position;
- gridVector.x = Mathf.Floor((gridVector.x - origin.x) / cellSize.x) * cellSize.x;
- gridVector.y = Mathf.Floor((gridVector.y - origin.y) / cellSize.y) * cellSize.y;
- gridVector.z = Mathf.Floor((gridVector.z - origin.z) / cellSize.z) * cellSize.z;
- List<Renderer> objs = null;
- string gridVectorStr = gridVector.ToString();
- if (cell2objs.ContainsKey(gridVectorStr)){
- objs = cell2objs[gridVectorStr];
- } else {
- objs = new List<Renderer>();
- cell2objs.Add (gridVectorStr,objs);
- }
- if (!objs.Contains(mrs[j])){
- objs.Add (mrs[j]);
- }
- }
- }
- }
- return cell2objs;
- }
-
- public Dictionary<string,List<Renderer>> FilterIntoGroupsPie(List<GameObject> selection){
- Dictionary<string,List<Renderer>> cell2objs = new Dictionary<string,List<Renderer>>();
- if (pieNumSegments == 0 ){
- LogManager.LogError ("pieNumSegments must be greater than zero.");
- return cell2objs;
- }
-
- if (pieAxis.magnitude <= .000001f ){
- LogManager.LogError ("Pie axis must have length greater than zero.");
- return cell2objs;
- }
-
- pieAxis.Normalize();
- Quaternion pieAxis2yIsUp = Quaternion.FromToRotation(pieAxis,Vector3.up);
-
- LogManager.Log("Collecting renderers in each cell");
- foreach (GameObject t in selection){
- GameObject go = t;
- Renderer[] mrs = go.GetComponentsInChildren<Renderer>();
- for (int j = 0; j < mrs.Length; j++){
- if (mrs[j] is MeshRenderer || mrs[j] is SkinnedMeshRenderer){
- //get the cell this gameObject is in
- Vector3 origin2obj = mrs[j].transform.position - origin;
- origin2obj.Normalize();
- origin2obj = pieAxis2yIsUp * origin2obj;
-
- float d_aboutY = 0f;
- if (Mathf.Abs(origin2obj.x) < 10e-5f && Mathf.Abs(origin2obj.z) < 10e-5f){
- d_aboutY = 0f;
- } else {
- d_aboutY = Mathf.Atan2(origin2obj.z,origin2obj.x) * Mathf.Rad2Deg;
- if (d_aboutY < 0f) d_aboutY = 360f + d_aboutY;
- }
-
- int segment = Mathf.FloorToInt(d_aboutY / 360f * pieNumSegments);
-
- List<Renderer> objs = null;
- string segStr = "seg_" + segment;
- if (cell2objs.ContainsKey(segStr)){
- objs = cell2objs[segStr];
- } else {
- objs = new List<Renderer>();
- cell2objs.Add (segStr,objs);
- }
- if (!objs.Contains(mrs[j])){
- objs.Add (mrs[j]);
- }
- }
- }
- }
- return cell2objs;
- }
- }
-
- public ClusterGrouper clusterGrouper;
- public bool clusterOnLMIndex;
-
- public void DoClustering(MB3_TextureBaker tb){
- if (clusterGrouper == null){
- LogManager.LogError("Cluster Grouper was null.");
- return;
- }
-
- //todo warn for no objects and no material bake result
- Dictionary<string,List<Renderer>> cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine());
-
- LogManager.Log ("Found " + cell2objs.Count + " cells with Renderers. Creating bakers.");
- if (clusterOnLMIndex){
- Dictionary<string,List<Renderer>> cell2objsNew = new Dictionary<string, List<Renderer>>();
- foreach (string key in cell2objs.Keys){
- List<Renderer> gaws = cell2objs[key];
- Dictionary<int,List<Renderer>> idx2objs = GroupByLightmapIndex(gaws);
- foreach(int keyIdx in idx2objs.Keys){
- string keyNew = key + "-LM-" + keyIdx;
- cell2objsNew.Add (keyNew,idx2objs[keyIdx]);
- }
- }
- cell2objs = cell2objsNew;
- }
- foreach (string key in cell2objs.Keys){
- List<Renderer> gaws = cell2objs[key];
- AddMeshBaker (tb,key,gaws);
- }
- }
-
- Dictionary<int,List<Renderer>> GroupByLightmapIndex(List<Renderer> gaws){
- Dictionary<int,List<Renderer>> idx2objs = new Dictionary<int, List<Renderer>>();
- for (int i = 0; i < gaws.Count; i++){
- List<Renderer> objs = null;
- if (idx2objs.ContainsKey(gaws[i].lightmapIndex)){
- objs = idx2objs[gaws[i].lightmapIndex];
- } else {
- objs = new List<Renderer>();
- idx2objs.Add (gaws[i].lightmapIndex,objs);
- }
- objs.Add (gaws[i]);
- }
- return idx2objs;
- }
-
- void AddMeshBaker(MB3_TextureBaker tb, string key, List<Renderer> gaws){
- int numVerts = 0;
- for (int i = 0; i < gaws.Count; i++){
- Mesh m = MB_Utility.GetMesh(gaws[i].gameObject);
- if (m != null)
- numVerts += m.vertexCount;
- }
-
- GameObject nmb = new GameObject("MeshBaker-" + key);
- nmb.transform.position = Vector3.zero;
- MB3_MeshBakerCommon newMeshBaker;
- if (numVerts >= 65535){
- newMeshBaker = nmb.AddComponent<MB3_MultiMeshBaker>();
- newMeshBaker.useObjsToMeshFromTexBaker = false;
- } else {
- newMeshBaker = nmb.AddComponent<MB3_MeshBaker>();
- newMeshBaker.useObjsToMeshFromTexBaker = false;
- }
- newMeshBaker.textureBakeResults = tb.textureBakeResults;
- newMeshBaker.transform.parent = tb.transform;
- for (int i = 0; i < gaws.Count; i++){
- newMeshBaker.GetObjectsToCombine().Add (gaws[i].gameObject);
- }
- }
- }
|