Exemplo n.º 1
0
    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);
    }
Exemplo n.º 2
0
    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);
    }
Exemplo n.º 3
0
        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;
        }
Exemplo n.º 4
0
 public OctTree(AABBBoundBox region)
 {
     s_treeBuilt  = false;
     s_treeReady  = false;
     this._region = region;
     objectList   = new List <T>();
     _curLife     = -1;
 }
Exemplo n.º 5
0
 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);
 }
Exemplo n.º 6
0
    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
    }
Exemplo n.º 7
0
 public AABBBoundBox GetBoundBox()
 {
     if (boundBox == null)
     {
         Bounds bound = this.GetComponent <BoxCollider>().bounds;
         boundBox = new AABBBoundBox(bound);
     }
     return(boundBox);
 }
Exemplo n.º 8
0
 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];
 }
Exemplo n.º 9
0
    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);
    }
Exemplo n.º 10
0
    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);
    }
Exemplo n.º 12
0
    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);
    }
Exemplo n.º 13
0
    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);
    }
Exemplo n.º 14
0
    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);
    }
Exemplo n.º 15
0
    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);
    }
Exemplo n.º 16
0
 public OctTree(AABBBoundBox region, List <T> objList)
 {
     this._region = region;
     objectList   = objList;
     _curLife     = -1;
 }
Exemplo n.º 17
0
 public OctTree()
 {
     _region    = new AABBBoundBox(Vector3.zero, Vector3.zero);
     objectList = new List <T>();
     _curLife   = -1;
 }
Exemplo n.º 18
0
    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;
    }