public static GameObject Create_Model_Prefab(string prefabName, Stream obj_file, ModelMat_Resolver_Delegate material_resolver, Model_Prefab_Transform[] transforms = null) { if (model_prefab_cache.ContainsKey(prefabName)) { return(model_prefab_cache[prefabName]); } var factory = new ObjLoaderFactory(); IObjLoader loader; if (material_resolver != null) { loader = factory.Create(new MaterialResourceProvider(material_resolver)); } else { loader = factory.Create(); } var mdl = loader.Load(obj_file); var matBuilder = new MaterialBuilder(material_resolver); var prefab = new GameObject(prefabName); prefab.SetActive(false); prefab.AddComponent <ModelData>(); prefab.AddComponent <Rigidbody>(); var data = new ModelData_Header(); data_cache.Add(prefabName, data); foreach (var group in mdl.Groups) { var gType = MdlGroupType.MESH; var Name = group.Name; foreach (var kvp in RESERVED_GROUP_PREFIXES) { var reg = kvp.Key; var match = reg.Match(Name); if (!match.Success) { continue; } if (match.Groups.Count <= 1) { continue; } //for (int i = 0; i < match.Groups.Count; i++) PLog.Info(" - {0}", match.Groups[i].Value); Name = match.Groups[1].Value.TrimStart(new char[] { '_' }); gType = kvp.Value; break; } //PLog.Info("- Group: \"{0}\" Type: {1}", gName, Enum.GetName(typeof(MdlGroupType), gType)); var gObj = new GameObject(group.Name); var builder = new MeshBuilder(mdl); var materials = new UnityEngine.Material[0]; foreach (SubMesh mesh in group.Meshes) { builder.Start_Sub_Mesh(); foreach (var face in mesh.Faces) { if (face.Count < 3) { continue; } else if (face.Count == 3) { builder.Push_Tri(face[0], face[1], face[2], transforms); } else if (face.Count == 4) { builder.Push_Tri(face[0], face[1], face[2], transforms); builder.Push_Tri(face[0], face[2], face[3], transforms); } } if (gType == MdlGroupType.ATTACHMENT_POS || gType == MdlGroupType.PHYS) { continue; } if (mesh.Material != null) { //PLog.Info("- Material: {0}", mesh.Material.Name); materials.AddToArray(matBuilder.Create(mesh.Material)); } } gObj.transform.SetParent(prefab.transform, false); gObj.transform.localPosition = Vector3.zero; gObj.transform.localRotation = Quaternion.identity; if (gType == MdlGroupType.ATTACHMENT_POS) { // Attachment positions should ideally contain only a single vertex. But if they contain more we should not be stupid and ignore them. // So let's just find the center of all points provided. gObj.transform.localPosition = builder.Calculate_Center_Point(group); data.Push_Attachment_Spot(group.Name, Name); } else { var filter = gObj.AddComponent <MeshFilter>(); filter.mesh = builder.Compile(); var renderer = gObj.AddComponent <MeshRenderer>();// All game objects need a MeshRenderer for that mesh to even give the object a size/bounds within the world! if (gType == MdlGroupType.PHYS || materials.Length <= 0) { renderer.enabled = false; } else { //PLog.Info("Creating material for: {0}", group.Material.Name); renderer.enabled = true; renderer.materials = materials; } var bx = gObj.AddComponent <BoxCollider>(); switch (gType) { case MdlGroupType.MESH: data.Push_Mesh(group.Name, Name); break; case MdlGroupType.STATE: data.Push_State(group.Name, Name); break; case MdlGroupType.PHYS: data.Push_Phys(group.Name, Name); break; default: throw new NotImplementedException("Unhandled " + nameof(MdlGroupType) + " value: " + gType); } } } if (model_prefab_cache.ContainsKey(prefabName)) { model_prefab_cache.Add(prefabName, prefab); } else { model_prefab_cache[prefabName] = prefab; } return(prefab); }