Ejemplo n.º 1
0
        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);
        }