using UnityEngine;

namespace NBF
{
    public class ModelViewerUtils
    {
        public static ModelViewerSettings InitSetting(GameObject go, ModelViewerSettings settings)
        {
            if (settings.objectPosition.magnitude < 0.0001f)
                settings.objectPosition = Vector3.zero;

            //---Zero the GameObject euler angles if they're very small in magnitude---//
            settings.objectRotation = go.transform.eulerAngles;
            if (settings.objectRotation.magnitude < 0.0001f)
                settings.objectRotation = Vector3.zero;

            //---Set the object scale variable---//
            settings.objectScale = go.transform.localScale;

            //将默认对象位置设为使其位于图标中心的位置
            Bounds bounds = GetObjectBounds(go);
            settings.objectPosition = GetObjectAutoOffset(bounds);

            // 将默认的相机设置调整为适合图标渲染中对象的呈现效果
            float camAuto = GetCameraAuto(bounds);
            settings.cameraSize = camAuto;
            settings.cameraPosition = Vector3.one * camAuto;


            return settings;
        }

        public static Bounds GetObjectBounds(GameObject go)
        {
            // 在将其位置归零之前先保存其位置信息
            Vector3 prefabPos = go.transform.position;
            go.transform.position = Vector3.zero;

            // 创建一个边界对象，并将对象网格的边界进行封装。
            MeshRenderer mr = go.GetComponent<MeshRenderer>();
            Bounds bounds = new Bounds(Vector3.zero, 0.000001f * Vector3.one);
            if (mr != null)
                bounds.Encapsulate(mr.bounds);
            else
            {
                SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
                if (smr != null)
                    bounds.Encapsulate(smr.bounds);
            }

            //同时将对象的子对象的范围也进行封装起来
            EncapsulateChildBounds(go.transform, ref bounds);

            //将预制物的位置重置为存储的值
            go.transform.position = prefabPos;

            return bounds;
        }

        public static Vector3 GetObjectAutoOffset(Bounds bounds)
        {
            //将偏移量应用到图标对象的位置上
            return -bounds.center;
        }

        public static float GetCameraAuto(Bounds bounds)
        {
            //---Scale camera size and position so that the object fits in the render---//
            Matrix4x4 trs = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 45, 0), 1.05f * Vector3.one);
            Vector3 corner = new Vector3(bounds.extents.x, bounds.extents.y, bounds.extents.z);
            corner = trs * corner;

            Vector2 refB2 = new Vector2(0.74f, 0.53f);
            Vector2 b2 = refB2 * corner.magnitude;

            return b2.magnitude;
        }

        public static void EncapsulateChildBounds(Transform t, ref Bounds bounds)
        {
            // 遍历所有子对象，封装边界
            MeshRenderer mr;
            for (int i = 0; i < t.childCount; i++)
            {
                mr = t.GetChild(i).GetComponent<MeshRenderer>();
                if (mr != null)
                    bounds.Encapsulate(mr.bounds);
                else
                {
                    SkinnedMeshRenderer smr = t.GetChild(i).GetComponent<SkinnedMeshRenderer>();
                    if (smr != null)
                        bounds.Encapsulate(smr.bounds);
                }

                EncapsulateChildBounds(t.GetChild(i), ref bounds);
            }
        }
    }
}