Ejemplo n.º 1
0
        /// <summary>
        /// Build the primitives to all selected objects to be used in the BVH
        /// </summary>
        public static void Build(ref List <ObjectData> allObjects, out List <BVHNode> nodes, out List <BVHTriangle> tris, out List <BVHTriangle> finalPrims)
        {
            // Current primitive id
            int pID = 0;

            // These buffers are disposed in the Main script from which this method is called
            nodes      = new List <BVHNode>();
            tris       = new List <BVHTriangle>();
            finalPrims = new List <BVHTriangle>();

            // Iterate thourgh all objects and create primitives using object's triangles
            foreach (ObjectData o in allObjects)
            {
                if (!o.IsValid)
                {
                    continue;
                }

                // Using the mesh verts and the tris from each submesh,
                // we can build the lumes separately for each submesh
                for (int i = 0; i < o.Indices.Length; i += 3)
                {
                    int trID0 = o.Indices[i + 0];
                    int trID1 = o.Indices[i + 1];
                    int trID2 = o.Indices[i + 2];

                    Vector3 v0 = o.VerticeList[trID0];
                    Vector3 v1 = o.VerticeList[trID1];
                    Vector3 v2 = o.VerticeList[trID2];

                    Vector3 n0 = o.HasNormals ? o.NormalList[trID0] : Vector3.zero;
                    Vector3 n1 = o.HasNormals ? o.NormalList[trID1] : Vector3.zero;
                    Vector3 n2 = o.HasNormals ? o.NormalList[trID2] : Vector3.zero;

                    // You have to add the check for excluding back face trinagles here

                    // Backfacing triangles skip
                    Vector3 n = Vector3.Cross((v1 - v0).normalized, (v2 - v0).normalized).normalized;

                    // Backfacing check
                    if (Vector3.Dot(Vector3.up, n) >= 0f)
                    {
                        tris.Add(new BVHTriangle(v0, v1, v2,
                                                 n0, n1, n2,
                                                 pID++, o.TerrainSourceID));
                    }
                }
            }

            // Creating (Building) the bvh
            Bvh = new BVHNode(tris, nodes, ref finalPrims);
        }
Ejemplo n.º 2
0
        public int    SplitAxis;        // 4 byte

        public LBVHNODE(BVHNode node)
        {
            BMin             = node.Min;
            BMax             = node.Max;
            NodeID           = node.NodeID;
            PrimitivesCount  = node.PrimitivesCount;
            PrimitivesOffset = node.PrimitivesOffset;
            ParentID         = node.ParentID;
            LChildID         = node.LChildID;
            RChildID         = node.RChildID;
            IsLeaf           = node.IsLeaf;
            SplitAxis        = node.SplitAxis;
            NearNodeID       = -1;
            FarNodeID        = -1;
        }
Ejemplo n.º 3
0
        public ObjectData(MeshRenderer r, int terrainSourceID)
        {
            Renderer = r;
            Mesh     = r.GetComponent <MeshFilter>().sharedMesh;
            IsValid  = Mesh != null;

            SubMesheCount   = 0;
            VerticeList     = null;
            NormalList      = null;
            Indices         = null;
            HasNormals      = false;
            Prims           = null;
            Nodes           = null;
            TerrainSourceID = terrainSourceID;

            BVH = new BVHNode();

            if (IsValid)
            {
                SubMesheCount = Mesh.subMeshCount;
                VerticeList   = new List <Vector3>();
                Mesh.GetVertices(VerticeList);
                NormalList = new List <Vector3>();
                Mesh.GetNormals(NormalList);
                Indices    = new int[Mesh.triangles.Length];
                Indices    = Mesh.triangles;
                HasNormals = NormalList.Count > 0;

                Matrix4x4 mtrx = Renderer.localToWorldMatrix;
                for (int v = 0; v < VerticeList.Count; v++)
                {
                    VerticeList[v] = mtrx.MultiplyPoint3x4(VerticeList[v]);
                    NormalList[v]  = mtrx.MultiplyVector(NormalList[v]);
                }
            }
        }
Ejemplo n.º 4
0
        public static BVHNode CreateBVHNode()
        {
            BVHNode b = new BVHNode
            {
                NodeType         = 0,
                IsLeaf           = 0,
                Centroid         = Vector3.zero,
                Min              = Vector3.one * float.MaxValue,
                Max              = Vector3.one * -float.MaxValue,
                PrimID           = -1,
                PrimitivesCount  = 0,
                PrimitivesOffset = 0,
                NodeID           = 0,
                ParentID         = -1,
                LChildID         = 0,
                RChildID         = 0,
                NearNodeID       = 0,
                FarNodeID        = 0,
                SplitAxis        = 0,
                SplitMethod      = 1
            };

            return(b);
        }
Ejemplo n.º 5
0
        public void Build(int nodeID, List <BVHTriangle> tris, ref List <BVHNode> nodes, ref List <BVHTriangle> finalPrims)
        {
            BVHNode node = nodes[nodeID];

            // Leaf
            if (tris.Count <= BVH.MaxPrimsCountPerNode)
            {
                // NOTE : the prims offset is calculated in the " Flattening BVH " method
                node.IsLeaf = 1;

                node.PrimitivesCount  = 1;
                node.PrimitivesOffset = finalPrims.Count;

                finalPrims.Add(tris[0]);
                nodes[nodeID] = node;
            }
            else
            {
                List <BVHTriangle> lTris = new List <BVHTriangle>();
                List <BVHTriangle> rTris = new List <BVHTriangle>();

                switch (node.SplitMethod)
                {
                // -------------------- Equal count split ! --------------------
                case 0:     //  (int)BVHSplitMethod.SPLIT_EQUAL_COUNTS:

                    node.GetLongestAxisAndValue();
                    int splitAxis = node.SplitAxis;

                    // Equal split
                    if (lTris.Count == 0 || rTris.Count == 0)
                    {
                        // In this case the incomming tris list should be sorted
                        switch (splitAxis)
                        {
                        case 0: tris.Sort(CompareX); break;

                        case 1: tris.Sort(CompareY); break;

                        case 2: tris.Sort(CompareZ); break;
                        }
                        int trisHalf = tris.Count / 2;

                        lTris = tris.GetRange(0, trisHalf);
                        rTris = tris.GetRange(trisHalf, tris.Count - trisHalf);
                    }

                    break;

                // -------------------- Median axis split ! --------------------
                case 1:     // (int)BVHSplitMethod.SPLIT_MIDDLE:

                    node.GetLongestAxisAndValue();

                    float splitValue = node.SplitValue;
                    splitAxis = node.SplitAxis;


                    // Median split triangle buffer
                    switch (splitAxis)
                    {
                    case 0:
                        lTris = tris.FindAll(n => n.Centroid.x < splitValue);
                        rTris = tris.FindAll(n => n.Centroid.x >= splitValue);
                        break;

                    case 1:
                        lTris = tris.FindAll(n => n.Centroid.y < splitValue);
                        rTris = tris.FindAll(n => n.Centroid.y >= splitValue);
                        break;

                    case 2:
                        lTris = tris.FindAll(n => n.Centroid.z < splitValue);
                        rTris = tris.FindAll(n => n.Centroid.z >= splitValue);
                        break;
                    }

                    // If median split was not good enough
                    // Switch to equal split
                    if (lTris.Count == 0 || rTris.Count == 0)
                    {
                        // In this case the incomming tris list should be sorted
                        switch (splitAxis)
                        {
                        case 0: tris.Sort(CompareX); break;

                        case 1: tris.Sort(CompareY); break;

                        case 2: tris.Sort(CompareZ); break;
                        }

                        int trisHalf = tris.Count / 2;
                        lTris = tris.GetRange(0, trisHalf);
                        rTris = tris.GetRange(trisHalf, tris.Count - trisHalf);
                    }
                    //Debug.Log("Sliptting primitives using median split");
                    break;

                // -------------------- Split using surface area heuristic ! --------------------
                case 2:     // BVHSplitMethod.SPLIT_SAH:

                    break;
                }
                BVHNode lChild = CreateBVHNode();
                BVHNode rChild = CreateBVHNode();

                lChild.NodeID = nodes.Count + 0;
                rChild.NodeID = nodes.Count + 1;

                lChild.ParentID = node.NodeID;
                rChild.ParentID = node.NodeID;

                lChild.NodeType = 1;
                rChild.NodeType = 2;

                node.LChildID = lChild.NodeID;
                node.RChildID = rChild.NodeID;

                lChild.CalculateBBox(lTris);
                rChild.CalculateBBox(rTris);

                // ----------------------------------------------------------------------------
                // Adding both children into the nodes list
                // ----------------------------------------------------------------------------

                nodes.Add(lChild);
                nodes.Add(rChild);

                // ----------------------------------------------------------------------------
                // Building the children nodes
                // ----------------------------------------------------------------------------

                // Use only when dealing with structs
                nodes[nodeID] = node;

                Build(lChild.NodeID, lTris, ref nodes, ref finalPrims);
                Build(rChild.NodeID, rTris, ref nodes, ref finalPrims);
            }
        }