public void OnGUI(PaintJob[] jobs) { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Combine Meshes")) { VertexPainterUtilities.MergeMeshes(jobs); } if (GUILayout.Button("Combine and Save")) { if (jobs.Length != 0) { string path = EditorUtility.SaveFilePanel("Save Asset", Application.dataPath, "models", "asset"); if (!string.IsNullOrEmpty(path)) { path = FileUtil.GetProjectRelativePath(path); GameObject go = VertexPainterUtilities.MergeMeshes(jobs); Mesh m = go.GetComponent <MeshFilter>().sharedMesh; AssetDatabase.CreateAsset(m, path); AssetDatabase.SaveAssets(); AssetDatabase.ImportAsset(path); GameObject.DestroyImmediate(go); } } } EditorGUILayout.EndHorizontal(); }
public void OnGUI(PaintJob[] jobs) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.Space(); if (GUILayout.Button("Save Mesh")) { VertexPainterUtilities.SaveMesh(jobs); } EditorGUILayout.Space(); EditorGUILayout.EndHorizontal(); }
void DoBakeAO(PaintJob[] jobs, VertexPainterWindow window) { Light[] aoLights = null; if (bakeLighting) { aoLights = GameObject.FindObjectsOfType <Light>(); } int sample = 0; int numVerts = 0; for (int i = 0; i < jobs.Length; ++i) { numVerts += jobs[i].verts.Length; } int numSamples = numVerts * aoSamples; float oldFloat = window.floatBrushValue; Color oldColor = window.brushColor; int oldVal = window.brushValue; // add temp colliders if needed bool[] tempCollider = new bool[jobs.Length]; for (int jIdx = 0; jIdx < jobs.Length; ++jIdx) { PaintJob job = jobs[jIdx]; if (job.meshFilter.GetComponent <Collider>() == null) { job.meshFilter.gameObject.AddComponent <MeshCollider>(); tempCollider[jIdx] = true; } } // do AO for (int jIdx = 0; jIdx < jobs.Length; ++jIdx) { PaintJob job = jobs[jIdx]; window.PrepBrushMode(job); // bake down the mesh so we take instance positions into account.. Mesh mesh = VertexPainterUtilities.BakeDownMesh(job.meshFilter.sharedMesh, job.stream); Vector3[] verts = mesh.vertices; if (mesh.normals == null || mesh.normals.Length == 0) { mesh.RecalculateNormals(); } Vector3[] normals = mesh.normals; window.brushValue = 255; window.floatBrushValue = 1.0f; window.brushColor = Color.white; var val = window.GetBrushValue(); VertexPainterWindow.Lerper lerper = null; VertexPainterWindow.Multiplier mult = null; if (aoBakeMode == AOBakeMode.Replace) { lerper = window.GetLerper(); for (int i = 0; i < job.verts.Length; ++i) { lerper.Invoke(job, i, ref val, 1); } } else { mult = window.GetMultiplier(); } for (int i = 0; i < verts.Length; i++) { Vector3 norm = normals[i]; // to world space! Vector3 v = job.meshFilter.transform.TransformPoint(verts[i]); Vector3 n = job.meshFilter.transform.TransformPoint(verts[i] + norm); Vector3 worldSpaceNormal = (n - v).normalized; float totalOcclusion = 0; // the slow part.. for (int j = 0; j < aoSamples; j++) { // random rotate around hemisphere float rot = 180.0f; float rot2 = rot / 2.0f; float rotx = ((rot * Random.value) - rot2); float roty = ((rot * Random.value) - rot2); float rotz = ((rot * Random.value) - rot2); Vector3 dir = Quaternion.Euler(rotx, roty, rotz) * Vector3.up; Quaternion dirq = Quaternion.FromToRotation(Vector3.up, worldSpaceNormal); Vector3 ray = dirq * dir; Vector3 offset = Vector3.Reflect(ray, worldSpaceNormal); // raycast ray = ray * (aoRange.y / ray.magnitude); if (Physics.Linecast(v - (offset * 0.1f), v + ray, out hit)) { if (hit.distance > aoRange.x) { totalOcclusion += Mathf.Clamp01(1 - (hit.distance / aoRange.y)); } } sample++; if (sample % 500 == 0) { EditorUtility.DisplayProgressBar("Baking AO...", "Baking...", (float)sample / (float)numSamples); } } totalOcclusion = Mathf.Clamp01(1 - ((totalOcclusion * aoIntensity) / aoSamples)); if (aoLights != null && aoLights.Length > 0) { Color c = aoLightAmbient; for (int l = 0; l < aoLights.Length; ++l) { Light light = aoLights[l]; ApplyAOLight(ref c, light, v, n); } c.r *= totalOcclusion; c.g *= totalOcclusion; c.b *= totalOcclusion; c.a = totalOcclusion; window.brushColor = c; // if we're lit and targeting a channel other than color, bake max intensity.. window.floatBrushValue = Mathf.Max(Mathf.Max(c.r, c.g), c.b) * totalOcclusion; window.brushValue = (int)(window.floatBrushValue * 255); } else { window.brushColor.r = totalOcclusion; window.brushColor.g = totalOcclusion; window.brushColor.b = totalOcclusion; window.brushColor.a = totalOcclusion; window.floatBrushValue = totalOcclusion; window.brushValue = (int)(totalOcclusion * 255); } val = window.GetBrushValue(); if (aoBakeMode == AOBakeMode.Replace) { lerper.Invoke(job, i, ref val, 1); } else { mult.Invoke(job.stream, i, ref val); } } job.stream.Apply(); EditorUtility.SetDirty(job.stream); EditorUtility.SetDirty(job.stream.gameObject); GameObject.DestroyImmediate(mesh); window.brushValue = oldVal; window.floatBrushValue = oldFloat; window.brushColor = oldColor; } // remove temp colliders for (int jIdx = 0; jIdx < jobs.Length; ++jIdx) { if (tempCollider[jIdx] == true) { Collider c = jobs[jIdx].meshFilter.GetComponent <Collider>(); if (c != null) { GameObject.DestroyImmediate(c); } } } EditorUtility.ClearProgressBar(); SceneView.RepaintAll(); }