/// <summary> /// Rebuild the mesh positions and submeshes. If vertex count matches new positions array the existing attributes are kept, otherwise the mesh is cleared. UV2 is the exception, it is always cleared. /// </summary> /// <param name="preferredTopology">Triangles and Quads are supported.</param> public void ToMesh(MeshTopology preferredTopology = MeshTopology.Triangles) { // if the mesh vertex count hasn't been modified, we can keep most of the mesh elements around if (mesh == null) { #if ENABLE_DRIVEN_PROPERTIES SerializationUtility.RegisterDrivenProperty(this, this, "m_Mesh"); #endif mesh = new Mesh(); } else if (mesh.vertexCount != vertexCount) { mesh.Clear(); } mesh.indexFormat = vertexCount > ushort.MaxValue ? Rendering.IndexFormat.UInt32 : Rendering.IndexFormat.UInt16; mesh.vertices = m_Positions; mesh.uv2 = null; if (m_MeshFormatVersion < k_MeshFormatVersion) { if (m_MeshFormatVersion < k_MeshFormatVersionSubmeshMaterialRefactor) { Submesh.MapFaceMaterialsToSubmeshIndex(this); } if (m_MeshFormatVersion < k_MeshFormatVersionAutoUVScaleOffset) { UvUnwrapping.UpgradeAutoUVScaleOffset(this); } m_MeshFormatVersion = k_MeshFormatVersion; } m_MeshFormatVersion = k_MeshFormatVersion; int materialCount = MaterialUtility.GetMaterialCount(renderer); Submesh[] submeshes = Submesh.GetSubmeshes(facesInternal, materialCount, preferredTopology); mesh.subMeshCount = materialCount; for (int i = 0; i < mesh.subMeshCount; i++) { #if DEVELOPER_MODE if (i >= materialCount) { Log.Warning("Submesh index " + i + " is out of bounds of the MeshRenderer materials array."); } if (submeshes[i] == null) { throw new Exception("Attempting to assign a null submesh. " + i + "/" + materialCount); } #endif mesh.SetIndices(submeshes[i].m_Indexes, submeshes[i].m_Topology, i, false); } mesh.name = string.Format("pb_Mesh{0}", id); EnsureMeshFilterIsAssigned(); }
internal void ApplyDrivenProperties() { SerializationUtility.RegisterDrivenProperty(this, this, "m_Mesh"); if (gameObject != null && gameObject.TryGetComponent(out MeshCollider meshCollider)) { SerializationUtility.RegisterDrivenProperty(this, meshCollider, "m_Mesh"); } }
internal void EnsureMeshColliderIsAssigned() { if (gameObject.TryGetComponent <MeshCollider>(out MeshCollider collider)) { #if ENABLE_DRIVEN_PROPERTIES SerializationUtility.RegisterDrivenProperty(this, collider, "m_Mesh"); #endif collider.sharedMesh = (mesh != null && mesh.vertexCount > 0) ? mesh : null; } }
void EnsureMeshColliderIsAssigned() { mesh.RecalculateBounds(); if (gameObject.TryGetComponent <MeshCollider>(out MeshCollider collider)) { SerializationUtility.RegisterDrivenProperty(this, collider, "m_Mesh"); collider.sharedMesh = null; collider.sharedMesh = mesh; } }
void RefreshCollisions() { mesh.RecalculateBounds(); MeshCollider collider; if (gameObject.TryGetComponent <MeshCollider>(out collider)) { SerializationUtility.UnregisterDrivenProperty(this, collider, "m_Mesh"); SerializationUtility.RegisterDrivenProperty(this, collider, "m_Mesh"); collider.sharedMesh = null; collider.sharedMesh = mesh; } }
void Awake() { // Register driven properties and set hide flags in Awake because OnEnable is called after serialization has // had a chance to register changes EnsureMeshFilterIsAssigned(); SerializationUtility.RegisterDrivenProperty(this, this, "m_Mesh"); if (vertexCount > 0 && faceCount > 0 && meshSyncState == MeshSyncState.Null) { Rebuild(); } }
// Using the internal callbacks here to avoid registering this component as "enable-able" void OnEnableINTERNAL() { SerializationUtility.RegisterDrivenProperty(this, this, "m_Mesh"); }