summaryrefslogtreecommitdiff
path: root/VRCSDK3Worlds/Assets/MeshBaker/scripts/MB3_MeshBakerRoot.cs
blob: 5f271f08f5b7274e02a70c3c64eb480ceab80b20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//----------------------------------------------
//            MeshBaker
// Copyright © 2011-2012 Ian Deane
//----------------------------------------------
using UnityEngine;
using System.Collections;
using System.Collections.Specialized;
using System;
using System.Collections.Generic;
using System.Text;
using DigitalOpus.MB.Core;

/// <summary>
/// Root class of all the baking Components
/// </summary>
public abstract class MB3_MeshBakerRoot : MonoBehaviour {

    /**
     * Transparent shaders often require objects to be sorted along 
     */
    public class ZSortObjects
    {
        public Vector3 sortAxis;
        public class Item
        {
            public GameObject go;
            public Vector3 point;
        }

        public class ItemComparer : IComparer<Item>
        {
            public int Compare(Item a, Item b)
            {
                return (int)Mathf.Sign(b.point.z - a.point.z);
            }
        }

        public void SortByDistanceAlongAxis(List<GameObject> gos)
        {
            if (sortAxis == Vector3.zero)
            {
                Debug.LogError("The sort axis cannot be the zero vector.");
                return;
            }
            Debug.Log("Z sorting meshes along axis numObjs=" + gos.Count);
            List<Item> items = new List<Item>();
            Quaternion q = Quaternion.FromToRotation(sortAxis, Vector3.forward);
            for (int i = 0; i < gos.Count; i++)
            {
                if (gos[i] != null)
                {
                    Item item = new Item();
                    item.point = gos[i].transform.position;
                    item.go = gos[i];
                    item.point = q * item.point;
                    items.Add(item);
                }
            }
            items.Sort(new ItemComparer());

            for (int i = 0; i < gos.Count; i++)
            {
                gos[i] = items[i].go;
            }
        }
    }

    public Vector3 sortAxis;

	[HideInInspector] public abstract MB2_TextureBakeResults textureBakeResults{
		get;
		set;
	}
	
	//todo switch this to List<Renderer>
	public virtual List<GameObject> GetObjectsToCombine(){
		return null;	
	}
	
	public static bool DoCombinedValidate(MB3_MeshBakerRoot mom, MB_ObjsToCombineTypes objToCombineType, MB2_EditorMethodsInterface editorMethods, MB2_ValidationLevel validationLevel){
		if (mom.textureBakeResults == null){
			Debug.LogError("Need to set Texture Bake Result on " + mom);
			return false;
		}
		if (mom is MB3_MeshBakerCommon){
			MB3_MeshBakerCommon momMB = (MB3_MeshBakerCommon) mom;
			MB3_TextureBaker tb = momMB.GetTextureBaker();
			if (tb != null && tb.textureBakeResults != mom.textureBakeResults){
				Debug.LogWarning("Texture Bake Result on this component is not the same as the Texture Bake Result on the MB3_TextureBaker.");
			}
		}

		Dictionary<int,MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = null;
		if (validationLevel == MB2_ValidationLevel.robust){
			meshAnalysisResultCache = new Dictionary<int, MB_Utility.MeshAnalysisResult>();
		}
		List<GameObject> objsToMesh = mom.GetObjectsToCombine();
		for (int i = 0; i < objsToMesh.Count; i++){
			GameObject go = objsToMesh[i];
			if (go == null){
				Debug.LogError("The list of objects to combine contains a null at position." + i + " Select and use [shift] delete to remove");
				return false;					
			}
			for (int j = i + 1; j < objsToMesh.Count; j++){
				if (objsToMesh[i] == objsToMesh[j]){
					Debug.LogError("The list of objects to combine contains duplicates at " + i + " and " + j);
					return false;	
				}
			}
			if (MB_Utility.GetGOMaterials(go).Length == 0){
				Debug.LogError("Object " + go + " in the list of objects to be combined does not have a material");
				return false;
			}
			Mesh m = MB_Utility.GetMesh(go);
			if (m == null){
				Debug.LogError("Object " + go + " in the list of objects to be combined does not have a mesh");
				return false;
			}
			if (m != null){ //This check can be very expensive and it only warns so only do this if we are in the editor.
				if (!Application.isEditor && 
				    Application.isPlaying &&
					mom.textureBakeResults.doMultiMaterial && 
					validationLevel >= MB2_ValidationLevel.robust){
					MB_Utility.MeshAnalysisResult mar;
					if (!meshAnalysisResultCache.TryGetValue(m.GetInstanceID(),out mar)){
						MB_Utility.doSubmeshesShareVertsOrTris(m,ref mar);
						meshAnalysisResultCache.Add (m.GetInstanceID(),mar);
					}
					if (mar.hasOverlappingSubmeshVerts){
						Debug.LogWarning("Object " + objsToMesh[i] + " in the list of objects to combine has overlapping submeshes (submeshes share vertices). If the UVs associated with the shared vertices are important then this bake may not work. If you are using multiple materials then this object can only be combined with objects that use the exact same set of textures (each atlas contains one texture). There may be other undesirable side affects as well. Mesh Master, available in the asset store can fix overlapping submeshes.");	
					}
				}
			}
		}

		
		List<GameObject> objs = objsToMesh;
		
		if (mom is MB3_MeshBaker)
		{
			objs = mom.GetObjectsToCombine();
			//if (((MB3_MeshBaker)mom).useObjsToMeshFromTexBaker && tb != null) objs = tb.GetObjectsToCombine(); 
			if (objs == null || objs.Count == 0)
			{
				Debug.LogError("No meshes to combine. Please assign some meshes to combine.");
				return false;
			}
			if (mom is MB3_MeshBaker && ((MB3_MeshBaker)mom).meshCombiner.settings.renderType == MB_RenderType.skinnedMeshRenderer){
				if (!editorMethods.ValidateSkinnedMeshes(objs))
				{
					return false;
				}
			}
		}
		
		if (editorMethods != null){
			editorMethods.CheckPrefabTypes(objToCombineType, objsToMesh);
		}
		return true;
	}
}