public void UpdateContactMatrix() {

			List<PhysicalMaterialClass> materialClasses = new List<PhysicalMaterialClass>();

			var guids = AssetDatabase.FindAssets("t:PhysicalMaterialClass");
			foreach (var guid in guids) {
				var path = AssetDatabase.GUIDToAssetPath(guid);
				var obj = (PhysicalMaterialClass)AssetDatabase.LoadAssetAtPath(path, typeof(PhysicalMaterialClass));
				materialClasses.Add(obj);
			}

			List<PhysicalContact> contacts = new List<PhysicalContact>();
			Dictionary<PhysicalMaterialClass, Dictionary<PhysicalMaterialClass, PhysicalContact>> contactMap = new Dictionary<PhysicalMaterialClass, Dictionary<PhysicalMaterialClass, PhysicalContact>>();

			foreach (var m in materialClasses) {
								
				// keep existing contacts for existing material pairs
				// add new contacts for new pairs.

				Dictionary<PhysicalMaterialClass, PhysicalContact> map;
				if (!contactMap.TryGetValue(m, out map)) {
					map = new Dictionary<PhysicalMaterialClass, PhysicalContact>();
					contactMap.Add(m, map);
				}

				foreach (var z in materialClasses) {
					Dictionary<PhysicalMaterialClass, PhysicalContact> zmap;
					contactMap.TryGetValue(z, out zmap);

					if (!map.ContainsKey(z)) {

						// see if z has contact
						PhysicalContact contact = null;

						if ((zmap == null) || !zmap.TryGetValue(m, out contact)) {

							if (this.contacts != null) {
								for (int i = 0; i < this.contacts.Length; ++i) {
									var c = this.contacts[i];
									if (((c.material1 == m) && (c.material2 == z)) || ((c.material1 == z) && (c.material2 == m))) {
										contact = c;
										break;
									}
								}
							}

							if (contact == null) {
								contact = new PhysicalContact();
							}
														
							contact.material1 = m;
							contact.material2 = z;
							contacts.Add(contact);

							if ((zmap != null) && !ReferenceEquals(map, zmap)) {
								zmap.Add(m, contact);
							}
						}
												
						map.Add(z, contact);						
					}
				}
			}

			bool changed = false;

			if ((this.contacts == null) || (this.contacts.Length != contacts.Count)) {
				changed = true;
			}

			if (!changed) {
				for (int i = 0; i < contacts.Count; ++i) {
					var a = this.contacts[i];
					var b = contacts[i];

					if (!ReferenceEquals(a, b)) {
						changed = true;
						break;
					}
				}
			}

			if (changed) {
				this.contacts = contacts.ToArray();
				EditorUtility.SetDirty(this);
			}
		}
		public void ClientPrecache() {
			PhysicalContact.ClientPrecache(contacts);
			defaultContact.ClientPrecache();
		}
		public void OnBeforeSerialize() {
			if (defaultContact == null) {
				defaultContact = new PhysicalContact();
			}
		}
			public ContactState(PhysicalContact contact) {
				_contact = contact;
			}