public OctTree <TriangleBound> ConstructSceneOctree(List <TriangleInfo> sceneTriangles, Bounds bound) { int count = 0; AABBBoundBox maxBound = new AABBBoundBox(bound); _octree = new OctTree <TriangleBound>(maxBound); List <TriangleInfo> triangleList = new List <TriangleInfo>(triangleCountInOneGroup); foreach (TriangleInfo tri in sceneTriangles) { triangleList.Add(tri); if (triangleList.Count == triangleCountInOneGroup) { TriangleBound triangleBound = GroupBoundBox(triangleList); //boundList.Add(triangleBound); if (maxBound.Contains(triangleBound.GetBoundBox()) || maxBound.Overlap(triangleBound.boundBox)) { _octree.Insert(triangleBound); count++; } triangleList.Clear(); } } if (triangleList.Count != 0) { _octree.Insert(GroupBoundBox(triangleList)); count++; } Debug.Log(count); _octree.UpdateTree(); return(_octree); }
public static TriangleInfo[] GetTriangles(MeshFilter filter) { Mesh mesh = filter.sharedMesh; if (mesh == null) { return(null); } Vector3[] vertices = mesh.vertices; int[] tris = mesh.triangles; TriangleInfo[] triangles = new TriangleInfo[tris.Length / 3]; for (int i = 0; i < tris.Length; i += 3) { Vector3 v1 = filter.transform.TransformPoint(vertices[tris[i]]); Vector3 v2 = filter.transform.TransformPoint(vertices[tris[i + 1]]); Vector3 v3 = filter.transform.TransformPoint(vertices[tris[i + 2]]); AABBBoundBox box = new AABBBoundBox(Vector3.positiveInfinity, Vector3.negativeInfinity); box.Extend(v1); box.Extend(v2); box.Extend(v3); triangles[i / 3] = new TriangleInfo { p1 = v1, p2 = v2, p3 = v3, }; } return(triangles); }
public ObjInfo(KeyValuePair <GameObject, TriangleInfo[]> pair) { GameObject go = pair.Key; Bounds bound = go.GetComponent <Renderer>().bounds; boundBox = new AABBBoundBox(bound.min, bound.max); triangles = pair.Value; }
public OctTree(AABBBoundBox region) { s_treeBuilt = false; s_treeReady = false; this._region = region; objectList = new List <T>(); _curLife = -1; }
public bool Contains(AABBBoundBox b) { if (this.min.x <= b.min.x && this.min.y <= b.min.y && this.min.z <= b.min.z && this.max.x >= b.max.x && this.max.y >= b.max.y && this.max.z >= b.max.z) { return(true); } return(false); }
private void IntersectTest() { #if UNITY_EDITOR GameObject go; // -- for debug Stopwatch stopwatch = Stopwatch.StartNew(); int objIndex = 0; int intersectCount = 0; List <Task> tasks = new List <Task>(); foreach (KeyValuePair <GameObject, TriangleInfo[]> pair in objDic) { if (pair.Value == null) { continue; } // 每个物体多线程相交测试 if (enableMultiThreading) { tasks.Add(Task.Factory.StartNew(MultiThreadingIntersectTest, new ObjInfo(pair))); continue; } // 单线程相交 objIndex++; intersectCount = 0; go = pair.Key; Bounds bound = go.GetComponent <Renderer>().bounds; AABBBoundBox objBox = new AABBBoundBox(bound.min, bound.max); var l = octree.GetIntersections(objBox); for (int i = 0; i < l.Count; i++) { foreach (TriangleInfo tInfo in pair.Value) { if (l[i].overlapWithTriangle) { continue; } if (IntersectionTest.AABBTriangle(l[i].boundBox, tInfo)) { l[i].overlapWithTriangle = true; } } intersectCount++; bool cancel = EditorUtility.DisplayCancelableProgressBar("Voxelize", $"No.{objIndex} Object (of {objDic.Count}), Intersect Count {intersectCount}/{l.Count}", (float)intersectCount / l.Count); if (cancel) { break; } } } Task.WaitAll(tasks.ToArray()); stopwatch.Stop(); EditorUtility.ClearProgressBar(); Debug.Log($"体素化完成,耗时:{stopwatch.ElapsedMilliseconds}ms"); #endif }
public AABBBoundBox GetBoundBox() { if (boundBox == null) { Bounds bound = this.GetComponent <BoxCollider>().bounds; boundBox = new AABBBoundBox(bound); } return(boundBox); }
public void SetParams(Vector3 voxelSize, OctTree <TriangleBound> tree) { _octree = tree; _voxelSize = voxelSize; _region = tree.region; _originPos = _region.min; _xMax = Mathf.RoundToInt(_region.size.x / _voxelSize.x); _yMax = Mathf.RoundToInt(_region.size.y / _voxelSize.y); _zMax = Mathf.RoundToInt(_region.size.z / _voxelSize.z); _voxels = new bool[_xMax, _yMax, _zMax]; }
private OctTree <T> CreateNode(AABBBoundBox region, List <T> objList) { if (objList.Count == 0) { return(null); } OctTree <T> ret = new OctTree <T>(region, objList); ret.parent = this; ret.treeDepth = treeDepth + 1; return(ret); }
private void IntersectTestDivide(object obj) { Tuple <int, int, int> indexTuple = (Tuple <int, int, int>)obj; int startX = indexTuple.Item1; int startY = indexTuple.Item2; int startZ = indexTuple.Item3; int xRange = startX + divide; int yRange = startY + divide; int zRange = startZ + divide; xRange = xRange < _xMax ? xRange : _xMax; yRange = yRange < _yMax ? yRange : _yMax; zRange = zRange < _zMax ? zRange : _zMax; #region Naive Simple Violent Loop... for (int x = startX; x < xRange; x++) { for (int y = startY; y < yRange; y++) { for (int z = startZ; z < zRange; z++) { if (_voxels[x, y, z]) { continue; } AABBBoundBox boundBox = new AABBBoundBox(GetVoxelBoundMin(x, y, z), GetVoxelBoundMax(x, y, z)); List <TriangleBound> triangleBoundList = _octree.GetIntersections(boundBox); for (int i = 0; i < triangleBoundList.Count; i++) { for (int j = 0; j < triangleBoundList[i].triangles.Length; j++) { if (IntersectionTest.AABBTriangle(boundBox, triangleBoundList[i].triangles[j])) { _voxels[x, y, z] = true; } } } } } } #endregion lock (_locker) { _completeCount++; } }
public List <TriangleInfo> RetreiveSceneTriangles() { _triangleList.Clear(); // 创建用于线程里的数据 int index = 0; List <MeshInfo> meshList = new List <MeshInfo>(); // MeshFilter MeshFilter[] meshFilters = GameObject.FindObjectsOfType <MeshFilter>(); foreach (MeshFilter filter in meshFilters) { AABBBoundBox gameObjectBound = new AABBBoundBox(filter.gameObject.GetComponent <Renderer>().bounds); if (!validAreaBox.Contains(gameObjectBound) && !validAreaBox.Overlap(gameObjectBound)) { continue; } MeshInfo meshInfo = FromMeshFilter(filter); if (meshInfo != null) { meshList.Add(meshInfo); } } List <Task> tasks = new List <Task>(); foreach (MeshInfo meshInfo in meshList) { tasks.Add(Task.Factory.StartNew(GetTriangles, meshInfo)); } //-----Progress bar #if UNITY_EDITOR int previousCount = 0; while (_completeCount < tasks.Count) { if (previousCount != _completeCount) { previousCount = _completeCount; EditorUtility.DisplayProgressBar("Traverse Triangle", "", (float)_completeCount / tasks.Count); } } EditorUtility.ClearProgressBar(); #endif //------------------------------------ return(_triangleList); }
public static bool AABBTriangle(AABBBoundBox aabb, TriangleInfo triange) { // 转换三角形顶点至以aabb的中心为原点的坐标系下 Vector3 v0 = triange.p1 - aabb.center; Vector3 v1 = triange.p2 - aabb.center; Vector3 v2 = triange.p3 - aabb.center; // 三角形边的向量形式 Vector3 f0 = v1 - v0; Vector3 f1 = v2 - v1; Vector3 f2 = v0 - v2; // AABB的法线 Vector3 u0 = new Vector3(1.0f, 0f, 0f); Vector3 u1 = new Vector3(0, 1.0f, 0); Vector3 u2 = new Vector3(0, 0, 1.0f); Vector3[] axiArray = new Vector3[] { // 叉积轴 Vector3.Cross(u0, f0), Vector3.Cross(u0, f1), Vector3.Cross(u0, f2), Vector3.Cross(u1, f0), Vector3.Cross(u1, f1), Vector3.Cross(u1, f2), Vector3.Cross(u2, f0), Vector3.Cross(u2, f1), Vector3.Cross(u2, f2), // AABB面法线 u0, u1, u2, // 三角形面法线 Vector3.Cross(f0, f1) }; for (int i = 0; i < axiArray.Length; i++) { // 判定该轴是不是一个分离轴 如果是的话可判定不相交 if (IsSeparateAxi(axiArray[i], aabb.half, v0, v1, v2)) { return(false); } } return(true); }
private TriangleBound GroupBoundBox(List <TriangleInfo> infoList) { TriangleBound triangeBound = new TriangleBound(); AABBBoundBox bound = new AABBBoundBox(Vector3.positiveInfinity, Vector3.negativeInfinity); triangeBound.triangles = new TriangleInfo[infoList.Count]; for (int i = 0; i < infoList.Count; i++) { triangeBound.triangles[i] = infoList[i]; bound.Extend(infoList[i].p1); bound.Extend(infoList[i].p2); bound.Extend(infoList[i].p3); } triangeBound.boundBox = bound; return(triangeBound); }
public bool Overlap(AABBBoundBox b) { if (this.min.x > b.max.x || b.min.x > this.max.x) { return(false); } if (this.min.y > b.max.y || b.min.y > this.max.y) { return(false); } if (this.min.z > b.max.z || b.min.z > this.max.z) { return(false); } return(true); }
public List <T> GetIntersections(AABBBoundBox box) { List <T> intersections = new List <T>(); for (int i = 0; i < objectList.Count; i++) { if (objectList[i].GetBoundBox().Overlap(box)) { intersections.Add(objectList[i]); } } for (int i = 0; i < 8; i++) { if (childNodes[i] != null && (box.Contains(childNodes[i]._region) || box.Overlap(childNodes[i]._region))) { intersections.AddRange(childNodes[i].GetIntersections(box)); } } return(intersections); }
public OctTree(AABBBoundBox region, List <T> objList) { this._region = region; objectList = objList; _curLife = -1; }
public OctTree() { _region = new AABBBoundBox(Vector3.zero, Vector3.zero); objectList = new List <T>(); _curLife = -1; }
private void BuildTree() { if (objectList.Count <= 1) { return; } Vector3 dimense = _region.size; if (dimense == Vector3.zero) { //如果该节点的region为0,则找它的包含区域 // _region = FindEnclosingRegion(); dimense = _region.size; } if (dimense.x <= MIN_SIZE && dimense.y <= MIN_SIZE && dimense.z <= MIN_SIZE) { return; } Vector3 half = _region.half; Vector3 center = _region.center; AABBBoundBox[] octant = new AABBBoundBox[8]; octant[0] = new AABBBoundBox(_region.min, center); octant[1] = new AABBBoundBox(new Vector3(center.x, _region.min.y, _region.min.z), new Vector3(_region.max.x, center.y, center.z)); octant[2] = new AABBBoundBox(new Vector3(center.x, _region.min.y, center.z), new Vector3(_region.max.x, center.y, _region.max.z)); octant[3] = new AABBBoundBox(new Vector3(_region.min.x, _region.min.y, center.z), new Vector3(center.x, center.y, _region.max.z)); octant[4] = new AABBBoundBox(new Vector3(_region.min.x, center.y, _region.min.z), new Vector3(center.x, _region.max.y, center.z)); octant[5] = new AABBBoundBox(new Vector3(center.x, center.y, _region.min.z), new Vector3(_region.max.x, _region.max.y, center.z)); octant[6] = new AABBBoundBox(center, _region.max); octant[7] = new AABBBoundBox(new Vector3(_region.min.x, center.y, center.z), new Vector3(center.x, _region.max.y, _region.max.z)); List <T>[] octListArray = new List <T> [8]; for (int i = 0; i < 8; i++) { octListArray[i] = new List <T>(); } List <T> delist = new List <T>(); // 当前节点的对象划分至子区域中 foreach (T obj in objectList) { if (obj.GetBoundBox().size != Vector3.zero) { for (int i = 0; i < 8; i++) { if (octant[i].Contains(obj.GetBoundBox())) { octListArray[i].Add(obj); delist.Add(obj); break; } } } } // 被添加子区域的对象从当前的节点中移除 foreach (T obj in delist) { objectList.Remove(obj); } // 对象数不为0的区域建立八叉树节点 for (int i = 0; i < 8; i++) { if (octListArray[i].Count != 0) { childNodes[i] = CreateNode(octant[i], octListArray[i]); activeNodesMask |= (byte)(1 << i); childNodes[i].BuildTree(); } } s_treeBuilt = true; s_treeReady = true; }