public void UpdateCamera(GameObject o)
    {
        if (o == null)
        {
            return;
        }
        var smrs = o.GetComponentsInChildren <SkinnedMeshRenderer>();

        if (smrs == null)
        {
            return;
        }
        var vList = new List <Vector3>();

        foreach (var smr in smrs)
        {
            vList.Add(smr.sharedMesh.bounds.max);
            vList.Add(smr.sharedMesh.bounds.min);
        }
        var bigBound = ObjManager.GetBoundsOfVector3Array(vList.ToArray());

        center = bigBound.center;
        var r = (bigBound.max - bigBound.min).magnitude / 2;

        transform.position = new Vector3(0, bigBound.center.y, 2 * r);
        transform.forward  = center - transform.position;
    }
    private List <Bounds> MergeContactPointsToMaxNum(List <Bounds> boundsList) //将接触点限制到最大数量内
    {
        if (boundsList.Count <= MAX_CONTACT_POINT_NUM)                         //未达到数量直接返回
        {
            return(boundsList);
        }
        var re = new List <Bounds>();
        var sd = new SortedDictionary <Cost, int[]>(new CostComparer());
        var f  = new List <int>(); //是否被合并的标志
        int id = 0;                //新加入sd的cost的id,SortedDictionary的key不能有相同的元素

        for (int i = 0; i < boundsList.Count; i++)
        {
            f.Add(i);
            for (int j = i + 1; j < boundsList.Count; j++)
            {
                var cost = BoundsToBoundsCost(boundsList[i], boundsList[j]);
                sd.Add(new Cost(cost, ++id), new int[] { i, j });
            }
        }
        int cnt = boundsList.Count;//还剩下多少接触点

        while (cnt > MAX_CONTACT_POINT_NUM)
        {
            var e = sd.GetEnumerator();
            e.MoveNext();
            var   ec   = e.Current;
            int[] pair = ec.Value;
            sd.Remove(ec.Key);
            if (f[pair[0]] != pair[0] || f[pair[1]] != pair[1])//该点已被合并
            {
                continue;
            }
            var u         = boundsList[pair[0]];
            var v         = boundsList[pair[1]];
            var vector3s  = new Vector3[] { u.max, u.min, v.max, v.min };
            var newBounds = ObjManager.GetBoundsOfVector3Array(vector3s);
            boundsList.Add(newBounds);
            f[pair[0]] = f.Count;             //合并老点
            f[pair[1]] = f.Count;
            for (int i = 0; i < f.Count; i++) //计算与其它球的cost
            {
                if (f[i] != i)
                {
                    continue;
                }
                var cost = BoundsToBoundsCost(boundsList[i], newBounds);//包围盒外接球球心距离减去半径距离除以两球半径和,尽量先合并小的球
                sd.Add(new Cost(cost, ++id), new int[] { i, f.Count });
            }
            f.Add(f.Count);//创建新点
            cnt--;
        }
        for (int i = 0; i < f.Count; i++)
        {
            if (i == f[i])
            {
                re.Add(boundsList[i]);
            }
        }
        return(re);
    }
    private IEnumerator SolveContactPoints()//对选中的模型计算接触点
    {
        yield return(new WaitForSeconds(0));

        buttonGCP.interactable = false;                                       //计算的时候不能再点击按钮
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); //记录开始时间
        sw.Start();
        textTimeCost.text = "";                                               //重新显示时间
        sliderGCP.value   = 0;                                                //进度条归零
        var selectedObjList               = new List <ListNode>();            //选中对象们
        var unselectedObjList             = new List <ListNode>();            //未选中对象们
        int totalSelectedObjVerticeNum    = 0;                                //总的选中物体顶点数
        int totalUnselectedObjVerticeNum  = 0;                                //总的未选中物体顶点数
        int totalSelectedObjTriangleNum   = 0;                                //总的选中物体三角面片数,用来控制进度条显示
        int totalUnselectedObjTriangleNum = 0;                                //总的未选中物体三角面片数

        yield return(new WaitForSeconds(0));

        foreach (var item in model3d.GetComponentsInChildren <SkinnedMeshRenderer>())//获得所有物体每个三角面片包围盒
        {
            var vertices   = ObjManager.GetRealVertices(item);
            var triangles  = item.sharedMesh.triangles;
            var boundsList = new List <Bounds>();
            var objBounds  = ObjManager.GetBoundsOfVector3Array(vertices);

            if (item.tag.Equals(Macro.SELECTED))
            {
                for (int i = 0; i < triangles.Length; i += 3)
                {
                    Vector3[] tmp = { vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]] };
                    boundsList.Add(ObjManager.GetBoundsOfVector3Array(tmp));
                }
                selectedObjList.Add(new ListNode(objBounds, boundsList));
                totalSelectedObjVerticeNum  += vertices.Length;
                totalSelectedObjTriangleNum += triangles.Length;
            }
            else if (item.tag.Equals(Macro.UNSELECTED))
            {
                for (int i = 0; i < triangles.Length; i += 3)
                {
                    Vector3[] tmp = { vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]] };
                    boundsList.Add(ObjManager.GetBoundsOfVector3Array(tmp));
                }
                unselectedObjList.Add(new ListNode(objBounds, boundsList));
                totalUnselectedObjVerticeNum  += vertices.Length;
                totalUnselectedObjTriangleNum += triangles.Length;
            }
        }
        yield return(new WaitForSeconds(0));

        Debug.Log("selectedObjNum: " + selectedObjList.Count);
        Debug.Log("unselectedObjNum: " + unselectedObjList.Count);
        Debug.Log("totalSelectedObjVerticeNum: " + totalSelectedObjVerticeNum);
        Debug.Log("totalSelectedObjVerticeNum: " + totalUnselectedObjVerticeNum);
        Debug.Log("totalSelectedObjTriangleNum: " + totalSelectedObjTriangleNum);
        Debug.Log("totalUnselectedObjTriangleNum: " + totalUnselectedObjTriangleNum);
        float sliderValueFz = 0;                   //slider value的分子
        var   xjBoundsList  = new List <Bounds>(); //不同物体相交的区域

        foreach (var so in selectedObjList)        //求交
        {
            foreach (var uso in unselectedObjList)
            {
                if (!DealBoundsIntersection(so.objBounds, uso.objBounds, false, xjBoundsList))//两物体的包围盒不相交
                {
                    sliderValueFz += so.triangleBoundsList.Count;
                    continue;
                }
                foreach (var sotb in so.triangleBoundsList)
                {
                    sliderValueFz++;
                    if (!DealBoundsIntersection(sotb, uso.objBounds, false, xjBoundsList))//选中物体三角面片包围盒不与未选中物体包围盒相交
                    {
                        continue;
                    }
                    foreach (var usotb in uso.triangleBoundsList)
                    {
                        if (DealBoundsIntersection(sotb, usotb, true, xjBoundsList))
                        {
                        }
                    }
                    var tmpV = sliderValueFz * 3 / (unselectedObjList.Count * totalSelectedObjTriangleNum);
                    if (tmpV - sliderGCP.value >= 0.05)
                    {
                        sliderGCP.value = tmpV;//更新进度条的值
                        yield return(new WaitForSeconds(0));
                    }
                }
            }
        }

        var contactPointNum = CreateContactPoints(xjBoundsList); //显示接触点

        sliderGCP.value = 1;                                     //计算完毕,进度条的值置为1
        Debug.Log("contactPointNum: " + contactPointNum);
        buttonGCP.interactable = true;                           //计算完成可以点击按钮
        sw.Stop();
        ShowTime(sw.Elapsed.TotalSeconds);
    }