/// <summary> /// Executes the baking. /// </summary> public void Bake(string trunkMeshPath, string foliageMeshPath) { //Get the root transform for the baked mesh. //If one tree is selected, use it. //Otherwise, just use the average position of all the selected trees. Matrix4x4 rootM; Vector3 avgPos = Vector3.zero; if (selectedBranches.Length > 1) { avgPos = selectedBranches[0].transform.position; for (int i = 1; i < selectedBranches.Length; ++i) avgPos += selectedBranches[i].transform.position; avgPos /= (float)selectedBranches.Length; rootM = Matrix4x4.TRS(-avgPos, Quaternion.identity, Vector3.one); } else { rootM = selectedBranches[0].transform.worldToLocalMatrix; } IEnumerable<TreeCurve> curves = selectedBranches.SelectMany(go => go.GetComponentsInChildren<TreeCurve>()); //Create one big mesh for all the branches. Mesh msh = CreateMesh(curves.Select(tc => tc.GetComponent<MeshFilter>()), rootM); ExportOBJ(msh, trunkMeshPath, "Trunk"); msh.Clear(); //Create one big mesh for all the foliage. CurveFoliage[] cFs = curves.GetComponentsInChildren<TreeCurve, CurveFoliage>().RemoveDuplicates().ToArray(); if (cFs.Length > 0) { if (cFs.Any(cf => cf.Mode == CurveFoliage.MeshModes.Point)) { Debug.LogError("Can't currently output point foliage meshes to OBJ"); cFs = new CurveFoliage[0]; } else { msh = CreateMesh(cFs.Select(cf => cf.GetComponent<MeshFilter>()), rootM); ExportOBJ(msh, foliageMeshPath, "Foliage"); msh.Clear(); } } //Replace the current tree object with one that just has the baked assets. //Put the original objects inside the new one and deactivate it. Transform bakedObj = new GameObject("Baked Trees").transform; if (selectedBranches.Length > 1) { bakedObj.position = avgPos; bakedObj.rotation = Quaternion.identity; bakedObj.localScale = Vector3.one; } else { Transform oldObj = selectedBranches[0].transform; bakedObj.position = oldObj.position; bakedObj.rotation = oldObj.rotation; bakedObj.localScale = oldObj.localScale; } AssetDatabase.Refresh(); Transform trunkChild = new GameObject("Trunk").transform; trunkChild.SetParent(bakedObj, false); MeshFilter mf = trunkChild.gameObject.AddComponent<MeshFilter>(); mf.sharedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(PathUtils.GetRelativePath(trunkMeshPath, "Assets")); MeshRenderer mr = trunkChild.gameObject.AddComponent<MeshRenderer>(); mr.sharedMaterial = branchMat; if (cFs.Length > 0) { Transform foliageChild = new GameObject("Foliage").transform; foliageChild.SetParent(bakedObj, false); mf = foliageChild.gameObject.AddComponent<MeshFilter>(); mf.sharedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(PathUtils.GetRelativePath(foliageMeshPath, "Assets")); mr = foliageChild.gameObject.AddComponent<MeshRenderer>(); mr.sharedMaterial = foliageMat; } }
/// <summary> /// Executes the baking. /// </summary> public void Bake(string trunkMeshPath, string foliageMeshPath) { //Get the root transform for the baked mesh. //If one tree is selected, use it. //Otherwise, just use the average position of all the selected trees. Matrix4x4 rootM; Vector3 avgPos = Vector3.zero; if (selectedBranches.Length > 1) { avgPos = selectedBranches[0].transform.position; for (int i = 1; i < selectedBranches.Length; ++i) { avgPos += selectedBranches[i].transform.position; } avgPos /= (float)selectedBranches.Length; rootM = Matrix4x4.TRS(-avgPos, Quaternion.identity, Vector3.one); } else { rootM = selectedBranches[0].transform.worldToLocalMatrix; } IEnumerable <TreeCurve> curves = selectedBranches.SelectMany(go => go.GetComponentsInChildren <TreeCurve>()); //Create one big mesh for all the branches. Mesh msh = CreateMesh(curves.Select(tc => tc.GetComponent <MeshFilter>()), rootM); ExportOBJ(msh, trunkMeshPath, "Trunk"); msh.Clear(); //Create one big mesh for all the foliage. CurveFoliage[] cFs = curves.GetComponentsInChildren <TreeCurve, CurveFoliage>().RemoveDuplicates().ToArray(); if (cFs.Length > 0) { if (cFs.Any(cf => cf.Mode == CurveFoliage.MeshModes.Point)) { Debug.LogError("Can't currently output point foliage meshes to OBJ"); cFs = new CurveFoliage[0]; } else { msh = CreateMesh(cFs.Select(cf => cf.GetComponent <MeshFilter>()), rootM); ExportOBJ(msh, foliageMeshPath, "Foliage"); msh.Clear(); } } //Replace the current tree object with one that just has the baked assets. //Put the original objects inside the new one and deactivate it. Transform bakedObj = new GameObject("Baked Trees").transform; if (selectedBranches.Length > 1) { bakedObj.position = avgPos; bakedObj.rotation = Quaternion.identity; bakedObj.localScale = Vector3.one; } else { Transform oldObj = selectedBranches[0].transform; bakedObj.position = oldObj.position; bakedObj.rotation = oldObj.rotation; bakedObj.localScale = oldObj.localScale; } AssetDatabase.Refresh(); Transform trunkChild = new GameObject("Trunk").transform; trunkChild.SetParent(bakedObj, false); MeshFilter mf = trunkChild.gameObject.AddComponent <MeshFilter>(); mf.sharedMesh = AssetDatabase.LoadAssetAtPath <Mesh>(PathUtils.GetRelativePath(trunkMeshPath, "Assets")); MeshRenderer mr = trunkChild.gameObject.AddComponent <MeshRenderer>(); mr.sharedMaterial = branchMat; if (cFs.Length > 0) { Transform foliageChild = new GameObject("Foliage").transform; foliageChild.SetParent(bakedObj, false); mf = foliageChild.gameObject.AddComponent <MeshFilter>(); mf.sharedMesh = AssetDatabase.LoadAssetAtPath <Mesh>(PathUtils.GetRelativePath(foliageMeshPath, "Assets")); mr = foliageChild.gameObject.AddComponent <MeshRenderer>(); mr.sharedMaterial = foliageMat; } }