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); }