public void ToMesh(Mesh m, bool computeLightMapUVs) { m.Clear(); m.indexFormat = triangles.Count > 65535 ? UnityEngine.Rendering.IndexFormat.UInt32 : UnityEngine.Rendering.IndexFormat.UInt16; m.SetVertices(vertices); m.SetNormals(normals); if (uvs0.Count == vertices.Count) { m.SetUVs(0, uvs0); } if (color32s.Count == vertices.Count) { m.SetColors(color32s); } m.subMeshCount = 1; m.SetTriangles(triangles, 0); if (computeLightMapUVs) { UnwrapParam param; UnwrapParam.SetDefaults(out param); param.packMargin = 0.02f; Unwrapping.GenerateSecondaryUVSet(m, param); } m.RecalculateBounds(); // TODO: Use bounds }
public static void UnwrapUV2(Mesh mesh, float hardAngle, float packingMargin){ UnwrapParam up = new UnwrapParam(); UnwrapParam.SetDefaults(out up); up.hardAngle = hardAngle; up.packMargin = packingMargin; Unwrapping.GenerateSecondaryUVSet(mesh,up); }
public static void GenerateSecondaryUVSet(Mesh meshsrc) { #if UNITY_EDITOR UnwrapParam param; UnwrapParam.SetDefaults(out param); Unwrapping.GenerateSecondaryUVSet(meshsrc, param); #else Debug.LogWarning("GenerateSecondaryUVSet is unavailable at runtime!"); #endif }
public static void GenerateUV2(this Mesh mesh, bool forceUpdate) { // SetUVParams(8f, 15f, 15f, 20f); UnwrapParam param; UnwrapParam.SetDefaults(out param); Unwrapping.GenerateSecondaryUVSet(mesh, param); EditorUtility.SetDirty(mesh as Object); }
private void RegenLightmapUV() { meshFilter = GetComponent <MeshFilter>(); if (!meshFilter) { Debug.LogError("No Mesh filter found on object"); return; } mesh = meshFilter.sharedMesh; if (!mesh) { Debug.LogError("Mesh not assigned in meshfilter..."); return; } Debug.Log("Secondary UV Set Generate: Start"); unwrapParam = new UnwrapParam(); UnwrapParam.SetDefaults(out unwrapParam); Unwrapping.GenerateSecondaryUVSet(mesh, unwrapParam); Debug.Log("Secondary UV Set Generate: Complete"); }
private void Change_Scaleinlightmap(GameObject go, bool OneMesh, Mesh finalMesh, Meshcombinervtwo myScript) { //Check if he got a renderer if (go.GetComponent <MeshRenderer>() != null) { //Find the property and modify them SerializedObject serializedObject2 = new UnityEditor.SerializedObject(go.GetComponent <Renderer>()); SerializedProperty m_nScaleInLightmap = serializedObject2.FindProperty("m_ScaleInLightmap"); SerializedProperty m_StitchLightmapSeams = serializedObject2.FindProperty("m_StitchLightmapSeams"); serializedObject2.Update(); m_nScaleInLightmap.floatValue = f_ScaleInLightmap.floatValue; m_StitchLightmapSeams.boolValue = b_StitchSeams.boolValue; serializedObject2.ApplyModifiedProperties(); } if (!OneMesh) { // If there is nothing to combine delete the object if (myScript.gameObject.GetComponent <MeshFilter>()) { myScript.gameObject.GetComponent <MeshFilter>().sharedMesh = null; } } else { UnwrapParam param = new UnwrapParam(); // enable lightmap UnwrapParam.SetDefaults(out param); param.hardAngle = _HardAngle.floatValue; param.packMargin = _PackMargin.floatValue; param.angleError = _AngleError.floatValue; param.areaError = _AreaError.floatValue; Unwrapping.GenerateSecondaryUVSet(finalMesh, param); } }
public static void GenerateUV2(this pb_Object pb, bool forceUpdate) { if (pb_Preferences_Internal.GetBool(pb_Constant.pbDisableAutoUV2Generation) && !forceUpdate) { return; } // SetUVParams(8f, 15f, 15f, 20f); UnwrapParam param; UnwrapParam.SetDefaults(out param); param.angleError = Mathf.Clamp(pb.angleError, 1f, 75f) * .01f; param.areaError = Mathf.Clamp(pb.areaError, 1f, 75f) * .01f; param.hardAngle = Mathf.Clamp(pb.hardAngle, 0f, 180f); param.packMargin = Mathf.Clamp(pb.packMargin, 1f, 64) * .001f; Unwrapping.GenerateSecondaryUVSet(pb.GetComponent <MeshFilter>().sharedMesh, param); EditorUtility.SetDirty(pb); }
public void ApplyTo(Mesh target, bool recalculateTangents, bool recalculateLightMapUVs) { target.Clear(false); target.vertices = vertices; if (normals != null) { target.normals = normals; } if (tangents != null) { target.tangents = tangents; } if (uvs != null) { target.SetUVs(0, new List <Vector2>(uvs)); } if (colors != null) { target.colors32 = colors; } target.SetTriangles(tris, 0); if (recalculateTangents) { target.RecalculateTangents(); } UnwrapParam param; UnwrapParam.SetDefaults(out param); param.packMargin = 0.02f; if (recalculateLightMapUVs) { Unwrapping.GenerateSecondaryUVSet(target, param); } }
void UvsGUI() { //EditorGUILayout.PropertyField(m_SwapUVChannels, Styles.SwapUVChannels); EditorGUILayout.PropertyField(m_GenerateSecondaryUV, Styles.GenerateSecondaryUV); if (m_GenerateSecondaryUV.boolValue) { m_SecondaryUVAdvancedOptions = EditorGUILayout.Foldout(m_SecondaryUVAdvancedOptions, Styles.GenerateSecondaryUVAdvanced, true, EditorStyles.foldout); if (m_SecondaryUVAdvancedOptions) { using (new EditorGUI.IndentLevelScope()) { // TODO: all slider min/max values should be revisited EditorGUI.BeginChangeCheck(); EditorGUILayout.Slider(m_SecondaryUVHardAngle, 0, 180, Styles.secondaryUVHardAngle); EditorGUILayout.Slider(m_SecondaryUVPackMargin, 1, 64, Styles.secondaryUVPackMargin); EditorGUILayout.Slider(m_SecondaryUVAngleDistortion, 1, 75, Styles.secondaryUVAngleDistortion); EditorGUILayout.Slider(m_SecondaryUVAreaDistortion, 1, 75, Styles.secondaryUVAreaDistortion); if (EditorGUI.EndChangeCheck()) { m_SecondaryUVHardAngle.floatValue = Mathf.Round(m_SecondaryUVHardAngle.floatValue); m_SecondaryUVPackMargin.floatValue = Mathf.Round(m_SecondaryUVPackMargin.floatValue); m_SecondaryUVAngleDistortion.floatValue = Mathf.Round(m_SecondaryUVAngleDistortion.floatValue); m_SecondaryUVAreaDistortion.floatValue = Mathf.Round(m_SecondaryUVAreaDistortion.floatValue); } if (GUILayout.Button("Reset LightmapSettings")) { UnwrapParam uvs; UnwrapParam.SetDefaults(out uvs); m_SecondaryUVHardAngle.floatValue = Mathf.Round(uvs.hardAngle); m_SecondaryUVPackMargin.floatValue = Mathf.Round(uvs.packMargin * 1000); //Debug.Log(uvs.packMargin*1000); m_SecondaryUVAngleDistortion.floatValue = Mathf.Round(uvs.angleError * 100); m_SecondaryUVAreaDistortion.floatValue = Mathf.Round(uvs.areaError * 100); } } } } }
public static void GenerateUV2(this pb_Object pb, bool show_NoDraw) { if (pb.onlyNodraw) { Vector2[] u = new Vector2[pb.msh.vertices.Length]; for (int n = 0; n < u.Length; n++) { u[n] = Vector2.zero; } pb.SetUV2(u); return; } Vector2[] uvs = pb.msh.uv; // nodraw uvs are nuked in this process, so save 'em pb.ToMesh(true); // re-draw meshes without nodraw faces // SetUVParams(8f, 15f, 15f, 20f); UnwrapParam param; UnwrapParam.SetDefaults(out param); param.angleError = Mathf.Clamp(pb.angleError, 1f, 75f) * .01f; param.areaError = Mathf.Clamp(pb.areaError, 1f, 75f) * .01f; param.hardAngle = Mathf.Clamp(pb.hardAngle, 0f, 180f); param.packMargin = Mathf.Clamp(pb.packMargin, 1f, 64) * .001f; Unwrapping.GenerateSecondaryUVSet(pb.GetComponent <MeshFilter>().sharedMesh, param); if (show_NoDraw) { pb.ToMesh(false); } pb.msh.uv = uvs; EditorUtility.SetDirty(pb); }
void OnPostprocessModel(GameObject g) { Init(); //if (storage == null) return; ModelImporter importer = (ModelImporter)assetImporter; if (importer.generateSecondaryUV) { // Auto UVs: Adjust UV padding per mesh //if (!storage.modifiedAssetPathList.Contains(assetPath) && g.tag == "BakeryProcessed") return; //if (ftLightmaps.IsModelProcessed(assetPath)) return; //g.tag = "BakeryProcessed"; Debug.Log("Bakery: processing auto-unwrapped asset " + assetPath); if (storage != null) { ftLightmaps.MarkModelProcessed(assetPath, true); } uparams = new UnwrapParam(); UnwrapParam.SetDefaults(out uparams); uparams.angleError = importer.secondaryUVAngleDistortion * 0.01f; uparams.areaError = importer.secondaryUVAreaDistortion * 0.01f; uparams.hardAngle = importer.secondaryUVHardAngle; #if UNITY_2017_1_OR_NEWER deserializedSuccess = false; var props = importer.extraUserProperties; for (int p = 0; p < props.Length; p++) { if (props[p].Substring(0, 7) == "#BAKERY") { var json = props[p].Substring(7); deserialized = JsonUtility.FromJson <ftGlobalStorage.AdjustedMesh>(json); deserializedSuccess = true; break; } } #endif if (storage != null) { storage.InitModifiedMeshMap(assetPath); } AdjustUV(g.transform); } else { if (storage == null) { return; } Debug.Log("Bakery: checking for UV overlaps in " + assetPath); //if (g.tag == "BakeryProcessed") g.tag = ""; ftLightmaps.MarkModelProcessed(assetPath, true);//false); // Manual UVs: check if overlapping CheckUVOverlap(g, assetPath); } if (g.tag == "BakeryProcessed") { g.tag = ""; // remove legacy mark } }
public Material mat; // Put here a material. This gameObject combine all the gameobject with this material. Assign material only for children of obj // Use this for initialization public void CombineMeshes() // -> Combine all the maesh with a specif material. { Quaternion oldRot = obj.transform.rotation; // Save the original position and rotation of obj Vector3 oldPos = obj.transform.position; bool OneMesh = false; // This variable is used to know if there is at least one mesh to combine obj.transform.rotation = Quaternion.identity; // Init position to zero obj.transform.position = Vector3.zero; // Init position to Vector3(0,0,0) MeshFilter[] filters = obj.GetComponentsInChildren <MeshFilter>(); // Find all the children with MeshFilter component Debug.Log(name + " is combining " + filters.Length + " meshes"); Mesh finalMesh = new Mesh(); // Create the new mesh CombineInstance[] combiners = new CombineInstance[filters.Length]; // Struct used to describe meshes to be combined using Mesh.CombineMeshes. for (int i = 0; i < filters.Length; i++) // Check all the children { if (filters[i].transform == obj.transform) // Do not select the parent himself { continue; } if (filters[i].gameObject.GetComponent <Renderer>() == null) // Check if there is Renderer component { continue; } bool checkTag = false; for (int j = 0; j < arrtags.Length; j++) // Check tag to know if you need to ignore this gameobject { if (filters[i].gameObject.tag == arrtags[j]) { checkTag = true; } } if (mat == filters[i].gameObject.GetComponent <Renderer>().sharedMaterial&& !checkTag && // Add this gameObject to the combiner filters[i].gameObject.GetComponent <Renderer>().enabled) { combiners[i].subMeshIndex = 0; combiners[i].mesh = filters[i].sharedMesh; combiners[i].transform = filters[i].transform.localToWorldMatrix; filters[i].gameObject.GetComponent <Renderer>().enabled = false; OneMesh = true; } } finalMesh.CombineMeshes(combiners); // Combine the new mesh GetComponent <MeshFilter>().sharedMesh = finalMesh; // Create the new Mesh Filter GetComponent <Renderer>().material = mat; // ADd the good material transform.rotation = oldRot; // Move the object at his original position transform.position = oldPos; obj.transform.rotation = oldRot; obj.transform.position = oldPos; if (!OneMesh) // If there is nothing to combine delete the object { gameObject.SetActive(false); GetComponent <MeshFilter>().sharedMesh = null; if (DeleteUnusedMaterial) { Object.DestroyImmediate(gameObject); } } else { UnwrapParam param = new UnwrapParam(); // enable lightmap UnwrapParam.SetDefaults(out param); Unwrapping.GenerateSecondaryUVSet(finalMesh, param); } }
public override void OnImportAsset(AssetImportContext ctx) { Debug.Log("Attempting to import AMF:" + ctx.assetPath); progressString += ctx.assetPath; EditorUtility.DisplayProgressBar(progressString, "Parsing...", 0); AMF amf = ParseAMF(ctx.assetPath); string workingDir = ctx.assetPath.Substring(0, ctx.assetPath.LastIndexOf("/") + 1); /* * Setup materials first */ Dictionary <string, Material> mats = new Dictionary <string, Material>(); Dictionary <string, AMFShaderInfo> matsHelpers = new Dictionary <string, AMFShaderInfo>(); System.IO.Directory.CreateDirectory(workingDir + "Materials/"); //System.IO.Directory.CreateDirectory(workingDir+"MaterialHelpers/"); AMFShaderInfo asi; float totalMats = amf.shaderInfos.Count; float matsComplete = 0; foreach (AdjutantSharp.ShaderInfo si in amf.shaderInfos) { EditorUtility.DisplayProgressBar("Setting up Materials...", si.sName, (matsComplete / totalMats)); asi = (AMFShaderInfo)AMFShaderInfo.CreateInstance(typeof(AMFShaderInfo)); asi.name = si.sName; asi.SaveData(si); if (!mats.ContainsKey(si.sName)) { string path = workingDir + "Materials/" + si.sName + ".mat"; Material material = (Material)AssetDatabase.LoadAssetAtPath(workingDir + "Materials/" + si.sName + ".mat", typeof(Material)); if (material == null) { asi.workingDir = workingDir; material = asi.CreateMaterial(); /* if(si.GetType()==typeof(RegularShader)){ * material=SetupRegularMaterial((RegularShader)si,workingDir); * }else{ * material=SetupTerrainMaterial((TerrainShader)si,workingDir); * } */ AssetDatabase.CreateAsset(material, workingDir + "Materials/" + si.sName + ".mat"); } mats.Add(si.sName, material); matsHelpers.Add(si.sName, asi); ctx.AddObjectToAsset("MaterialHelper-" + asi.sName, asi); ctx.DependsOnSourceAsset(workingDir + "Materials/" + si.sName + ".mat"); /* if(material!=null) * ctx.AddObjectToAsset(material.name,material); */ } matsComplete++; } //EditorUtility.DisplayProgressBar(progressString,"[4/5] Creating Meshes...",(4f/5f)); /* * Create Meshes */ GameObject root = new GameObject(amf.modelName); ctx.AddObjectToAsset(amf.modelName, root); ctx.SetMainObject(root); Dictionary <long, Mesh> meshList = ConvertMeshes(amf, mats, matsHelpers, root); //root.transform.rotation=Quaternion.Euler(-90f,0f,0f); /* LoadRegions(amf,root); * List<Mesh> meshList=CreateMeshes(amf,root.transform,mats); */ UnwrapParam.SetDefaults(out uvSettings); EditorUtility.DisplayProgressBar(progressString, "[5/5] Finishing up...", (5f / 5f)); float lightCount = 0; float totalLight = meshList.Count; foreach (Mesh m in meshList.Values) { /* if(GenerateLightmapUVs){ * EditorUtility.DisplayProgressBar("Generating Lightmaps","["+lightCount+"/"+totalLight+"] Generating UVs...",(lightCount/totalLight)); * Unwrapping.GenerateSecondaryUVSet(m,uvSettings); * lightCount++; * } */ ctx.AddObjectToAsset(m.name, m); } Debug.Log("AMF import complete"); EditorUtility.ClearProgressBar(); }
private void OnEnable() { UnwrapParam.SetDefaults(out unwrapParam); }
public void CombineMeshes(Material mat) // -> Combine all the maesh with a specif material. { Meshcombinervtwo myScript = (Meshcombinervtwo)target; GameObject newGameObject = new GameObject(); newGameObject.AddComponent <MeshFilter>(); newGameObject.AddComponent <MeshRenderer>(); newGameObject.GetComponent <Renderer>().sharedMaterial = null; newGameObject.name = "Combine_" + mat.name; Undo.RegisterCreatedObjectUndo(newGameObject, "CombineMat" + mat.name); myScript.list_CreatedObjects.Add(newGameObject); bool OneMesh = false; // This variable is used to know if there is at least one mesh to combine newGameObject.transform.rotation = Quaternion.identity; // Init position to zero newGameObject.transform.SetParent(myScript.transform); newGameObject.transform.localPosition = new Vector3(0, 0, 0); // Init position to Vector3(0,0,0) newGameObject.isStatic = true; MeshFilter[] filters = myScript.gameObject.GetComponentsInChildren <MeshFilter>(); // Find all the children with MeshFilter component Mesh finalMesh = new Mesh(); // Create the new mesh CombineInstance[] combiners = new CombineInstance[filters.Length]; // Struct used to describe meshes to be combined using Mesh.CombineMeshes. for (int i = 0; i < filters.Length; i++) // Check all the children { if (filters[i].transform == myScript.gameObject.transform) // Do not select the parent himself { continue; } if (filters[i].gameObject.GetComponent <Renderer>() == null) // Check if there is Renderer component { continue; } bool checkTag = false; for (int j = 0; j < myScript.list_Tags.Count; j++) // Check tag to know if you need to ignore this gameobject { if (filters[i].gameObject.tag == myScript.list_Tags[j]) { checkTag = true; } } if (mat == filters[i].gameObject.GetComponent <Renderer>().sharedMaterial&& !checkTag && // Add this gameObject to the combiner filters[i].gameObject.GetComponent <Renderer>().enabled) { combiners[i].subMeshIndex = 0; combiners[i].mesh = filters[i].sharedMesh; combiners[i].transform = filters[i].transform.localToWorldMatrix; myScript.list_CombineObjects.Add(filters[i].gameObject); SerializedObject serializedObject3 = new UnityEditor.SerializedObject(filters[i].gameObject.GetComponents <Renderer>()); serializedObject3.Update(); SerializedProperty tmpSer2 = serializedObject3.FindProperty("m_Enabled"); tmpSer2.boolValue = false; serializedObject3.ApplyModifiedProperties(); OneMesh = true; } } finalMesh.CombineMeshes(combiners); // Combine the new mesh newGameObject.GetComponent <MeshFilter>().sharedMesh = finalMesh; // Create the new Mesh Filter newGameObject.GetComponent <Renderer>().material = mat; // ADd the good material if (!OneMesh) // If there is nothing to combine delete the object { if (myScript.gameObject.GetComponent <MeshFilter>()) { myScript.gameObject.GetComponent <MeshFilter>().sharedMesh = null; } } else { UnwrapParam param = new UnwrapParam(); // enable lightmap UnwrapParam.SetDefaults(out param); Unwrapping.GenerateSecondaryUVSet(finalMesh, param); } }
static string QuadsToMesh( MeshFilter mf, // output mesh filter quadByUV quads, // input structure -> quads string undoTitle // title for undo operation ) { // output a quad list to a mesh structure if (mf == null || // no output MeshFilter quads == null || // OR no quad list quads.Count <= 0) // OR no quad entries { return(""); } // get original asset path and convert to a path we can load from/save to string path = AssetDatabase.GetAssetPath(mf.sharedMesh); string suffix = path.Substring(path.LastIndexOf(".")); string name = path.Replace(suffix, ".asset"); // get a previous instance of the mesh. if none, create new asset at path. Mesh m = AssetDatabase.LoadAssetAtPath <Mesh>(name); if (m == null) { // no old asset could be loaded. create new asset with new GUID. AssetDatabase.CreateAsset(new Mesh(), name); // create file in DB AssetDatabase.SaveAssets(); // save changes AssetDatabase.Refresh(); // update DB m = AssetDatabase.LoadAssetAtPath <Mesh>(name); // reload from new path } // now dump every quad into the mesh. decimate vertices by only saving unique sets HashSet <Vertex> allVertices = new HashSet <Vertex>(); // unique vertex entries of (P,N,UV) List <List <Vertex> > allQuads = new List <List <Vertex> >(); // list of quad faces for indexing foreach (Vector2 UV in quads.Keys) // by UV color { foreach (Vector3 N in quads[UV].Keys) // by normal direction { foreach (float r in quads[UV][N].Keys) // by row { foreach (HashSet <Vector3> A in quads[UV][N][r]) // for every "quad vertex set A" { // dump every quads contents into the lists // get clockwise winding, create vertex entries List <Vector3> v = SortVerticesClockwise(A, N); // raw A,B,C,D vectors List <Vertex> e = new List <Vertex>(); // face vertex entries foreach (Vector3 p in v) // create vertex entry { e.Add(new Vertex(p, N, UV)); } allVertices.UnionWith(e); // add them to the global list // now create the references and add them to the face list List <Vertex> singleQuad = new List <Vertex>(); singleQuad.AddRange // add vertex-links for A+B triangle (new Vertex[] { e[0], e[1], e[2], e[0], e[2], e[3] }); allQuads.Add(singleQuad); // add to global quad face list } } } } // convert the vertex lists to arrays. (V,N,UV)-lists have to be of same size (WTF, Unity?) List <Vertex> entries = new List <Vertex>(allVertices); List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Color32> colors = new List <Color32>(); foreach (Vertex e in entries) { e.Dump(vertices, normals, uvs, colors); } // relink the faces to a proper index into the dumped lists List <int> faces = new List <int>(); foreach (List <Vertex> vertexIndices in allQuads) { foreach (Vertex e in vertexIndices) { faces.Add(entries.IndexOf(e)); } } // set final contents of output mesh m.Clear(); // clear old contents first m.vertices = vertices.ToArray(); // vertices m.normals = normals.ToArray(); // normals m.uv = uvs.ToArray(); // UV1 m.colors32 = colors.ToArray(); // vertex colors m.SetTriangles(faces.ToArray(), 0); // triangles indices // optimize structures m.Optimize(); m.RecalculateBounds(); // generate lightmap set as UV2 UnwrapParam up; // unwrapping parameters UnwrapParam.SetDefaults(out up); // set to default up.hardAngle *= 4; // increase hard angles for less seams up.packMargin *= 4; // increase margin (otherwise: black streaks) Unwrapping.GenerateSecondaryUVSet(m, up); // generate UV2 // save changes, update AssetDatabase again AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); // update the MeshFilter to use the generated mesh Undo.RecordObject(mf, undoTitle); mf.sharedMesh = m; // check if we have to update a MeshCollider as well MeshCollider mc = mf.GetComponent <MeshCollider>(); if (mc != null) { // if a MeshCollider is present, also update it's shared mesh Undo.RecordObject(mc, undoTitle); mc.sharedMesh = m; } // return the title of the converted new mesh asset return(name); }